Skip to content

Commit 06ea457

Browse files
authored
Merge branch 'main' into fix/flatten-command-type
2 parents 1b5d5cf + 9775ddb commit 06ea457

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2032
-1357
lines changed

.git-blame-ignore-revs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Formatting commits. You can ignore them during git-blame with `--ignore-rev` or `--ignore-revs-file`.
2+
#
3+
# $ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
4+
#
5+
# Change linter to Ruff (#158)
6+
c67f778c653c295ec26146cf6422d3b06ac640e8

examples/__init__.py

Whitespace-only changes.

examples/filesystem.py

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import os
2-
import stat
1+
from __future__ import annotations
32

4-
from datetime import datetime
3+
import stat
4+
from pathlib import Path
5+
from typing import TYPE_CHECKING
56

67
from flow.record import RecordDescriptor, RecordWriter
78

9+
if TYPE_CHECKING:
10+
from collections.abc import Iterator
11+
12+
813
descriptor = """
914
filesystem/unix/entry
1015
string path;
@@ -22,34 +27,32 @@
2227
FilesystemFile = RecordDescriptor(descriptor)
2328

2429

25-
def hash_file(path, t):
26-
f = open(path, "rb")
27-
while 1:
28-
d = f.read(4096)
29-
if d == "":
30-
break
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
3236

3337

3438
class FilesystemIterator:
3539
basepath = None
3640

37-
def __init__(self, basepath):
41+
def __init__(self, basepath: str | None):
3842
self.basepath = basepath
3943
self.recordType = FilesystemFile
4044

41-
def classify(self, source, classification):
45+
def classify(self, source: str, classification: str) -> None:
4246
self.recordType = FilesystemFile.base(_source=source, _classification=classification)
4347

44-
def iter(self, path):
45-
path = os.path.abspath(path)
46-
return self._iter(path)
48+
def iter(self, path: str | Path) -> Iterator[FilesystemFile]:
49+
return self._iter(Path(path).resolve())
4750

48-
def _iter(self, path):
49-
if path.startswith("/proc"):
51+
def _iter(self, path: Path) -> Iterator[FilesystemFile]:
52+
if path.is_relative_to("/proc"):
5053
return
5154

52-
st = os.lstat(path)
55+
st = path.lstat()
5356

5457
abspath = path
5558
if self.basepath and abspath.startswith(self.basepath):
@@ -59,7 +62,7 @@ def _iter(self, path):
5962

6063
link = None
6164
if ifmt == stat.S_IFLNK:
62-
link = os.readlink(path)
65+
link = path.readlink()
6366

6467
yield self.recordType(
6568
path=abspath,
@@ -69,20 +72,16 @@ def _iter(self, path):
6972
size=st.st_size,
7073
uid=st.st_uid,
7174
gid=st.st_gid,
72-
ctime=datetime.fromtimestamp(st.st_ctime),
73-
mtime=datetime.fromtimestamp(st.st_mtime),
74-
atime=datetime.fromtimestamp(st.st_atime),
75+
ctime=st.st_ctime,
76+
mtime=st.st_mtime,
77+
atime=st.st_atime,
7578
link=link,
7679
)
7780

7881
if ifmt == stat.S_IFDIR:
79-
for i in os.listdir(path):
80-
if i in (".", ".."):
81-
continue
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)
8685

8786

8887
chunk = []

examples/passivedns.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
#!/usr/bin/env pypy
2-
import record
2+
from __future__ import annotations
3+
34
import sys
4-
import datetime
5+
from datetime import datetime, timezone
56

67
import net.ipv4
7-
8+
import record
89
from fileprocessing import DirectoryProcessor
910

11+
UTC_TIMEZONE = timezone.utc
12+
1013

11-
def ts(s):
12-
return datetime.datetime.fromtimestamp(float(s))
14+
def ts(s: float) -> datetime:
15+
return datetime.fromtimestamp(float(s), tz=UTC_TIMEZONE)
1316

1417

15-
def ip(s):
18+
def ip(s: str) -> net.ipv4.Address:
1619
return net.ipv4.Address(s)
1720

1821

@@ -21,7 +24,7 @@ class SeparatedFile:
2124
seperator = None
2225
format = None
2326

24-
def __init__(self, fp, seperator, format):
27+
def __init__(self, fp: list[str], seperator: str | None, format: list[tuple]):
2528
self.fp = fp
2629
self.seperator = seperator
2730
self.format = format
@@ -46,7 +49,7 @@ def __iter__(self):
4649
yield recordtype(**r)
4750

4851

49-
def PassiveDnsFile(fp):
52+
def PassiveDnsFile(fp: list[str]) -> SeparatedFile:
5053
return SeparatedFile(fp, "||", PASSIVEDNS_FORMAT)
5154

5255

@@ -63,7 +66,7 @@ def PassiveDnsFile(fp):
6366
]
6467

6568

66-
def main():
69+
def main() -> None:
6770
rs = record.RecordOutput(sys.stdout)
6871
for r in DirectoryProcessor(sys.argv[1], PassiveDnsFile, r"\.log\.gz"):
6972
rs.write(r)

examples/tcpconn.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import random
2+
from datetime import datetime, timezone
23

3-
from datetime import datetime
44
from flow import record
55

6+
UTC_TIMEZONE = timezone.utc
7+
68
descriptor = """
79
network/traffic/tcp/connection
810
datetime ts;
@@ -32,9 +34,9 @@
3234

3335
rs = record.RecordWriter()
3436

35-
for i in range(500):
37+
for _ in range(500):
3638
r = conn(
37-
ts=datetime.now(),
39+
ts=datetime.now(tz=UTC_TIMEZONE),
3840
src=random.choice(ip_list),
3941
srcport=random.choice(port_list),
4042
dst=random.choice(ip_list),

flow/record/__init__.py

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
from __future__ import annotations
2+
13
import gzip
2-
import os
4+
from pathlib import Path
35

46
from flow.record.base import (
57
IGNORE_FIELDS_FOR_COMPARISON,
@@ -39,71 +41,61 @@
3941

4042
__all__ = [
4143
"IGNORE_FIELDS_FOR_COMPARISON",
42-
"RECORD_VERSION",
4344
"RECORDSTREAM_MAGIC",
45+
"RECORD_VERSION",
46+
"DynamicDescriptor",
4447
"FieldType",
45-
"Record",
4648
"GroupedRecord",
47-
"RecordDescriptor",
49+
"JsonRecordPacker",
50+
"PathTemplateWriter",
51+
"Record",
4852
"RecordAdapter",
53+
"RecordArchiver",
54+
"RecordDescriptor",
55+
"RecordDescriptorError",
4956
"RecordField",
50-
"RecordReader",
51-
"RecordWriter",
5257
"RecordOutput",
53-
"RecordPrinter",
5458
"RecordPacker",
55-
"JsonRecordPacker",
56-
"RecordStreamWriter",
59+
"RecordPrinter",
60+
"RecordReader",
5761
"RecordStreamReader",
58-
"open_path_or_stream",
62+
"RecordStreamWriter",
63+
"RecordWriter",
64+
"dynamic_fieldtype",
65+
"extend_record",
66+
"ignore_fields_for_comparison",
67+
"iter_timestamped_records",
5968
"open_path",
69+
"open_path_or_stream",
6070
"open_stream",
61-
"ignore_fields_for_comparison",
71+
"record_stream",
6272
"set_ignored_fields_for_comparison",
6373
"stream",
64-
"dynamic_fieldtype",
65-
"DynamicDescriptor",
66-
"PathTemplateWriter",
67-
"RecordArchiver",
68-
"RecordDescriptorError",
69-
"record_stream",
70-
"extend_record",
71-
"iter_timestamped_records",
7274
]
7375

7476

75-
class View:
76-
fields = None
77-
78-
def __init__(self, fields):
79-
self.fields = fields
80-
81-
def __iter__(self, fields):
82-
pass
83-
84-
8577
class RecordDateSplitter:
8678
basepath = None
8779
out = None
8880

89-
def __init__(self, basepath):
90-
self.basepath = basepath
81+
def __init__(self, basepath: str | Path):
82+
self.basepath = Path(basepath)
9183
self.out = {}
9284

93-
def getstream(self, t):
85+
def getstream(self, t: tuple[int, int, int]) -> RecordStreamWriter:
9486
if t not in self.out:
95-
path = os.path.join(self.basepath, "-".join(["{:2d}".format(v) for v in t]) + ".rec.gz")
87+
path = self.basepath.joinpath("-".join([f"{v:2d}" for v in t]) + ".rec.gz")
9688
f = gzip.GzipFile(path, "wb")
9789
rs = RecordStreamWriter(f)
9890
self.out[t] = rs
9991
return self.out[t]
10092

101-
def write(self, r):
93+
def write(self, r: Record) -> None:
10294
t = (r.ts.year, r.ts.month, r.ts.day)
10395
rs = self.getstream(t)
10496
rs.write(r)
10597
rs.fp.flush()
10698

107-
def close(self):
99+
def close(self) -> None:
108100
for rs in self.out.values():
109101
rs.close()

flow/record/adapter/__init__.py

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,53 @@
1+
from __future__ import annotations
2+
13
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # make this namespace extensible from other packages
24
import abc
5+
from typing import TYPE_CHECKING
36

7+
if TYPE_CHECKING:
8+
from collections.abc import Iterator
49

5-
def with_metaclass(meta, *bases):
6-
"""Create a base class with a metaclass. Python 2 and 3 compatible."""
7-
8-
# This requires a bit of explanation: the basic idea is to make a dummy
9-
# metaclass for one level of class instantiation that replaces itself with
10-
# the actual metaclass.
11-
class metaclass(type):
12-
def __new__(cls, name, this_bases, d):
13-
return meta(name, bases, d)
14-
15-
@classmethod
16-
def __prepare__(cls, name, this_bases):
17-
return meta.__prepare__(name, bases)
18-
19-
return type.__new__(metaclass, "temporary_class", (), {})
10+
from flow.record.base import Record
2011

2112

22-
class AbstractWriter(with_metaclass(abc.ABCMeta, object)):
13+
class AbstractWriter(metaclass=abc.ABCMeta):
2314
@abc.abstractmethod
24-
def write(self, rec):
15+
def write(self, rec: Record) -> None:
2516
"""Write a record."""
2617
raise NotImplementedError
2718

2819
@abc.abstractmethod
29-
def flush(self):
20+
def flush(self) -> None:
3021
"""Flush any buffered writes."""
3122
raise NotImplementedError
3223

3324
@abc.abstractmethod
34-
def close(self):
25+
def close(self) -> None:
3526
"""Close the Writer, no more writes will be possible."""
3627
raise NotImplementedError
3728

38-
def __del__(self):
29+
def __del__(self) -> None:
3930
self.close()
4031

41-
def __enter__(self):
32+
def __enter__(self) -> AbstractWriter: # noqa: PYI034
4233
return self
4334

44-
def __exit__(self, *args):
35+
def __exit__(self, *args) -> None:
4536
self.flush()
4637
self.close()
4738

4839

49-
class AbstractReader(with_metaclass(abc.ABCMeta, object)):
40+
class AbstractReader(metaclass=abc.ABCMeta):
5041
@abc.abstractmethod
51-
def __iter__(self):
42+
def __iter__(self) -> Iterator[Record]:
5243
"""Return a record iterator."""
5344
raise NotImplementedError
5445

55-
def close(self):
46+
def close(self) -> None: # noqa: B027
5647
"""Close the Reader, can be overriden to properly free resources."""
57-
pass
5848

59-
def __enter__(self):
49+
def __enter__(self) -> AbstractReader: # noqa: PYI034
6050
return self
6151

62-
def __exit__(self, *args):
52+
def __exit__(self, *args) -> None:
6353
self.close()

0 commit comments

Comments
 (0)