pycraftcore 0.1.0__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 (124) hide show
  1. pycraftcore-0.1.0/LICENSE +21 -0
  2. pycraftcore-0.1.0/PKG-INFO +34 -0
  3. pycraftcore-0.1.0/pyproject.toml +67 -0
  4. pycraftcore-0.1.0/setup.cfg +4 -0
  5. pycraftcore-0.1.0/src/pycraftcore/__init__.py +0 -0
  6. pycraftcore-0.1.0/src/pycraftcore/app_configuration/__init__.py +5 -0
  7. pycraftcore-0.1.0/src/pycraftcore/app_configuration/adapter/__init__.py +0 -0
  8. pycraftcore-0.1.0/src/pycraftcore/app_configuration/adapter/load_configuration.py +41 -0
  9. pycraftcore-0.1.0/src/pycraftcore/app_configuration/adapter/omega_configuration_reader.py +52 -0
  10. pycraftcore-0.1.0/src/pycraftcore/app_configuration/adapter/schema.py +29 -0
  11. pycraftcore-0.1.0/src/pycraftcore/app_configuration/enum/__init__.py +0 -0
  12. pycraftcore-0.1.0/src/pycraftcore/app_configuration/enum/connector_type.py +9 -0
  13. pycraftcore-0.1.0/src/pycraftcore/app_configuration/enum/file_operation_action.py +7 -0
  14. pycraftcore-0.1.0/src/pycraftcore/app_configuration/enum/run_type_application.py +6 -0
  15. pycraftcore-0.1.0/src/pycraftcore/app_configuration/enum/run_type_environment.py +8 -0
  16. pycraftcore-0.1.0/src/pycraftcore/app_configuration/model/__init__.py +0 -0
  17. pycraftcore-0.1.0/src/pycraftcore/app_configuration/model/configuration.py +22 -0
  18. pycraftcore-0.1.0/src/pycraftcore/app_configuration/model/connector.py +43 -0
  19. pycraftcore-0.1.0/src/pycraftcore/app_configuration/model/cronjob.py +10 -0
  20. pycraftcore-0.1.0/src/pycraftcore/app_configuration/model/operation.py +32 -0
  21. pycraftcore-0.1.0/src/pycraftcore/app_configuration/port/__init__.py +0 -0
  22. pycraftcore-0.1.0/src/pycraftcore/app_configuration/port/configuration.py +9 -0
  23. pycraftcore-0.1.0/src/pycraftcore/app_configuration/port/configuration_reader.py +7 -0
  24. pycraftcore-0.1.0/src/pycraftcore/authentication/__init__.py +5 -0
  25. pycraftcore-0.1.0/src/pycraftcore/authentication/model/__init__.py +0 -0
  26. pycraftcore-0.1.0/src/pycraftcore/authentication/model/auth_type.py +7 -0
  27. pycraftcore-0.1.0/src/pycraftcore/authentication/model/basic_auth.py +10 -0
  28. pycraftcore-0.1.0/src/pycraftcore/authentication/model/no_auth.py +8 -0
  29. pycraftcore-0.1.0/src/pycraftcore/authentication/model/token_auth.py +10 -0
  30. pycraftcore-0.1.0/src/pycraftcore/computation_engine/__init__.py +0 -0
  31. pycraftcore-0.1.0/src/pycraftcore/computation_engine/adapter/__init__.py +0 -0
  32. pycraftcore-0.1.0/src/pycraftcore/computation_engine/adapter/compute_engine.py +20 -0
  33. pycraftcore-0.1.0/src/pycraftcore/computation_engine/adapter/numpy_arithmetic_operation.py +49 -0
  34. pycraftcore-0.1.0/src/pycraftcore/computation_engine/adapter/scipy_calculus_operation.py +21 -0
  35. pycraftcore-0.1.0/src/pycraftcore/computation_engine/const_typing.py +15 -0
  36. pycraftcore-0.1.0/src/pycraftcore/computation_engine/port/__init__.py +0 -0
  37. pycraftcore-0.1.0/src/pycraftcore/computation_engine/port/arithmetic_operation.py +15 -0
  38. pycraftcore-0.1.0/src/pycraftcore/computation_engine/port/calculus_operation.py +11 -0
  39. pycraftcore-0.1.0/src/pycraftcore/computation_engine/port/engine.py +16 -0
  40. pycraftcore-0.1.0/src/pycraftcore/file_handler/__init__.py +0 -0
  41. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/__init__.py +0 -0
  42. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/extension/__init__.py +0 -0
  43. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/extension/yml_reader.py +12 -0
  44. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/extension/yml_writer.py +12 -0
  45. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/factory.py +37 -0
  46. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/handler.py +12 -0
  47. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/provider.py +10 -0
  48. pycraftcore-0.1.0/src/pycraftcore/file_handler/adapter/strategy.py +23 -0
  49. pycraftcore-0.1.0/src/pycraftcore/file_handler/port/__init__.py +0 -0
  50. pycraftcore-0.1.0/src/pycraftcore/file_handler/port/reader.py +8 -0
  51. pycraftcore-0.1.0/src/pycraftcore/file_handler/port/writer.py +8 -0
  52. pycraftcore-0.1.0/src/pycraftcore/http/__init__.py +0 -0
  53. pycraftcore-0.1.0/src/pycraftcore/http/adapter/__init__.py +15 -0
  54. pycraftcore-0.1.0/src/pycraftcore/http/adapter/aiohttp_client.py +148 -0
  55. pycraftcore-0.1.0/src/pycraftcore/http/adapter/circuit_breaker_policy.py +94 -0
  56. pycraftcore-0.1.0/src/pycraftcore/http/adapter/httpx_client.py +210 -0
  57. pycraftcore-0.1.0/src/pycraftcore/http/adapter/resilient_client.py +51 -0
  58. pycraftcore-0.1.0/src/pycraftcore/http/adapter/retry_policy.py +50 -0
  59. pycraftcore-0.1.0/src/pycraftcore/http/configuration/__init__.py +15 -0
  60. pycraftcore-0.1.0/src/pycraftcore/http/configuration/circuite_breaker_configuration.py +8 -0
  61. pycraftcore-0.1.0/src/pycraftcore/http/configuration/client_configuration.py +6 -0
  62. pycraftcore-0.1.0/src/pycraftcore/http/configuration/http_client_configuration.py +16 -0
  63. pycraftcore-0.1.0/src/pycraftcore/http/configuration/limits_configuration.py +11 -0
  64. pycraftcore-0.1.0/src/pycraftcore/http/configuration/retry_configuration.py +13 -0
  65. pycraftcore-0.1.0/src/pycraftcore/http/configuration/security_configuration.py +7 -0
  66. pycraftcore-0.1.0/src/pycraftcore/http/context/__init__.py +0 -0
  67. pycraftcore-0.1.0/src/pycraftcore/http/context/request_context.py +4 -0
  68. pycraftcore-0.1.0/src/pycraftcore/http/enum/__init__.py +4 -0
  69. pycraftcore-0.1.0/src/pycraftcore/http/enum/circuit_breaker_status.py +7 -0
  70. pycraftcore-0.1.0/src/pycraftcore/http/enum/http_method.py +6 -0
  71. pycraftcore-0.1.0/src/pycraftcore/http/exception/__init__.py +0 -0
  72. pycraftcore-0.1.0/src/pycraftcore/http/exception/circuit_breaker_open_exception.py +1 -0
  73. pycraftcore-0.1.0/src/pycraftcore/http/middleware/__init__.py +0 -0
  74. pycraftcore-0.1.0/src/pycraftcore/http/middleware/request_id_middleware.py +25 -0
  75. pycraftcore-0.1.0/src/pycraftcore/http/port/__init__.py +5 -0
  76. pycraftcore-0.1.0/src/pycraftcore/http/port/async_circuit_breaker.py +18 -0
  77. pycraftcore-0.1.0/src/pycraftcore/http/port/async_http_client.py +28 -0
  78. pycraftcore-0.1.0/src/pycraftcore/http/port/async_resilient_http_client.py +8 -0
  79. pycraftcore-0.1.0/src/pycraftcore/http/port/retry.py +12 -0
  80. pycraftcore-0.1.0/src/pycraftcore/logger/__init__.py +0 -0
  81. pycraftcore-0.1.0/src/pycraftcore/logger/adapter/__init__.py +0 -0
  82. pycraftcore-0.1.0/src/pycraftcore/logger/adapter/loguru_logger.py +38 -0
  83. pycraftcore-0.1.0/src/pycraftcore/logger/port/__init__.py +3 -0
  84. pycraftcore-0.1.0/src/pycraftcore/logger/port/logger.py +15 -0
  85. pycraftcore-0.1.0/src/pycraftcore/profiler/__init__.py +0 -0
  86. pycraftcore-0.1.0/src/pycraftcore/profiler/profiled.py +20 -0
  87. pycraftcore-0.1.0/src/pycraftcore/query_language/__init__.py +0 -0
  88. pycraftcore-0.1.0/src/pycraftcore/query_language/constants/__init__.py +0 -0
  89. pycraftcore-0.1.0/src/pycraftcore/query_language/constants/allowed_root_statements.py +9 -0
  90. pycraftcore-0.1.0/src/pycraftcore/query_language/constants/forbidden_statements.py +17 -0
  91. pycraftcore-0.1.0/src/pycraftcore/query_language/sql/__init__.py +0 -0
  92. pycraftcore-0.1.0/src/pycraftcore/query_language/sql/adapter.py +40 -0
  93. pycraftcore-0.1.0/src/pycraftcore/query_language/sql/factory.py +7 -0
  94. pycraftcore-0.1.0/src/pycraftcore/query_language/sql/sql_handler.py +9 -0
  95. pycraftcore-0.1.0/src/pycraftcore/repository/__init__.py +0 -0
  96. pycraftcore-0.1.0/src/pycraftcore/repository/repository.py +17 -0
  97. pycraftcore-0.1.0/src/pycraftcore/repository/sqlite/__init__.py +0 -0
  98. pycraftcore-0.1.0/src/pycraftcore/repository/sqlite/adapter.py +36 -0
  99. pycraftcore-0.1.0/src/pycraftcore/repository/sqlite/factory.py +70 -0
  100. pycraftcore-0.1.0/src/pycraftcore/repository/sqlite/mapper.py +14 -0
  101. pycraftcore-0.1.0/src/pycraftcore/repository/sqlite/schema.py +7 -0
  102. pycraftcore-0.1.0/src/pycraftcore/runtime/__init__.py +0 -0
  103. pycraftcore-0.1.0/src/pycraftcore/runtime/code.py +16 -0
  104. pycraftcore-0.1.0/src/pycraftcore/runtime/python/__init__.py +0 -0
  105. pycraftcore-0.1.0/src/pycraftcore/runtime/python/adapter.py +193 -0
  106. pycraftcore-0.1.0/src/pycraftcore/runtime/python/factory.py +22 -0
  107. pycraftcore-0.1.0/src/pycraftcore/runtime/python/schema.py +14 -0
  108. pycraftcore-0.1.0/src/pycraftcore/serializer/__init__.py +0 -0
  109. pycraftcore-0.1.0/src/pycraftcore/serializer/adapter/__init__.py +0 -0
  110. pycraftcore-0.1.0/src/pycraftcore/serializer/adapter/binary_serializer.py +16 -0
  111. pycraftcore-0.1.0/src/pycraftcore/serializer/adapter/dictionary_serializer.py +14 -0
  112. pycraftcore-0.1.0/src/pycraftcore/serializer/adapter/json_serializer.py +15 -0
  113. pycraftcore-0.1.0/src/pycraftcore/serializer/port/__init__.py +0 -0
  114. pycraftcore-0.1.0/src/pycraftcore/serializer/port/serializer.py +11 -0
  115. pycraftcore-0.1.0/src/pycraftcore/telemetry/__init__.py +3 -0
  116. pycraftcore-0.1.0/src/pycraftcore/telemetry/adapter/__init__.py +0 -0
  117. pycraftcore-0.1.0/src/pycraftcore/telemetry/adapter/open_telemetry.py +108 -0
  118. pycraftcore-0.1.0/src/pycraftcore/telemetry/port/__init__.py +0 -0
  119. pycraftcore-0.1.0/src/pycraftcore/telemetry/port/telemetry.py +15 -0
  120. pycraftcore-0.1.0/src/pycraftcore.egg-info/PKG-INFO +34 -0
  121. pycraftcore-0.1.0/src/pycraftcore.egg-info/SOURCES.txt +122 -0
  122. pycraftcore-0.1.0/src/pycraftcore.egg-info/dependency_links.txt +1 -0
  123. pycraftcore-0.1.0/src/pycraftcore.egg-info/requires.txt +21 -0
  124. pycraftcore-0.1.0/src/pycraftcore.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 stoufik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycraftcore
3
+ Version: 0.1.0
4
+ Summary: Provides reusable technical infrastructure and adapter implementations for Python applications
5
+ Author-email: Toufik Saouchi <toufik.saouchi@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/s-toufik/pycraftcore
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.14
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: numpy
14
+ Requires-Dist: aiohttp
15
+ Requires-Dist: orjson
16
+ Requires-Dist: pyyaml
17
+ Requires-Dist: omegaconf
18
+ Requires-Dist: opentelemetry-api
19
+ Requires-Dist: opentelemetry-sdk
20
+ Requires-Dist: opentelemetry-exporter-otlp
21
+ Requires-Dist: pyinstrument
22
+ Requires-Dist: asyncpg
23
+ Requires-Dist: pydantic>=2
24
+ Requires-Dist: python-dotenv
25
+ Requires-Dist: msgpack>=1.1.2
26
+ Requires-Dist: loguru>=0.7.3
27
+ Requires-Dist: scipy>=1.17.1
28
+ Requires-Dist: httpx
29
+ Requires-Dist: tenacity
30
+ Requires-Dist: aiobreaker
31
+ Requires-Dist: aiosqlite
32
+ Requires-Dist: sqlglot
33
+ Requires-Dist: starlette
34
+ Dynamic: license-file
@@ -0,0 +1,67 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pycraftcore"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name = "Toufik Saouchi", email = "toufik.saouchi@gmail.com" },
10
+ ]
11
+ description = "Provides reusable technical infrastructure and adapter implementations for Python applications"
12
+ readme = "README.md"
13
+ requires-python = ">=3.14"
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "Operating System :: OS Independent",
17
+ ]
18
+ license = "MIT"
19
+ dependencies = [
20
+ "numpy",
21
+ "aiohttp",
22
+ "orjson",
23
+ "pyyaml",
24
+ "omegaconf",
25
+ "opentelemetry-api",
26
+ "opentelemetry-sdk",
27
+ "opentelemetry-exporter-otlp",
28
+ "pyinstrument",
29
+ "asyncpg",
30
+ "pydantic>=2",
31
+ "python-dotenv",
32
+ "msgpack>=1.1.2",
33
+ "loguru>=0.7.3",
34
+ "scipy>=1.17.1",
35
+ "httpx",
36
+ "tenacity",
37
+ "aiobreaker",
38
+ "aiosqlite",
39
+ "sqlglot",
40
+ "starlette",
41
+ ]
42
+
43
+ [dependency-groups]
44
+ dev = [
45
+ "pytest",
46
+ "hypothesis>=6.151.9",
47
+ "pytest-asyncio",
48
+ "pytest-cov>=7.1.0",
49
+ "ruff",
50
+ "scipy-stubs>=1.17.1.3",
51
+ "Pyright",
52
+ "mypy"
53
+ ]
54
+
55
+ [tool.ruff]
56
+ line-length = 100
57
+ target-version = "py314"
58
+
59
+ [tool.mypy]
60
+ python_version = "3.14"
61
+ strict = true
62
+
63
+ [tool.setuptools.packages.find]
64
+ where = ["src"]
65
+
66
+ [project.urls]
67
+ Homepage = "https://github.com/s-toufik/pycraftcore"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,5 @@
1
+ from pycraftcore.app_configuration.model.configuration import AppConfiguration
2
+ from pycraftcore.app_configuration.port.configuration import Configuration
3
+ from pycraftcore.app_configuration.port.configuration_reader import ConfigurationReader
4
+
5
+ __all__ = ["AppConfiguration", "Configuration", "ConfigurationReader"]
@@ -0,0 +1,41 @@
1
+ import threading
2
+ from typing import ParamSpec
3
+
4
+ from pycraftcore.app_configuration.model.configuration import AppConfiguration
5
+ from pycraftcore.app_configuration.port.configuration_reader import (
6
+ ConfigurationReader,
7
+ )
8
+ from pycraftcore.logger.port.logger import Logger
9
+
10
+ P = ParamSpec("P")
11
+
12
+
13
+ class LoadConfiguration:
14
+ _instance = None
15
+ _lock = threading.Lock()
16
+
17
+ def __new__(cls, *args: P.args, **kwargs: P.kwargs):
18
+ if not cls._instance:
19
+ with cls._lock:
20
+ if not cls._instance:
21
+ cls._instance = object.__new__(cls)
22
+ return cls._instance
23
+
24
+ def __init__(self, configuration_reader: ConfigurationReader, logger: Logger):
25
+ self._configuration_reader = configuration_reader
26
+ self._logger = logger
27
+ self._cached_config: AppConfiguration | None = None
28
+
29
+ def load(self) -> AppConfiguration | None:
30
+ if self._cached_config is None:
31
+ try:
32
+ self._cached_config = self._configuration_reader.read()
33
+ except Exception as exception:
34
+ self._logger.critical(exception.__str__())
35
+ return self._cached_config
36
+
37
+ def reload(self) -> AppConfiguration | None:
38
+ with self._lock:
39
+ configuration = self._configuration_reader.read()
40
+ self._cached_config = configuration
41
+ return self._cached_config
@@ -0,0 +1,52 @@
1
+ from pathlib import Path
2
+ from typing import cast, Any
3
+
4
+ from omegaconf import OmegaConf, DictConfig
5
+
6
+ from pycraftcore.app_configuration.adapter.schema import (
7
+ AppConfigurationSchema,
8
+ MapperDomainSchema,
9
+ )
10
+ from pycraftcore.app_configuration.enum.run_type_environment import (
11
+ RunTypeEnvironment,
12
+ )
13
+ from pycraftcore.app_configuration.model.configuration import AppConfiguration
14
+
15
+
16
+ class OmegaConfigurationReader:
17
+ FILE_EXTENSION = "yml"
18
+ ROOT_CONFIG_FILE_NAME = "root"
19
+ CONNECTOR_CONFIG_FILE_NAME = "connector"
20
+ OPERATION_CONFIG_FILE_NAME = "operation"
21
+ CRONJOB_CONFIG_FILE_NAME = "cronjob"
22
+
23
+ def __init__(self, env: RunTypeEnvironment, config_directory: Path) -> None:
24
+ self._env = env
25
+ self._config_directory = config_directory
26
+
27
+ def read(self) -> AppConfiguration:
28
+ config_root: Path = (
29
+ self._config_directory / f"{self.ROOT_CONFIG_FILE_NAME}.{self.FILE_EXTENSION}"
30
+ )
31
+ config_dir_env = self._config_directory / f"{self._env.value}"
32
+
33
+ omega_config: DictConfig = self._omega_read(config_dir_env, config_root)
34
+ omega_container: Any = OmegaConf.to_container(
35
+ omega_config.app_configuration, resolve=True, throw_on_missing=True
36
+ )
37
+ app_config_schema = AppConfigurationSchema(**omega_container)
38
+ return MapperDomainSchema.map(app_config_schema)
39
+
40
+ def _omega_read(self, config_dir_env: Path, config_root: Path) -> DictConfig:
41
+ return cast(
42
+ DictConfig,
43
+ OmegaConf.merge(
44
+ *self._load_yml_dir(config_dir_env / self.CONNECTOR_CONFIG_FILE_NAME),
45
+ *self._load_yml_dir(config_dir_env / self.OPERATION_CONFIG_FILE_NAME),
46
+ *self._load_yml_dir(config_dir_env / self.CRONJOB_CONFIG_FILE_NAME),
47
+ OmegaConf.load(config_root),
48
+ ),
49
+ )
50
+
51
+ def _load_yml_dir(self, directory: Path) -> list:
52
+ return [OmegaConf.load(f) for f in sorted(directory.glob(f"*.{self.FILE_EXTENSION}"))]
@@ -0,0 +1,29 @@
1
+ from pydantic import BaseModel
2
+ from typing import Sequence
3
+
4
+ from pycraftcore.app_configuration.enum.connector_type import ConnectorType
5
+ from pycraftcore.app_configuration.enum.run_type_application import (
6
+ RunTypeApplication,
7
+ )
8
+ from pycraftcore.app_configuration.enum.run_type_environment import (
9
+ RunTypeEnvironment,
10
+ )
11
+ from pycraftcore.app_configuration.model.configuration import AppConfiguration
12
+ from pycraftcore.app_configuration.model.connector import ConnectorTyping
13
+
14
+ from pycraftcore.app_configuration.model.cronjob import CronJob
15
+ from pycraftcore.app_configuration.model.operation import OperationTyping
16
+
17
+
18
+ class AppConfigurationSchema(BaseModel):
19
+ env: RunTypeEnvironment
20
+ run: RunTypeApplication
21
+ connector: dict[ConnectorType, dict[str, ConnectorTyping]]
22
+ operation: dict[str, OperationTyping]
23
+ cronjob: Sequence[CronJob]
24
+
25
+
26
+ class MapperDomainSchema:
27
+ @staticmethod
28
+ def map(app_configuration_schema: AppConfigurationSchema) -> AppConfiguration:
29
+ return AppConfiguration(**vars(app_configuration_schema))
@@ -0,0 +1,9 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ConnectorType(Enum):
5
+ api = "api"
6
+ database = "database"
7
+ cache = "cache"
8
+ file = "file"
9
+ telemetry = "telemetry"
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+
4
+ class FileOperationAction(Enum):
5
+ read = "read"
6
+ write = "write"
7
+ delete = "delete"
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class RunTypeApplication(Enum):
5
+ asynchronous = "async"
6
+ synchronous = "sync"
@@ -0,0 +1,8 @@
1
+ from enum import Enum
2
+
3
+
4
+ class RunTypeEnvironment(Enum):
5
+ debug = "debug"
6
+ production = "prod"
7
+ staging = "stg"
8
+ develop = "dev"
@@ -0,0 +1,22 @@
1
+ from typing import Sequence
2
+ from dataclasses import dataclass
3
+
4
+ from pycraftcore.app_configuration.enum.connector_type import ConnectorType
5
+ from pycraftcore.app_configuration.enum.run_type_application import (
6
+ RunTypeApplication,
7
+ )
8
+ from pycraftcore.app_configuration.enum.run_type_environment import (
9
+ RunTypeEnvironment,
10
+ )
11
+ from pycraftcore.app_configuration.model.connector import ConnectorTyping
12
+ from pycraftcore.app_configuration.model.cronjob import CronJob
13
+ from pycraftcore.app_configuration.model.operation import OperationTyping
14
+
15
+
16
+ @dataclass(frozen=True, slots=True)
17
+ class AppConfiguration:
18
+ env: RunTypeEnvironment
19
+ run: RunTypeApplication
20
+ connector: dict[ConnectorType, dict[str, ConnectorTyping]]
21
+ operation: dict[str, OperationTyping]
22
+ cronjob: Sequence[CronJob]
@@ -0,0 +1,43 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Union
3
+
4
+ from pycraftcore.app_configuration.enum.connector_type import ConnectorType
5
+ from pycraftcore.authentication import AuthTyping
6
+
7
+
8
+ @dataclass(slots=True)
9
+ class BaseConnector:
10
+ name: str
11
+ type: ConnectorType
12
+ auth: AuthTyping
13
+
14
+
15
+ @dataclass(slots=True)
16
+ class ApiConnector(BaseConnector):
17
+ base_url: str
18
+ timeout: int
19
+ retry: int
20
+ certificate: str | None = field(default=None)
21
+
22
+
23
+ @dataclass(slots=True)
24
+ class DatabaseConnector(BaseConnector):
25
+ engine: str
26
+ host: str
27
+ port: int
28
+ default_name: str
29
+ pool: dict[str, int]
30
+
31
+
32
+ @dataclass(slots=True)
33
+ class FileConnector(BaseConnector):
34
+ base_path: str
35
+
36
+
37
+ @dataclass(slots=True)
38
+ class TelemetryConnector(BaseConnector):
39
+ host: str
40
+ port: int
41
+
42
+
43
+ ConnectorTyping = Union[ApiConnector, FileConnector, DatabaseConnector, TelemetryConnector]
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+
3
+ from pycraftcore.app_configuration.model.operation import OperationTyping
4
+
5
+
6
+ @dataclass(slots=True)
7
+ class CronJob:
8
+ name: str
9
+ cron: str
10
+ operation: OperationTyping
@@ -0,0 +1,32 @@
1
+ from dataclasses import dataclass
2
+ from typing import Union, List
3
+
4
+ from pycraftcore.app_configuration.enum.file_operation_action import (
5
+ FileOperationAction,
6
+ )
7
+ from pycraftcore.app_configuration.model.connector import ConnectorTyping
8
+ from pycraftcore.http.enum.http_method import HttpMethod
9
+
10
+ ParamType = Union[str, List[str]]
11
+
12
+
13
+ @dataclass(slots=True)
14
+ class BaseOperation:
15
+ name: str
16
+ connector: ConnectorTyping
17
+
18
+
19
+ @dataclass(slots=True)
20
+ class ApiOperation(BaseOperation):
21
+ endpoint: str
22
+ method: HttpMethod
23
+ parameters: dict[str, ParamType]
24
+
25
+
26
+ @dataclass(slots=True)
27
+ class FileOperation(BaseOperation):
28
+ action: FileOperationAction
29
+ parameters: dict[str, ParamType]
30
+
31
+
32
+ OperationTyping = Union[FileOperation, ApiOperation]
@@ -0,0 +1,9 @@
1
+ from typing import Protocol
2
+
3
+ from pycraftcore.app_configuration.model.configuration import AppConfiguration
4
+
5
+
6
+ class Configuration(Protocol):
7
+ def load(self) -> AppConfiguration | None: ...
8
+
9
+ def reload(self) -> AppConfiguration | None: ...
@@ -0,0 +1,7 @@
1
+ from typing import Protocol
2
+
3
+ from pycraftcore.app_configuration.model.configuration import AppConfiguration
4
+
5
+
6
+ class ConfigurationReader(Protocol):
7
+ def read(self) -> AppConfiguration: ...
@@ -0,0 +1,5 @@
1
+ from pycraftcore.authentication.model.basic_auth import BasicAuth
2
+ from pycraftcore.authentication.model.no_auth import NoAuth
3
+ from pycraftcore.authentication.model.token_auth import TokenAuth
4
+
5
+ AuthTyping = NoAuth | TokenAuth | BasicAuth
@@ -0,0 +1,7 @@
1
+ import enum
2
+
3
+
4
+ class AuthType(enum.Enum):
5
+ token = "token"
6
+ basic = "basic"
7
+ none = "none"
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass, field
2
+
3
+ from .auth_type import AuthType
4
+
5
+
6
+ @dataclass(frozen=True, slots=True)
7
+ class BasicAuth:
8
+ username: str
9
+ password: str
10
+ type: AuthType = field(default=AuthType.basic)
@@ -0,0 +1,8 @@
1
+ from dataclasses import dataclass, field
2
+
3
+ from .auth_type import AuthType
4
+
5
+
6
+ @dataclass(frozen=True, slots=True)
7
+ class NoAuth:
8
+ type: AuthType = field(default=AuthType.none)
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass, field
2
+
3
+ from .auth_type import AuthType
4
+
5
+
6
+ @dataclass(frozen=True, slots=True)
7
+ class TokenAuth:
8
+ key_name: str
9
+ key_value: str
10
+ type: AuthType = field(default=AuthType.token)
@@ -0,0 +1,20 @@
1
+ from pycraftcore.computation_engine.port.arithmetic_operation import (
2
+ ArithmeticOperation,
3
+ )
4
+ from pycraftcore.computation_engine.port.calculus_operation import (
5
+ CalculusOperation,
6
+ )
7
+
8
+
9
+ class ComputeEngine:
10
+ def __init__(self, arithmetic: ArithmeticOperation, calculus: CalculusOperation):
11
+ self._arithmetic = arithmetic
12
+ self._calculus = calculus
13
+
14
+ @property
15
+ def arithmetic(self) -> ArithmeticOperation:
16
+ return self._arithmetic
17
+
18
+ @property
19
+ def calculus(self) -> CalculusOperation:
20
+ return self._calculus
@@ -0,0 +1,49 @@
1
+ from typing import Sequence, Any
2
+
3
+ import numpy as np
4
+
5
+ from pycraftcore.computation_engine.const_typing import Numeric
6
+
7
+
8
+ class NumPyArithmeticOperation:
9
+ def to_array(self, sequence: Sequence[Any]) -> np.ndarray:
10
+ return self._as_array(sequence)
11
+
12
+ def log_returns(self, sequence: Sequence[Numeric]) -> np.ndarray:
13
+
14
+ if len(sequence) < 2:
15
+ return self._empty_array()
16
+
17
+ array = self._as_array(sequence)
18
+
19
+ ratio = array[1:] / array[:-1]
20
+ ratio = np.where(ratio <= 0, np.nan, ratio)
21
+ return np.log(ratio)
22
+
23
+ def rolling_average(self, sequence: Sequence[Numeric], window: int = 5) -> np.ndarray:
24
+ if len(sequence) < window:
25
+ return self._empty_array()
26
+
27
+ array = self._as_array(sequence)
28
+ kernel = self._as_array((np.ones(window) / window).astype(np.float64))
29
+ return np.convolve(array, kernel)
30
+
31
+ def rolling_standard_deviation(
32
+ self, sequence: Sequence[Numeric], window: int = 5
33
+ ) -> np.ndarray:
34
+ if len(sequence) < window:
35
+ return self._empty_array()
36
+
37
+ array = self._as_array(sequence)
38
+
39
+ return np.array([np.std(array[i : i + window]) for i in range(len(array) - window + 1)])
40
+
41
+ @staticmethod
42
+ def _empty_array() -> np.ndarray:
43
+ return np.array([], dtype=np.float64)
44
+
45
+ @staticmethod
46
+ def _as_array(sequence: Sequence[Any]) -> np.ndarray:
47
+ if isinstance(sequence, np.ndarray):
48
+ return sequence
49
+ return np.asarray(sequence, dtype=np.float64)
@@ -0,0 +1,21 @@
1
+ from typing import Sequence, Any
2
+
3
+ import numpy as np
4
+ from scipy import interpolate, integrate
5
+
6
+ from pycraftcore.computation_engine.const_typing import Numeric, Kind
7
+
8
+
9
+ class ScipyCalculusOperation:
10
+ def _to_array(self, sequence: Sequence[Any]) -> np.ndarray:
11
+ return np.asarray(sequence, dtype=np.float64)
12
+
13
+ def integrate(self, sequence: Sequence[Numeric], dx: float) -> float:
14
+ arr = self._to_array(sequence)
15
+ return float(integrate.trapezoid(arr, dx=dx))
16
+
17
+ def interpolate(self, sequence: Sequence[Numeric], kind: Kind = "linear") -> Sequence[Numeric]:
18
+ arr = self._to_array(sequence)
19
+ x = np.arange(len(arr))
20
+ f = interpolate.interp1d(x, arr, kind=kind)
21
+ return f(x)
@@ -0,0 +1,15 @@
1
+ from typing import Literal
2
+
3
+ Numeric = int | float
4
+
5
+ Kind = Literal[
6
+ "linear",
7
+ "nearest",
8
+ "nearest-up",
9
+ "zero",
10
+ "slinear",
11
+ "quadratic",
12
+ "cubic",
13
+ "previous",
14
+ "next",
15
+ ]
@@ -0,0 +1,15 @@
1
+ from typing import Sequence, Any, Protocol
2
+
3
+ from pycraftcore.computation_engine.const_typing import Numeric
4
+
5
+
6
+ class ArithmeticOperation(Protocol):
7
+ def to_array(self, sequence: Sequence[Any]) -> Sequence[Any]: ...
8
+
9
+ def log_returns(self, sequence: Sequence[Numeric]) -> Sequence[Numeric]: ...
10
+
11
+ def rolling_average(self, sequence: Sequence[Numeric], window: int) -> Sequence[Numeric]: ...
12
+
13
+ def rolling_standard_deviation(
14
+ self, sequence: Sequence[Numeric], window: int
15
+ ) -> Sequence[Numeric]: ...
@@ -0,0 +1,11 @@
1
+ from typing import Sequence, Protocol
2
+
3
+ from pycraftcore.computation_engine.const_typing import Numeric, Kind
4
+
5
+
6
+ class CalculusOperation(Protocol):
7
+ def integrate(self, sequence: Sequence[Numeric], dx: float) -> float: ...
8
+
9
+ def interpolate(
10
+ self, sequence: Sequence[Numeric], kind: Kind = "linear"
11
+ ) -> Sequence[Numeric]: ...
@@ -0,0 +1,16 @@
1
+ from typing import Protocol
2
+
3
+ from pycraftcore.computation_engine.port.arithmetic_operation import (
4
+ ArithmeticOperation,
5
+ )
6
+ from pycraftcore.computation_engine.port.calculus_operation import (
7
+ CalculusOperation,
8
+ )
9
+
10
+
11
+ class Engine(Protocol):
12
+ @property
13
+ def arithmetic(self) -> ArithmeticOperation: ...
14
+
15
+ @property
16
+ def calculus(self) -> CalculusOperation: ...