Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ New features
Bug fixes
~~~~~~~~~

- Fixed :func:`~icalendar.parser.string.escape_char` to accept :class:`bytes` input by converting it to :class:`str` with :func:`~icalendar.parser_tools.to_unicode` before applying replacements. :issue:`1226`
- ...

Documentation
Expand Down
6 changes: 3 additions & 3 deletions src/icalendar/parser/string.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import re

from icalendar.parser_tools import DEFAULT_ENCODING
from icalendar.parser_tools import DEFAULT_ENCODING, to_unicode


def escape_char(text: str | bytes) -> str | bytes:
def escape_char(text: str | bytes) -> str:
r"""Format value according to iCalendar TEXT escaping rules.

Escapes special characters in text values according to :rfc:`5545#section-3.3.11`
Expand All @@ -29,7 +29,7 @@ def escape_char(text: str | bytes) -> str | bytes:
6. ``"\n"`` -> ``r"\n"`` (transform a newline character to a literal, or raw,
newline character)
"""
assert isinstance(text, (str, bytes))
text = to_unicode(text)
# NOTE: ORDER MATTERS!
return (
text.replace(r"\N", "\n")
Expand Down
13 changes: 12 additions & 1 deletion src/icalendar/tests/test_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from icalendar.cal.calendar import Calendar
from icalendar.cal.component_factory import ComponentFactory
from icalendar.cal.event import Event
from icalendar.parser import Contentline, Parameters, unescape_char
from icalendar.parser import Contentline, Parameters, unescape_char, escape_char


@pytest.mark.parametrize(
Expand Down Expand Up @@ -280,3 +280,14 @@ def test_create_a_component():
my_component_class = factory.get_component_class("My-Component")
assert my_component_class.name == "MY-COMPONENT"
assert my_component_class.__name__ == "MyComponent"


def test_escape_char_bytes():
"""Test that escape_char accepts bytes input and returns str."""
assert escape_char(b"hello,world") == "hello\\,world"
assert escape_char(b"hello;world") == "hello\\;world"
assert escape_char(b"hello\\world") == "hello\\\\world"
assert escape_char(b"hello\nworld") == "hello\\nworld"
assert escape_char(b"hello\r\nworld") == "hello\\nworld"
assert escape_char(b"hello\\Nworld") == "hello\\nworld"
assert escape_char("hello,world") == "hello\\,world"
Loading