flow.record 3.19.dev9__tar.gz → 3.20.dev1__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 (85) hide show
  1. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/PKG-INFO +5 -1
  2. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/text.py +2 -2
  3. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/tools/rdump.py +23 -1
  4. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/version.py +2 -2
  5. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/PKG-INFO +5 -1
  6. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/requires.txt +5 -0
  7. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/pyproject.toml +5 -0
  8. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_rdump.py +26 -0
  9. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/.git-blame-ignore-revs +0 -0
  10. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/COPYRIGHT +0 -0
  11. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/LICENSE +0 -0
  12. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/MANIFEST.in +0 -0
  13. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/README.md +0 -0
  14. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/filesystem.py +0 -0
  15. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/passivedns.py +0 -0
  16. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/records.json +0 -0
  17. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/tcpconn.py +0 -0
  18. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/__init__.py +0 -0
  19. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/__init__.py +0 -0
  20. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/archive.py +0 -0
  21. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/avro.py +0 -0
  22. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/broker.py +0 -0
  23. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/csvfile.py +0 -0
  24. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/duckdb.py +0 -0
  25. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/elastic.py +0 -0
  26. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/jsonfile.py +0 -0
  27. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/line.py +0 -0
  28. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/mongo.py +0 -0
  29. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/split.py +0 -0
  30. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/splunk.py +0 -0
  31. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/sqlite.py +0 -0
  32. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/stream.py +0 -0
  33. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/xlsx.py +0 -0
  34. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/base.py +0 -0
  35. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/exceptions.py +0 -0
  36. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/__init__.py +0 -0
  37. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/credential.py +0 -0
  38. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/__init__.py +0 -0
  39. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/ip.py +0 -0
  40. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/ipv4.py +0 -0
  41. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/tcp.py +0 -0
  42. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/udp.py +0 -0
  43. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/jsonpacker.py +0 -0
  44. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/packer.py +0 -0
  45. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/selector.py +0 -0
  46. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/stream.py +0 -0
  47. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/tools/__init__.py +0 -0
  48. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/tools/geoip.py +0 -0
  49. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/utils.py +0 -0
  50. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/whitelist.py +0 -0
  51. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/SOURCES.txt +0 -0
  52. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/dependency_links.txt +0 -0
  53. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/entry_points.txt +0 -0
  54. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/top_level.txt +0 -0
  55. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/setup.cfg +0 -0
  56. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/__init__.py +0 -0
  57. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/_utils.py +0 -0
  58. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/docs/Makefile +0 -0
  59. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/docs/conf.py +0 -0
  60. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/docs/index.rst +0 -0
  61. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/selector_explain_example.py +0 -0
  62. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/standalone_test.py +0 -0
  63. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_adapter_line.py +0 -0
  64. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_adapter_text.py +0 -0
  65. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_avro.py +0 -0
  66. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_avro_adapter.py +0 -0
  67. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_compiled_selector.py +0 -0
  68. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_csv_adapter.py +0 -0
  69. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_deprecations.py +0 -0
  70. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_elastic_adapter.py +0 -0
  71. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_fieldtype_ip.py +0 -0
  72. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_fieldtypes.py +0 -0
  73. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_json_packer.py +0 -0
  74. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_json_record_adapter.py +0 -0
  75. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_multi_timestamp.py +0 -0
  76. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_packer.py +0 -0
  77. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_record.py +0 -0
  78. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_record_adapter.py +0 -0
  79. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_record_descriptor.py +0 -0
  80. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_regression.py +0 -0
  81. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_selector.py +0 -0
  82. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_splunk_adapter.py +0 -0
  83. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_sqlite_duckdb_adapter.py +0 -0
  84. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_xlsx_adapter.py +0 -0
  85. {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: flow.record
3
- Version: 3.19.dev9
3
+ Version: 3.20.dev1
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
@@ -43,6 +43,10 @@ Requires-Dist: flow.record[avro]; extra == "test"
43
43
  Requires-Dist: flow.record[elastic]; extra == "test"
44
44
  Requires-Dist: duckdb; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
45
45
  Requires-Dist: pytz; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
46
+ Requires-Dist: tqdm; extra == "test"
47
+ Provides-Extra: full
48
+ Requires-Dist: flow.record[compression]; extra == "full"
49
+ Requires-Dist: tqdm; extra == "full"
46
50
 
47
51
  # flow.record
48
52
 
@@ -30,9 +30,9 @@ class DefaultMissing(dict):
30
30
 
31
31
  Example:
32
32
  >>> d = DefaultMissing({"foo": "bar"})
33
- >>> d['foo']
33
+ >>> d["foo"]
34
34
  'bar'
35
- >>> d['missing_key']
35
+ >>> d["missing_key"]
36
36
  '{missing_key}'
37
37
  """
38
38
 
@@ -21,6 +21,14 @@ try:
21
21
  except ImportError:
22
22
  version = "unknown"
23
23
 
24
+ try:
25
+ import tqdm
26
+
27
+ HAS_TQDM = True
28
+
29
+ except ImportError:
30
+ HAS_TQDM = False
31
+
24
32
  log = logging.getLogger(__name__)
25
33
 
26
34
 
@@ -112,6 +120,12 @@ def main(argv: list[str] | None = None) -> int:
112
120
  help="Generate suffixes of length LEN for splitted output files",
113
121
  )
114
122
  output.add_argument("--multi-timestamp", action="store_true", help="Create records for datetime fields")
123
+ output.add_argument(
124
+ "-p",
125
+ "--progress",
126
+ action="store_true",
127
+ help="Show progress bar (requires tqdm)",
128
+ )
115
129
 
116
130
  advanced = parser.add_argument_group("advanced")
117
131
  advanced.add_argument(
@@ -217,7 +231,14 @@ def main(argv: list[str] | None = None) -> int:
217
231
  seen_desc = set()
218
232
  islice_stop = (args.count + args.skip) if args.count else None
219
233
  record_iterator = islice(record_stream(args.src, selector), args.skip, islice_stop)
234
+
235
+ if args.progress:
236
+ if not HAS_TQDM:
237
+ parser.error("tqdm is required for progress bar")
238
+ record_iterator = tqdm.tqdm(record_iterator, unit=" records", delay=sys.float_info.min)
239
+
220
240
  count = 0
241
+ record_writer = None
221
242
 
222
243
  try:
223
244
  record_writer = RecordWriter(uri)
@@ -246,7 +267,8 @@ def main(argv: list[str] | None = None) -> int:
246
267
  record_writer.write(rec)
247
268
 
248
269
  finally:
249
- record_writer.__exit__()
270
+ if record_writer:
271
+ record_writer.__exit__()
250
272
 
251
273
  if args.list:
252
274
  print(f"Processed {count} records")
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.19.dev9'
16
- __version_tuple__ = version_tuple = (3, 19, 'dev9')
15
+ __version__ = version = '3.20.dev1'
16
+ __version_tuple__ = version_tuple = (3, 20, 'dev1')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: flow.record
3
- Version: 3.19.dev9
3
+ Version: 3.20.dev1
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
@@ -43,6 +43,10 @@ Requires-Dist: flow.record[avro]; extra == "test"
43
43
  Requires-Dist: flow.record[elastic]; extra == "test"
44
44
  Requires-Dist: duckdb; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
45
45
  Requires-Dist: pytz; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
46
+ Requires-Dist: tqdm; extra == "test"
47
+ Provides-Extra: full
48
+ Requires-Dist: flow.record[compression]; extra == "full"
49
+ Requires-Dist: tqdm; extra == "full"
46
50
 
47
51
  # flow.record
48
52
 
@@ -20,6 +20,10 @@ pytz
20
20
  [elastic]
21
21
  elasticsearch
22
22
 
23
+ [full]
24
+ flow.record[compression]
25
+ tqdm
26
+
23
27
  [geoip]
24
28
  maxminddb
25
29
 
@@ -30,6 +34,7 @@ httpx
30
34
  flow.record[compression]
31
35
  flow.record[avro]
32
36
  flow.record[elastic]
37
+ tqdm
33
38
 
34
39
  [test:platform_python_implementation != "PyPy" and python_version < "3.12"]
35
40
  duckdb
@@ -62,6 +62,11 @@ test = [
62
62
  "flow.record[elastic]",
63
63
  "duckdb; platform_python_implementation != 'PyPy' and python_version < '3.12'", # duckdb
64
64
  "pytz; platform_python_implementation != 'PyPy' and python_version < '3.12'", # duckdb
65
+ "tqdm",
66
+ ]
67
+ full = [
68
+ "flow.record[compression]",
69
+ "tqdm",
65
70
  ]
66
71
 
67
72
  [project.scripts]
@@ -696,3 +696,29 @@ def test_rdump_line_verbose(tmp_path: Path, capsys: pytest.CaptureFixture, rdump
696
696
  assert "data (bytes) =" in captured.out
697
697
  assert "counter (uint32) =" in captured.out
698
698
  assert "foo (string) =" in captured.out
699
+
700
+
701
+ def test_rdump_list_progress(tmp_path: Path, capsys: pytest.CaptureFixture) -> None:
702
+ TestRecord = RecordDescriptor(
703
+ "test/rdump/progress",
704
+ [
705
+ ("uint32", "counter"),
706
+ ],
707
+ )
708
+ record_path = tmp_path / "test.records"
709
+
710
+ with RecordWriter(record_path) as writer:
711
+ for i in range(100):
712
+ writer.write(TestRecord(counter=i))
713
+
714
+ rdump.main(["--list", "--progress", str(record_path)])
715
+ captured = capsys.readouterr()
716
+
717
+ # stderr should contain tqdm progress bar
718
+ # 100 records [00:00, 64987.67 records/s]
719
+ assert "\r100 records [" in captured.err
720
+ assert " records/s]" in captured.err
721
+
722
+ # stdout should contain the RecordDescriptor definition and count
723
+ assert "# <RecordDescriptor test/rdump/progress, hash=eeb21156>" in captured.out
724
+ assert "Processed 100 records" in captured.out
File without changes
File without changes