From f7945e27e340f8cfd101580a08eba52068efeb47 Mon Sep 17 00:00:00 2001 From: Schamper <1254028+Schamper@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:29:09 +0100 Subject: [PATCH] Add path compatibility with Python 3.13 --- flow/record/fieldtypes/__init__.py | 25 ++++++++++++++++--------- tests/test_fieldtypes.py | 11 +++++++++-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/flow/record/fieldtypes/__init__.py b/flow/record/fieldtypes/__init__.py index 2a02077..62d6d7c 100644 --- a/flow/record/fieldtypes/__init__.py +++ b/flow/record/fieldtypes/__init__.py @@ -33,6 +33,7 @@ PY_311_OR_HIGHER = sys.version_info >= (3, 11, 0) PY_312_OR_HIGHER = sys.version_info >= (3, 12, 0) +PY_313_OR_HIGHER = sys.version_info >= (3, 13, 0) TYPE_POSIX = 0 TYPE_WINDOWS = 1 @@ -600,12 +601,18 @@ def _unpack(cls, data): return data -def _is_posixlike_path(path: Any): - return isinstance(path, pathlib.PurePath) and "\\" not in (path._flavour.sep, path._flavour.altsep) +def _is_posixlike_path(path: Any) -> bool: + if isinstance(path, pathlib.PurePath): + obj = getattr(path, "parser", None) or path._flavour + return "\\" not in (obj.sep, obj.altsep) + return False -def _is_windowslike_path(path: Any): - return isinstance(path, pathlib.PurePath) and "\\" in (path._flavour.sep, path._flavour.altsep) +def _is_windowslike_path(path: Any) -> bool: + if isinstance(path, pathlib.PurePath): + obj = getattr(path, "parser", None) or path._flavour + return "\\" in (obj.sep, obj.altsep) + return False class path(pathlib.PurePath, FieldType): @@ -684,17 +691,17 @@ def __repr__(self) -> str: return repr(str(self)) @property - def parent(self): + def parent(self) -> path: if self._empty_path: return self return super().parent - def _pack(self): + def _pack(self) -> tuple[str, int]: path_type = TYPE_WINDOWS if isinstance(self, windows_path) else TYPE_POSIX return (str(self), path_type) @classmethod - def _unpack(cls, data: tuple[str, str]): + def _unpack(cls, data: tuple[str, str]) -> posix_path | windows_path: path_, path_type = data if path_type == TYPE_POSIX: return posix_path(path_) @@ -705,12 +712,12 @@ def _unpack(cls, data: tuple[str, str]): return posix_path(path_) @classmethod - def from_posix(cls, path_: str): + def from_posix(cls, path_: str) -> posix_path: """Initialize a path instance from a posix path string using / as a separator.""" return posix_path(path_) @classmethod - def from_windows(cls, path_: str): + def from_windows(cls, path_: str) -> windows_path: """Initialize a path instance from a windows path string using \\ or / as a separator.""" return windows_path(path_) diff --git a/tests/test_fieldtypes.py b/tests/test_fieldtypes.py index ace9db6..d1e4cbe 100644 --- a/tests/test_fieldtypes.py +++ b/tests/test_fieldtypes.py @@ -15,6 +15,7 @@ from flow.record import RecordDescriptor, RecordReader, RecordWriter, fieldtypes from flow.record.fieldtypes import ( PY_312_OR_HIGHER, + PY_313_OR_HIGHER, TYPE_POSIX, TYPE_WINDOWS, _is_posixlike_path, @@ -557,8 +558,14 @@ def __new__(cls): instance.altsep = altsep return instance - class PureCustomPath(pathlib.PurePath): - _flavour = CustomFlavour() + if PY_313_OR_HIGHER: + + class PureCustomPath(pathlib.PurePath): + parser = CustomFlavour() + else: + + class PureCustomPath(pathlib.PurePath): + _flavour = CustomFlavour() return PureCustomPath