Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Minor changes
~~~~~~~~~~~~~

- Deprecate ``icalendar.parser.escape_string`` and ``icalendar.parser.unescape_string`` for icalendar version 8. Use ``_escape_string`` and ``_unescape_string`` internally. :issue:`1011`
- Deprecate ``icalendar.parser.q_split`` for icalendar version 8. Use the private ``_q_split`` internally.
- Deprecate ``icalendar.parser.q_join`` for icalendar version 8. Use the private ``_q_join`` internally.
- Deprecate ``icalendar.parser.foldline`` for icalendar version 8. Use the private ``_foldline`` internally.
Comment thread
siddhirajkatkar marked this conversation as resolved.
Outdated
- Added behavioral tests for :class:`~icalendar.cal.lazy.LazyCalendar` covering serialization round-trips, ``.todos``, ``.journals``, forward timezone references, and ``with_uid()`` substring false-positives. :issue:`1050`
- Added edge case tests for :class:`~icalendar.prop.conference.Conference` parameter normalization covering string passthrough, empty list filtering, and None omission. :issue:`925`
- Make icalendar an explicit editable install for clarity. :pr:`1268`
Expand Down
4 changes: 4 additions & 0 deletions src/icalendar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
# chars.
from icalendar.parser import (
Parameters,
_q_join,
_q_split,
q_join,
q_split,
)
Expand Down Expand Up @@ -144,6 +146,8 @@
"__version__",
"__version_tuple__",
"is_utc",
"_q_join",
"_q_split",
"q_join",
"q_split",
"use_pytz",
Expand Down
8 changes: 4 additions & 4 deletions src/icalendar/cal/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
Contentline,
Contentlines,
Parameters,
q_join,
q_split,
_q_join,
_q_split,
)
from icalendar.parser.ical.component import ComponentIcalParser
from icalendar.parser_tools import DEFAULT_ENCODING
Expand Down Expand Up @@ -372,7 +372,7 @@ def decoded(self, name: str, default: Any = _marker) -> Any:

def get_inline(self, name, decode=1):
"""Returns a list of values (split on comma)."""
vals = [v.strip('" ') for v in q_split(self[name])]
vals = [v.strip('" ') for v in _q_split(self[name])]
if decode:
return [self._decode(name, val) for val in vals]
return vals
Expand All @@ -383,7 +383,7 @@ def set_inline(self, name, values, encode=1):
"""
if encode:
values = [self._encode(name, value, encode=1) for value in values]
self[name] = self.types_factory["inline"](q_join(values))
self[name] = self.types_factory["inline"](_q_join(values))

#########################
# Handling of components
Expand Down
79 changes: 59 additions & 20 deletions src/icalendar/caselessdict.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

import warnings
from collections import OrderedDict
from typing import TYPE_CHECKING, Any, TypeVar

from icalendar.parser_tools import to_unicode
from icalendar.parser_tools import _to_unicode

if TYPE_CHECKING:
from collections.abc import Iterable, Mapping
Expand All @@ -17,7 +18,7 @@
VT = TypeVar("VT")


def canonsort_keys(
def _canonsort_keys(
keys: Iterable[KT], canonical_order: Iterable[KT] | None = None
) -> list[KT]:
"""Sort leading keys according to a canonical order.
Expand All @@ -38,8 +39,8 @@ def canonsort_keys(
Example:
.. code-block:: pycon

>>> from icalendar.caselessdict import canonsort_keys
>>> canonsort_keys(["C", "A", "B"], ["B", "C"])
>>> from icalendar.caselessdict import _canonsort_keys
>>> _canonsort_keys(["C", "A", "B"], ["B", "C"])
['B', 'C', 'A']
"""
canonical_map = {k: i for i, k in enumerate(canonical_order or [])}
Expand All @@ -48,7 +49,26 @@ def canonsort_keys(
return sorted(head, key=lambda k: canonical_map[k]) + sorted(tail)


def canonsort_items(
def canonsort_keys(
keys: Iterable[KT], canonical_order: Iterable[KT] | None = None
) -> list[KT]:
"""Sort leading keys according to a canonical order.

.. deprecated:: 7.0.0
Use the private :func:`_canonsort_keys` internally. For external use,
this function is deprecated. Please contact the maintainers if you
rely on this function.
"""
warnings.warn(
"canonsort_keys is deprecated and will be removed in a future version. "
"If you are using this function externally, please contact the maintainers.",
DeprecationWarning,
stacklevel=2,
)
return _canonsort_keys(keys, canonical_order)


def _canonsort_items(
dict1: Mapping[KT, VT], canonical_order: Iterable[KT] | None = None
) -> list[tuple[KT, VT]]:
"""Sort items from a mapping according to a canonical key order.
Expand All @@ -64,11 +84,30 @@ def canonsort_items(
Example:
.. code-block:: pycon

>>> from icalendar.caselessdict import canonsort_items
>>> canonsort_items({"C": 3, "A": 1, "B": 2}, ["B", "C"])
>>> from icalendar.caselessdict import _canonsort_items
>>> _canonsort_items({"C": 3, "A": 1, "B": 2}, ["B", "C"])
[('B', 2), ('C', 3), ('A', 1)]
"""
return [(k, dict1[k]) for k in canonsort_keys(dict1.keys(), canonical_order)]
return [(k, dict1[k]) for k in _canonsort_keys(dict1.keys(), canonical_order)]


def canonsort_items(
dict1: Mapping[KT, VT], canonical_order: Iterable[KT] | None = None
) -> list[tuple[KT, VT]]:
"""Sort items from a mapping according to a canonical key order.

.. deprecated:: 7.0.0
Use the private :func:`_canonsort_items` internally. For external use,
this function is deprecated. Please contact the maintainers if you
rely on this function.
"""
warnings.warn(
"canonsort_items is deprecated and will be removed in a future version. "
"If you are using this function externally, please contact the maintainers.",
DeprecationWarning,
stacklevel=2,
)
return _canonsort_items(dict1, canonical_order)


class CaselessDict(OrderedDict):
Expand Down Expand Up @@ -100,7 +139,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
"""
super().__init__(*args, **kwargs)
for key, value in self.items():
key_upper = to_unicode(key).upper()
key_upper = _to_unicode(key).upper()
if key != key_upper:
super().__delitem__(key)
self[key_upper] = value
Expand All @@ -120,7 +159,7 @@ def __getitem__(self, key: Any) -> Any:
Raises:
KeyError: If the key is not found.
"""
key = to_unicode(key)
key = _to_unicode(key)
return super().__getitem__(key.upper())

def __setitem__(self, key: Any, value: Any) -> None:
Expand All @@ -130,7 +169,7 @@ def __setitem__(self, key: Any, value: Any) -> None:
key: The key of the pair, case-insensitive.
value: The value to associate with the key.
"""
key = to_unicode(key)
key = _to_unicode(key)
super().__setitem__(key.upper(), value)

def __delitem__(self, key: Any) -> None:
Expand All @@ -142,7 +181,7 @@ def __delitem__(self, key: Any) -> None:
Raises:
KeyError: If the key is not found.
"""
key = to_unicode(key)
key = _to_unicode(key)
super().__delitem__(key.upper())

def __contains__(self, key: Any) -> bool:
Expand All @@ -154,7 +193,7 @@ def __contains__(self, key: Any) -> bool:
Returns:
``True`` if the uppercased key exists, else ``False``.
"""
key = to_unicode(key)
key = _to_unicode(key)
return super().__contains__(key.upper())

def get(self, key: Any, default: Any = None) -> Any:
Expand All @@ -167,7 +206,7 @@ def get(self, key: Any, default: Any = None) -> Any:
Returns:
The value for the key, if present, else the value specified by ``default``.
"""
key = to_unicode(key)
key = _to_unicode(key)
return super().get(key.upper(), default)

def setdefault(self, key: Any, value: Any = None) -> Any:
Expand All @@ -182,7 +221,7 @@ def setdefault(self, key: Any, value: Any = None) -> Any:
Returns:
The value for the key.
"""
key = to_unicode(key)
key = _to_unicode(key)
return super().setdefault(key.upper(), value)

def pop(self, key: Any, default: Any = None) -> Any:
Expand All @@ -195,7 +234,7 @@ def pop(self, key: Any, default: Any = None) -> Any:
Returns:
The removed value, or the value of ``default``.
"""
key = to_unicode(key)
key = _to_unicode(key)
return super().pop(key.upper(), default)

def popitem(self) -> tuple[Any, Any]:
Expand All @@ -220,7 +259,7 @@ def has_key(self, key: Any) -> bool:
Returns:
``True`` if the key exists, else ``False``.
"""
key = to_unicode(key)
key = _to_unicode(key)
return super().__contains__(key.upper())

def update(self, *args: Any, **kwargs: Any) -> None:
Expand Down Expand Up @@ -298,7 +337,7 @@ def sorted_keys(self) -> list[str]:
Returns:
A sorted list of keys.
"""
return canonsort_keys(self.keys(), self.canonical_order)
return _canonsort_keys(self.keys(), self.canonical_order)

def sorted_items(self) -> list[tuple[Any, Any]]:
"""Sort items according to the canonical order for this class.
Expand All @@ -309,7 +348,7 @@ def sorted_items(self) -> list[tuple[Any, Any]]:
Returns:
A sorted list of (key, value) tuples.
"""
return canonsort_items(self, self.canonical_order)
return _canonsort_items(self, self.canonical_order)


__all__ = ["CaselessDict", "canonsort_items", "canonsort_keys"]
__all__ = ["CaselessDict", "_canonsort_items", "_canonsort_keys", "canonsort_items", "canonsort_keys"]
20 changes: 20 additions & 0 deletions src/icalendar/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,27 @@
Members will be added and removed without deprecation warnings.
"""

import warnings
from typing import TYPE_CHECKING


def deprecate_for_version_8(name: str) -> None:
Comment thread
siddhirajkatkar marked this conversation as resolved.
Outdated
"""Emit a DeprecationWarning for a function scheduled for removal in icalendar 8.

Call this as the first statement inside a deprecated public wrapper function.
``stacklevel=3`` makes the warning point at the external caller's line, not at
the wrapper or at this helper.

Parameters:
name: The public name of the deprecated function (e.g. ``"q_split"``).
"""
warnings.warn(
f"{name} is deprecated and will be removed in icalendar 8. "
"If you are using this function externally, please contact the maintainers.",
DeprecationWarning,
stacklevel=3,
)

try:
from typing import Self
except ImportError:
Expand Down Expand Up @@ -37,4 +56,5 @@
"Self",
"TypeGuard",
"TypeIs",
"deprecate_for_version_8",
]
26 changes: 26 additions & 0 deletions src/icalendar/parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
from .content_line import Contentline, Contentlines
from .parameter import (
Parameters,
_dquote,
_param_value,
_q_join,
_q_split,
_rfc_6868_escape,
_rfc_6868_unescape,
_validate_param_value,
dquote,
param_value,
q_join,
Expand All @@ -18,6 +25,10 @@
validate_param_value,
)
from .property import (
_split_on_unescaped_comma,
_split_on_unescaped_semicolon,
_unescape_backslash,
_unescape_list_or_string,
split_on_unescaped_comma,
split_on_unescaped_semicolon,
unescape_backslash,
Expand All @@ -26,8 +37,10 @@
from .string import (
_escape_char,
_escape_string,
_foldline,
_unescape_char,
_unescape_string,
_validate_token,
escape_char,
escape_string,
foldline,
Expand All @@ -40,10 +53,23 @@
"Contentline",
"Contentlines",
"Parameters",
"_dquote",
"_escape_char",
"_escape_string",
"_foldline",
"_param_value",
"_q_join",
"_q_split",
"_rfc_6868_escape",
"_rfc_6868_unescape",
"_split_on_unescaped_comma",
"_split_on_unescaped_semicolon",
"_unescape_backslash",
"_unescape_char",
"_unescape_list_or_string",
"_unescape_string",
"_validate_param_value",
"_validate_token",
"dquote",
"escape_char",
"escape_string",
Expand Down
Loading
Loading