flow.record 3.16.dev8__tar.gz → 3.16.dev9__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 (82) hide show
  1. {flow_record-3.16.dev8/flow.record.egg-info → flow_record-3.16.dev9}/PKG-INFO +1 -1
  2. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/__init__.py +16 -8
  3. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/version.py +2 -2
  4. {flow_record-3.16.dev8 → flow_record-3.16.dev9/flow.record.egg-info}/PKG-INFO +1 -1
  5. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_fieldtypes.py +40 -2
  6. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/COPYRIGHT +0 -0
  7. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/LICENSE +0 -0
  8. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/MANIFEST.in +0 -0
  9. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/README.md +0 -0
  10. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/examples/filesystem.py +0 -0
  11. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/examples/passivedns.py +0 -0
  12. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/examples/records.json +0 -0
  13. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/examples/tcpconn.py +0 -0
  14. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/__init__.py +0 -0
  15. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/__init__.py +0 -0
  16. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/archive.py +0 -0
  17. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/avro.py +0 -0
  18. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/broker.py +0 -0
  19. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/csvfile.py +0 -0
  20. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/duckdb.py +0 -0
  21. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/elastic.py +0 -0
  22. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/jsonfile.py +0 -0
  23. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/line.py +0 -0
  24. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/mongo.py +0 -0
  25. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/split.py +0 -0
  26. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/splunk.py +0 -0
  27. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/sqlite.py +0 -0
  28. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/stream.py +0 -0
  29. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/text.py +0 -0
  30. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/adapter/xlsx.py +0 -0
  31. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/base.py +0 -0
  32. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/exceptions.py +0 -0
  33. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/credential.py +0 -0
  34. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/net/__init__.py +0 -0
  35. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/net/ip.py +0 -0
  36. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/net/ipv4.py +0 -0
  37. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/net/tcp.py +0 -0
  38. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/fieldtypes/net/udp.py +0 -0
  39. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/jsonpacker.py +0 -0
  40. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/packer.py +0 -0
  41. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/selector.py +0 -0
  42. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/stream.py +0 -0
  43. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/tools/__init__.py +0 -0
  44. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/tools/geoip.py +0 -0
  45. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/tools/rdump.py +0 -0
  46. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/utils.py +0 -0
  47. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow/record/whitelist.py +0 -0
  48. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow.record.egg-info/SOURCES.txt +0 -0
  49. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow.record.egg-info/dependency_links.txt +0 -0
  50. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow.record.egg-info/entry_points.txt +0 -0
  51. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow.record.egg-info/requires.txt +0 -0
  52. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/flow.record.egg-info/top_level.txt +0 -0
  53. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/pyproject.toml +0 -0
  54. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/setup.cfg +0 -0
  55. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/__init__.py +0 -0
  56. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/_utils.py +0 -0
  57. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/docs/Makefile +0 -0
  58. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/docs/conf.py +0 -0
  59. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/docs/index.rst +0 -0
  60. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/selector_explain_example.py +0 -0
  61. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/standalone_test.py +0 -0
  62. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_avro.py +0 -0
  63. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_avro_adapter.py +0 -0
  64. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_compiled_selector.py +0 -0
  65. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_csv_adapter.py +0 -0
  66. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_deprecations.py +0 -0
  67. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_elastic_adapter.py +0 -0
  68. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_fieldtype_ip.py +0 -0
  69. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_json_packer.py +0 -0
  70. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_json_record_adapter.py +0 -0
  71. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_multi_timestamp.py +0 -0
  72. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_packer.py +0 -0
  73. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_rdump.py +0 -0
  74. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_record.py +0 -0
  75. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_record_adapter.py +0 -0
  76. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_record_descriptor.py +0 -0
  77. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_regression.py +0 -0
  78. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_selector.py +0 -0
  79. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_splunk_adapter.py +0 -0
  80. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/test_sqlite_duckdb_adapter.py +0 -0
  81. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tests/utils_inspect.py +0 -0
  82. {flow_record-3.16.dev8 → flow_record-3.16.dev9}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flow.record
3
- Version: 3.16.dev8
3
+ Version: 3.16.dev9
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: Affero General Public License v3
@@ -32,8 +32,8 @@ NATIVE_UNICODE = isinstance("", str)
32
32
 
33
33
  UTC = timezone.utc
34
34
 
35
- PY_311 = sys.version_info >= (3, 11, 0)
36
- PY_312 = sys.version_info >= (3, 12, 0)
35
+ PY_311_OR_HIGHER = sys.version_info >= (3, 11, 0)
36
+ PY_312_OR_HIGHER = sys.version_info >= (3, 12, 0)
37
37
 
38
38
  TYPE_POSIX = 0
39
39
  TYPE_WINDOWS = 1
@@ -288,7 +288,7 @@ class datetime(_dt, FieldType):
288
288
  # - Python 3.10 and older requires "T" between date and time in fromisoformat()
289
289
  #
290
290
  # There are other incompatibilities, but we don't care about those for now.
291
- if not PY_311:
291
+ if not PY_311_OR_HIGHER:
292
292
  # Convert Z to +00:00 so that fromisoformat() works correctly on Python 3.10 and older
293
293
  if arg[-1] == "Z":
294
294
  arg = arg[:-1] + "+00:00"
@@ -633,6 +633,8 @@ def _is_windowslike_path(path: Any):
633
633
 
634
634
 
635
635
  class path(pathlib.PurePath, FieldType):
636
+ _empty_path = False
637
+
636
638
  def __new__(cls, *args):
637
639
  # This is modelled after pathlib.PurePath's __new__(), which means you
638
640
  # will never get an instance of path, only instances of either
@@ -647,7 +649,7 @@ class path(pathlib.PurePath, FieldType):
647
649
  for path_part in args:
648
650
  if isinstance(path_part, pathlib.PureWindowsPath):
649
651
  cls = windows_path
650
- if not PY_312:
652
+ if not PY_312_OR_HIGHER:
651
653
  # For Python < 3.12, the (string) representation of a
652
654
  # pathlib.PureWindowsPath is not round trip equivalent if a path
653
655
  # starts with a \ or / followed by a drive letter, e.g.: \C:\...
@@ -670,7 +672,7 @@ class path(pathlib.PurePath, FieldType):
670
672
  # This handles any custom PurePath based implementations that have a windows
671
673
  # like path separator (\).
672
674
  cls = windows_path
673
- if not PY_312:
675
+ if not PY_312_OR_HIGHER:
674
676
  args = tuple(str(arg) for arg in args)
675
677
  elif _is_posixlike_path(path_part):
676
678
  # This handles any custom PurePath based implementations that don't have a
@@ -680,7 +682,7 @@ class path(pathlib.PurePath, FieldType):
680
682
  continue
681
683
  break
682
684
 
683
- if PY_312:
685
+ if PY_312_OR_HIGHER:
684
686
  obj = super().__new__(cls)
685
687
  else:
686
688
  obj = cls._from_parts(args)
@@ -693,8 +695,8 @@ class path(pathlib.PurePath, FieldType):
693
695
  def __eq__(self, other: Any) -> bool:
694
696
  if isinstance(other, str):
695
697
  return str(self) == other or self == self.__class__(other)
696
- if self._empty_path:
697
- return isinstance(other, self.__class__) and other._empty_path
698
+ elif isinstance(other, self.__class__) and (self._empty_path or other._empty_path):
699
+ return self._empty_path == other._empty_path
698
700
  return super().__eq__(other)
699
701
 
700
702
  def __str__(self) -> str:
@@ -705,6 +707,12 @@ class path(pathlib.PurePath, FieldType):
705
707
  def __repr__(self) -> str:
706
708
  return repr(str(self))
707
709
 
710
+ @property
711
+ def parent(self):
712
+ if self._empty_path:
713
+ return self
714
+ return super().parent
715
+
708
716
  def _pack(self):
709
717
  path_type = TYPE_WINDOWS if isinstance(self, windows_path) else TYPE_POSIX
710
718
  return (str(self), path_type)
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.16.dev8'
16
- __version_tuple__ = version_tuple = (3, 16, 'dev8')
15
+ __version__ = version = '3.16.dev9'
16
+ __version_tuple__ = version_tuple = (3, 16, 'dev9')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flow.record
3
- Version: 3.16.dev8
3
+ Version: 3.16.dev9
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: Affero General Public License v3
@@ -13,7 +13,7 @@ import pytest
13
13
  import flow.record.fieldtypes
14
14
  from flow.record import RecordDescriptor, RecordReader, RecordWriter, fieldtypes
15
15
  from flow.record.fieldtypes import (
16
- PY_312,
16
+ PY_312_OR_HIGHER,
17
17
  TYPE_POSIX,
18
18
  TYPE_WINDOWS,
19
19
  _is_posixlike_path,
@@ -543,7 +543,7 @@ def custom_pure_path(sep, altsep):
543
543
  # The flavour property of Path's is replaced by a link to e.g.
544
544
  # posixpath or ntpath.
545
545
  # See also: https://github.com/python/cpython/issues/88302
546
- if PY_312:
546
+ if PY_312_OR_HIGHER:
547
547
 
548
548
  class CustomFlavour:
549
549
  def __new__(cls, *args, **kwargs):
@@ -1154,6 +1154,7 @@ def test_empty_path(path_cls) -> None:
1154
1154
  assert p1._empty_path
1155
1155
  assert str(p1) == ""
1156
1156
  assert p1 != path_cls(".")
1157
+ assert path_cls(".") != p1
1157
1158
 
1158
1159
  # initialize without any arguments
1159
1160
  p2 = path_cls()
@@ -1161,6 +1162,7 @@ def test_empty_path(path_cls) -> None:
1161
1162
  assert p2._empty_path
1162
1163
  assert str(p2) == ""
1163
1164
  assert p2 != path_cls(".")
1165
+ assert path_cls(".") != p2
1164
1166
 
1165
1167
  assert p1 == p2
1166
1168
 
@@ -1213,5 +1215,41 @@ def test_empty_path_serialization(tmp_path) -> None:
1213
1215
  assert record.value == ""
1214
1216
 
1215
1217
 
1218
+ def test_empty_windows_path_parent() -> None:
1219
+ # test that the parent of an empty path is also an empty path
1220
+ path = fieldtypes.windows_path("")
1221
+ assert path.parent == ""
1222
+ assert path.parent.parent == ""
1223
+ assert path._empty_path
1224
+ assert path.parent._empty_path
1225
+ assert list(path.parents) == []
1226
+
1227
+ path = fieldtypes.windows_path("c:/windows/temp")
1228
+ assert path.parent == "c:/windows"
1229
+ assert path.parent.parent == "c:/"
1230
+ assert path.parent.parent.parent == "c:/"
1231
+ assert not path.parent._empty_path
1232
+ assert not path._empty_path
1233
+ assert list(path.parents) == ["c:/windows", "c:/"]
1234
+
1235
+
1236
+ def test_empty_posix_path_parent() -> None:
1237
+ # test that the parent of an empty path is also an empty path
1238
+ path = fieldtypes.posix_path("")
1239
+ assert path.parent == ""
1240
+ assert path.parent.parent == ""
1241
+ assert path._empty_path
1242
+ assert path.parent._empty_path
1243
+ assert list(path.parents) == []
1244
+
1245
+ path = fieldtypes.posix_path("/var/log")
1246
+ assert path.parent == "/var"
1247
+ assert path.parent.parent == "/"
1248
+ assert path.parent.parent.parent == "/"
1249
+ assert not path.parent._empty_path
1250
+ assert not path._empty_path
1251
+ assert list(path.parents) == ["/var", "/"]
1252
+
1253
+
1216
1254
  if __name__ == "__main__":
1217
1255
  __import__("standalone_test").main(globals())
File without changes
File without changes