flow.record 3.21.dev3__tar.gz → 3.21.dev4__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.21.dev3 → flow_record-3.21.dev4}/PKG-INFO +4 -1
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/examples/filesystem.py +28 -29
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/examples/passivedns.py +12 -9
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/examples/tcpconn.py +5 -3
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/elastic.py +2 -4
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/base.py +1 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/tools/rdump.py +1 -2
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/version.py +2 -2
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow.record.egg-info/PKG-INFO +4 -1
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow.record.egg-info/SOURCES.txt +1 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow.record.egg-info/requires.txt +4 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/pyproject.toml +4 -0
- flow_record-3.21.dev4/tests/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/standalone_test.py +1 -1
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_fieldtypes.py +9 -3
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_packer.py +7 -5
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_rdump.py +1 -2
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_xlsx_adapter.py +1 -2
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/.git-blame-ignore-revs +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/COPYRIGHT +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/LICENSE +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/MANIFEST.in +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/README.md +0 -0
- {flow_record-3.21.dev3/flow/record/tools → flow_record-3.21.dev4/examples}/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/examples/records.json +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/archive.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/avro.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/broker.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/csvfile.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/duckdb.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/jsonfile.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/line.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/mongo.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/split.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/splunk.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/sqlite.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/stream.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/text.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/adapter/xlsx.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/exceptions.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/credential.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/net/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/net/ip.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/net/ipv4.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/net/tcp.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/fieldtypes/net/udp.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/jsonpacker.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/packer.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/selector.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/stream.py +0 -0
- {flow_record-3.21.dev3/tests → flow_record-3.21.dev4/flow/record/tools}/__init__.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/tools/geoip.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/utils.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow/record/whitelist.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow.record.egg-info/dependency_links.txt +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow.record.egg-info/entry_points.txt +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/flow.record.egg-info/top_level.txt +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/setup.cfg +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/_utils.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/docs/Makefile +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/docs/conf.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/docs/index.rst +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/selector_explain_example.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_adapter_line.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_adapter_text.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_avro.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_avro_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_compiled_selector.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_csv_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_deprecations.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_elastic_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_fieldtype_ip.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_json_packer.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_json_record_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_multi_timestamp.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_record.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_record_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_record_descriptor.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_regression.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_selector.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_splunk_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_sqlite_duckdb_adapter.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tests/test_utils.py +0 -0
- {flow_record-3.21.dev3 → flow_record-3.21.dev4}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flow.record
|
|
3
|
-
Version: 3.21.
|
|
3
|
+
Version: 3.21.dev4
|
|
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
|
|
@@ -37,10 +37,13 @@ Requires-Dist: duckdb; extra == "duckdb"
|
|
|
37
37
|
Requires-Dist: pytz; extra == "duckdb"
|
|
38
38
|
Provides-Extra: splunk
|
|
39
39
|
Requires-Dist: httpx; extra == "splunk"
|
|
40
|
+
Provides-Extra: xlsx
|
|
41
|
+
Requires-Dist: openpyxl; extra == "xlsx"
|
|
40
42
|
Provides-Extra: test
|
|
41
43
|
Requires-Dist: flow.record[compression]; extra == "test"
|
|
42
44
|
Requires-Dist: flow.record[avro]; extra == "test"
|
|
43
45
|
Requires-Dist: flow.record[elastic]; extra == "test"
|
|
46
|
+
Requires-Dist: flow.record[xlsx]; extra == "test"
|
|
44
47
|
Requires-Dist: duckdb; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
|
|
45
48
|
Requires-Dist: pytz; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
|
|
46
49
|
Requires-Dist: tqdm; extra == "test"
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import stat
|
|
1
|
+
from __future__ import annotations
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import stat
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
from flow.record import RecordDescriptor, RecordWriter
|
|
7
8
|
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from collections.abc import Iterator
|
|
11
|
+
|
|
12
|
+
|
|
8
13
|
descriptor = """
|
|
9
14
|
filesystem/unix/entry
|
|
10
15
|
string path;
|
|
@@ -22,34 +27,32 @@ filesystem/unix/entry
|
|
|
22
27
|
FilesystemFile = RecordDescriptor(descriptor)
|
|
23
28
|
|
|
24
29
|
|
|
25
|
-
def hash_file(path
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
f.close()
|
|
30
|
+
def hash_file(path: str | Path) -> None:
|
|
31
|
+
with Path(path).open("rb") as f:
|
|
32
|
+
while True:
|
|
33
|
+
d = f.read(4096)
|
|
34
|
+
if not d:
|
|
35
|
+
break
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
class FilesystemIterator:
|
|
35
39
|
basepath = None
|
|
36
40
|
|
|
37
|
-
def __init__(self, basepath):
|
|
41
|
+
def __init__(self, basepath: str | None):
|
|
38
42
|
self.basepath = basepath
|
|
39
43
|
self.recordType = FilesystemFile
|
|
40
44
|
|
|
41
|
-
def classify(self, source, classification):
|
|
45
|
+
def classify(self, source: str, classification: str) -> None:
|
|
42
46
|
self.recordType = FilesystemFile.base(_source=source, _classification=classification)
|
|
43
47
|
|
|
44
|
-
def iter(self, path):
|
|
45
|
-
|
|
46
|
-
return self._iter(path)
|
|
48
|
+
def iter(self, path: str | Path) -> Iterator[FilesystemFile]:
|
|
49
|
+
return self._iter(Path(path).resolve())
|
|
47
50
|
|
|
48
|
-
def _iter(self, path):
|
|
49
|
-
if path.
|
|
51
|
+
def _iter(self, path: Path) -> Iterator[FilesystemFile]:
|
|
52
|
+
if path.is_relative_to("/proc"):
|
|
50
53
|
return
|
|
51
54
|
|
|
52
|
-
st =
|
|
55
|
+
st = path.lstat()
|
|
53
56
|
|
|
54
57
|
abspath = path
|
|
55
58
|
if self.basepath and abspath.startswith(self.basepath):
|
|
@@ -59,7 +62,7 @@ class FilesystemIterator:
|
|
|
59
62
|
|
|
60
63
|
link = None
|
|
61
64
|
if ifmt == stat.S_IFLNK:
|
|
62
|
-
link =
|
|
65
|
+
link = path.readlink()
|
|
63
66
|
|
|
64
67
|
yield self.recordType(
|
|
65
68
|
path=abspath,
|
|
@@ -69,20 +72,16 @@ class FilesystemIterator:
|
|
|
69
72
|
size=st.st_size,
|
|
70
73
|
uid=st.st_uid,
|
|
71
74
|
gid=st.st_gid,
|
|
72
|
-
ctime=
|
|
73
|
-
mtime=
|
|
74
|
-
atime=
|
|
75
|
+
ctime=st.st_ctime,
|
|
76
|
+
mtime=st.st_mtime,
|
|
77
|
+
atime=st.st_atime,
|
|
75
78
|
link=link,
|
|
76
79
|
)
|
|
77
80
|
|
|
78
81
|
if ifmt == stat.S_IFDIR:
|
|
79
|
-
for i in
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
fullpath = os.path.join(path, i)
|
|
84
|
-
for e in self.iter(fullpath):
|
|
85
|
-
yield e
|
|
82
|
+
for i in path.iterdir():
|
|
83
|
+
fullpath = path.joinpath(i)
|
|
84
|
+
yield from self.iter(fullpath)
|
|
86
85
|
|
|
87
86
|
|
|
88
87
|
chunk = []
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env pypy
|
|
2
|
-
import
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
3
4
|
import sys
|
|
4
|
-
import datetime
|
|
5
|
+
from datetime import datetime, timezone
|
|
5
6
|
|
|
6
7
|
import net.ipv4
|
|
7
|
-
|
|
8
|
+
import record
|
|
8
9
|
from fileprocessing import DirectoryProcessor
|
|
9
10
|
|
|
11
|
+
UTC_TIMEZONE = timezone.utc
|
|
12
|
+
|
|
10
13
|
|
|
11
|
-
def ts(s):
|
|
12
|
-
return datetime.
|
|
14
|
+
def ts(s: float) -> datetime:
|
|
15
|
+
return datetime.fromtimestamp(float(s), tz=UTC_TIMEZONE)
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
def ip(s):
|
|
18
|
+
def ip(s: str) -> net.ipv4.Address:
|
|
16
19
|
return net.ipv4.Address(s)
|
|
17
20
|
|
|
18
21
|
|
|
@@ -21,7 +24,7 @@ class SeparatedFile:
|
|
|
21
24
|
seperator = None
|
|
22
25
|
format = None
|
|
23
26
|
|
|
24
|
-
def __init__(self, fp, seperator, format):
|
|
27
|
+
def __init__(self, fp: list[str], seperator: str | None, format: list[tuple]):
|
|
25
28
|
self.fp = fp
|
|
26
29
|
self.seperator = seperator
|
|
27
30
|
self.format = format
|
|
@@ -46,7 +49,7 @@ class SeparatedFile:
|
|
|
46
49
|
yield recordtype(**r)
|
|
47
50
|
|
|
48
51
|
|
|
49
|
-
def PassiveDnsFile(fp):
|
|
52
|
+
def PassiveDnsFile(fp: list[str]) -> SeparatedFile:
|
|
50
53
|
return SeparatedFile(fp, "||", PASSIVEDNS_FORMAT)
|
|
51
54
|
|
|
52
55
|
|
|
@@ -63,7 +66,7 @@ PASSIVEDNS_FORMAT = [
|
|
|
63
66
|
]
|
|
64
67
|
|
|
65
68
|
|
|
66
|
-
def main():
|
|
69
|
+
def main() -> None:
|
|
67
70
|
rs = record.RecordOutput(sys.stdout)
|
|
68
71
|
for r in DirectoryProcessor(sys.argv[1], PassiveDnsFile, r"\.log\.gz"):
|
|
69
72
|
rs.write(r)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import random
|
|
2
|
+
from datetime import datetime, timezone
|
|
2
3
|
|
|
3
|
-
from datetime import datetime
|
|
4
4
|
from flow import record
|
|
5
5
|
|
|
6
|
+
UTC_TIMEZONE = timezone.utc
|
|
7
|
+
|
|
6
8
|
descriptor = """
|
|
7
9
|
network/traffic/tcp/connection
|
|
8
10
|
datetime ts;
|
|
@@ -32,9 +34,9 @@ port_list = [
|
|
|
32
34
|
|
|
33
35
|
rs = record.RecordWriter()
|
|
34
36
|
|
|
35
|
-
for
|
|
37
|
+
for _ in range(500):
|
|
36
38
|
r = conn(
|
|
37
|
-
ts=datetime.now(),
|
|
39
|
+
ts=datetime.now(tz=UTC_TIMEZONE),
|
|
38
40
|
src=random.choice(ip_list),
|
|
39
41
|
srcport=random.choice(port_list),
|
|
40
42
|
dst=random.choice(ip_list),
|
|
@@ -6,6 +6,8 @@ import queue
|
|
|
6
6
|
import threading
|
|
7
7
|
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
|
+
import urllib3
|
|
10
|
+
|
|
9
11
|
try:
|
|
10
12
|
import elasticsearch
|
|
11
13
|
import elasticsearch.helpers
|
|
@@ -103,8 +105,6 @@ class ElasticWriter(AbstractWriter):
|
|
|
103
105
|
|
|
104
106
|
if not verify_certs:
|
|
105
107
|
# Disable InsecureRequestWarning of urllib3, caused by the verify_certs flag.
|
|
106
|
-
import urllib3
|
|
107
|
-
|
|
108
108
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
109
109
|
|
|
110
110
|
self.metadata_fields = {}
|
|
@@ -235,8 +235,6 @@ class ElasticReader(AbstractReader):
|
|
|
235
235
|
|
|
236
236
|
if not verify_certs:
|
|
237
237
|
# Disable InsecureRequestWarning of urllib3, caused by the verify_certs flag.
|
|
238
|
-
import urllib3
|
|
239
|
-
|
|
240
238
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
241
239
|
|
|
242
240
|
def __iter__(self) -> Iterator[Record]:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
import argparse
|
|
4
5
|
import logging
|
|
5
6
|
import sys
|
|
6
7
|
from importlib import import_module
|
|
@@ -69,8 +70,6 @@ def list_adapters() -> None:
|
|
|
69
70
|
|
|
70
71
|
@catch_sigpipe
|
|
71
72
|
def main(argv: list[str] | None = None) -> int:
|
|
72
|
-
import argparse
|
|
73
|
-
|
|
74
73
|
parser = argparse.ArgumentParser(
|
|
75
74
|
description="Record dumper, a tool that can read, write and filter records",
|
|
76
75
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '3.21.
|
|
21
|
-
__version_tuple__ = version_tuple = (3, 21, '
|
|
20
|
+
__version__ = version = '3.21.dev4'
|
|
21
|
+
__version_tuple__ = version_tuple = (3, 21, 'dev4')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flow.record
|
|
3
|
-
Version: 3.21.
|
|
3
|
+
Version: 3.21.dev4
|
|
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
|
|
@@ -37,10 +37,13 @@ Requires-Dist: duckdb; extra == "duckdb"
|
|
|
37
37
|
Requires-Dist: pytz; extra == "duckdb"
|
|
38
38
|
Provides-Extra: splunk
|
|
39
39
|
Requires-Dist: httpx; extra == "splunk"
|
|
40
|
+
Provides-Extra: xlsx
|
|
41
|
+
Requires-Dist: openpyxl; extra == "xlsx"
|
|
40
42
|
Provides-Extra: test
|
|
41
43
|
Requires-Dist: flow.record[compression]; extra == "test"
|
|
42
44
|
Requires-Dist: flow.record[avro]; extra == "test"
|
|
43
45
|
Requires-Dist: flow.record[elastic]; extra == "test"
|
|
46
|
+
Requires-Dist: flow.record[xlsx]; extra == "test"
|
|
44
47
|
Requires-Dist: duckdb; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
|
|
45
48
|
Requires-Dist: pytz; (platform_python_implementation != "PyPy" and python_version < "3.12") and extra == "test"
|
|
46
49
|
Requires-Dist: tqdm; extra == "test"
|
|
@@ -56,10 +56,14 @@ duckdb = [
|
|
|
56
56
|
splunk = [
|
|
57
57
|
"httpx",
|
|
58
58
|
]
|
|
59
|
+
xlsx = [
|
|
60
|
+
"openpyxl",
|
|
61
|
+
]
|
|
59
62
|
test = [
|
|
60
63
|
"flow.record[compression]",
|
|
61
64
|
"flow.record[avro]",
|
|
62
65
|
"flow.record[elastic]",
|
|
66
|
+
"flow.record[xlsx]",
|
|
63
67
|
"duckdb; platform_python_implementation != 'PyPy' and python_version < '3.12'", # duckdb
|
|
64
68
|
"pytz; platform_python_implementation != 'PyPy' and python_version < '3.12'", # duckdb
|
|
65
69
|
"tqdm",
|
|
File without changes
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import traceback
|
|
3
4
|
from typing import Callable
|
|
4
5
|
|
|
5
6
|
|
|
@@ -14,6 +15,5 @@ def main(glob: dict[str, Callable[..., None]]) -> None:
|
|
|
14
15
|
print("PASSED")
|
|
15
16
|
except Exception:
|
|
16
17
|
print("FAILED")
|
|
17
|
-
import traceback
|
|
18
18
|
|
|
19
19
|
traceback.print_exc()
|
|
@@ -376,15 +376,21 @@ def test_uri_type() -> None:
|
|
|
376
376
|
assert r.path.protocol == "http"
|
|
377
377
|
assert r.path.hostname == "example.com"
|
|
378
378
|
|
|
379
|
-
with pytest.warns(
|
|
379
|
+
with pytest.warns(
|
|
380
|
+
DeprecationWarning, match=r"Do not use class uri\(...\) for filesystem paths, use class path\(...\)"
|
|
381
|
+
):
|
|
380
382
|
r = TestRecord(uri.from_windows(r"c:\windows\program files\Fox-IT B.V\flow.exe"))
|
|
381
383
|
assert r.path.filename == "flow.exe"
|
|
382
384
|
|
|
383
385
|
r = TestRecord()
|
|
384
|
-
with pytest.warns(
|
|
386
|
+
with pytest.warns(
|
|
387
|
+
DeprecationWarning, match=r"Do not use class uri\(...\) for filesystem paths, use class path\(...\)"
|
|
388
|
+
):
|
|
385
389
|
r.path = uri.normalize(r"c:\Users\Fox-IT\Downloads\autoruns.exe")
|
|
386
390
|
assert r.path.filename == "autoruns.exe"
|
|
387
|
-
with pytest.warns(
|
|
391
|
+
with pytest.warns(
|
|
392
|
+
DeprecationWarning, match=r"Do not use class uri\(...\) for filesystem paths, use class path\(...\)"
|
|
393
|
+
):
|
|
388
394
|
assert r.path.dirname == uri.normalize(r"\Users\Fox-IT\Downloads")
|
|
389
395
|
assert r.path.dirname == "/Users/Fox-IT/Downloads"
|
|
390
396
|
|
|
@@ -22,7 +22,7 @@ def test_uri_packing() -> None:
|
|
|
22
22
|
],
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Construct with an url
|
|
26
26
|
record = TestRecord("http://www.google.com/evil.bin")
|
|
27
27
|
data = packer.pack(record)
|
|
28
28
|
record = packer.unpack(data)
|
|
@@ -30,8 +30,9 @@ def test_uri_packing() -> None:
|
|
|
30
30
|
assert record.path.filename == "evil.bin"
|
|
31
31
|
assert record.path.dirname == "/"
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
with pytest.warns(
|
|
34
|
+
DeprecationWarning, match=r"Do not use class uri\(...\) for filesystem paths, use class path\(...\)"
|
|
35
|
+
):
|
|
35
36
|
path = uri.from_windows(r"c:\Program Files\Fox-IT\flow is awesome.exe")
|
|
36
37
|
record = TestRecord(path)
|
|
37
38
|
data = packer.pack(record)
|
|
@@ -40,8 +41,9 @@ def test_uri_packing() -> None:
|
|
|
40
41
|
assert record.path.filename == "flow is awesome.exe"
|
|
41
42
|
assert record.path.dirname == "/Program Files/Fox-IT"
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
with pytest.warns(
|
|
45
|
+
DeprecationWarning, match=r"Do not use class uri\(...\) for filesystem paths, use class path\(...\)"
|
|
46
|
+
):
|
|
45
47
|
path = uri.from_windows(r"c:\Users\Hello World\foo.bar.exe")
|
|
46
48
|
record = TestRecord(path)
|
|
47
49
|
data = packer.pack(record)
|
|
@@ -17,6 +17,7 @@ import pytest
|
|
|
17
17
|
|
|
18
18
|
import flow.record.fieldtypes
|
|
19
19
|
from flow.record import RecordDescriptor, RecordReader, RecordWriter
|
|
20
|
+
from flow.record.adapter.line import field_types_for_record_descriptor
|
|
20
21
|
from flow.record.fieldtypes import flow_record_tz
|
|
21
22
|
from flow.record.tools import rdump
|
|
22
23
|
|
|
@@ -681,8 +682,6 @@ def test_rdump_line_verbose(tmp_path: Path, capsys: pytest.CaptureFixture, rdump
|
|
|
681
682
|
writer.write(TestRecord(counter=2))
|
|
682
683
|
writer.write(TestRecord(counter=3))
|
|
683
684
|
|
|
684
|
-
from flow.record.adapter.line import field_types_for_record_descriptor
|
|
685
|
-
|
|
686
685
|
field_types_for_record_descriptor.cache_clear()
|
|
687
686
|
assert field_types_for_record_descriptor.cache_info().currsize == 0
|
|
688
687
|
rdump.main([str(record_path), *rdump_params])
|
|
@@ -9,6 +9,7 @@ from unittest.mock import MagicMock
|
|
|
9
9
|
import pytest
|
|
10
10
|
|
|
11
11
|
from flow.record import fieldtypes
|
|
12
|
+
from flow.record.adapter.xlsx import sanitize_fieldvalues
|
|
12
13
|
|
|
13
14
|
if TYPE_CHECKING:
|
|
14
15
|
from collections.abc import Iterator
|
|
@@ -27,8 +28,6 @@ def mock_openpyxl_package(monkeypatch: pytest.MonkeyPatch) -> Iterator[MagicMock
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def test_sanitize_field_values(mock_openpyxl_package: MagicMock) -> None:
|
|
30
|
-
from flow.record.adapter.xlsx import sanitize_fieldvalues
|
|
31
|
-
|
|
32
31
|
assert list(
|
|
33
32
|
sanitize_fieldvalues(
|
|
34
33
|
[
|
|
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
|