python-corekit 0.2.0__py3-none-any.whl → 0.3.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.
Files changed (84) hide show
  1. corekit/api/application.py +47 -9
  2. corekit/api/lifespan.py +26 -3
  3. corekit/concurrency/__init__.py +2 -2
  4. corekit/concurrency/decorators.py +32 -5
  5. corekit/concurrency/thread_local.py +2 -2
  6. corekit/concurrency/worker.py +9 -0
  7. corekit/config/loader.py +42 -5
  8. corekit/config/settings.py +11 -1
  9. corekit/connections/__init__.py +7 -1
  10. corekit/connections/connectable.py +45 -4
  11. corekit/connections/redis/connection.py +53 -10
  12. corekit/connections/sql/__init__.py +2 -1
  13. corekit/connections/sql/connection.py +39 -5
  14. corekit/connections/sql/fields/__init__.py +2 -2
  15. corekit/connections/sql/fields/jsonb.py +13 -6
  16. corekit/connections/sql/migration/__init__.py +4 -0
  17. corekit/connections/sql/migration/operations.py +69 -2
  18. corekit/connections/sql/operations/base.py +11 -2
  19. corekit/connections/sql/operations/statements.py +25 -5
  20. corekit/connections/sql/table.py +7 -29
  21. corekit/crypto/__init__.py +3 -1
  22. corekit/crypto/constants.py +2 -2
  23. corekit/crypto/hasher.py +9 -4
  24. corekit/data/dataset.py +8 -2
  25. corekit/data/expressions/__init__.py +3 -3
  26. corekit/data/expressions/comparison.py +19 -80
  27. corekit/data/expressions/expression.py +0 -32
  28. corekit/data/expressions/operator.py +13 -28
  29. corekit/data/stats.py +3 -0
  30. corekit/decorators/exception_handling.py +36 -8
  31. corekit/docker/watchdog.py +50 -31
  32. corekit/etl/__init__.py +2 -1
  33. corekit/etl/connection.py +14 -12
  34. corekit/etl/extract/extractor.py +6 -13
  35. corekit/etl/orchestrator.py +19 -2
  36. corekit/etl/schemas.py +2 -2
  37. corekit/etl/transform/transformer.py +4 -1
  38. corekit/events/publisher.py +1 -1
  39. corekit/events/reader.py +26 -21
  40. corekit/events/sse.py +4 -1
  41. corekit/events/websocket.py +24 -11
  42. corekit/exceptions/__init__.py +24 -9
  43. corekit/exceptions/base.py +139 -10
  44. corekit/exceptions/enum.py +17 -0
  45. corekit/exceptions/types.py +6 -6
  46. corekit/files/__init__.py +2 -4
  47. corekit/files/base.py +15 -2
  48. corekit/files/enum.py +0 -5
  49. corekit/files/json.py +16 -2
  50. corekit/http/__init__.py +43 -5
  51. corekit/http/api.py +24 -0
  52. corekit/http/client.py +100 -73
  53. corekit/http/exceptions.py +140 -0
  54. corekit/http/response.py +50 -1
  55. corekit/http/status.py +89 -0
  56. corekit/jobs/runner.py +12 -1
  57. corekit/jobs/task.py +23 -2
  58. corekit/log_monitor/models.py +8 -2
  59. corekit/log_monitor/service.py +77 -38
  60. corekit/notifications/base.py +18 -10
  61. corekit/observability/__init__.py +9 -2
  62. corekit/observability/benchmarkable.py +23 -5
  63. corekit/observability/loggable.py +21 -0
  64. corekit/observability/request_context.py +55 -2
  65. corekit/observability/timing/timer.py +4 -2
  66. corekit/registry/__init__.py +2 -2
  67. corekit/registry/registry.py +55 -14
  68. corekit/schemas/enum.py +22 -1
  69. corekit/schemas/types.py +6 -1
  70. corekit/serialization/__init__.py +2 -0
  71. corekit/serialization/pickle_file.py +61 -0
  72. corekit/serialization/serializable.py +22 -2
  73. corekit/serialization/serializer.py +9 -2
  74. corekit/utils/collections.py +22 -13
  75. corekit/utils/payload.py +12 -0
  76. {python_corekit-0.2.0.dist-info → python_corekit-0.3.0.dist-info}/METADATA +7 -7
  77. python_corekit-0.3.0.dist-info/RECORD +145 -0
  78. corekit/constants.py +0 -45
  79. corekit/exceptions/http/exceptions.py +0 -37
  80. corekit/files/pickle.py +0 -12
  81. python_corekit-0.2.0.dist-info/RECORD +0 -143
  82. {python_corekit-0.2.0.dist-info → python_corekit-0.3.0.dist-info}/WHEEL +0 -0
  83. {python_corekit-0.2.0.dist-info → python_corekit-0.3.0.dist-info}/licenses/LICENSE +0 -0
  84. {python_corekit-0.2.0.dist-info → python_corekit-0.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,61 @@
1
+ """
2
+ Reading and writing signed pickle files.
3
+
4
+ Pickle executes code on load. ``PickleFileManager`` therefore requires a key
5
+ and stores authenticated payloads via ``Serializer``, never bare ``pickle.dumps``.
6
+ Partial reads and line streaming are refused: a pickle document is not
7
+ line-oriented and a fragment is not a valid payload.
8
+
9
+ Lives under ``serialization`` rather than ``files`` so ``corekit.config`` can
10
+ import ``TomlFileManager`` without forming a files ↔ serialization cycle.
11
+ """
12
+
13
+ from typing import Any, Iterator
14
+
15
+ from corekit.files.base import FileContent, FileError, FileManager
16
+ from corekit.files.enum import FileMode
17
+ from corekit.serialization.enum import SerializerEngine
18
+ from corekit.serialization.serializer import Serializer
19
+
20
+ __all__ = ["PickleFileManager"]
21
+
22
+
23
+ class PickleFileManager(FileManager):
24
+ """
25
+ A FileManager that round-trips values through a signed pickle ``Serializer``.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ file_path: str,
31
+ mode: FileMode | None = None,
32
+ *,
33
+ key: bytes | str,
34
+ binary: bool = True,
35
+ ) -> None:
36
+ if not binary:
37
+ raise FileError("PickleFileManager requires binary mode; pickle payloads are bytes.")
38
+ super().__init__(file_path, mode=mode or FileMode.get_default(binary=True), binary=True)
39
+ self._serializer = Serializer(SerializerEngine.PICKLE, key=key)
40
+
41
+ def _serialize(self, content: Any) -> FileContent:
42
+ return self._serializer.serialize(content)
43
+
44
+ def _deserialize(self, content: FileContent) -> Any:
45
+ if isinstance(content, str):
46
+ content = content.encode("utf-8")
47
+ return self._serializer.deserialize(content)
48
+
49
+ def read(self, size: int = -1) -> Any:
50
+ """
51
+ Read and verify the whole file. Partial reads are refused.
52
+ """
53
+ if size != -1:
54
+ raise FileError("PickleFileManager refuses partial reads; read the whole file with size=-1.")
55
+ return super().read(size)
56
+
57
+ def readline(self) -> Any:
58
+ raise FileError("PickleFileManager cannot readline; pickle payloads are not line-oriented.")
59
+
60
+ def stream(self) -> Iterator[Any]:
61
+ raise FileError("PickleFileManager cannot stream; pickle payloads are not line-oriented.")
@@ -15,11 +15,28 @@ class Serializable:
15
15
 
16
16
  Serializing an arbitrary object needs pickle or dill, both of which execute
17
17
  code on load, so a key is required -- see ``Serializer``.
18
+
19
+ The HMAC key on ``_serializer`` is never written into the payload. Signing
20
+ authenticates provenance; it is not encryption.
18
21
  """
19
22
 
20
23
  def __init__(self, **kwargs: Any) -> None:
21
24
  self._serializer = Serializer(**kwargs)
22
25
 
26
+ def __getstate__(self) -> dict[str, Any]:
27
+ """
28
+ Drop ``_serializer`` so a pickle/dill payload cannot carry the HMAC key.
29
+ """
30
+ state = self.__dict__.copy()
31
+ state.pop("_serializer", None)
32
+ return state
33
+
34
+ def __setstate__(self, state: dict[str, Any]) -> None:
35
+ """
36
+ Restore instance state. The serializer is reattached by ``from_serialized``.
37
+ """
38
+ self.__dict__.update(state)
39
+
23
40
  @classmethod
24
41
  def from_serialized(cls, serialized: bytes, **kwargs: Any) -> Any:
25
42
  """
@@ -28,11 +45,14 @@ class Serializable:
28
45
  The engine and key are supplied by the caller rather than read from the
29
46
  payload, so the receiver decides how the bytes are decoded.
30
47
  """
31
- return Serializer(**kwargs).deserialize(serialized)
48
+ obj = Serializer(**kwargs).deserialize(serialized)
49
+ if isinstance(obj, Serializable):
50
+ obj._serializer = Serializer(**kwargs)
51
+ return obj
32
52
 
33
53
  def serialize(self) -> bytes:
34
54
  """
35
- Encode this object.
55
+ Encode this object without embedding the HMAC key.
36
56
  """
37
57
  if not self._serializer.is_valid_for_class():
38
58
  raise TypeError(
@@ -24,6 +24,7 @@ from typing import Any
24
24
  import dill
25
25
 
26
26
  from corekit.config import get_settings
27
+ from corekit.exceptions import InternalCoreException, Retryability
27
28
  from corekit.serialization.enum import SerializerEngine
28
29
 
29
30
  __all__ = ["Serializer", "SignatureError", "UnsafeEngineError"]
@@ -42,17 +43,23 @@ _ENGINE_MODULES = {
42
43
  }
43
44
 
44
45
 
45
- class SignatureError(Exception):
46
+ class SignatureError(InternalCoreException):
46
47
  """
47
48
  Raised when a payload's signature is missing or does not verify.
48
49
  """
49
50
 
51
+ def __init__(self, message: str, *, error: str | None = None) -> None:
52
+ super().__init__(message, retryable=Retryability.NON_RETRYABLE, error=error)
50
53
 
51
- class UnsafeEngineError(Exception):
54
+
55
+ class UnsafeEngineError(InternalCoreException):
52
56
  """
53
57
  Raised when a code-executing engine is requested without a key.
54
58
  """
55
59
 
60
+ def __init__(self, message: str, *, error: str | None = None) -> None:
61
+ super().__init__(message, retryable=Retryability.NON_RETRYABLE, error=error)
62
+
56
63
 
57
64
  class Serializer:
58
65
  """
@@ -56,18 +56,24 @@ class keygetter:
56
56
  def call(self, data: dict[str, Any]) -> Any | MultiMatch:
57
57
  """
58
58
  Apply the predicate, returning the match, a ``MultiMatch``, or ``UNSET``.
59
+
60
+ The keymap is replaced on every call. The same instance can be a step
61
+ more than once in one path; keeping the previous matches would make
62
+ the second step see keys from the first.
59
63
  """
64
+ matches = MultiMatch()
60
65
  for key, value in data.items():
61
66
  if self.func(key):
62
- self._keymap[key] = value
67
+ matches[key] = value
68
+ self._keymap = matches
63
69
 
64
- if not self._keymap:
70
+ if not matches:
65
71
  return UNSET
66
72
 
67
- if len(self._keymap) == 1:
68
- return next(iter(self._keymap.values()))
73
+ if len(matches) == 1:
74
+ return next(iter(matches.values()))
69
75
 
70
- return self._keymap
76
+ return matches
71
77
 
72
78
 
73
79
  def repeated_get(
@@ -91,10 +97,14 @@ def repeated_get(
91
97
 
92
98
  def _get_item(current: Any, key: str | keygetter) -> Any | MultiMatch:
93
99
  if current is UNSET or not isinstance(current, dict):
94
- return fallback
100
+ return UNSET
95
101
 
96
102
  if isinstance(key, keygetter):
97
- return key.func(current)
103
+ return key.call(current)
104
+ if callable(key):
105
+ # A bare predicate is the same step as a keygetter. A reused
106
+ # instance still goes through call(), which owns the keymap.
107
+ return keygetter(key).call(current)
98
108
 
99
109
  return current.get(key, UNSET)
100
110
 
@@ -103,12 +113,11 @@ def repeated_get(
103
113
  for key in keys:
104
114
  if isinstance(result, MultiMatch):
105
115
  collected = MultiMatch()
106
- for _parent_key, branch in result.items():
107
- if not isinstance(branch, dict):
108
- continue
109
- for child_key, child_value in branch.items():
110
- collected[child_key] = _get_item(child_value, key)
111
- result = deepcopy(collected)
116
+ for parent_key, branch in result.items():
117
+ child = _get_item(branch, key)
118
+ if child is not UNSET:
119
+ collected[parent_key] = child
120
+ result = collected if collected else UNSET
112
121
  else:
113
122
  result = _get_item(result, key)
114
123
 
corekit/utils/payload.py CHANGED
@@ -13,10 +13,14 @@ so a value that cannot cross fails at the call site where the offending
13
13
  argument is still visible.
14
14
  """
15
15
 
16
+ import base64
16
17
  import json
17
18
  from datetime import date, datetime
19
+ from decimal import Decimal
18
20
  from enum import Enum
21
+ from pathlib import Path
19
22
  from typing import Any, NamedTuple
23
+ from uuid import UUID
20
24
 
21
25
  __all__ = ["Payload", "decode_payload", "encode_payload"]
22
26
 
@@ -65,6 +69,14 @@ def _encode_extra(value: Any) -> Any:
65
69
  return value.value
66
70
  if isinstance(value, (datetime, date)):
67
71
  return value.isoformat()
72
+ if isinstance(value, UUID):
73
+ return str(value)
74
+ if isinstance(value, Path):
75
+ return str(value)
76
+ if isinstance(value, Decimal):
77
+ return str(value)
78
+ if isinstance(value, bytes):
79
+ return base64.b64encode(value).decode("ascii")
68
80
  raise TypeError(f"Object of type {type(value).__name__} is not JSON serializable")
69
81
 
70
82
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-corekit
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Shared foundations for Python projects: logging, benchmarking, registries, FastAPI application and routers, SQL statements and migrations, background tasks, and ETL
5
5
  Author: Steven Jacobsen
6
6
  License-Expression: MIT
@@ -55,7 +55,7 @@ extras to remember, and no import that fails because something was left out.
55
55
  Pin a compatible release rather than tracking whatever is newest:
56
56
 
57
57
  ```
58
- python-corekit~=0.2.0
58
+ python-corekit~=0.3.0
59
59
  ```
60
60
 
61
61
  Before 1.0, the minor version carries breaking changes.
@@ -284,7 +284,7 @@ instead, which loses results silently and so is opt-in.
284
284
  ## HTTP clients
285
285
 
286
286
  ```python
287
- from corekit.http.client import BaseApiClient
287
+ from corekit.http import BaseApiClient
288
288
 
289
289
  class GithubClient(BaseApiClient):
290
290
  """
@@ -301,7 +301,8 @@ response.data["login"]
301
301
 
302
302
  Retries 429 and 5xx with exponential backoff. Every response is a
303
303
  `BaseApiResponse`, so a non-JSON error page leaves `data` empty rather than
304
- raising. `async_get`, `async_post` and friends do the same without blocking.
304
+ raising. The same methods are awaitable inside a running event loop:
305
+ `await client.get(...)`.
305
306
 
306
307
  ## Serialization
307
308
 
@@ -351,7 +352,7 @@ Settings are grouped by concern, so `get_settings().concurrency.max_threads`
351
352
  says where a value belongs. Environment variables use a double underscore for
352
353
  the section: `COREKIT_CONCURRENCY__MAX_THREADS=16`.
353
354
 
354
- Environment variables use a `COREKIT_` prefix (`COREKIT_CRYPTO_SALT`). Empty
355
+ Environment variables use a `COREKIT_` prefix (`COREKIT_CRYPTO__SALT`). Empty
355
356
  values are treated as unset, because container runtimes routinely pass `FOO=`
356
357
  for a variable that was never set.
357
358
 
@@ -375,7 +376,6 @@ Imports go downward only.
375
376
  ```
376
377
  corekit/
377
378
  config/ settings, sources, loader
378
- constants.py
379
379
 
380
380
  exceptions/ error types
381
381
 
@@ -390,7 +390,7 @@ corekit/
390
390
  connections/ the Connectable lifecycle and @connect
391
391
  sql/ SQLConnection, statements, migrations
392
392
  redis/ RedisConnection
393
- http/ BaseApiClient, retries, responses
393
+ http/ BaseHttpClient, BaseApiClient, retries, responses
394
394
 
395
395
  api/ Application, lifespan, middleware, routers
396
396
  docker/ notifications/ etl/
@@ -0,0 +1,145 @@
1
+ corekit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ corekit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ corekit/api/__init__.py,sha256=44gtrMRkllhAQdwpfIKrkMuSl3qg61xRxgaTDldzmjg,688
4
+ corekit/api/application.py,sha256=CDdJRHSbXFR6XLufg0idzNm_FFnsYl_0w8B5ArIN-KQ,12001
5
+ corekit/api/handler.py,sha256=vYrao8_B5e6MZGI7GLm1Mr-e8NH8rYt8TNAcnoEuzRQ,2659
6
+ corekit/api/lifespan.py,sha256=OLkiaDfQlhOz3p-gmDXywZgOsO6T-txNjhzeIN44NDk,8848
7
+ corekit/api/middleware.py,sha256=6M5VPjRZTTPEfX5Hm7DHLoDwwWWAgmvWNiTuSykUA98,3168
8
+ corekit/api/responses.py,sha256=bvADoj7snxqCKHIWFiU5rH8Mg5dmvi-ldxVLJbtVEQs,1258
9
+ corekit/api/routers.py,sha256=j2DSkYTTIGd5qFEzYFlY5YM0qhdvhjUu8iFxWc9KM6o,7910
10
+ corekit/concurrency/__init__.py,sha256=ovt0x-VqJhit2ygp0Y7j9gSc67xoQ6mJvQ8fNEF-HHY,348
11
+ corekit/concurrency/decorators.py,sha256=vYnRb2xPTvmX-vmpLk7OL5H6uUYMtvX-pYc3KBV0VDw,3580
12
+ corekit/concurrency/thread_local.py,sha256=8KA0JzX6kV1qjbRv5JZ8X2us8I0tdjS0TAvE-znh77E,3188
13
+ corekit/concurrency/worker.py,sha256=V6wVrcYMTnSWUVTchP7F_ieReQTi6QP9tZDKUspaKSg,2280
14
+ corekit/config/__init__.py,sha256=dw2Y2HvpHw1MXwLSVxdARGPYse9j6IteVN3q70c3Kic,1227
15
+ corekit/config/loader.py,sha256=qjmOEJjO27U2vIgYBfsatNbZB73MkHJHZKbIKY03d2Q,6704
16
+ corekit/config/settings.py,sha256=cmDNMPHkfdHGNmKlxPjFTWzO9fl3pKu7vCMFLP5QHSc,5283
17
+ corekit/config/sources.py,sha256=kdeji29XnEOaDGRctiwEfp7bKuA2jBYGbvAdVEs21KE,3923
18
+ corekit/connections/__init__.py,sha256=LipBfhpCyOG0JiQXqclIB1rUHJ18GMj_9ggpSykH-do,1167
19
+ corekit/connections/connectable.py,sha256=WbNmfGUM9DYmD2daVKqAii_Vx4fs0CUCDDZsd1GOikg,8099
20
+ corekit/connections/decorators.py,sha256=7xfmLuMr3kkceEkkxHxY_Pen2OakJEVukXtiOYAd-6Q,3606
21
+ corekit/connections/registry.py,sha256=BR04dGthcGCtON2MxNsl-TlhRgbRlvGj0RLymDFBkGQ,3119
22
+ corekit/connections/redis/__init__.py,sha256=BsWLZNqpKAqIoreHGLEtftnMqVw-ESK8jbexDAughag,174
23
+ corekit/connections/redis/connection.py,sha256=H6r5WsDfXFgIQlp6vq3rKjp-oBFQoE5h_YaJXZEvHIs,9850
24
+ corekit/connections/sql/__init__.py,sha256=WRBcQ9draDQSooYi4k4peWyuRTgSyEk_WwOYYOAN9K4,882
25
+ corekit/connections/sql/connection.py,sha256=PvLhYXMmq6JneshWhoUb2WD2usGH7uOA9H_ZufybKgQ,12318
26
+ corekit/connections/sql/query.py,sha256=8s5atIssmN2l9FCL2IHnIQqwxOk0fA_mPNh36koLhoE,233
27
+ corekit/connections/sql/table.py,sha256=C7_QCRPd7C1JeH7aIByUBVWsx5qiEOFavWOo6c72djM,3125
28
+ corekit/connections/sql/fields/__init__.py,sha256=2I-TCsvi321yQhesKNZgY1T77FtATZ6o7pw0MNHtbAo,184
29
+ corekit/connections/sql/fields/jsonb.py,sha256=wGjtCP6v3i2bX73X-VVqBNuDNr0-MeWIosc6nvWyO9Q,2313
30
+ corekit/connections/sql/migration/__init__.py,sha256=NBQyKdz84y6Y_QJVTJQVfHz0WrY1CXNoeko113GUoTg,1652
31
+ corekit/connections/sql/migration/base.py,sha256=b-3ISuCRgt_HuLl4lWNPq2QiNC2_3fiNrd1dEgDd7pE,1344
32
+ corekit/connections/sql/migration/operations.py,sha256=UIO0TPJceo0vtGsNQiATn7i7sEnseyli4TttLsSMpUw,15394
33
+ corekit/connections/sql/migration/registry.py,sha256=M1iS7v7aKYfgyf_grvF-6Ogn4KfQ1EEWbA1MO02CiB0,6728
34
+ corekit/connections/sql/migration/table.py,sha256=CpOkJl-4rcG2hTZYq-Yt7OvGTpVhVJ42IrubVO3BUvs,666
35
+ corekit/connections/sql/operations/__init__.py,sha256=f6fnAbD3k8ALXwcwJ31fIHQwkvud_WqmUod_apTErpY,480
36
+ corekit/connections/sql/operations/base.py,sha256=PQSiEz79qd_bp29K7mOh4-qQA-_Wk_r4QfL4oo3hGPY,3286
37
+ corekit/connections/sql/operations/statements.py,sha256=AuJyMM-a3Kiqky_jxi2lH40a6rCeHOaesRPKJuIOGrY,4888
38
+ corekit/crypto/__init__.py,sha256=Qf_FCUoG_jb7Q9tnN4ctX8I6xyaeaJwk74ag_bSchAQ,87
39
+ corekit/crypto/constants.py,sha256=m-uq7_EJ4XfUTSZxFv6h429UkKSrGTj3o_9DfRFGyvU,298
40
+ corekit/crypto/enum.py,sha256=0csj06cATCYDPY_QTNy66j_hB16WCqcHg8tJOO0lMNU,212
41
+ corekit/crypto/hasher.py,sha256=KkxBM8pwaFwdUV31D-LO7Pg8bFULI5Y8rtUDTWti08w,3184
42
+ corekit/data/__init__.py,sha256=COGfw3-OBRp6KKWBSixid5vfaeasFVY5X4Wza0mB_kY,1977
43
+ corekit/data/dataset.py,sha256=TK1yAs7bNCQpV7Z16YqCzYf2Q_Vpu2IbEs1sqMMbikM,12835
44
+ corekit/data/record.py,sha256=EczoOvcxl-lHO1M92AjUh_5E9UQJ2qwBsiu6Yo-34gs,5233
45
+ corekit/data/stats.py,sha256=cRnLGgUHEz66GS1Rs7c_wr2ZVvIJ8WbKq4ifBKR_t0U,4950
46
+ corekit/data/expressions/__init__.py,sha256=_uOPah6QnbnT_W3DROD399b-TtjYQhsmnooD1pr62rE,1301
47
+ corekit/data/expressions/comparison.py,sha256=teLuLEpZ-oohAaE9Oom6tdUSWGTGMDpTxJdWPKv6_7I,9374
48
+ corekit/data/expressions/expression.py,sha256=J8EVyzRjh3VZvqiJyryjHZJfp5c2KwwENVYhZo8S2aw,2126
49
+ corekit/data/expressions/operator.py,sha256=o_QFyiM9v9Ms83k2p2c6fhL3F05TIJ-gplhTk_t1LJk,893
50
+ corekit/data/expressions/target.py,sha256=QSl7sH1qFVUc-mL7gsasTsCahWKhHqdo0bMHt--t2m8,470
51
+ corekit/decorators/__init__.py,sha256=YrBcc_4wkSs7nEb3OjC7C7a8fNEvBk3RzOpD8QccHKM,83
52
+ corekit/decorators/exception_handling.py,sha256=p86gfvdmsmC7_va042NSoGkWrJrbLLuw0ncE131wLWU,2326
53
+ corekit/decorators/warnings.py,sha256=RS7AS6OS05VxiWaMjkj6kYky9FbpT4Z-Cb7TQoPOObk,1109
54
+ corekit/docker/__init__.py,sha256=LtrmEvqorme1-YwL0jGNFLEASdgn69s0eYuh490anmg,104
55
+ corekit/docker/watchdog.py,sha256=kAOF9x-h_oQmyKrkcc4eQ1_HIofRDyYyrfeAULyyBtQ,8855
56
+ corekit/etl/__init__.py,sha256=KFuGv6xstJbEJHHYo_X5akEq_b7muDyKXCGdFeZ3_0M,1369
57
+ corekit/etl/connection.py,sha256=_gWqR36x5f7qb5IYJjrc_7d_6oU2CXm1QeSNCCh0coo,1270
58
+ corekit/etl/orchestrator.py,sha256=GkecTu8gKt17ePDM9PJBUuZTPYoPMdK1yYzBHjMdw3A,7959
59
+ corekit/etl/schemas.py,sha256=3z0qZBintCO45BcxT6TY0Boi_ibrRa0z85wBJvLXNd4,385
60
+ corekit/etl/extract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ corekit/etl/extract/extractor.py,sha256=D_MmEVGUimPlFmNR1CIFOKii8d6y0XIr3MdXo8M0FU4,1434
62
+ corekit/etl/extract/schemas.py,sha256=Hqse-GUwaCuN7eAW7Cacuj4k7Vy1dEu-NagruabiYWU,386
63
+ corekit/etl/load/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
+ corekit/etl/load/loader.py,sha256=Oh8UZq1gRXFaO1a0poDxMNtdcnIayPsh06XuBQM9KjI,1579
65
+ corekit/etl/load/schemas.py,sha256=c4hZrbjgN_zFKMBhDeNwaPARTiJdgnVFSIW8Lah4c3U,860
66
+ corekit/etl/transform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ corekit/etl/transform/schemas.py,sha256=_Kr8DAXQKZH6nIqYjXVpaeeA0shAsk1vjWOcEcAXly8,319
68
+ corekit/etl/transform/transformer.py,sha256=foNmqhFq1dwWKfMN7hN9l8gMQaV1GBjhDcqu9MEkrY8,1040
69
+ corekit/events/__init__.py,sha256=BrNQKcLnSs5zT1vjDJZ4UX_CD0g87dA5resmzKs0nQQ,1065
70
+ corekit/events/enum.py,sha256=K7ziTjKDjZEZlDO8whjDph8X-bTT_ze2guTrYDGozYc,1342
71
+ corekit/events/frames.py,sha256=ICuF9EKWQ1NqcSfkL0JFHvMB6zrikzkwoujP-292Q8k,1480
72
+ corekit/events/models.py,sha256=faE-Z2qwggOaSBrzte-mBWXuomrzWMIl0gOEkjvPqLo,470
73
+ corekit/events/publisher.py,sha256=70lHyEIEg0eXUWJ9k9eUNVBBmckm4rYBgvTZgRfbcl8,2598
74
+ corekit/events/reader.py,sha256=HoJs6zb9N3VDD-nJV2fpks7ny2OI8UaAKQMBaXcK7_k,4994
75
+ corekit/events/sse.py,sha256=lhF4KUQ_XrdExGLWbKYJghti2t6ExNzXYoA6dOZi9mA,4090
76
+ corekit/events/websocket.py,sha256=S6CUh9duI5xHVrKqbHpss8FrnKKqnFHBFJpSkmgInN4,3858
77
+ corekit/exceptions/__init__.py,sha256=8q9EX-0bzOiJI1FOzCbViQFwx53Ugs8NH482Cvpci6k,995
78
+ corekit/exceptions/base.py,sha256=k0AfTfPrLWR6x-l2qvvjqD_sup0fiWhqu1OoNaNM-Lk,5596
79
+ corekit/exceptions/enum.py,sha256=D-YL-cZXs-F2jS1GgRBhPWmuqBfX33B1QP61vAXdAes,324
80
+ corekit/exceptions/types.py,sha256=rxhQ8sghV2TCHh_vB7tX6Yb6Vkyv1PF_0PLtalyFVxY,665
81
+ corekit/exceptions/custom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
+ corekit/exceptions/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
+ corekit/files/__init__.py,sha256=IllQEAWtcT72vVUdRaMwfF5VlhzMJ16VIKDhqvWG9Cw,612
84
+ corekit/files/base.py,sha256=Ca2bhdlwntHh425PedaUG-UW2fEFZsPCss_3f7REsAE,4022
85
+ corekit/files/enum.py,sha256=mcrQXcp-AizTAp4VoaVMLj9zu5D81XXMsnZwZqe6fz0,597
86
+ corekit/files/json.py,sha256=pRYLKNjeVmkDQsgtjBboFFY5Ljx1Pwa3MFEeQBc4o-g,909
87
+ corekit/files/toml.py,sha256=YFRwghMapbCRSl7srqcI7IhqaTQDyO56XRasGMu_Aug,1273
88
+ corekit/http/__init__.py,sha256=cOZum0wNWuVGDB4PfX2OpWq01BurhV2dir3V0AcStfQ,1508
89
+ corekit/http/api.py,sha256=L4iZ9TdCQH3klKWxIxFE3bEQzqMTDOwy-HKrvHXwsbI,784
90
+ corekit/http/client.py,sha256=O7DSDQaiz1_NvBtT00LWsDqICEEIWGrUWKwgYA84AgQ,6603
91
+ corekit/http/exceptions.py,sha256=etkKN6rgnhENctO7YNvaRAKsctK0PXKCxAe15l6mNwY,4252
92
+ corekit/http/exponential_backoff.py,sha256=5jjGTspX_BC9aBKPr5Y5dNhJqXesmljsjJoQ6i2d4_I,3180
93
+ corekit/http/response.py,sha256=rOcUEgPYxfmKXfGO5fQsMA8q4YJof8dNNGBf-nb7l8k,2375
94
+ corekit/http/status.py,sha256=rZ-cdliG9EAvWMTzvxjqjipRkZRc6RgSzcBY4Kewdg0,2377
95
+ corekit/jobs/__init__.py,sha256=vsv8o23ApT6MlOwOq-AFYeQW2NT1kjyvu89A5CL2PsY,880
96
+ corekit/jobs/registry.py,sha256=cco6884eVuIYHEtSv6P62MICFjX-QhuSZIFkEJcQi_M,2557
97
+ corekit/jobs/runner.py,sha256=KRzUIaeXVqLFekoIi2C5cnZ8F-5V5Oy_91xOPHjhjmY,2650
98
+ corekit/jobs/task.py,sha256=tqr-QaQSHyfPjbyZscM5i-YgT-fl58cpd2FVxevtG_E,6112
99
+ corekit/log_monitor/__init__.py,sha256=uuXTQdI8EMeFbdt69G-2K8dKh5Nt-h9SzBEsOGcu0lo,371
100
+ corekit/log_monitor/constants.py,sha256=8nzIzU3Qit9h7_stZLWW1Q_0DTnYglw_j5bQUsF586g,230
101
+ corekit/log_monitor/models.py,sha256=EiXVzPMdupbVOHoSFbagAyNhtdBf5jx_LlJqgQpoKqI,4999
102
+ corekit/log_monitor/service.py,sha256=xGIaNYDfs8DZrJoKMMb5ZsUbdcmbHvn5OXvhFyZJl10,18606
103
+ corekit/notifications/__init__.py,sha256=dLSyNnW7pOCgUNFsHRqTNzMRGYTItpwTWR3-wL7WxAI,255
104
+ corekit/notifications/base.py,sha256=cAgENDk6EEeQNzaDPAitm9OybkC0i8gFjcrDh8TfCtg,1889
105
+ corekit/notifications/models.py,sha256=cCAxNFCYCgzSclkUWHQL9O-uWdE058KUUaMewY5PL6M,646
106
+ corekit/observability/__init__.py,sha256=DTUg9SQvUDRSG_3qOVaTXEk0jlqZzWXXMQdP8CH2Lzs,968
107
+ corekit/observability/benchmarkable.py,sha256=VBO70x-UeBareVIBXRZRQX3TqAHhVYCjZWNyX19kcdo,993
108
+ corekit/observability/loggable.py,sha256=VajvdhPB09QERyq585yItHMYTngvW-DWBv1sxkySlbc,1769
109
+ corekit/observability/request_context.py,sha256=X2WDmp2fV-PJVILkWU2S0WksxW0BYD2nG4mDhEjPYNM,6698
110
+ corekit/observability/timing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
+ corekit/observability/timing/constants.py,sha256=Cv6h98NHzJiTJJufVQBVMBpdI0_fNMTnxAZF0j0vrsg,22
112
+ corekit/observability/timing/split.py,sha256=qoITQnLLKfXe6NdCRvpL4ch8C9f_9G6a-P4bSQFYGYw,528
113
+ corekit/observability/timing/timer.py,sha256=IPHCkoIWK-eBRlEOJSx92AU1YxbgLiww3_EKyFgONGY,1080
114
+ corekit/registry/__init__.py,sha256=R67Jssr06Eyx2u5AbX1omm2LziWvwS_Sd7fExnNv9CM,681
115
+ corekit/registry/ordered.py,sha256=_KS4mWzmLgFvODW2M0_ugxZIBW_dKhwwxrVrtNqLMfs,2506
116
+ corekit/registry/registry.py,sha256=t1iwzxgvd-iyLIf_5wahg_P7eN9V1oumpupkAqi2GdQ,5601
117
+ corekit/schemas/__init__.py,sha256=lpGVfqzXLpxpdP5ijS9uye_XfF1yNgjJ0Rt4m2EkwPE,298
118
+ corekit/schemas/enum.py,sha256=gLc44kIXRfpDFkV51JoN4KT1CU92hnb529rd1b88fBM,2033
119
+ corekit/schemas/types.py,sha256=AWIxZHXUiUjJRZjmOhAdCq3RIsRzL-Fy7RvYy4i5Ozo,1347
120
+ corekit/schemas/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
+ corekit/schemas/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
+ corekit/schemas/models/arbitrary.py,sha256=L2Uqxo_twPAmzoly3Lyo5rzYhDzReSB_U-oAuRgWubg,396
123
+ corekit/schemas/models/date_models.py,sha256=UOlSLVsWqgr_jnHfxVRgSl4nVVdfbe6zPBYveOgRcIg,399
124
+ corekit/schemas/pydantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
+ corekit/schemas/pydantic/fields.py,sha256=ScP2ZQCR2qTWaqwjKl7lGvkTGSIeQBJ0yeNs79E47AA,1175
126
+ corekit/serialization/__init__.py,sha256=RuS_bQmN1gz2-wg9HcyM03d_CU9MZO0QliIcnZGEq8I,830
127
+ corekit/serialization/enum.py,sha256=pzHuAIXeonEF7-jyN1uYddJk-xvmQGuymDf1U6RWR5w,566
128
+ corekit/serialization/pickle_file.py,sha256=dudKIxR8ueT3wx_IBxHJeoqnFeP1rT7dlTb_PXlSkd8,2251
129
+ corekit/serialization/serializable.py,sha256=viF3ZCKRJ90hk6m4lbqIfo6ifsY2c4sXr4xZrn1Yz-Q,1999
130
+ corekit/serialization/serializer.py,sha256=XlGE1Rq8M55Jl2a4F5MkvDcba2VI7lrh0v9kwL0DWG8,6617
131
+ corekit/utils/__init__.py,sha256=n3feLbH1WrGqWZACyg-hChxkTrqfADFlFkxm5ie2JGo,1769
132
+ corekit/utils/coercion.py,sha256=Aq63jrxQYg1ooWUFXHff2uepB_LoHm1izao8_3xkzEU,3650
133
+ corekit/utils/collections.py,sha256=Kxjlw4ybNo3ClaJQamsZ1ZGRc_KpU2v1HXnR2me2zl8,4013
134
+ corekit/utils/ids.py,sha256=BVniaYqewM-EosDxcJAT_S_7T9C1c5X8nsaVGs5up34,1731
135
+ corekit/utils/payload.py,sha256=T7EgdVU0S5h8MAzvQsmkfRPMatWqUbxjHL9hmZdM9ho,3882
136
+ corekit/utils/raise_exc.py,sha256=cz7ljc6ZW90AGQussKuANN8PLsDLUhl-E8FZ0Ipsw-0,175
137
+ corekit/utils/text.py,sha256=54maLM4jsS8cjVXRQCNVFzVszGimuzgaNzudhZzZeio,1694
138
+ corekit/utils/time.py,sha256=-iPaETXcgDu7J39Kwe938JyZKhPVjl6a572BBqsqcDQ,2215
139
+ corekit/utils/validators.py,sha256=_HVKo3y264KGNaZ-1RyM1x46VPvu7XKcQkrHWDC9uxs,340
140
+ corekit/utils/void.py,sha256=eXDb2QynuguiSgHGJLdgE08MuRnxBdYebRdMD7s1m9o,178
141
+ python_corekit-0.3.0.dist-info/licenses/LICENSE,sha256=357LYxbxAQZ95q5cV-8JK6j-KNgiE6AteRodjEsm-kE,1072
142
+ python_corekit-0.3.0.dist-info/METADATA,sha256=59HC-Dee9ORoSCa6YSxqd41jf4euLDkF9d6sE2ZzZZk,13167
143
+ python_corekit-0.3.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
144
+ python_corekit-0.3.0.dist-info/top_level.txt,sha256=SDK4o8BoaI47E9tPbiNCbbWoc2y6N_wCjwnIEfr-GWI,8
145
+ python_corekit-0.3.0.dist-info/RECORD,,
corekit/constants.py DELETED
@@ -1,45 +0,0 @@
1
- # Minutes
2
- ONE_MINUTE = 60
3
- TWO_MINUTES = ONE_MINUTE * 2
4
- THREE_MINUTES = ONE_MINUTE * 3
5
- FIVE_MINUTES = ONE_MINUTE * 5
6
- TEN_MINUTES = ONE_MINUTE * 10
7
- FIFTEEN_MINUTES = ONE_MINUTE * 15
8
- THIRTY_MINUTES = ONE_MINUTE * 30
9
- FORTY_FIVE_MINUTES = ONE_MINUTE * 45
10
-
11
- # Hours
12
- ONE_HOUR = ONE_MINUTE * 60
13
- TWO_HOURS = ONE_HOUR * 2
14
- THREE_HOURS = ONE_HOUR * 3
15
- FIVE_HOURS = ONE_HOUR * 5
16
- SIX_HOURS = ONE_HOUR * 6
17
- NINE_HOURS = ONE_HOUR * 9
18
- TWELVE_HOURS = ONE_HOUR * 12
19
- FIFTEEN_HOURS = ONE_HOUR * 15
20
- EIGHTEEN_HOURS = ONE_HOUR * 18
21
-
22
- # Days
23
- ONE_DAY = ONE_HOUR * 24
24
- TWO_DAYS = ONE_DAY * 2
25
- THREE_DAYS = ONE_DAY * 3
26
- FOUR_DAYS = ONE_DAY * 4
27
- FIVE_DAYS = ONE_DAY * 5
28
- SIX_DAYS = ONE_DAY * 6
29
- TEN_DAYS = ONE_DAY * 10
30
- FIFTEEN_DAYS = ONE_DAY * 15
31
- THIRTY_DAYS = ONE_DAY * 30
32
- FORTY_FIVE_DAYS = ONE_DAY * 45
33
- SIXTY_FIVE_DAYS = ONE_DAY * 60
34
- NINETY_FIVE_DAYS = ONE_DAY * 90
35
- ONE_HUNDRED_TWENTY_DAYS = ONE_DAY * 120
36
- ONE_HUNDRED_EIGHTY_DAYS = ONE_DAY * 180
37
-
38
- # Weeks
39
- ONE_WEEK = ONE_DAY * 7
40
- TWO_WEEKS = ONE_WEEK * 2
41
- THREE_WEEKS = ONE_WEEK * 3
42
- FOUR_WEEKS = ONE_WEEK * 4
43
-
44
- # Years
45
- ONE_YEAR = ONE_DAY * 365
@@ -1,37 +0,0 @@
1
- from typing import Any
2
-
3
- from fastapi import status
4
-
5
- from corekit.exceptions.base import CustomHTTPException
6
-
7
-
8
- # 400 Errors
9
- class UnauthorizedException(CustomHTTPException):
10
- def __init__(self, **kwargs: Any) -> None:
11
- super().__init__(status_code=status.HTTP_401_UNAUTHORIZED, **kwargs)
12
-
13
-
14
- class ForbiddenException(CustomHTTPException):
15
- def __init__(self, **kwargs: Any) -> None:
16
- super().__init__(status_code=status.HTTP_403_FORBIDDEN, **kwargs)
17
-
18
-
19
- class NotFoundException(CustomHTTPException):
20
- def __init__(self, **kwargs: Any) -> None:
21
- super().__init__(status_code=status.HTTP_404_NOT_FOUND, **kwargs)
22
-
23
-
24
- class ConflictErrorException(CustomHTTPException):
25
- def __init__(self, **kwargs: Any) -> None:
26
- super().__init__(status_code=status.HTTP_409_CONFLICT, **kwargs)
27
-
28
-
29
- class UnprocessableEntityException(CustomHTTPException):
30
- def __init__(self, **kwargs: Any) -> None:
31
- super().__init__(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, **kwargs)
32
-
33
-
34
- # 500 Errors
35
- class InternalServerErrorException(CustomHTTPException):
36
- def __init__(self, **kwargs: Any) -> None:
37
- super().__init__(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, **kwargs)
corekit/files/pickle.py DELETED
@@ -1,12 +0,0 @@
1
- import pickle
2
- from typing import Any
3
-
4
- from corekit.files.base import FileContent, FileManager
5
-
6
-
7
- class PickleFileManager(FileManager):
8
- def _serialize(self, content: Any) -> FileContent:
9
- return pickle.dumps(content)
10
-
11
- def _deserialize(self, content: FileContent) -> Any:
12
- return pickle.loads(content)