8000 Add Python 3.12 compatibility for path fieldtype by yunzheng · Pull Request #91 · fox-it/flow.record · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add Python 3.12 compatibility for path fieldtype #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 4, 2024
Merged
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
42 changes: 25 additions & 17 deletions flow/record/fieldtypes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
UTC = timezone.utc

PY_311 = sys.version_info >= (3, 11, 0)
PY_312 = sys.version_info >= (3, 12, 0)

PATH_POSIX = 0
PATH_WINDOWS = 1
Expand Down Expand Up @@ -645,28 +646,31 @@ def __new__(cls, *args):
for path_part in args:
if isinstance(path_part, pathlib.PureWindowsPath):
cls = windows_path
# The (string) representation of a pathlib.PureWindowsPath is not round trip equivalent if a
# path starts with a \ or / followed by a drive letter, e.g.: \C:\...
# Meaning:
#
# str(PureWindowsPath(r"\C:\WINDOWS/Temp")) !=
# str(PureWindowsPath(PureWindowsPath(r"\C:\WINDOWS/Temp"))),
#
# repr(PureWindowsPath(r"\C:\WINDOWS/Temp")) !=
# repr(PureWindowsPath(PureWindowsPath(r"\C:\WINDOWS/Temp"))),
#
# This would be the case though when using PurePosixPath instead.
#
# This construction works around that by converting all path parts
# to strings first.
args = (str(arg) for arg in args)
if not PY_312:
# For Python < 3.12, the (string) representation of a
# pathlib.PureWindowsPath is not round trip equivalent if a path
# starts with a \ or / followed by a drive letter, e.g.: \C:\...
# Meaning:
#
# str(PureWindowsPath(r"\C:\WINDOWS/Temp")) !=
# str(PureWindowsPath(PureWindowsPath(r"\C:\WINDOWS/Temp"))),
#
# repr(PureWindowsPath(r"\C:\WINDOWS/Temp")) !=
# repr(PureWindowsPath(PureWindowsPath(r"\C:\WINDOWS/Temp"))),
#
# This would be the case though when using PurePosixPath instead.
#
# This construction works around that by converting all path parts
# to strings first.
args = (str(arg) for arg in args)
elif isinstance(path_part, pathlib.PurePosixPath):
cls = posix_path
elif _is_windowslike_path(path_part):
# This handles any custom PurePath based implementations that have a windows
# like path separator (\).
cls = windows_path
args = (str(arg) for arg in args)
if not PY_312:
args = (str(arg) for arg in args)
elif _is_posixlike_path(path_part):
# This handles any custom PurePath based implementations that don't have a
# windows like path separator (\).
Expand All @@ -675,7 +679,11 @@ def __new__(cls, *args):
continue
break

return cls._from_parts(args)
if PY_312:
obj = super().__new__(cls)
else:
obj = cls._from_parts(args)
return obj

def __eq__(self, other: Any) -> bool:
if isinstance(other, str):
Expand Down
32 changes: 26 additions & 6 deletions tests/test_fieldtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import hashlib
import os
import pathlib
import posixpath
import types
from datetime import datetime, timedelta, timezone

import pytest
Expand All @@ -12,6 +14,7 @@
from flow.record.fieldtypes import (
PATH_POSIX,
PATH_WINDOWS,
PY_312,
_is_posixlike_path,
_is_windowslike_path,
)
Expand Down Expand Up @@ -527,12 +530,29 @@ def test_digest():


def custom_pure_path(sep, altsep):
class CustomFlavour(pathlib._PosixFlavour):
def __new__(cls):
instance = pathlib._PosixFlavour.__new__(cls)
instance.sep = sep
instance.altsep = altsep
return instance
# Starting from Python 3.12, pathlib._Flavours are removed as you can
# now properly subclass pathlib.Path
# The flavour property of Path's is replaced by a link to e.g.
# posixpath or ntpath.
# See also: https://github.com/python/cpython/issues/88302
if PY_312:

class CustomFlavour:
def __new__(cls, *args, **kwargs):
flavour = types.ModuleType("mockpath")
flavour.__dict__.update(posixpath.__dict__)
flavour.sep = sep
flavour.altsep = altsep
return flavour

else:

class CustomFlavour(pathlib._PosixFlavour):
def __new__(cls):
instance = super().__new__(cls)
instance.sep = sep
instance.altsep = altsep
return instance

class PureCustomPath(pathlib.PurePath):
_flavour = CustomFlavour()
Expand Down
0