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.
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/PKG-INFO +5 -1
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/text.py +2 -2
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/tools/rdump.py +23 -1
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/version.py +2 -2
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/PKG-INFO +5 -1
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/requires.txt +5 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/pyproject.toml +5 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_rdump.py +26 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/.git-blame-ignore-revs +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/COPYRIGHT +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/LICENSE +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/MANIFEST.in +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/README.md +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/filesystem.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/passivedns.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/records.json +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/examples/tcpconn.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/__init__.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/__init__.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/archive.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/avro.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/broker.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/csvfile.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/duckdb.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/elastic.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/jsonfile.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/line.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/mongo.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/split.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/splunk.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/sqlite.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/stream.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/adapter/xlsx.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/base.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/exceptions.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/__init__.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/credential.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/__init__.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/ip.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/ipv4.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/tcp.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/fieldtypes/net/udp.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/jsonpacker.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/packer.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/selector.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/stream.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/tools/__init__.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/tools/geoip.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/utils.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow/record/whitelist.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/SOURCES.txt +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/dependency_links.txt +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/entry_points.txt +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/flow.record.egg-info/top_level.txt +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/setup.cfg +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/__init__.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/_utils.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/docs/Makefile +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/docs/conf.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/docs/index.rst +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/selector_explain_example.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/standalone_test.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_adapter_line.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_adapter_text.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_avro.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_avro_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_compiled_selector.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_csv_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_deprecations.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_elastic_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_fieldtype_ip.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_fieldtypes.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_json_packer.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_json_record_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_multi_timestamp.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_packer.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_record.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_record_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_record_descriptor.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_regression.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_selector.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_splunk_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_sqlite_duckdb_adapter.py +0 -0
- {flow_record-3.19.dev9 → flow_record-3.20.dev1}/tests/test_xlsx_adapter.py +0 -0
- {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.
|
|
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
|
|
|
@@ -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
|
|
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.
|
|
16
|
-
__version_tuple__ = version_tuple = (3,
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|