flow.record 3.21.dev16__tar.gz → 3.22.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/PKG-INFO +2 -2
  2. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/base.py +13 -11
  3. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/__init__.py +9 -0
  4. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/version.py +3 -3
  5. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow.record.egg-info/PKG-INFO +2 -2
  6. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow.record.egg-info/requires.txt +2 -2
  7. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/pyproject.toml +2 -2
  8. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/fieldtypes/test_fieldtypes.py +8 -2
  9. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/record/test_adapter.py +1 -3
  10. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/.git-blame-ignore-revs +0 -0
  11. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/.gitattributes +0 -0
  12. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/COPYRIGHT +0 -0
  13. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/LICENSE +0 -0
  14. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/MANIFEST.in +0 -0
  15. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/README.md +0 -0
  16. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/examples/__init__.py +0 -0
  17. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/examples/filesystem.py +0 -0
  18. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/examples/passivedns.py +0 -0
  19. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/examples/records.json +0 -0
  20. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/examples/selectors.py +0 -0
  21. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/examples/tcpconn.py +0 -0
  22. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/__init__.py +0 -0
  23. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/__init__.py +0 -0
  24. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/archive.py +0 -0
  25. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/avro.py +0 -0
  26. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/broker.py +0 -0
  27. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/csvfile.py +0 -0
  28. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/duckdb.py +0 -0
  29. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/elastic.py +0 -0
  30. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/jsonfile.py +0 -0
  31. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/line.py +0 -0
  32. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/mongo.py +0 -0
  33. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/split.py +0 -0
  34. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/splunk.py +0 -0
  35. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/sqlite.py +0 -0
  36. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/stream.py +0 -0
  37. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/text.py +0 -0
  38. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/adapter/xlsx.py +0 -0
  39. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/context.py +0 -0
  40. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/exceptions.py +0 -0
  41. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/credential.py +0 -0
  42. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/net/__init__.py +0 -0
  43. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/net/ip.py +0 -0
  44. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/net/ipv4.py +0 -0
  45. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/net/tcp.py +0 -0
  46. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/fieldtypes/net/udp.py +0 -0
  47. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/jsonpacker.py +0 -0
  48. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/packer.py +0 -0
  49. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/selector.py +0 -0
  50. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/stream.py +0 -0
  51. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/tools/__init__.py +0 -0
  52. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/tools/geoip.py +0 -0
  53. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/tools/rdump.py +0 -0
  54. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/utils.py +0 -0
  55. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow/record/whitelist.py +0 -0
  56. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow.record.egg-info/SOURCES.txt +0 -0
  57. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow.record.egg-info/dependency_links.txt +0 -0
  58. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow.record.egg-info/entry_points.txt +0 -0
  59. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/flow.record.egg-info/top_level.txt +0 -0
  60. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/setup.cfg +0 -0
  61. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/__init__.py +0 -0
  62. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/_data/.gitkeep +0 -0
  63. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/_docs/Makefile +0 -0
  64. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/_docs/conf.py +0 -0
  65. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/_docs/index.rst +0 -0
  66. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/_utils.py +0 -0
  67. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/__init__.py +0 -0
  68. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_avro.py +0 -0
  69. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_csv.py +0 -0
  70. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_elastic.py +0 -0
  71. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_json.py +0 -0
  72. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_line.py +0 -0
  73. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_splunk.py +0 -0
  74. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_sqlite_duckdb.py +0 -0
  75. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_text.py +0 -0
  76. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/adapter/test_xlsx.py +0 -0
  77. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/conftest.py +0 -0
  78. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/fieldtypes/__init__.py +0 -0
  79. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/fieldtypes/test_ip.py +0 -0
  80. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/packer/__init__.py +0 -0
  81. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/packer/test_json_packer.py +0 -0
  82. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/packer/test_packer.py +0 -0
  83. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/record/__init__.py +0 -0
  84. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/record/test_context.py +0 -0
  85. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/record/test_descriptor.py +0 -0
  86. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/record/test_multi_timestamp.py +0 -0
  87. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/record/test_record.py +0 -0
  88. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/selector/__init__.py +0 -0
  89. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/selector/test_compiled.py +0 -0
  90. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/selector/test_selectors.py +0 -0
  91. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/test_deprecations.py +0 -0
  92. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/test_regressions.py +0 -0
  93. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/test_utils.py +0 -0
  94. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/tools/__init__.py +0 -0
  95. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tests/tools/test_rdump.py +0 -0
  96. {flow_record-3.21.dev16 → flow_record-3.22.dev2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flow.record
3
- Version: 3.21.dev16
3
+ Version: 3.22.dev2
4
4
  Summary: A library for defining and creating structured data (called records) that can be streamed to disk or piped to other tools that use flow.record
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -23,7 +23,7 @@ Requires-Dist: msgpack>=0.5.2
23
23
  Requires-Dist: tzdata; platform_system == "Windows"
24
24
  Provides-Extra: compression
25
25
  Requires-Dist: lz4; extra == "compression"
26
- Requires-Dist: zstandard; platform_python_implementation != "PyPy" and extra == "compression"
26
+ Requires-Dist: backports.zstd; python_version < "3.14" and extra == "compression"
27
27
  Provides-Extra: elastic
28
28
  Requires-Dist: elasticsearch; extra == "elastic"
29
29
  Provides-Extra: geoip
@@ -27,25 +27,33 @@ from urllib.parse import parse_qsl, urlparse
27
27
  from flow.record.exceptions import RecordAdapterNotFound, RecordDescriptorError
28
28
  from flow.record.utils import get_stdin, get_stdout
29
29
 
30
+ # lz4
30
31
  try:
31
32
  import lz4.frame as lz4
32
33
 
33
34
  HAS_LZ4 = True
34
35
  except ImportError:
35
36
  HAS_LZ4 = False
37
+
38
+ # bzip2
36
39
  try:
37
40
  import bz2
38
41
 
39
42
  HAS_BZ2 = True
40
43
  except ImportError:
41
44
  HAS_BZ2 = False
42
- try:
43
- import zstandard as zstd
44
45
 
46
+ # zstandard
47
+ try:
48
+ if sys.version_info >= (3, 14):
49
+ from compression import zstd # novermin
50
+ else:
51
+ from backports import zstd
45
52
  HAS_ZSTD = True
46
53
  except ImportError:
47
54
  HAS_ZSTD = False
48
55
 
56
+ # fastavro
49
57
  try:
50
58
  import fastavro as avro # noqa
51
59
 
@@ -727,8 +735,7 @@ def open_stream(fp: BinaryIO, mode: str) -> BinaryIO:
727
735
  elif HAS_LZ4 and peek_data[:4] == LZ4_MAGIC:
728
736
  fp = lz4.open(fp, mode=mode)
729
737
  elif HAS_ZSTD and peek_data[:4] == ZSTD_MAGIC:
730
- dctx = zstd.ZstdDecompressor()
731
- fp = dctx.stream_reader(fp)
738
+ fp = zstd.ZstdFile(fp, mode=mode)
732
739
 
733
740
  return fp
734
741
 
@@ -804,13 +811,8 @@ def open_path(path: str, mode: str, clobber: bool = True) -> IO:
804
811
  fp = lz4.open(path, mode)
805
812
  elif path.endswith((".zstd", ".zst")):
806
813
  if not HAS_ZSTD:
807
- raise RuntimeError("zstandard python module not available")
808
- if not out:
809
- dctx = zstd.ZstdDecompressor()
810
- fp = dctx.stream_reader(pathobj.open("rb"))
811
- else:
812
- cctx = zstd.ZstdCompressor()
813
- fp = cctx.stream_writer(pathobj.open("wb"))
814
+ raise RuntimeError("backports.zstd python module not available")
815
+ fp = zstd.ZstdFile(path, mode)
814
816
 
815
817
  # normal file or stdio for reading or writing
816
818
  if not fp:
@@ -28,6 +28,7 @@ except ImportError:
28
28
  from flow.record.base import FieldType, Record
29
29
 
30
30
  RE_NORMALIZE_PATH = re.compile(r"[\\/]+")
31
+ RE_WINDOWS_PATH = re.compile(r"^[a-zA-Z]:[\\/]")
31
32
 
32
33
  UTC = timezone.utc
33
34
 
@@ -602,6 +603,10 @@ def _is_posixlike_path(path: Any) -> bool:
602
603
  if isinstance(path, pathlib.PurePath):
603
604
  obj = getattr(path, "parser", None) or path._flavour
604
605
  return "\\" not in (obj.sep, obj.altsep)
606
+ if isinstance(path, str):
607
+ if RE_WINDOWS_PATH.match(path):
608
+ return False
609
+ return "/" in path and "\\" not in path
605
610
  return False
606
611
 
607
612
 
@@ -609,6 +614,10 @@ def _is_windowslike_path(path: Any) -> bool:
609
614
  if isinstance(path, pathlib.PurePath):
610
615
  obj = getattr(path, "parser", None) or path._flavour
611
616
  return "\\" in (obj.sep, obj.altsep)
617
+ if isinstance(path, str):
618
+ if RE_WINDOWS_PATH.match(path):
619
+ return True
620
+ return "\\" in path
612
621
  return False
613
622
 
614
623
 
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.21.dev16'
32
- __version_tuple__ = version_tuple = (3, 21, 'dev16')
31
+ __version__ = version = '3.22.dev2'
32
+ __version_tuple__ = version_tuple = (3, 22, 'dev2')
33
33
 
34
- __commit_id__ = commit_id = 'gb0cb20acb'
34
+ __commit_id__ = commit_id = 'gcd69cf171'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flow.record
3
- Version: 3.21.dev16
3
+ Version: 3.22.dev2
4
4
  Summary: A library for defining and creating structured data (called records) that can be streamed to disk or piped to other tools that use flow.record
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -23,7 +23,7 @@ Requires-Dist: msgpack>=0.5.2
23
23
  Requires-Dist: tzdata; platform_system == "Windows"
24
24
  Provides-Extra: compression
25
25
  Requires-Dist: lz4; extra == "compression"
26
- Requires-Dist: zstandard; platform_python_implementation != "PyPy" and extra == "compression"
26
+ Requires-Dist: backports.zstd; python_version < "3.14" and extra == "compression"
27
27
  Provides-Extra: elastic
28
28
  Requires-Dist: elasticsearch; extra == "elastic"
29
29
  Provides-Extra: geoip
@@ -9,8 +9,8 @@ fastavro[snappy]
9
9
  [compression]
10
10
  lz4
11
11
 
12
- [compression:platform_python_implementation != "PyPy"]
13
- zstandard
12
+ [compression:python_version < "3.14"]
13
+ backports.zstd
14
14
 
15
15
  [duckdb]
16
16
 
@@ -37,7 +37,7 @@ repository = "https://github.com/fox-it/flow.record"
37
37
  # Note: these compression libraries do not work well with pypy
38
38
  compression = [
39
39
  "lz4",
40
- "zstandard; platform_python_implementation != 'PyPy'",
40
+ "backports.zstd; python_version < '3.14'",
41
41
  ]
42
42
  elastic = [
43
43
  "elasticsearch",
@@ -68,7 +68,7 @@ full = [
68
68
  [dependency-groups]
69
69
  compression = [
70
70
  "lz4",
71
- "zstandard; platform_python_implementation != 'PyPy'",
71
+ "backports.zstd; python_version < '3.14'",
72
72
  ]
73
73
  elastic = [
74
74
  "elasticsearch",
@@ -578,7 +578,10 @@ def custom_pure_path(sep: str, altsep: str) -> pathlib.PurePath:
578
578
  (custom_pure_path(sep="/", altsep="")("/foo/bar"), True),
579
579
  (custom_pure_path(sep="\\", altsep="/")(r"C:\foo\bar"), False),
580
580
  (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), False),
581
- ("/foo/bar", False),
581
+ ("/foo/bar", True),
582
+ (r"C:\foo\bar", False),
583
+ (r"C:/foo/bar", False),
584
+ (r"\??\C:\Windows\System32\calc.exe", False),
582
585
  ],
583
586
  )
584
587
  def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> None:
@@ -594,6 +597,9 @@ def test__is_posixlike_path(path_: pathlib.PurePath | str, is_posix: bool) -> No
594
597
  (custom_pure_path(sep="\\", altsep="/")(r"C:\foo\bar"), True),
595
598
  (custom_pure_path(sep=":", altsep="\\")(r"C:\foo\bar"), True),
596
599
  ("/foo/bar", False),
600
+ (r"C:\foo\bar", True),
601
+ (r"C:/foo/bar", True),
602
+ (r"\??\C:\Windows\System32\calc.exe", True),
597
603
  ],
598
604
  )
599
605
  def test__is_windowslike_path(path_: pathlib.PurePath, is_windows: bool) -> None:
@@ -677,7 +683,7 @@ def test_path() -> None:
677
683
  ),
678
684
  (
679
685
  ("/some/path", pathlib.PureWindowsPath("win/path"), pathlib.PurePosixPath("pos/path")),
680
- flow.record.fieldtypes.windows_path,
686
+ flow.record.fieldtypes.posix_path,
681
687
  ),
682
688
  (
683
689
  (pathlib.PurePosixPath("pos/path"), pathlib.PureWindowsPath("win/path")),
@@ -85,12 +85,10 @@ def test_compressed_writer_reader(tmp_path: Path, compression: str) -> None:
85
85
  if compression == "lz4" and not HAS_LZ4:
86
86
  pytest.skip("lz4 module not installed")
87
87
  if compression == "zstd" and not HAS_ZSTD:
88
- pytest.skip("zstandard module not installed")
88
+ pytest.skip("backports.zstd module not installed")
89
89
 
90
90
  if compression == "lz4" and platform.python_implementation() == "PyPy":
91
91
  pytest.skip("lz4 module not supported on PyPy")
92
- if compression == "zstd" and platform.python_implementation() == "PyPy":
93
- pytest.skip("zstandard module not supported on PyPy")
94
92
 
95
93
  p = tmp_path.joinpath(f"{compression}-test")
96
94
  p.mkdir()