karton-core 5.6.1__py3-none-any.whl → 5.8.0__py3-none-any.whl
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.
- karton/core/__version__.py +1 -1
- karton/core/asyncio/__init__.py +21 -0
- karton/core/asyncio/backend.py +370 -0
- karton/core/asyncio/base.py +133 -0
- karton/core/asyncio/karton.py +359 -0
- karton/core/asyncio/logger.py +57 -0
- karton/core/asyncio/resource.py +384 -0
- karton/core/backend.py +160 -114
- karton/core/base.py +123 -94
- karton/core/config.py +11 -8
- karton/core/karton.py +14 -12
- karton/core/logger.py +33 -15
- karton/core/resource.py +44 -30
- karton/core/task.py +24 -2
- karton/core/test.py +3 -2
- karton/system/system.py +22 -7
- {karton_core-5.6.1.dist-info → karton_core-5.8.0.dist-info}/METADATA +3 -2
- karton_core-5.8.0.dist-info/RECORD +33 -0
- karton_core-5.6.1.dist-info/RECORD +0 -27
- /karton_core-5.6.1-nspkg.pth → /karton_core-5.8.0-nspkg.pth +0 -0
- {karton_core-5.6.1.dist-info → karton_core-5.8.0.dist-info}/LICENSE +0 -0
- {karton_core-5.6.1.dist-info → karton_core-5.8.0.dist-info}/WHEEL +0 -0
- {karton_core-5.6.1.dist-info → karton_core-5.8.0.dist-info}/entry_points.txt +0 -0
- {karton_core-5.6.1.dist-info → karton_core-5.8.0.dist-info}/namespace_packages.txt +0 -0
- {karton_core-5.6.1.dist-info → karton_core-5.8.0.dist-info}/top_level.txt +0 -0
karton/core/config.py
CHANGED
@@ -111,12 +111,15 @@ class Config(object):
|
|
111
111
|
return True
|
112
112
|
|
113
113
|
@overload
|
114
|
-
def getint(self, section_name: str, option_name: str, fallback: int) -> int:
|
115
|
-
...
|
114
|
+
def getint(self, section_name: str, option_name: str, fallback: int) -> int: ...
|
116
115
|
|
117
116
|
@overload
|
118
|
-
def getint(self, section_name: str, option_name: str) -> Optional[int]:
|
119
|
-
|
117
|
+
def getint(self, section_name: str, option_name: str) -> Optional[int]: ...
|
118
|
+
|
119
|
+
@overload
|
120
|
+
def getint(
|
121
|
+
self, section_name: str, option_name: str, fallback: Optional[int]
|
122
|
+
) -> Optional[int]: ...
|
120
123
|
|
121
124
|
def getint(
|
122
125
|
self, section_name: str, option_name: str, fallback: Optional[int] = None
|
@@ -131,12 +134,12 @@ class Config(object):
|
|
131
134
|
return int(value)
|
132
135
|
|
133
136
|
@overload
|
134
|
-
def getboolean(
|
135
|
-
|
137
|
+
def getboolean(
|
138
|
+
self, section_name: str, option_name: str, fallback: bool
|
139
|
+
) -> bool: ...
|
136
140
|
|
137
141
|
@overload
|
138
|
-
def getboolean(self, section_name: str, option_name: str) -> Optional[bool]:
|
139
|
-
...
|
142
|
+
def getboolean(self, section_name: str, option_name: str) -> Optional[bool]: ...
|
140
143
|
|
141
144
|
def getboolean(
|
142
145
|
self, section_name: str, option_name: str, fallback: Optional[bool] = None
|
karton/core/karton.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
Base library for karton subsystems.
|
3
3
|
"""
|
4
|
+
|
4
5
|
import abc
|
5
6
|
import argparse
|
6
7
|
import sys
|
@@ -136,7 +137,7 @@ class Consumer(KartonServiceBase):
|
|
136
137
|
)
|
137
138
|
if self.task_timeout is None:
|
138
139
|
self.task_timeout = self.config.getint("karton", "task_timeout")
|
139
|
-
|
140
|
+
|
140
141
|
self._pre_hooks: List[Tuple[Optional[str], Callable[[Task], None]]] = []
|
141
142
|
self._post_hooks: List[
|
142
143
|
Tuple[
|
@@ -169,19 +170,18 @@ class Consumer(KartonServiceBase):
|
|
169
170
|
"""
|
170
171
|
|
171
172
|
self.current_task = task
|
172
|
-
self.log_handler.set_task(self.current_task)
|
173
173
|
|
174
|
-
if not
|
174
|
+
if not task.matches_filters(self.filters):
|
175
175
|
self.log.info("Task rejected because binds are no longer valid.")
|
176
|
-
self.backend.set_task_status(
|
176
|
+
self.backend.set_task_status(task, TaskState.FINISHED)
|
177
177
|
# Task rejected: end of processing
|
178
178
|
return
|
179
179
|
|
180
180
|
exception_str = None
|
181
181
|
|
182
182
|
try:
|
183
|
-
self.log.info("Received new task - %s",
|
184
|
-
self.backend.set_task_status(
|
183
|
+
self.log.info("Received new task - %s", task.uid)
|
184
|
+
self.backend.set_task_status(task, TaskState.STARTED)
|
185
185
|
|
186
186
|
self._run_pre_hooks()
|
187
187
|
|
@@ -189,22 +189,22 @@ class Consumer(KartonServiceBase):
|
|
189
189
|
try:
|
190
190
|
if self.task_timeout:
|
191
191
|
with timeout(self.task_timeout):
|
192
|
-
self.process(
|
192
|
+
self.process(task)
|
193
193
|
else:
|
194
|
-
self.process(
|
194
|
+
self.process(task)
|
195
195
|
except (Exception, TaskTimeoutError) as exc:
|
196
196
|
saved_exception = exc
|
197
197
|
raise
|
198
198
|
finally:
|
199
199
|
self._run_post_hooks(saved_exception)
|
200
200
|
|
201
|
-
self.log.info("Task done - %s",
|
201
|
+
self.log.info("Task done - %s", task.uid)
|
202
202
|
except (Exception, TaskTimeoutError):
|
203
203
|
exc_info = sys.exc_info()
|
204
204
|
exception_str = traceback.format_exception(*exc_info)
|
205
205
|
|
206
206
|
self.backend.increment_metrics(KartonMetrics.TASK_CRASHED, self.identity)
|
207
|
-
self.log.exception("Failed to process task - %s",
|
207
|
+
self.log.exception("Failed to process task - %s", task.uid)
|
208
208
|
finally:
|
209
209
|
self.backend.increment_metrics(KartonMetrics.TASK_CONSUMED, self.identity)
|
210
210
|
|
@@ -214,9 +214,10 @@ class Consumer(KartonServiceBase):
|
|
214
214
|
# if an exception was caught while processing
|
215
215
|
if exception_str is not None:
|
216
216
|
task_state = TaskState.CRASHED
|
217
|
-
|
217
|
+
task.error = exception_str
|
218
218
|
|
219
|
-
self.backend.set_task_status(
|
219
|
+
self.backend.set_task_status(task, task_state)
|
220
|
+
self.current_task = None
|
220
221
|
|
221
222
|
@property
|
222
223
|
def _bind(self) -> KartonBind:
|
@@ -227,6 +228,7 @@ class Consumer(KartonServiceBase):
|
|
227
228
|
filters=self.filters,
|
228
229
|
persistent=self.persistent,
|
229
230
|
service_version=self.__class__.version,
|
231
|
+
is_async=False,
|
230
232
|
)
|
231
233
|
|
232
234
|
@classmethod
|
karton/core/logger.py
CHANGED
@@ -2,30 +2,32 @@ import logging
|
|
2
2
|
import platform
|
3
3
|
import traceback
|
4
4
|
import warnings
|
5
|
-
from typing import
|
5
|
+
from typing import Any, Callable, Dict
|
6
6
|
|
7
7
|
from .backend import KartonBackend
|
8
|
-
from .task import
|
8
|
+
from .task import get_current_task
|
9
9
|
|
10
10
|
HOSTNAME = platform.node()
|
11
11
|
|
12
12
|
|
13
|
-
class
|
13
|
+
class TaskContextFilter(logging.Filter):
|
14
14
|
"""
|
15
|
-
|
15
|
+
This is a filter which injects information about current task ID to the log.
|
16
16
|
"""
|
17
17
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
19
|
+
current_task = get_current_task()
|
20
|
+
if current_task is not None:
|
21
|
+
record.task_id = current_task.task_uid
|
22
|
+
else:
|
23
|
+
record.task_id = "(no task)"
|
24
|
+
return True
|
24
25
|
|
25
|
-
def set_task(self, task: Task) -> None:
|
26
|
-
self.task = task
|
27
26
|
|
28
|
-
|
27
|
+
class LogLineFormatterMixin:
|
28
|
+
format: Callable[[logging.LogRecord], str]
|
29
|
+
|
30
|
+
def prepare_log_line(self, record: logging.LogRecord) -> Dict[str, Any]:
|
29
31
|
ignore_fields = [
|
30
32
|
"args",
|
31
33
|
"asctime",
|
@@ -54,11 +56,27 @@ class KartonLogHandler(logging.Handler):
|
|
54
56
|
log_line["type"] = "log"
|
55
57
|
log_line["message"] = self.format(record)
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
+
current_task = get_current_task()
|
60
|
+
if current_task is not None:
|
61
|
+
log_line["task"] = current_task.serialize()
|
59
62
|
|
60
63
|
log_line["hostname"] = HOSTNAME
|
64
|
+
return log_line
|
65
|
+
|
66
|
+
|
67
|
+
class KartonLogHandler(logging.Handler, LogLineFormatterMixin):
|
68
|
+
"""
|
69
|
+
logging.Handler that passes logs to the Karton backend.
|
70
|
+
"""
|
71
|
+
|
72
|
+
def __init__(self, backend: KartonBackend, channel: str) -> None:
|
73
|
+
logging.Handler.__init__(self)
|
74
|
+
self.backend = backend
|
75
|
+
self.is_consumer_active: bool = True
|
76
|
+
self.channel: str = channel
|
61
77
|
|
78
|
+
def emit(self, record: logging.LogRecord) -> None:
|
79
|
+
log_line = self.prepare_log_line(record)
|
62
80
|
log_consumed = self.backend.produce_log(
|
63
81
|
log_line, logger_name=self.channel, level=record.levelname
|
64
82
|
)
|
karton/core/resource.py
CHANGED
@@ -39,6 +39,7 @@ class ResourceBase(object):
|
|
39
39
|
bucket: Optional[str] = None,
|
40
40
|
metadata: Optional[Dict[str, Any]] = None,
|
41
41
|
sha256: Optional[str] = None,
|
42
|
+
fd: Optional[IO[bytes]] = None,
|
42
43
|
_uid: Optional[str] = None,
|
43
44
|
_size: Optional[int] = None,
|
44
45
|
_flags: Optional[List[str]] = None,
|
@@ -66,6 +67,16 @@ class ResourceBase(object):
|
|
66
67
|
for byte_block in iter(lambda: f.read(4096), b""):
|
67
68
|
sha256_hash.update(byte_block)
|
68
69
|
sha256 = sha256_hash.hexdigest()
|
70
|
+
elif fd is not None:
|
71
|
+
if calculate_hash:
|
72
|
+
# we need to calculate the whole hash and return pos as it was
|
73
|
+
sha256_hash = hashlib.sha256()
|
74
|
+
last_position = fd.tell()
|
75
|
+
fd.seek(0)
|
76
|
+
for byte_block in iter(lambda: fd.read(4096), b""):
|
77
|
+
sha256_hash.update(byte_block)
|
78
|
+
sha256 = sha256_hash.hexdigest()
|
79
|
+
fd.seek(last_position)
|
69
80
|
elif content:
|
70
81
|
if isinstance(content, str):
|
71
82
|
self._content = content.encode()
|
@@ -139,34 +150,7 @@ class ResourceBase(object):
|
|
139
150
|
}
|
140
151
|
|
141
152
|
|
142
|
-
class
|
143
|
-
"""
|
144
|
-
Represents local resource with arbitrary binary data e.g. file contents.
|
145
|
-
|
146
|
-
Local resources will be uploaded to object hub (S3) during
|
147
|
-
task dispatching.
|
148
|
-
|
149
|
-
.. code-block:: python
|
150
|
-
|
151
|
-
# Creating resource from bytes
|
152
|
-
sample = Resource("original_name.exe", content=b"X5O!P%@AP[4\\
|
153
|
-
PZX54(P^)7CC)7}$EICAR-STANDARD-ANT...")
|
154
|
-
|
155
|
-
# Creating resource from path
|
156
|
-
sample = Resource("original_name.exe", path="sample/original_name.exe")
|
157
|
-
|
158
|
-
:param name: Name of the resource (e.g. name of file)
|
159
|
-
:param content: Resource content
|
160
|
-
:param path: Path of file with resource content
|
161
|
-
:param bucket: Alternative S3 bucket for resource
|
162
|
-
:param metadata: Resource metadata
|
163
|
-
:param uid: Alternative S3 resource id
|
164
|
-
:param sha256: Resource sha256 hash
|
165
|
-
:param fd: Seekable file descriptor
|
166
|
-
:param _flags: Resource flags
|
167
|
-
:param _close_fd: Close file descriptor after upload (default: False)
|
168
|
-
"""
|
169
|
-
|
153
|
+
class LocalResourceBase(ResourceBase):
|
170
154
|
def __init__(
|
171
155
|
self,
|
172
156
|
name: str,
|
@@ -183,13 +167,14 @@ class LocalResource(ResourceBase):
|
|
183
167
|
if len(list(filter(None, [path, content, fd]))) != 1:
|
184
168
|
raise ValueError("You must exclusively provide a path, content or fd")
|
185
169
|
|
186
|
-
super(
|
170
|
+
super().__init__(
|
187
171
|
name,
|
188
172
|
content=content,
|
189
173
|
path=path,
|
190
174
|
bucket=bucket,
|
191
175
|
metadata=metadata,
|
192
176
|
sha256=sha256,
|
177
|
+
fd=fd,
|
193
178
|
_uid=uid,
|
194
179
|
_flags=_flags,
|
195
180
|
)
|
@@ -235,7 +220,7 @@ class LocalResource(ResourceBase):
|
|
235
220
|
bucket: Optional[str] = None,
|
236
221
|
metadata: Optional[Dict[str, Any]] = None,
|
237
222
|
uid: Optional[str] = None,
|
238
|
-
) -> "
|
223
|
+
) -> "LocalResourceBase":
|
239
224
|
"""
|
240
225
|
Resource extension, allowing to pass whole directory as a zipped resource.
|
241
226
|
|
@@ -293,6 +278,35 @@ class LocalResource(ResourceBase):
|
|
293
278
|
_close_fd=True,
|
294
279
|
)
|
295
280
|
|
281
|
+
|
282
|
+
class LocalResource(LocalResourceBase):
|
283
|
+
"""
|
284
|
+
Represents local resource with arbitrary binary data e.g. file contents.
|
285
|
+
|
286
|
+
Local resources will be uploaded to object hub (S3) during
|
287
|
+
task dispatching.
|
288
|
+
|
289
|
+
.. code-block:: python
|
290
|
+
|
291
|
+
# Creating resource from bytes
|
292
|
+
sample = Resource("original_name.exe", content=b"X5O!P%@AP[4\\
|
293
|
+
PZX54(P^)7CC)7}$EICAR-STANDARD-ANT...")
|
294
|
+
|
295
|
+
# Creating resource from path
|
296
|
+
sample = Resource("original_name.exe", path="sample/original_name.exe")
|
297
|
+
|
298
|
+
:param name: Name of the resource (e.g. name of file)
|
299
|
+
:param content: Resource content
|
300
|
+
:param path: Path of file with resource content
|
301
|
+
:param bucket: Alternative S3 bucket for resource
|
302
|
+
:param metadata: Resource metadata
|
303
|
+
:param uid: Alternative S3 resource id
|
304
|
+
:param sha256: Resource sha256 hash
|
305
|
+
:param fd: Seekable file descriptor
|
306
|
+
:param _flags: Resource flags
|
307
|
+
:param _close_fd: Close file descriptor after upload (default: False)
|
308
|
+
"""
|
309
|
+
|
296
310
|
def _upload(self, backend: "KartonBackend") -> None:
|
297
311
|
"""Internal function for uploading resources
|
298
312
|
|
karton/core/task.py
CHANGED
@@ -3,6 +3,7 @@ import json
|
|
3
3
|
import time
|
4
4
|
import uuid
|
5
5
|
import warnings
|
6
|
+
from contextvars import ContextVar
|
6
7
|
from typing import (
|
7
8
|
TYPE_CHECKING,
|
8
9
|
Any,
|
@@ -24,6 +25,16 @@ if TYPE_CHECKING:
|
|
24
25
|
|
25
26
|
import orjson
|
26
27
|
|
28
|
+
current_task: ContextVar[Optional["Task"]] = ContextVar("current_task")
|
29
|
+
|
30
|
+
|
31
|
+
def get_current_task() -> Optional["Task"]:
|
32
|
+
return current_task.get(None)
|
33
|
+
|
34
|
+
|
35
|
+
def set_current_task(task: Optional["Task"]):
|
36
|
+
current_task.set(task)
|
37
|
+
|
27
38
|
|
28
39
|
class TaskState(enum.Enum):
|
29
40
|
DECLARED = "Declared" # Task declared in TASKS_QUEUE
|
@@ -375,12 +386,15 @@ class Task(object):
|
|
375
386
|
data: Union[str, bytes],
|
376
387
|
backend: Optional["KartonBackend"] = None,
|
377
388
|
parse_resources: bool = True,
|
389
|
+
resource_unserializer: Optional[Callable[[Dict], Any]] = None,
|
378
390
|
) -> "Task":
|
379
391
|
"""
|
380
392
|
Unserialize Task instance from JSON string
|
381
393
|
|
382
394
|
:param data: JSON-serialized task
|
383
|
-
:param backend:
|
395
|
+
:param backend: |
|
396
|
+
Backend instance to be bound to RemoteResource objects.
|
397
|
+
Deprecated: pass resource_unserializer instead.
|
384
398
|
:param parse_resources: |
|
385
399
|
If set to False (default is True), method doesn't
|
386
400
|
deserialize '__karton_resource__' entries, which speeds up deserialization
|
@@ -388,6 +402,9 @@ class Task(object):
|
|
388
402
|
filtering based on status.
|
389
403
|
When resource deserialization is turned off, Task.unserialize will try
|
390
404
|
to use faster 3rd-party JSON parser (orjson).
|
405
|
+
:param resource_unserializer: |
|
406
|
+
Resource factory used for deserialization of __karton_resource__
|
407
|
+
dictionary values.
|
391
408
|
:return: Unserialized Task object
|
392
409
|
|
393
410
|
:meta private:
|
@@ -399,7 +416,12 @@ class Task(object):
|
|
399
416
|
RemoteResource object instances
|
400
417
|
"""
|
401
418
|
if isinstance(value, dict) and "__karton_resource__" in value:
|
402
|
-
|
419
|
+
if resource_unserializer is None:
|
420
|
+
return RemoteResource.from_dict(
|
421
|
+
value["__karton_resource__"], backend
|
422
|
+
)
|
423
|
+
else:
|
424
|
+
return resource_unserializer(value["__karton_resource__"])
|
403
425
|
return value
|
404
426
|
|
405
427
|
if not isinstance(data, str):
|
karton/core/test.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
"""
|
2
2
|
Test stubs for karton subsystem unit tests
|
3
3
|
"""
|
4
|
+
|
4
5
|
import hashlib
|
5
6
|
import logging
|
6
7
|
import unittest
|
7
8
|
from collections import defaultdict
|
8
|
-
from typing import Any, BinaryIO, Dict, List, Union, cast
|
9
|
+
from typing import Any, BinaryIO, Dict, List, Optional, Union, cast
|
9
10
|
from unittest import mock
|
10
11
|
|
11
12
|
from .backend import KartonBackend, KartonMetrics
|
@@ -66,7 +67,7 @@ class BackendMock:
|
|
66
67
|
bucket: str,
|
67
68
|
object_uid: str,
|
68
69
|
content: Union[bytes, BinaryIO],
|
69
|
-
length: int = None,
|
70
|
+
length: Optional[int] = None,
|
70
71
|
) -> None:
|
71
72
|
log.debug("Uploading object %s to bucket %s", object_uid, bucket)
|
72
73
|
if isinstance(content, bytes):
|
karton/system/system.py
CHANGED
@@ -31,6 +31,7 @@ class SystemService(KartonServiceBase):
|
|
31
31
|
TASK_DISPATCHED_TIMEOUT = 24 * 3600
|
32
32
|
TASK_STARTED_TIMEOUT = 24 * 3600
|
33
33
|
TASK_CRASHED_TIMEOUT = 3 * 24 * 3600
|
34
|
+
TASK_TRACKING_TTL = 30 * 24 * 3600
|
34
35
|
|
35
36
|
def __init__(self, config: Optional[Config]) -> None:
|
36
37
|
super().__init__(config=config)
|
@@ -52,6 +53,12 @@ class SystemService(KartonServiceBase):
|
|
52
53
|
self.enable_null_version_deletion = self.config.getboolean(
|
53
54
|
"system", "enable_null_version_deletion", False
|
54
55
|
)
|
56
|
+
self.enable_task_tracking = self.config.getboolean(
|
57
|
+
"system", "enable_task_tracking", True
|
58
|
+
)
|
59
|
+
self.task_tracking_ttl = self.config.getint(
|
60
|
+
"system", "task_tracking_ttl", self.TASK_TRACKING_TTL
|
61
|
+
)
|
55
62
|
|
56
63
|
self.last_gc_trigger = time.time()
|
57
64
|
|
@@ -65,6 +72,8 @@ class SystemService(KartonServiceBase):
|
|
65
72
|
" enable_gc:\t%s\n"
|
66
73
|
" enable_router:\t%s\n"
|
67
74
|
" enable_null_version_deletion:\t%s\n"
|
75
|
+
" enable_task_tracking:\t%s\n"
|
76
|
+
" task_tracking_ttl:\t%s\n"
|
68
77
|
" crash_started_tasks_on_timeout:\t%s",
|
69
78
|
self.gc_interval,
|
70
79
|
self.task_dispatched_timeout,
|
@@ -73,6 +82,8 @@ class SystemService(KartonServiceBase):
|
|
73
82
|
self.enable_gc,
|
74
83
|
self.enable_router,
|
75
84
|
self.enable_null_version_deletion,
|
85
|
+
self.enable_task_tracking,
|
86
|
+
self.task_tracking_ttl,
|
76
87
|
self.crash_started_tasks_on_timeout,
|
77
88
|
)
|
78
89
|
|
@@ -227,10 +238,13 @@ class SystemService(KartonServiceBase):
|
|
227
238
|
def route_task(self, task: Task, binds: List[KartonBind]) -> None:
|
228
239
|
# Performs routing of task
|
229
240
|
self.log.info("[%s] Processing task %s", task.root_uid, task.task_uid)
|
230
|
-
# store the producer-task relationship in redis for task tracking
|
231
|
-
self.
|
232
|
-
|
233
|
-
|
241
|
+
# if enabled, store the producer-task relationship in redis for task tracking
|
242
|
+
if self.enable_task_tracking:
|
243
|
+
self.backend.log_identity_output(
|
244
|
+
task.headers.get("origin", "unknown"),
|
245
|
+
task.headers,
|
246
|
+
self.task_tracking_ttl,
|
247
|
+
)
|
234
248
|
|
235
249
|
pipe = self.backend.make_pipeline()
|
236
250
|
for bind in binds:
|
@@ -285,9 +299,10 @@ class SystemService(KartonServiceBase):
|
|
285
299
|
operation_bodies.append(operation_body)
|
286
300
|
|
287
301
|
self.backend.register_tasks(tasks)
|
288
|
-
self.
|
289
|
-
|
290
|
-
|
302
|
+
if self.enable_publish_log:
|
303
|
+
self.backend.produce_logs(
|
304
|
+
operation_bodies, logger_name=KARTON_OPERATIONS_QUEUE, level="INFO"
|
305
|
+
)
|
291
306
|
|
292
307
|
def process_routing(self) -> None:
|
293
308
|
# Order does matter! task dispatching must be before
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: karton-core
|
3
|
-
Version: 5.
|
3
|
+
Version: 5.8.0
|
4
4
|
Summary: Distributed malware analysis orchestration framework
|
5
5
|
Home-page: https://github.com/CERT-Polska/karton
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
@@ -9,7 +9,8 @@ Classifier: License :: OSI Approved :: BSD License
|
|
9
9
|
Requires-Python: >=3.8
|
10
10
|
Description-Content-Type: text/markdown
|
11
11
|
License-File: LICENSE
|
12
|
-
Requires-Dist:
|
12
|
+
Requires-Dist: aioboto3 ==14.3.0
|
13
|
+
Requires-Dist: boto3 <1.37.4,>=1.37.2
|
13
14
|
Requires-Dist: orjson
|
14
15
|
Requires-Dist: redis
|
15
16
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
karton_core-5.8.0-nspkg.pth,sha256=vHa-jm6pBTeInFrmnsHMg9AOeD88czzQy-6QCFbpRcM,539
|
2
|
+
karton/core/__init__.py,sha256=QuT0BWZyp799eY90tK3H1OD2hwuusqMJq8vQwpB3kG4,337
|
3
|
+
karton/core/__version__.py,sha256=duDTiv1rL8Ee9_jtzzhpq-j4xkkpVPkUh2Daa_Ou-xA,22
|
4
|
+
karton/core/backend.py,sha256=3tmjAM35jaoZr_5QqarcVH81LvKMEB63vyvMKCYXPCM,39934
|
5
|
+
karton/core/base.py,sha256=6PEQiEWHjMtJKRj0dfgEEpNhgSRoKOBYF1WBlrmyBp0,9064
|
6
|
+
karton/core/config.py,sha256=UTd0hLqYNUttfI7FYUDOJPaz-C3uj1Kw7xxataTG_OM,8234
|
7
|
+
karton/core/exceptions.py,sha256=8i9WVzi4PinNlX10Cb-lQQC35Hl-JB5R_UKXa9AUKoQ,153
|
8
|
+
karton/core/inspect.py,sha256=aIJQEOEkD5q2xLlV8nhxY5qL5zqcnprP-2DdP6ecKlE,6150
|
9
|
+
karton/core/karton.py,sha256=4CISOmUTfaEaCJUtbYxJSBMzydT27o3a-R14VBNpmr0,15269
|
10
|
+
karton/core/logger.py,sha256=UhYCoVARXaatvoJ2lO2mfBHeODOS7z8O-vqdeQhNmV4,2654
|
11
|
+
karton/core/main.py,sha256=ir1-dhn3vbwfh2YHiM6ZYfRBbjwLvJSz0d8tuK1mb_4,8310
|
12
|
+
karton/core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
karton/core/query.py,sha256=sf24DweVlXfJuBbBD_ns2LXhOV-IBwuPG3jBfTJu77s,12063
|
14
|
+
karton/core/resource.py,sha256=GkU3JGSP1kOsAoblon4BWbQp31eZiDsCjaaDKanEokk,20872
|
15
|
+
karton/core/task.py,sha256=QvAsSUIsyYiRmkgxgugrYkHWH2gczrFDfw2V4izdt1E,19566
|
16
|
+
karton/core/test.py,sha256=cj6W4gNt0BpRjsYiiBt0hPE8dmRfUeIc8sSVkxB50cU,9123
|
17
|
+
karton/core/utils.py,sha256=sEVqGdVPyYswWuVn8wYXBQmln8Az826N_2HgC__pmW8,4090
|
18
|
+
karton/core/asyncio/__init__.py,sha256=ZgndeKzS3Yg2o8hebwFYJWlCRdW3ImdCOShK4EVmZ14,457
|
19
|
+
karton/core/asyncio/backend.py,sha256=GF0z9YxWvUKYkvnBatCDthX0M9Kwt9cRfVSWQq5bc9E,12751
|
20
|
+
karton/core/asyncio/base.py,sha256=YDNGyWzgVvt2TnfKvHYbJbcNJaQl95bdBq45YGEo-3Q,4246
|
21
|
+
karton/core/asyncio/karton.py,sha256=LhzMGuJsmXdTEa323gZted8KgVfHH6l0j0_tTqMh4Z4,12932
|
22
|
+
karton/core/asyncio/logger.py,sha256=BjkbuAeWylTmFjWv8-ckmOGf4nL2Tma96W0nIOc2vwk,1752
|
23
|
+
karton/core/asyncio/resource.py,sha256=86AYm7JeVjEYRNw--h02HIS9xFvgddhktmDUp0qvTO4,12517
|
24
|
+
karton/system/__init__.py,sha256=JF51OqRU_Y4c0unOulvmv1KzSHSq4ZpXU8ZsH4nefRM,63
|
25
|
+
karton/system/__main__.py,sha256=QJkwIlSwaPRdzwKlNmCAL41HtDAa73db9MZKWmOfxGM,56
|
26
|
+
karton/system/system.py,sha256=d_5hhLTthJdr_4gZEGQ6Y-kHvxeBqyQxjjx_wRs3xMA,17285
|
27
|
+
karton_core-5.8.0.dist-info/LICENSE,sha256=o8h7hYhn7BJC_-DmrfqWwLjaR_Gbe0TZOOQJuN2ca3I,1519
|
28
|
+
karton_core-5.8.0.dist-info/METADATA,sha256=26n1VrX-0ESRMG7fug5hqKxYT1URIa_NgypF5N1E2gg,6860
|
29
|
+
karton_core-5.8.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
30
|
+
karton_core-5.8.0.dist-info/entry_points.txt,sha256=OgLlsXy61GP6-Yob3oXqeJ2hlRU6LBLj33fr0NufKz0,98
|
31
|
+
karton_core-5.8.0.dist-info/namespace_packages.txt,sha256=X8SslCPsqXDCnGZqrYYolzT3xPzJMq1r-ZQSc0jfAEA,7
|
32
|
+
karton_core-5.8.0.dist-info/top_level.txt,sha256=X8SslCPsqXDCnGZqrYYolzT3xPzJMq1r-ZQSc0jfAEA,7
|
33
|
+
karton_core-5.8.0.dist-info/RECORD,,
|
@@ -1,27 +0,0 @@
|
|
1
|
-
karton_core-5.6.1-nspkg.pth,sha256=vHa-jm6pBTeInFrmnsHMg9AOeD88czzQy-6QCFbpRcM,539
|
2
|
-
karton/core/__init__.py,sha256=QuT0BWZyp799eY90tK3H1OD2hwuusqMJq8vQwpB3kG4,337
|
3
|
-
karton/core/__version__.py,sha256=-q9tSF5ofTJum4PMjvbhaE1xmTXehc_9rxMGcmfodcw,22
|
4
|
-
karton/core/backend.py,sha256=g0BSQBsFAksRd_VY5QDjBJ8yIIyzAmwxy-kfJgAZ_lo,38628
|
5
|
-
karton/core/base.py,sha256=C6Lco3E0XCsxvEjeVOLR9fxh_IWJ1vjC9BqUYsQyewE,8083
|
6
|
-
karton/core/config.py,sha256=7oKchitq6pWzPuXRfjBXqVT_BgGIz2p-CDo1RGaNJQg,8118
|
7
|
-
karton/core/exceptions.py,sha256=8i9WVzi4PinNlX10Cb-lQQC35Hl-JB5R_UKXa9AUKoQ,153
|
8
|
-
karton/core/inspect.py,sha256=aIJQEOEkD5q2xLlV8nhxY5qL5zqcnprP-2DdP6ecKlE,6150
|
9
|
-
karton/core/karton.py,sha256=Fi3wNqMGiKvHN2BECsqsvfxkiyuwPdlC21jpqQdkeak,15434
|
10
|
-
karton/core/logger.py,sha256=J3XAyG88U0cwYC9zR6E3QD1uJenrQh7zS9-HgxhqeAs,2040
|
11
|
-
karton/core/main.py,sha256=ir1-dhn3vbwfh2YHiM6ZYfRBbjwLvJSz0d8tuK1mb_4,8310
|
12
|
-
karton/core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
karton/core/query.py,sha256=sf24DweVlXfJuBbBD_ns2LXhOV-IBwuPG3jBfTJu77s,12063
|
14
|
-
karton/core/resource.py,sha256=tA3y_38H9HVKIrCeAU70zHUkQUv0BuCQWMC470JLxxc,20321
|
15
|
-
karton/core/task.py,sha256=gW1szMi5PN2Y06X-Ryo7cmEVluZv1r7W5tvmwIJiD94,18808
|
16
|
-
karton/core/test.py,sha256=tms-YM7sUKQDHN0vm2_W7DIvHnO_ld_VPsWHnsbKSfk,9102
|
17
|
-
karton/core/utils.py,sha256=sEVqGdVPyYswWuVn8wYXBQmln8Az826N_2HgC__pmW8,4090
|
18
|
-
karton/system/__init__.py,sha256=JF51OqRU_Y4c0unOulvmv1KzSHSq4ZpXU8ZsH4nefRM,63
|
19
|
-
karton/system/__main__.py,sha256=QJkwIlSwaPRdzwKlNmCAL41HtDAa73db9MZKWmOfxGM,56
|
20
|
-
karton/system/system.py,sha256=cFE4hCS0LWnwdCiIjU0ym8dHujE5ORi4REJR_y5b2gA,16671
|
21
|
-
karton_core-5.6.1.dist-info/LICENSE,sha256=o8h7hYhn7BJC_-DmrfqWwLjaR_Gbe0TZOOQJuN2ca3I,1519
|
22
|
-
karton_core-5.6.1.dist-info/METADATA,sha256=AJoa9O_0SOYI3IuVHXhwB6lXoUSs7S4nU6QM8_xHxVI,6818
|
23
|
-
karton_core-5.6.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
24
|
-
karton_core-5.6.1.dist-info/entry_points.txt,sha256=OgLlsXy61GP6-Yob3oXqeJ2hlRU6LBLj33fr0NufKz0,98
|
25
|
-
karton_core-5.6.1.dist-info/namespace_packages.txt,sha256=X8SslCPsqXDCnGZqrYYolzT3xPzJMq1r-ZQSc0jfAEA,7
|
26
|
-
karton_core-5.6.1.dist-info/top_level.txt,sha256=X8SslCPsqXDCnGZqrYYolzT3xPzJMq1r-ZQSc0jfAEA,7
|
27
|
-
karton_core-5.6.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|