From b352c13563bb2506b8d87f0da34beafb5cb32641 Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Fri, 5 Dec 2025 09:39:30 +0000 Subject: [PATCH 1/7] Enhance path type detection for posix and windows paths in fieldtypes fixes #199 --- flow/record/fieldtypes/__init__.py | 7 +++++++ tests/fieldtypes/test_fieldtypes.py | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/flow/record/fieldtypes/__init__.py b/flow/record/fieldtypes/__init__.py index ed1337f9..ff543e61 100644 --- a/flow/record/fieldtypes/__init__.py +++ b/flow/record/fieldtypes/__init__.py @@ -602,6 +602,8 @@ 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) + if isinstance(path, str): + return "/" in path and "\\" not in path return False @@ -609,6 +611,11 @@ 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) + if isinstance(path, str): + if re.match(r"^[a-zA-Z]:[\\/]", path): + return True + if "\\" in path: + return True return False diff --git a/tests/fieldtypes/test_fieldtypes.py b/tests/fieldtypes/test_fieldtypes.py index c4784b31..2494b6ae 100644 --- a/tests/fieldtypes/test_fieldtypes.py +++ b/tests/fieldtypes/test_fieldtypes.py @@ -578,7 +578,7 @@ class PureCustomPath(pathlib.PurePath): (custom_pure_path(sep="/", altsep="")("/foo/bar"), True), (custom_pure_path(sep="\\", altsep="/")(r"C:\foo\bar"), False), (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), False), - ("/foo/bar", False), + ("/foo/bar", True), ], ) def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> None: @@ -677,7 +677,7 @@ def test_path() -> None: ), ( ("/some/path", pathlib.PureWindowsPath("win/path"), pathlib.PurePosixPath("pos/path")), - flow.record.fieldtypes.windows_path, + flow.record.fieldtypes.posix_path, ), ( (pathlib.PurePosixPath("pos/path"), pathlib.PureWindowsPath("win/path")), From 1c05fee26975417c812ed7774110924b9624ccce Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Fri, 5 Dec 2025 10:46:06 +0100 Subject: [PATCH 2/7] Update flow/record/fieldtypes/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- flow/record/fieldtypes/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flow/record/fieldtypes/__init__.py b/flow/record/fieldtypes/__init__.py index ff543e61..8412f5d3 100644 --- a/flow/record/fieldtypes/__init__.py +++ b/flow/record/fieldtypes/__init__.py @@ -603,6 +603,8 @@ def _is_posixlike_path(path: Any) -> bool: obj = getattr(path, "parser", None) or path._flavour return "\\" not in (obj.sep, obj.altsep) if isinstance(path, str): + if re.match(r"^[a-zA-Z]:[\\/]", path): + return False return "/" in path and "\\" not in path return False From 1a475602ab74f07b4a9362729f16c11657c0347f Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Fri, 5 Dec 2025 09:48:09 +0000 Subject: [PATCH 3/7] Add extra test case --- tests/fieldtypes/test_fieldtypes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fieldtypes/test_fieldtypes.py b/tests/fieldtypes/test_fieldtypes.py index 2494b6ae..cefb057f 100644 --- a/tests/fieldtypes/test_fieldtypes.py +++ b/tests/fieldtypes/test_fieldtypes.py @@ -579,6 +579,7 @@ class PureCustomPath(pathlib.PurePath): (custom_pure_path(sep="\\", altsep="/")(r"C:\foo\bar"), False), (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), False), ("/foo/bar", True), + (r"C:\foo\bar", False), ], ) def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> None: @@ -594,6 +595,7 @@ def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> No (custom_pure_path(sep="\\", altsep="/")(r"C:\foo\bar"), True), (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), True), ("/foo/bar", False), + (r"C:\foo\bar", True), ], ) def test__is_windowslike_path(path_: pathlib.PurePath, is_windows: bool) -> None: From d37ed03f0c3e0a03ac33d24b415edf408b12f739 Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Fri, 5 Dec 2025 09:52:01 +0000 Subject: [PATCH 4/7] Add one more test --- tests/fieldtypes/test_fieldtypes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fieldtypes/test_fieldtypes.py b/tests/fieldtypes/test_fieldtypes.py index cefb057f..a7dd8e14 100644 --- a/tests/fieldtypes/test_fieldtypes.py +++ b/tests/fieldtypes/test_fieldtypes.py @@ -580,6 +580,7 @@ class PureCustomPath(pathlib.PurePath): (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), False), ("/foo/bar", True), (r"C:\foo\bar", False), + (r"C:/foo/bar", False), ], ) def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> None: @@ -596,6 +597,7 @@ def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> No (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), True), ("/foo/bar", False), (r"C:\foo\bar", True), + (r"C:/foo/bar", True), ], ) def test__is_windowslike_path(path_: pathlib.PurePath, is_windows: bool) -> None: From 27d4ce175045e28d3f40b729baf9c51936a4b40d Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Mon, 8 Dec 2025 14:29:02 +0000 Subject: [PATCH 5/7] Use a compiled regex --- flow/record/fieldtypes/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flow/record/fieldtypes/__init__.py b/flow/record/fieldtypes/__init__.py index 8412f5d3..1a8326c4 100644 --- a/flow/record/fieldtypes/__init__.py +++ b/flow/record/fieldtypes/__init__.py @@ -28,6 +28,7 @@ from flow.record.base import FieldType, Record RE_NORMALIZE_PATH = re.compile(r"[\\/]+") +RE_WINDOWS_PATH = re.compile(r"^[a-zA-Z]:[\\/]") UTC = timezone.utc @@ -603,7 +604,7 @@ def _is_posixlike_path(path: Any) -> bool: obj = getattr(path, "parser", None) or path._flavour return "\\" not in (obj.sep, obj.altsep) if isinstance(path, str): - if re.match(r"^[a-zA-Z]:[\\/]", path): + if RE_WINDOWS_PATH.match(path): return False return "/" in path and "\\" not in path return False @@ -614,7 +615,7 @@ def _is_windowslike_path(path: Any) -> bool: obj = getattr(path, "parser", None) or path._flavour return "\\" in (obj.sep, obj.altsep) if isinstance(path, str): - if re.match(r"^[a-zA-Z]:[\\/]", path): + if RE_WINDOWS_PATH.match(path): return True if "\\" in path: return True From d886580c0d676632411bbb49b05400c668a86dad Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Mon, 8 Dec 2025 14:35:14 +0000 Subject: [PATCH 6/7] Add extra test for NT namespace path --- tests/fieldtypes/test_fieldtypes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fieldtypes/test_fieldtypes.py b/tests/fieldtypes/test_fieldtypes.py index a7dd8e14..65e2b1fd 100644 --- a/tests/fieldtypes/test_fieldtypes.py +++ b/tests/fieldtypes/test_fieldtypes.py @@ -581,6 +581,7 @@ class PureCustomPath(pathlib.PurePath): ("/foo/bar", True), (r"C:\foo\bar", False), (r"C:/foo/bar", False), + (r"\??\C:\Windows\System32\calc.exe", False), ], ) def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> None: @@ -598,6 +599,7 @@ def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> No ("/foo/bar", False), (r"C:\foo\bar", True), (r"C:/foo/bar", True), + (r"\??\C:\Windows\System32\calc.exe", True), ], ) def test__is_windowslike_path(path_: pathlib.PurePath, is_windows: bool) -> None: From d907074d4d935cfd92385c174d8409cf82fff98e Mon Sep 17 00:00:00 2001 From: Yun Zheng Hu Date: Tue, 9 Dec 2025 11:00:14 +0100 Subject: [PATCH 7/7] Apply suggestions from code review Co-authored-by: Erik Schamper <1254028+Schamper@users.noreply.github.com> --- flow/record/fieldtypes/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flow/record/fieldtypes/__init__.py b/flow/record/fieldtypes/__init__.py index 1a8326c4..5aa97ad5 100644 --- a/flow/record/fieldtypes/__init__.py +++ b/flow/record/fieldtypes/__init__.py @@ -617,8 +617,7 @@ def _is_windowslike_path(path: Any) -> bool: if isinstance(path, str): if RE_WINDOWS_PATH.match(path): return True - if "\\" in path: - return True + return "\\" in path return False