flow.record 3.18.dev1__tar.gz → 3.19.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 (84) hide show
  1. {flow_record-3.18.dev1/flow.record.egg-info → flow_record-3.19.dev1}/PKG-INFO +1 -1
  2. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/elastic.py +30 -13
  3. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/tools/rdump.py +6 -1
  4. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/version.py +2 -2
  5. {flow_record-3.18.dev1 → flow_record-3.19.dev1/flow.record.egg-info}/PKG-INFO +1 -1
  6. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/COPYRIGHT +0 -0
  7. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/LICENSE +0 -0
  8. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/MANIFEST.in +0 -0
  9. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/README.md +0 -0
  10. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/examples/filesystem.py +0 -0
  11. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/examples/passivedns.py +0 -0
  12. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/examples/records.json +0 -0
  13. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/examples/tcpconn.py +0 -0
  14. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/__init__.py +0 -0
  15. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/__init__.py +0 -0
  16. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/archive.py +0 -0
  17. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/avro.py +0 -0
  18. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/broker.py +0 -0
  19. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/csvfile.py +0 -0
  20. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/duckdb.py +0 -0
  21. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/jsonfile.py +0 -0
  22. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/line.py +0 -0
  23. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/mongo.py +0 -0
  24. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/split.py +0 -0
  25. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/splunk.py +0 -0
  26. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/sqlite.py +0 -0
  27. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/stream.py +0 -0
  28. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/text.py +0 -0
  29. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/adapter/xlsx.py +0 -0
  30. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/base.py +0 -0
  31. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/exceptions.py +0 -0
  32. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/__init__.py +0 -0
  33. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/credential.py +0 -0
  34. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/net/__init__.py +0 -0
  35. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/net/ip.py +0 -0
  36. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/net/ipv4.py +0 -0
  37. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/net/tcp.py +0 -0
  38. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/fieldtypes/net/udp.py +0 -0
  39. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/jsonpacker.py +0 -0
  40. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/packer.py +0 -0
  41. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/selector.py +0 -0
  42. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/stream.py +0 -0
  43. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/tools/__init__.py +0 -0
  44. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/tools/geoip.py +0 -0
  45. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/utils.py +0 -0
  46. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow/record/whitelist.py +0 -0
  47. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow.record.egg-info/SOURCES.txt +0 -0
  48. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow.record.egg-info/dependency_links.txt +0 -0
  49. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow.record.egg-info/entry_points.txt +0 -0
  50. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow.record.egg-info/requires.txt +0 -0
  51. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/flow.record.egg-info/top_level.txt +0 -0
  52. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/pyproject.toml +0 -0
  53. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/setup.cfg +0 -0
  54. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/__init__.py +0 -0
  55. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/_utils.py +0 -0
  56. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/docs/Makefile +0 -0
  57. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/docs/conf.py +0 -0
  58. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/docs/index.rst +0 -0
  59. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/selector_explain_example.py +0 -0
  60. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/standalone_test.py +0 -0
  61. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_adapter_line.py +0 -0
  62. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_adapter_text.py +0 -0
  63. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_avro.py +0 -0
  64. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_avro_adapter.py +0 -0
  65. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_compiled_selector.py +0 -0
  66. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_csv_adapter.py +0 -0
  67. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_deprecations.py +0 -0
  68. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_elastic_adapter.py +0 -0
  69. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_fieldtype_ip.py +0 -0
  70. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_fieldtypes.py +0 -0
  71. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_json_packer.py +0 -0
  72. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_json_record_adapter.py +0 -0
  73. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_multi_timestamp.py +0 -0
  74. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_packer.py +0 -0
  75. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_rdump.py +0 -0
  76. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_record.py +0 -0
  77. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_record_adapter.py +0 -0
  78. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_record_descriptor.py +0 -0
  79. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_regression.py +0 -0
  80. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_selector.py +0 -0
  81. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_splunk_adapter.py +0 -0
  82. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_sqlite_duckdb_adapter.py +0 -0
  83. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tests/test_xlsx_adapter.py +0 -0
  84. {flow_record-3.18.dev1 → flow_record-3.19.dev1}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flow.record
3
- Version: 3.18.dev1
3
+ Version: 3.19.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
@@ -1,8 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import hashlib
2
4
  import logging
3
5
  import queue
4
6
  import threading
5
- from typing import Iterator, Optional, Union
7
+ from typing import Iterator
6
8
 
7
9
  import elasticsearch
8
10
  import elasticsearch.helpers
@@ -37,10 +39,10 @@ class ElasticWriter(AbstractWriter):
37
39
  self,
38
40
  uri: str,
39
41
  index: str = "records",
40
- verify_certs: Union[str, bool] = True,
41
- http_compress: Union[str, bool] = True,
42
- hash_record: Union[str, bool] = False,
43
- api_key: Optional[str] = None,
42
+ verify_certs: str | bool = True,
43
+ http_compress: str | bool = True,
44
+ hash_record: str | bool = False,
45
+ api_key: str | None = None,
44
46
  **kwargs,
45
47
  ) -> None:
46
48
  self.index = index
@@ -52,6 +54,9 @@ class ElasticWriter(AbstractWriter):
52
54
  if not uri.lower().startswith(("http://", "https://")):
53
55
  uri = "http://" + uri
54
56
 
57
+ self.queue: queue.Queue[Record | StopIteration] = queue.Queue()
58
+ self.event = threading.Event()
59
+
55
60
  self.es = elasticsearch.Elasticsearch(
56
61
  uri,
57
62
  verify_certs=verify_certs,
@@ -60,10 +65,11 @@ class ElasticWriter(AbstractWriter):
60
65
  )
61
66
 
62
67
  self.json_packer = JsonRecordPacker()
63
- self.queue: queue.Queue[Union[Record, StopIteration]] = queue.Queue()
64
- self.event = threading.Event()
68
+
65
69
  self.thread = threading.Thread(target=self.streaming_bulk_thread)
66
70
  self.thread.start()
71
+ self.exception: Exception | None = None
72
+ threading.excepthook = self.excepthook
67
73
 
68
74
  if not verify_certs:
69
75
  # Disable InsecureRequestWarning of urllib3, caused by the verify_certs flag.
@@ -76,6 +82,12 @@ class ElasticWriter(AbstractWriter):
76
82
  if arg_key.startswith("_meta_"):
77
83
  self.metadata_fields[arg_key[6:]] = arg_val
78
84
 
85
+ def excepthook(self, exc: threading.ExceptHookArgs, *args, **kwargs) -> None:
86
+ log.error("Exception in thread: %s", exc)
87
+ self.exception = getattr(exc, "exc_value", exc)
88
+ self.event.set()
89
+ self.close()
90
+
79
91
  def record_to_document(self, record: Record, index: str) -> dict:
80
92
  """Convert a record to a Elasticsearch compatible document dictionary"""
81
93
  rdict = record._asdict()
@@ -120,6 +132,7 @@ class ElasticWriter(AbstractWriter):
120
132
 
121
133
  def streaming_bulk_thread(self) -> None:
122
134
  """Thread that streams the documents to ES via the bulk api"""
135
+
123
136
  for ok, item in elasticsearch.helpers.streaming_bulk(
124
137
  self.es,
125
138
  self.document_stream(),
@@ -138,21 +151,25 @@ class ElasticWriter(AbstractWriter):
138
151
  pass
139
152
 
140
153
  def close(self) -> None:
154
+ self.queue.put(StopIteration)
155
+ self.event.wait()
156
+
141
157
  if hasattr(self, "es"):
142
- self.queue.put(StopIteration)
143
- self.event.wait()
144
158
  self.es.close()
145
159
 
160
+ if self.exception:
161
+ raise self.exception
162
+
146
163
 
147
164
  class ElasticReader(AbstractReader):
148
165
  def __init__(
149
166
  self,
150
167
  uri: str,
151
168
  index: str = "records",
152
- verify_certs: Union[str, bool] = True,
153
- http_compress: Union[str, bool] = True,
154
- selector: Union[None, Selector, CompiledSelector] = None,
155
- api_key: Optional[str] = None,
169
+ verify_certs: str | bool = True,
170
+ http_compress: str | bool = True,
171
+ selector: None | Selector | CompiledSelector = None,
172
+ api_key: str | None = None,
156
173
  **kwargs,
157
174
  ) -> None:
158
175
  self.index = index
@@ -218,7 +218,9 @@ def main(argv=None):
218
218
  islice_stop = (args.count + args.skip) if args.count else None
219
219
  record_iterator = islice(record_stream(args.src, selector), args.skip, islice_stop)
220
220
  count = 0
221
- with RecordWriter(uri) as record_writer:
221
+
222
+ try:
223
+ record_writer = RecordWriter(uri)
222
224
  for count, rec in enumerate(record_iterator, start=1):
223
225
  if args.record_source is not None:
224
226
  rec._source = args.record_source
@@ -243,6 +245,9 @@ def main(argv=None):
243
245
  else:
244
246
  record_writer.write(rec)
245
247
 
248
+ finally:
249
+ record_writer.__exit__()
250
+
246
251
  if args.list:
247
252
  print("Processed {} records".format(count))
248
253
 
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.18.dev1'
16
- __version_tuple__ = version_tuple = (3, 18, 'dev1')
15
+ __version__ = version = '3.19.dev1'
16
+ __version_tuple__ = version_tuple = (3, 19, 'dev1')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flow.record
3
- Version: 3.18.dev1
3
+ Version: 3.19.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
File without changes
File without changes