pycraftcore 2.0.1__tar.gz → 2.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 (207) hide show
  1. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/PKG-INFO +124 -32
  2. pycraftcore-2.0.1/src/pycraftcore.egg-info/PKG-INFO → pycraftcore-2.1.0/Readme.md +35 -45
  3. pycraftcore-2.1.0/pyproject.toml +113 -0
  4. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/adapter/schema.py +4 -1
  5. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/enum/operation_type.py +1 -0
  6. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/model/operation.py +12 -2
  7. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/sqlite/adapter.py +2 -2
  8. pycraftcore-2.1.0/src/pycraftcore/serializer/__init__.py +0 -0
  9. pycraftcore-2.0.1/Readme.md → pycraftcore-2.1.0/src/pycraftcore.egg-info/PKG-INFO +137 -5
  10. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore.egg-info/SOURCES.txt +1 -0
  11. pycraftcore-2.1.0/src/pycraftcore.egg-info/requires.txt +96 -0
  12. pycraftcore-2.0.1/pyproject.toml +0 -84
  13. pycraftcore-2.0.1/src/pycraftcore.egg-info/requires.txt +0 -26
  14. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/LICENSE +0 -0
  15. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/setup.cfg +0 -0
  16. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/__init__.py +0 -0
  17. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/__init__.py +0 -0
  18. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/adapter/__init__.py +0 -0
  19. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/adapter/load_application_configuration.py +0 -0
  20. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/adapter/omega_configuration_reader.py +0 -0
  21. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/enum/__init__.py +0 -0
  22. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/enum/connector_type.py +0 -0
  23. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/enum/file_operation_action.py +0 -0
  24. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/enum/run_type_application.py +0 -0
  25. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/enum/run_type_environment.py +0 -0
  26. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/model/__init__.py +0 -0
  27. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/model/configuration.py +0 -0
  28. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/model/connector.py +0 -0
  29. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/port/__init__.py +0 -0
  30. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/port/configuration.py +0 -0
  31. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/application_configuration/port/configuration_reader.py +0 -0
  32. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/authentication/__init__.py +0 -0
  33. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/authentication/model/__init__.py +0 -0
  34. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/authentication/model/auth_type.py +0 -0
  35. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/authentication/model/basic_auth.py +0 -0
  36. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/authentication/model/no_auth.py +0 -0
  37. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/authentication/model/token_auth.py +0 -0
  38. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/__init__.py +0 -0
  39. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/adapter/__init__.py +0 -0
  40. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/adapter/aiobreaker_circuit_breaker_policy.py +0 -0
  41. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/configuration/__init__.py +0 -0
  42. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/configuration/circuit_breaker_configuration.py +0 -0
  43. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/enum/__init__.py +0 -0
  44. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/enum/circuit_breaker_status.py +0 -0
  45. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/exception/__init__.py +0 -0
  46. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/exception/circuit_breaker_open_exception.py +0 -0
  47. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/port/__init__.py +0 -0
  48. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/circuit_breaker/port/async_circuit_breaker.py +0 -0
  49. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/__init__.py +0 -0
  50. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/adapter/__init__.py +0 -0
  51. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/adapter/compute_engine.py +0 -0
  52. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/adapter/numpy_arithmetic_operation.py +0 -0
  53. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/adapter/scipy_calculus_operation.py +0 -0
  54. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/const_typing.py +0 -0
  55. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/port/__init__.py +0 -0
  56. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/port/arithmetic_operation.py +0 -0
  57. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/port/calculus_operation.py +0 -0
  58. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/computation_engine/port/engine.py +0 -0
  59. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/context/__init__.py +0 -0
  60. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/context/request_id_context.py +0 -0
  61. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/__init__.py +0 -0
  62. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/__init__.py +0 -0
  63. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/__init__.py +0 -0
  64. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/csv/__init__.py +0 -0
  65. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/csv/csv_reader.py +0 -0
  66. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/csv/csv_writer.py +0 -0
  67. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/json/__init__.py +0 -0
  68. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/json/json_reader.py +0 -0
  69. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/json/json_writer.py +0 -0
  70. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/markdown/__init__.py +0 -0
  71. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/markdown/markdown_reader.py +0 -0
  72. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/markdown/markdown_writer.py +0 -0
  73. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/svg/__init__.py +0 -0
  74. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/svg/svg_reader.py +0 -0
  75. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/svg/svg_writer.py +0 -0
  76. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/txt/__init__.py +0 -0
  77. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/txt/txt_reader.py +0 -0
  78. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/txt/txt_writer.py +0 -0
  79. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/yml/__init__.py +0 -0
  80. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/yml/yml_reader.py +0 -0
  81. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/extension/yml/yml_writer.py +0 -0
  82. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/factory.py +0 -0
  83. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/handler.py +0 -0
  84. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/provider.py +0 -0
  85. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/adapter/strategy.py +0 -0
  86. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/enum/__init__.py +0 -0
  87. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/enum/read_chunk_mode.py +0 -0
  88. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/port/__init__.py +0 -0
  89. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/port/file_handler_factory.py +0 -0
  90. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/port/file_handler_provider.py +0 -0
  91. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/port/reader.py +0 -0
  92. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/port/writer.py +0 -0
  93. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/schema/__init__.py +0 -0
  94. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/file_handler/schema/file_manifest.py +0 -0
  95. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/__init__.py +0 -0
  96. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/adapter/__init__.py +0 -0
  97. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/adapter/aiohttp_client.py +0 -0
  98. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/adapter/httpx_client.py +0 -0
  99. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/configuration/__init__.py +0 -0
  100. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/configuration/client_configuration.py +0 -0
  101. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/configuration/http_client_configuration.py +0 -0
  102. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/configuration/limits_configuration.py +0 -0
  103. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/configuration/security_configuration.py +0 -0
  104. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/context/__init__.py +0 -0
  105. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/context/request_context.py +0 -0
  106. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/enum/__init__.py +0 -0
  107. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/enum/http_method.py +0 -0
  108. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/middleware/__init__.py +0 -0
  109. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/middleware/request_id_middleware.py +0 -0
  110. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/middleware/request_middleware.py +0 -0
  111. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/policy/__init__.py +0 -0
  112. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/policy/http_error_policy.py +0 -0
  113. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/port/__init__.py +0 -0
  114. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/http/port/async_http_client.py +0 -0
  115. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/logger/__init__.py +0 -0
  116. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/logger/adapter/__init__.py +0 -0
  117. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/logger/adapter/standard_logger.py +0 -0
  118. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/logger/configuration.py +0 -0
  119. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/logger/port/__init__.py +0 -0
  120. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/logger/port/logger.py +0 -0
  121. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/profiler/__init__.py +0 -0
  122. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/profiler/profiled.py +0 -0
  123. /pycraftcore-2.0.1/src/pycraftcore/query_language/__init__.py → /pycraftcore-2.1.0/src/pycraftcore/py.typed +0 -0
  124. {pycraftcore-2.0.1/src/pycraftcore/query_language/constants/sql → pycraftcore-2.1.0/src/pycraftcore/query_language}/__init__.py +0 -0
  125. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/adapter/__init__.py +0 -0
  126. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/adapter/sql/__init__.py +0 -0
  127. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/adapter/sql/adapter.py +0 -0
  128. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/adapter/sql/factory.py +0 -0
  129. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/constants/__init__.py +0 -0
  130. {pycraftcore-2.0.1/src/pycraftcore/repository → pycraftcore-2.1.0/src/pycraftcore/query_language/constants/sql}/__init__.py +0 -0
  131. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/constants/sql/allowed_sql_root_statements.py +0 -0
  132. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/constants/sql/forbidden_sql_statements.py +0 -0
  133. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/port/__init__.py +0 -0
  134. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/query_language/port/query_handler.py +0 -0
  135. {pycraftcore-2.0.1/src/pycraftcore/repository/adapter/no_sql → pycraftcore-2.1.0/src/pycraftcore/repository}/__init__.py +0 -0
  136. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/__init__.py +0 -0
  137. {pycraftcore-2.0.1/src/pycraftcore/repository/adapter/no_sql/mongodb → pycraftcore-2.1.0/src/pycraftcore/repository/adapter/no_sql}/__init__.py +0 -0
  138. {pycraftcore-2.0.1/src/pycraftcore/repository/adapter/sql → pycraftcore-2.1.0/src/pycraftcore/repository/adapter/no_sql/mongodb}/__init__.py +0 -0
  139. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/no_sql/mongodb/adapter.py +0 -0
  140. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/no_sql/mongodb/factory.py +0 -0
  141. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/no_sql/mongodb/mapper.py +0 -0
  142. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/no_sql/mongodb/schema.py +0 -0
  143. {pycraftcore-2.0.1/src/pycraftcore/repository/adapter/sql/postgresql → pycraftcore-2.1.0/src/pycraftcore/repository/adapter/sql}/__init__.py +0 -0
  144. {pycraftcore-2.0.1/src/pycraftcore/resilient_http → pycraftcore-2.1.0/src/pycraftcore/repository/adapter/sql/postgresql}/__init__.py +0 -0
  145. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/postgresql/adapter.py +0 -0
  146. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/postgresql/factory.py +0 -0
  147. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/postgresql/mapper.py +0 -0
  148. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/postgresql/schema.py +0 -0
  149. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/sqlite/__init__.py +0 -0
  150. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/sqlite/factory.py +0 -0
  151. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/sqlite/mapper.py +0 -0
  152. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/adapter/sql/sqlite/schema.py +0 -0
  153. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/port/__init__.py +0 -0
  154. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/repository/port/repository.py +0 -0
  155. {pycraftcore-2.0.1/src/pycraftcore/retry → pycraftcore-2.1.0/src/pycraftcore/resilient_http}/__init__.py +0 -0
  156. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/adapter/__init__.py +0 -0
  157. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/adapter/resilient_client.py +0 -0
  158. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/adapter/resilient_http_client_factory.py +0 -0
  159. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/adapter/resilient_transport.py +0 -0
  160. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/adapter/resilient_transport_factory.py +0 -0
  161. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/configuration/__init__.py +0 -0
  162. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/configuration/resilient_http_configuration.py +0 -0
  163. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/port/__init__.py +0 -0
  164. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/resilient_http/port/async_resilient_http_client.py +0 -0
  165. {pycraftcore-2.0.1/src/pycraftcore/serializer → pycraftcore-2.1.0/src/pycraftcore/retry}/__init__.py +0 -0
  166. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/retry/adapter/__init__.py +0 -0
  167. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/retry/adapter/tenacity_retry_policy.py +0 -0
  168. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/retry/configuration/__init__.py +0 -0
  169. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/retry/configuration/retry_configuration.py +0 -0
  170. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/retry/port/__init__.py +0 -0
  171. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/retry/port/retry.py +0 -0
  172. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/__init__.py +0 -0
  173. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/adapter/__init__.py +0 -0
  174. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/adapter/python/__init__.py +0 -0
  175. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/adapter/python/adapter.py +0 -0
  176. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/adapter/python/factory.py +0 -0
  177. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/adapter/python/host_bridge_server.py +0 -0
  178. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/adapter/python/python_runner_template.py +0 -0
  179. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/port/__init__.py +0 -0
  180. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/port/code.py +0 -0
  181. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/schema/__init__.py +0 -0
  182. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/schema/code_result.py +0 -0
  183. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/schema/code_stdout.py +0 -0
  184. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/schema/host_bridge.py +0 -0
  185. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/runtime/schema/safe_code_settings.py +0 -0
  186. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/serializer/adapter/__init__.py +0 -0
  187. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/serializer/adapter/binary_serializer.py +0 -0
  188. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/serializer/adapter/dictionary_serializer.py +0 -0
  189. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/serializer/adapter/json_serializer.py +0 -0
  190. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/serializer/port/__init__.py +0 -0
  191. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/serializer/port/serializer.py +0 -0
  192. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/__init__.py +0 -0
  193. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/__init__.py +0 -0
  194. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/null_telemetry.py +0 -0
  195. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/open_telemetry.py +0 -0
  196. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/open_telemetry_logger_provider.py +0 -0
  197. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/open_telemetry_meter_provider.py +0 -0
  198. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/open_telemetry_provider.py +0 -0
  199. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/adapter/open_telemetry_tracer.py +0 -0
  200. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/port/__init__.py +0 -0
  201. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/port/logger_provider.py +0 -0
  202. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/port/meter_provider.py +0 -0
  203. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/port/telemetry.py +0 -0
  204. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/port/trace_provider.py +0 -0
  205. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore/telemetry/port/tracer.py +0 -0
  206. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore.egg-info/dependency_links.txt +0 -0
  207. {pycraftcore-2.0.1 → pycraftcore-2.1.0}/src/pycraftcore.egg-info/top_level.txt +0 -0
@@ -1,41 +1,103 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycraftcore
3
- Version: 2.0.1
3
+ Version: 2.1.0
4
4
  Summary: Provides reusable technical infrastructure and adapter implementations for Python applications
5
5
  Author-email: Toufik Saouchi <toufik.saouchi@gmail.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/s-toufik/pycraftcore
8
+ Project-URL: Repository, https://github.com/s-toufik/pycraftcore
9
+ Project-URL: Issues, https://github.com/s-toufik/pycraftcore/issues
10
+ Keywords: infrastructure,hexagonal-architecture,configuration,logging,opentelemetry,resilient-http,repository,sandbox,asyncio
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Framework :: AsyncIO
13
+ Classifier: Intended Audience :: Developers
8
14
  Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.14
9
17
  Classifier: Operating System :: OS Independent
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Typing :: Typed
10
20
  Requires-Python: >=3.14
11
21
  Description-Content-Type: text/markdown
12
22
  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: scipy>=1.17.1
27
- Requires-Dist: httpx
28
- Requires-Dist: tenacity
29
- Requires-Dist: aiobreaker
30
- Requires-Dist: aiosqlite
31
- Requires-Dist: sqlglot
32
- Requires-Dist: starlette
33
- Requires-Dist: pandas
34
- Requires-Dist: matplotlib
35
- Requires-Dist: pymongo<4.18,>=4.9
36
- Requires-Dist: psycopg[binary]
37
- Requires-Dist: psycopg-pool
38
- Requires-Dist: opentelemetry-instrumentation-logging>=0.65b0
23
+ Provides-Extra: authentication
24
+ Provides-Extra: context
25
+ Provides-Extra: logger
26
+ Provides-Extra: profiler
27
+ Requires-Dist: pyinstrument; extra == "profiler"
28
+ Provides-Extra: query-language
29
+ Requires-Dist: sqlglot; extra == "query-language"
30
+ Provides-Extra: computation-engine
31
+ Requires-Dist: numpy; extra == "computation-engine"
32
+ Requires-Dist: scipy; extra == "computation-engine"
33
+ Provides-Extra: serializer
34
+ Requires-Dist: orjson; extra == "serializer"
35
+ Requires-Dist: msgpack; extra == "serializer"
36
+ Requires-Dist: pydantic>=2; extra == "serializer"
37
+ Provides-Extra: file-handler
38
+ Requires-Dist: orjson; extra == "file-handler"
39
+ Requires-Dist: pyyaml; extra == "file-handler"
40
+ Provides-Extra: runtime
41
+ Requires-Dist: pydantic>=2; extra == "runtime"
42
+ Provides-Extra: circuit-breaker
43
+ Requires-Dist: aiobreaker; extra == "circuit-breaker"
44
+ Requires-Dist: pycraftcore[logger]; extra == "circuit-breaker"
45
+ Provides-Extra: retry
46
+ Requires-Dist: tenacity; extra == "retry"
47
+ Requires-Dist: pycraftcore[logger]; extra == "retry"
48
+ Provides-Extra: http
49
+ Requires-Dist: aiohttp; extra == "http"
50
+ Requires-Dist: httpx; extra == "http"
51
+ Requires-Dist: orjson; extra == "http"
52
+ Requires-Dist: starlette; extra == "http"
53
+ Requires-Dist: pycraftcore[context,logger]; extra == "http"
54
+ Provides-Extra: resilient-http
55
+ Requires-Dist: aiohttp; extra == "resilient-http"
56
+ Requires-Dist: httpx; extra == "resilient-http"
57
+ Requires-Dist: pycraftcore[circuit_breaker,http,logger,retry,telemetry]; extra == "resilient-http"
58
+ Provides-Extra: application-configuration
59
+ Requires-Dist: omegaconf; extra == "application-configuration"
60
+ Requires-Dist: pydantic>=2; extra == "application-configuration"
61
+ Requires-Dist: python-dotenv; extra == "application-configuration"
62
+ Requires-Dist: pycraftcore[authentication,http,logger]; extra == "application-configuration"
63
+ Provides-Extra: telemetry
64
+ Requires-Dist: opentelemetry-api; extra == "telemetry"
65
+ Requires-Dist: opentelemetry-sdk; extra == "telemetry"
66
+ Requires-Dist: opentelemetry-exporter-otlp; extra == "telemetry"
67
+ Requires-Dist: opentelemetry-instrumentation-logging; extra == "telemetry"
68
+ Requires-Dist: pycraftcore[application_configuration,context]; extra == "telemetry"
69
+ Provides-Extra: repository
70
+ Requires-Dist: aiosqlite; extra == "repository"
71
+ Requires-Dist: pymongo; extra == "repository"
72
+ Requires-Dist: psycopg[binary]; extra == "repository"
73
+ Requires-Dist: psycopg-pool; extra == "repository"
74
+ Requires-Dist: orjson; extra == "repository"
75
+ Requires-Dist: pydantic>=2; extra == "repository"
76
+ Requires-Dist: pycraftcore[application_configuration,authentication]; extra == "repository"
77
+ Provides-Extra: runtime-sandbox
78
+ Requires-Dist: pandas; extra == "runtime-sandbox"
79
+ Requires-Dist: numpy; extra == "runtime-sandbox"
80
+ Requires-Dist: matplotlib; extra == "runtime-sandbox"
81
+ Requires-Dist: python-dateutil; extra == "runtime-sandbox"
82
+ Requires-Dist: pycraftcore[runtime]; extra == "runtime-sandbox"
83
+ Provides-Extra: all
84
+ Requires-Dist: pycraftcore[application_configuration]; extra == "all"
85
+ Requires-Dist: pycraftcore[authentication]; extra == "all"
86
+ Requires-Dist: pycraftcore[circuit_breaker]; extra == "all"
87
+ Requires-Dist: pycraftcore[computation_engine]; extra == "all"
88
+ Requires-Dist: pycraftcore[context]; extra == "all"
89
+ Requires-Dist: pycraftcore[file_handler]; extra == "all"
90
+ Requires-Dist: pycraftcore[http]; extra == "all"
91
+ Requires-Dist: pycraftcore[logger]; extra == "all"
92
+ Requires-Dist: pycraftcore[profiler]; extra == "all"
93
+ Requires-Dist: pycraftcore[query_language]; extra == "all"
94
+ Requires-Dist: pycraftcore[repository]; extra == "all"
95
+ Requires-Dist: pycraftcore[resilient_http]; extra == "all"
96
+ Requires-Dist: pycraftcore[retry]; extra == "all"
97
+ Requires-Dist: pycraftcore[runtime]; extra == "all"
98
+ Requires-Dist: pycraftcore[runtime-sandbox]; extra == "all"
99
+ Requires-Dist: pycraftcore[serializer]; extra == "all"
100
+ Requires-Dist: pycraftcore[telemetry]; extra == "all"
39
101
  Dynamic: license-file
40
102
 
41
103
  # pycraftcore
@@ -67,11 +129,40 @@ The shared technical foundation of the homelab's Python services: configuration,
67
129
 
68
130
  ### Install
69
131
 
132
+ Requires Python 3.14. Each module's third-party dependencies sit behind an extra of the same name, so a service installs only what it uses:
133
+
70
134
  ```bash
71
- uv add pycraftcore # or: pip install pycraftcore
135
+ uv add "pycraftcore[http,repository]" # or: pip install "pycraftcore[http,repository]"
136
+ uv add "pycraftcore[all]" # every module
72
137
  ```
73
138
 
74
- Requires Python 3.14. Development builds are published to TestPyPI (`pip install -i https://test.pypi.org/simple/ pycraftcore`); use them for testing only.
139
+ A bare `pycraftcore` installs no third-party packages: only `authentication`, `context` and `logger` work without an extra. For any other module, importing its adapters without the extra fails with `ModuleNotFoundError`.
140
+
141
+ | Extra | Third-party packages | Also brings in |
142
+ |---|---|---|
143
+ | `authentication`, `context`, `logger` | none | — |
144
+ | `profiler` | pyinstrument | — |
145
+ | `query_language` | sqlglot | — |
146
+ | `computation_engine` | numpy, scipy | — |
147
+ | `serializer` | orjson, msgpack, pydantic | — |
148
+ | `file_handler` | orjson, pyyaml | — |
149
+ | `runtime` | pydantic | — |
150
+ | `runtime-sandbox` | pandas, numpy, matplotlib, python-dateutil | `runtime` |
151
+ | `circuit_breaker` | aiobreaker | `logger` |
152
+ | `retry` | tenacity | `logger` |
153
+ | `http` | aiohttp, httpx, orjson, starlette | `context`, `logger` |
154
+ | `application_configuration` | omegaconf, pydantic, python-dotenv | `http`, `logger`, `authentication` |
155
+ | `telemetry` | opentelemetry (api, sdk, otlp exporter, logging instrumentation) | `application_configuration`, `context` |
156
+ | `resilient_http` | aiohttp, httpx | `circuit_breaker`, `http`, `retry`, `telemetry` |
157
+ | `repository` | aiosqlite, pymongo, psycopg, psycopg-pool, orjson, pydantic | `application_configuration`, `authentication` |
158
+
159
+ List every module your code imports, even when one extra already brings in another. That way your service stays correct if these links change. For the Python sandbox, use `runtime-sandbox` rather than `runtime`: the sandboxed code runs on your service's interpreter, so the libraries it may import (pandas, numpy, matplotlib, dateutil) must be installed there.
160
+
161
+ Development builds are published to TestPyPI; use them for testing only. Their dependencies come from PyPI, so add it as an extra index:
162
+
163
+ ```bash
164
+ pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "pycraftcore[http]"
165
+ ```
75
166
 
76
167
  ### What's inside
77
168
 
@@ -298,12 +389,13 @@ Not every module needs every folder: add a folder when it has something to hold.
298
389
  1. Define the protocol in `<module>/port/`.
299
390
  2. Implement it in `<module>/adapter/`, with its settings in `configuration/` and the data it exchanges in `schema/`.
300
391
  3. Export the public names from the package's `__init__.py`.
301
- 4. Add tests under `tests/<module>/`, and the module to [What's inside](#whats-inside) — with a short example under Using pycraftcore if services will use it directly.
392
+ 4. Declare its third-party packages as an extra named after the module in `[project.optional-dependencies]` (pull in other modules with `pycraftcore[<module>]`). Then add it to `all`, to the [Install](#install) table, and to the `extras` matrix in `.github/workflows/cicd.yml`, which installs each extra alone and imports its package.
393
+ 5. Add tests under `tests/<module>/`, and the module to [What's inside](#whats-inside) — with a short example under Using pycraftcore if services will use it directly.
302
394
 
303
395
  ### Tests and checks
304
396
 
305
397
  ```bash
306
- make install_dev # uv sync --group dev
398
+ make install_dev # uv sync --group dev --all-extras
307
399
  make check # ruff + ty + pytest
308
400
  make test
309
401
  make lint / make fix / make format / make typecheck
@@ -321,6 +413,6 @@ uv run pre-commit install --hook-type pre-commit --hook-type pre-push
321
413
  1. Bump `version` in `pyproject.toml`.
322
414
  2. `make build`.
323
415
  3. `make publish_dev` to TestPyPI (needs `TEST_PYPI_TOKEN`), try it in a service, then `make publish` to PyPI (needs `RELEASE_PYPI_TOKEN`).
324
- 4. Raise the minimum version in the services that need the change (`pycraftcore>=…` in their `pyproject.toml`), then `uv lock --upgrade-package pycraftcore`.
416
+ 4. Raise the minimum version in the services that need the change (`pycraftcore[<extras>]>=…` in their `pyproject.toml`), then `uv lock --upgrade-package pycraftcore`.
325
417
 
326
418
  To work on pycraftcore and a service at the same time, point the service at your checkout with an editable path dependency in its `pyproject.toml`: `pycraftcore = { path = "../pycraftcore", editable = true }` under `[tool.uv.sources]`.
@@ -1,43 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: pycraftcore
3
- Version: 2.0.1
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: scipy>=1.17.1
27
- Requires-Dist: httpx
28
- Requires-Dist: tenacity
29
- Requires-Dist: aiobreaker
30
- Requires-Dist: aiosqlite
31
- Requires-Dist: sqlglot
32
- Requires-Dist: starlette
33
- Requires-Dist: pandas
34
- Requires-Dist: matplotlib
35
- Requires-Dist: pymongo<4.18,>=4.9
36
- Requires-Dist: psycopg[binary]
37
- Requires-Dist: psycopg-pool
38
- Requires-Dist: opentelemetry-instrumentation-logging>=0.65b0
39
- Dynamic: license-file
40
-
41
1
  # pycraftcore
42
2
 
43
3
  The shared technical foundation of the homelab's Python services: configuration, logging, telemetry, resilient HTTP, database repositories, safe SQL and a sandbox for running untrusted Python. Small, swappable building blocks rather than a framework — every module is an interface (a port) plus the implementations behind it (adapters).
@@ -67,11 +27,40 @@ The shared technical foundation of the homelab's Python services: configuration,
67
27
 
68
28
  ### Install
69
29
 
30
+ Requires Python 3.14. Each module's third-party dependencies sit behind an extra of the same name, so a service installs only what it uses:
31
+
70
32
  ```bash
71
- uv add pycraftcore # or: pip install pycraftcore
33
+ uv add "pycraftcore[http,repository]" # or: pip install "pycraftcore[http,repository]"
34
+ uv add "pycraftcore[all]" # every module
72
35
  ```
73
36
 
74
- Requires Python 3.14. Development builds are published to TestPyPI (`pip install -i https://test.pypi.org/simple/ pycraftcore`); use them for testing only.
37
+ A bare `pycraftcore` installs no third-party packages: only `authentication`, `context` and `logger` work without an extra. For any other module, importing its adapters without the extra fails with `ModuleNotFoundError`.
38
+
39
+ | Extra | Third-party packages | Also brings in |
40
+ |---|---|---|
41
+ | `authentication`, `context`, `logger` | none | — |
42
+ | `profiler` | pyinstrument | — |
43
+ | `query_language` | sqlglot | — |
44
+ | `computation_engine` | numpy, scipy | — |
45
+ | `serializer` | orjson, msgpack, pydantic | — |
46
+ | `file_handler` | orjson, pyyaml | — |
47
+ | `runtime` | pydantic | — |
48
+ | `runtime-sandbox` | pandas, numpy, matplotlib, python-dateutil | `runtime` |
49
+ | `circuit_breaker` | aiobreaker | `logger` |
50
+ | `retry` | tenacity | `logger` |
51
+ | `http` | aiohttp, httpx, orjson, starlette | `context`, `logger` |
52
+ | `application_configuration` | omegaconf, pydantic, python-dotenv | `http`, `logger`, `authentication` |
53
+ | `telemetry` | opentelemetry (api, sdk, otlp exporter, logging instrumentation) | `application_configuration`, `context` |
54
+ | `resilient_http` | aiohttp, httpx | `circuit_breaker`, `http`, `retry`, `telemetry` |
55
+ | `repository` | aiosqlite, pymongo, psycopg, psycopg-pool, orjson, pydantic | `application_configuration`, `authentication` |
56
+
57
+ List every module your code imports, even when one extra already brings in another. That way your service stays correct if these links change. For the Python sandbox, use `runtime-sandbox` rather than `runtime`: the sandboxed code runs on your service's interpreter, so the libraries it may import (pandas, numpy, matplotlib, dateutil) must be installed there.
58
+
59
+ Development builds are published to TestPyPI; use them for testing only. Their dependencies come from PyPI, so add it as an extra index:
60
+
61
+ ```bash
62
+ pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "pycraftcore[http]"
63
+ ```
75
64
 
76
65
  ### What's inside
77
66
 
@@ -298,12 +287,13 @@ Not every module needs every folder: add a folder when it has something to hold.
298
287
  1. Define the protocol in `<module>/port/`.
299
288
  2. Implement it in `<module>/adapter/`, with its settings in `configuration/` and the data it exchanges in `schema/`.
300
289
  3. Export the public names from the package's `__init__.py`.
301
- 4. Add tests under `tests/<module>/`, and the module to [What's inside](#whats-inside) — with a short example under Using pycraftcore if services will use it directly.
290
+ 4. Declare its third-party packages as an extra named after the module in `[project.optional-dependencies]` (pull in other modules with `pycraftcore[<module>]`). Then add it to `all`, to the [Install](#install) table, and to the `extras` matrix in `.github/workflows/cicd.yml`, which installs each extra alone and imports its package.
291
+ 5. Add tests under `tests/<module>/`, and the module to [What's inside](#whats-inside) — with a short example under Using pycraftcore if services will use it directly.
302
292
 
303
293
  ### Tests and checks
304
294
 
305
295
  ```bash
306
- make install_dev # uv sync --group dev
296
+ make install_dev # uv sync --group dev --all-extras
307
297
  make check # ruff + ty + pytest
308
298
  make test
309
299
  make lint / make fix / make format / make typecheck
@@ -321,6 +311,6 @@ uv run pre-commit install --hook-type pre-commit --hook-type pre-push
321
311
  1. Bump `version` in `pyproject.toml`.
322
312
  2. `make build`.
323
313
  3. `make publish_dev` to TestPyPI (needs `TEST_PYPI_TOKEN`), try it in a service, then `make publish` to PyPI (needs `RELEASE_PYPI_TOKEN`).
324
- 4. Raise the minimum version in the services that need the change (`pycraftcore>=…` in their `pyproject.toml`), then `uv lock --upgrade-package pycraftcore`.
314
+ 4. Raise the minimum version in the services that need the change (`pycraftcore[<extras>]>=…` in their `pyproject.toml`), then `uv lock --upgrade-package pycraftcore`.
325
315
 
326
316
  To work on pycraftcore and a service at the same time, point the service at your checkout with an editable path dependency in its `pyproject.toml`: `pycraftcore = { path = "../pycraftcore", editable = true }` under `[tool.uv.sources]`.
@@ -0,0 +1,113 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pycraftcore"
7
+ version = "2.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
+ keywords = ["infrastructure", "hexagonal-architecture", "configuration", "logging", "opentelemetry", "resilient-http", "repository", "sandbox", "asyncio"]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Framework :: AsyncIO",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Operating System :: OS Independent",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ "Typing :: Typed",
25
+ ]
26
+ license = "MIT"
27
+ dependencies = []
28
+
29
+ [project.optional-dependencies]
30
+ # Independent dependencies
31
+ authentication = []
32
+ context = []
33
+ logger = []
34
+ profiler = ["pyinstrument"]
35
+ query_language = ["sqlglot"]
36
+ computation_engine = ["numpy", "scipy"]
37
+ serializer = ["orjson", "msgpack", "pydantic>=2"]
38
+ file_handler = ["orjson", "pyyaml"]
39
+ runtime = ["pydantic>=2"]
40
+
41
+ # Dependent dependencies
42
+ circuit_breaker = ["aiobreaker", "pycraftcore[logger]"]
43
+ retry = ["tenacity", "pycraftcore[logger]"]
44
+ http = ["aiohttp", "httpx", "orjson", "starlette", "pycraftcore[context, logger]"]
45
+ resilient_http = ["aiohttp", "httpx", "pycraftcore[circuit_breaker, http, logger, retry, telemetry]"]
46
+ application_configuration = ["omegaconf", "pydantic>=2", "python-dotenv", "pycraftcore[logger, http, authentication]"]
47
+ telemetry = ["opentelemetry-api", "opentelemetry-sdk", "opentelemetry-exporter-otlp", "opentelemetry-instrumentation-logging", "pycraftcore[application_configuration, context]"]
48
+ repository = ["aiosqlite", "pymongo", "psycopg[binary]", "psycopg-pool", "orjson", "pydantic>=2", "pycraftcore[application_configuration, authentication]"]
49
+ runtime-sandbox = ["pandas", "numpy", "matplotlib", "python-dateutil", "pycraftcore[runtime]"]
50
+
51
+ all = [
52
+ "pycraftcore[application_configuration]",
53
+ "pycraftcore[authentication]",
54
+ "pycraftcore[circuit_breaker]",
55
+ "pycraftcore[computation_engine]",
56
+ "pycraftcore[context]",
57
+ "pycraftcore[file_handler]",
58
+ "pycraftcore[http]",
59
+ "pycraftcore[logger]",
60
+ "pycraftcore[profiler]",
61
+ "pycraftcore[query_language]",
62
+ "pycraftcore[repository]",
63
+ "pycraftcore[resilient_http]",
64
+ "pycraftcore[retry]",
65
+ "pycraftcore[runtime]",
66
+ "pycraftcore[runtime-sandbox]",
67
+ "pycraftcore[serializer]",
68
+ "pycraftcore[telemetry]",
69
+
70
+ ]
71
+
72
+ [dependency-groups]
73
+ dev = [
74
+ "pytest",
75
+ "hypothesis",
76
+ "pytest-asyncio",
77
+ "pytest-cov",
78
+ "ruff",
79
+ "ty",
80
+ "scipy-stubs",
81
+ "pre-commit"
82
+ ]
83
+
84
+ [tool.ruff]
85
+ line-length = 100
86
+ target-version = "py314"
87
+
88
+ [tool.ruff.lint]
89
+ select = [
90
+ "E", # pycodestyle
91
+ "F", # pyflakes
92
+ "UP", # pyupgrade
93
+ ]
94
+ ignore = [
95
+ "B017", # Blind exeception in tests
96
+ "BLE001", # Blind exception in code
97
+ "E501", # Line length
98
+ ]
99
+
100
+ [tool.ty.src]
101
+ include = ["src", "tests/ducktype"]
102
+ exclude = [".venv"]
103
+
104
+ [tool.setuptools.packages.find]
105
+ where = ["src"]
106
+
107
+ [tool.setuptools.package-data]
108
+ pycraftcore = ["py.typed"]
109
+
110
+ [project.urls]
111
+ Homepage = "https://github.com/s-toufik/pycraftcore"
112
+ Repository = "https://github.com/s-toufik/pycraftcore"
113
+ Issues = "https://github.com/s-toufik/pycraftcore/issues"
@@ -23,6 +23,7 @@ from pycraftcore.application_configuration.model.connector import (
23
23
  from pycraftcore.application_configuration.model.operation import (
24
24
  ApiOperation,
25
25
  FileOperation,
26
+ McpOperation,
26
27
  OperationRegistry,
27
28
  )
28
29
 
@@ -41,7 +42,9 @@ _ConnectorSchemaTyping = Annotated[
41
42
  ]
42
43
 
43
44
  _OperationSchemaTyping = Annotated[
44
- Annotated[ApiOperation, Tag("api")] | Annotated[FileOperation, Tag("file")],
45
+ Annotated[ApiOperation, Tag("api")]
46
+ | Annotated[FileOperation, Tag("file")]
47
+ | Annotated[McpOperation, Tag("mcp")],
45
48
  Discriminator(_kind_tag),
46
49
  ]
47
50
 
@@ -4,3 +4,4 @@ from enum import Enum
4
4
  class OperationType(Enum):
5
5
  api = "api"
6
6
  file = "file"
7
+ mcp = "mcp"
@@ -7,7 +7,7 @@ from pycraftcore.application_configuration.enum.file_operation_action import (
7
7
  from pycraftcore.application_configuration.enum.operation_type import OperationType
8
8
  from pycraftcore.application_configuration.model.connector import (
9
9
  ApiConnector,
10
- FileConnector,
10
+ FileConnector, McpConnector,
11
11
  )
12
12
  from pycraftcore.http.enum.http_method import HttpMethod
13
13
 
@@ -32,12 +32,19 @@ class FileOperation(BaseOperation):
32
32
  action: FileOperationAction
33
33
  parameters: dict[str, Any]
34
34
 
35
+ @dataclass(slots=True)
36
+ class McpOperation(BaseOperation):
37
+ connector: McpConnector
38
+ parameters: dict[str, Any]
39
+
35
40
 
36
- OperationTyping = FileOperation | ApiOperation
41
+
42
+ OperationTyping = FileOperation | ApiOperation | McpOperation
37
43
 
38
44
  _OPERATION_CLASS_BY_TYPE: dict[OperationType, type[OperationTyping]] = {
39
45
  OperationType.api: ApiOperation,
40
46
  OperationType.file: FileOperation,
47
+ OperationType.mcp: McpOperation,
41
48
  }
42
49
 
43
50
 
@@ -62,6 +69,9 @@ class OperationRegistry:
62
69
  def file(self, name: str) -> FileOperation:
63
70
  return self._get(name, FileOperation)
64
71
 
72
+ def mcp(self, name: str) -> McpOperation:
73
+ return self._get(name, McpOperation)
74
+
65
75
  def _get[T: OperationTyping](self, name: str, expected: type[T]) -> T:
66
76
  try:
67
77
  operation = self.by_name[name]
@@ -1,5 +1,5 @@
1
1
  import asyncio
2
- from collections.abc import AsyncIterator, Iterable
2
+ from collections.abc import AsyncGenerator, Iterable
3
3
  from contextlib import asynccontextmanager
4
4
  from typing import Any
5
5
 
@@ -13,7 +13,7 @@ class SqliteRepository:
13
13
  self._pool.put_nowait(connection)
14
14
 
15
15
  @asynccontextmanager
16
- async def _acquire(self) -> AsyncIterator[Connection]:
16
+ async def _acquire(self) -> AsyncGenerator[Connection]:
17
17
  connection = await self._pool.get()
18
18
  try:
19
19
  yield connection