alpha-python 0.6.0__tar.gz → 0.6.1__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 (154) hide show
  1. alpha_python-0.6.1/PKG-INFO +210 -0
  2. alpha_python-0.6.1/README.md +153 -0
  3. {alpha_python-0.6.0 → alpha_python-0.6.1}/pyproject.toml +12 -5
  4. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/cli.py +27 -23
  5. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/encoder.py +4 -3
  6. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/jwt_factory.py +10 -7
  7. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/password_factory.py +8 -1
  8. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/api_generate_handler.py +5 -0
  9. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/__main__.mustache +26 -9
  10. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/controller.mustache +23 -22
  11. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/models/json_patch.py +1 -1
  12. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/models/order_by.py +4 -2
  13. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/models/query_clause.py +2 -2
  14. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/token_factory.py +5 -3
  15. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/models/identity.py +5 -5
  16. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/oidc_provider.py +0 -2
  17. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/services/authentication_service.py +10 -4
  18. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/logging_configurator.py +1 -1
  19. alpha_python-0.6.1/src/alpha/utils/openapi_test/response.py +12 -0
  20. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/openapi_test/service.py +0 -6
  21. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/response_object.py +10 -1
  22. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/verify_identity.py +7 -7
  23. alpha_python-0.6.1/src/alpha_python.egg-info/PKG-INFO +210 -0
  24. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha_python.egg-info/SOURCES.txt +1 -0
  25. alpha_python-0.6.0/PKG-INFO +0 -117
  26. alpha_python-0.6.0/README.md +0 -60
  27. alpha_python-0.6.0/src/alpha_python.egg-info/PKG-INFO +0 -117
  28. {alpha_python-0.6.0 → alpha_python-0.6.1}/LICENSE +0 -0
  29. {alpha_python-0.6.0 → alpha_python-0.6.1}/setup.cfg +0 -0
  30. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/__init__.py +0 -0
  31. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/adapters/__init__.py +0 -0
  32. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/adapters/rest_api_unit_of_work.py +0 -0
  33. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/adapters/sqla_unit_of_work.py +0 -0
  34. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/containers/__init__.py +0 -0
  35. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/containers/container.py +0 -0
  36. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/__init__.py +0 -0
  37. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/models/__init__.py +0 -0
  38. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/models/base_model.py +0 -0
  39. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/models/group.py +0 -0
  40. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/models/life_cycle_base.py +0 -0
  41. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/models/role.py +0 -0
  42. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/domain/models/user.py +0 -0
  43. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/exceptions.py +0 -0
  44. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/__init__.py +0 -0
  45. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/_type_conversion_matrix.py +0 -0
  46. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/_type_mapping.py +0 -0
  47. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/class_factories.py +0 -0
  48. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/default_field_factory.py +0 -0
  49. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/field_iterator.py +0 -0
  50. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/logging_handler_factory.py +0 -0
  51. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/model_class_factory.py +0 -0
  52. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/models/__init__.py +0 -0
  53. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/models/factory_classes.py +0 -0
  54. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/request_factory.py +0 -0
  55. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/response_factory.py +0 -0
  56. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/factories/type_factories.py +0 -0
  57. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/__init__.py +0 -0
  58. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/api_run_handler.py +0 -0
  59. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/base_handler.py +0 -0
  60. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/gen-code.sh +0 -0
  61. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/models/__init__.py +0 -0
  62. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/models/argument.py +0 -0
  63. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/models/command.py +0 -0
  64. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/models/section.py +0 -0
  65. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/models/subparser.py +0 -0
  66. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/run-api.sh +0 -0
  67. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/__init__.py +0 -0
  68. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/Dockerfile.mustache +0 -0
  69. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/README.mustache +0 -0
  70. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/__init__model.mustache +0 -0
  71. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/__init__test.mustache +0 -0
  72. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/base_model.mustache +0 -0
  73. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/controller_test.mustache +0 -0
  74. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/dockerignore.mustache +0 -0
  75. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/encoder.mustache +0 -0
  76. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/git_push.sh.mustache +0 -0
  77. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/gitignore.mustache +0 -0
  78. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/model.mustache +0 -0
  79. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/openapi.mustache +0 -0
  80. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/param_type.mustache +0 -0
  81. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/requirements.mustache +0 -0
  82. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/security_controller_.mustache +0 -0
  83. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/setup.mustache +0 -0
  84. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/test-requirements.mustache +0 -0
  85. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/tox.mustache +0 -0
  86. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/travis.mustache +0 -0
  87. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/typing_utils.mustache +0 -0
  88. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/handlers/templates/python-flask/util.mustache +0 -0
  89. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/__init__.py +0 -0
  90. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/connectors/__init__.py +0 -0
  91. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/connectors/ldap_connector.py +0 -0
  92. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/connectors/oidc_connector.py +0 -0
  93. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/connectors/sql_alchemy.py +0 -0
  94. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/databases/__init__.py +0 -0
  95. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/databases/sql_alchemy.py +0 -0
  96. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/models/__init__.py +0 -0
  97. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/models/filter_operators.py +0 -0
  98. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/infra/models/search_filter.py +0 -0
  99. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/__init__.py +0 -0
  100. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/api_repository.py +0 -0
  101. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/attrs_instance.py +0 -0
  102. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/dataclass_instance.py +0 -0
  103. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/factories.py +0 -0
  104. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/handler.py +0 -0
  105. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/openapi_model.py +0 -0
  106. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/patchable.py +0 -0
  107. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/providers.py +0 -0
  108. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/pydantic_instance.py +0 -0
  109. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/sql_database.py +0 -0
  110. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/sql_mapper.py +0 -0
  111. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/sql_repository.py +0 -0
  112. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/unit_of_work.py +0 -0
  113. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/interfaces/updatable.py +0 -0
  114. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/mixins/__init__.py +0 -0
  115. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/mixins/group_lifecycle.py +0 -0
  116. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/mixins/jwt_provider.py +0 -0
  117. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/mixins/user_lifecycle.py +0 -0
  118. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/__init__.py +0 -0
  119. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/api_key_provider.py +0 -0
  120. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/database_provider.py +0 -0
  121. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/ldap_provider.py +0 -0
  122. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/models/__init__.py +0 -0
  123. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/models/credentials.py +0 -0
  124. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/providers/models/token.py +0 -0
  125. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/py.typed +0 -0
  126. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/repositories/__init__.py +0 -0
  127. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/repositories/models/__init__.py +0 -0
  128. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/repositories/models/repository_model.py +0 -0
  129. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/repositories/rest_api_repository.py +0 -0
  130. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/repositories/sql_alchemy_repository.py +0 -0
  131. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/services/__init__.py +0 -0
  132. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/services/models/__init__.py +0 -0
  133. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/services/models/cookie.py +0 -0
  134. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/services/user_lifecycle_management.py +0 -0
  135. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/__init__.py +0 -0
  136. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/_http_codes.py +0 -0
  137. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/cookie.py +0 -0
  138. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/is_attrs.py +0 -0
  139. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/is_pydantic.py +0 -0
  140. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/logging_level_checker.py +0 -0
  141. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/openapi_test/__init__.py +0 -0
  142. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/openapi_test/container.py +0 -0
  143. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/openapi_test/exceptions.py +0 -0
  144. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/openapi_test/models.py +0 -0
  145. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/openapi_test/orm.py +0 -0
  146. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/request_headers.py +0 -0
  147. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/secret_generator.py +0 -0
  148. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha/utils/version_checker.py +0 -0
  149. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha_python.egg-info/dependency_links.txt +0 -0
  150. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha_python.egg-info/entry_points.txt +0 -0
  151. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha_python.egg-info/requires.txt +0 -0
  152. {alpha_python-0.6.0 → alpha_python-0.6.1}/src/alpha_python.egg-info/top_level.txt +0 -0
  153. {alpha_python-0.6.0 → alpha_python-0.6.1}/tests/test_cli.py +0 -0
  154. {alpha_python-0.6.0 → alpha_python-0.6.1}/tests/test_encoder.py +0 -0
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.4
2
+ Name: alpha-python
3
+ Version: 0.6.1
4
+ Summary: Alpha is intended to be the first dependency you need to add to your Python application. It is a Python library which contains standard building blocks that can be used in applications that are used as APIs and/or make use of database interaction.
5
+ Author-email: Bart Reijling <bart@reijling.eu>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/breijling/alpha
8
+ Project-URL: Issues, https://github.com/breijling/alpha/issues
9
+ Project-URL: Documentation, https://alpha-python.readthedocs.io/en/latest/
10
+ Project-URL: Changelog, https://alpha-python.readthedocs.io/en/latest/changelog/
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: <3.15,>=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: attrs>=25.4.0
23
+ Requires-Dist: gunicorn>=23.0.0
24
+ Requires-Dist: jsonpatch>=1.33
25
+ Requires-Dist: numpy>=2.3.5
26
+ Requires-Dist: pandas>=1.13
27
+ Requires-Dist: pydantic>=2.12.5
28
+ Requires-Dist: pyjwt>=2.10.1
29
+ Requires-Dist: six>=1.17.0
30
+ Requires-Dist: sqlalchemy>=2.0.44
31
+ Requires-Dist: requests>=2.28.1
32
+ Requires-Dist: dependency-injector[yaml]!=4.48.3,<5.0.0,>=4.42.0
33
+ Requires-Dist: argon2-cffi>=25.1.0
34
+ Requires-Dist: httpx
35
+ Requires-Dist: cryptography
36
+ Provides-Extra: api-generator
37
+ Requires-Dist: openapi-generator-cli==7.14.0; extra == "api-generator"
38
+ Requires-Dist: jdk4py; extra == "api-generator"
39
+ Provides-Extra: flask
40
+ Requires-Dist: connexion[swagger-ui]<3,>=2.14.2; extra == "flask"
41
+ Requires-Dist: swagger-ui-bundle>=0.0.2; extra == "flask"
42
+ Requires-Dist: python_dateutil>=2.6.0; extra == "flask"
43
+ Requires-Dist: itsdangerous==1.1.0; extra == "flask"
44
+ Requires-Dist: MarkupSafe<2.0.2; extra == "flask"
45
+ Requires-Dist: Jinja2==2.11.2; extra == "flask"
46
+ Requires-Dist: Flask<2,>=1.1.2; extra == "flask"
47
+ Requires-Dist: Werkzeug<2.1.0,>=1.0.1; extra == "flask"
48
+ Requires-Dist: flask-cors>=3.0.10; extra == "flask"
49
+ Requires-Dist: Flask-Compress>=1.13; extra == "flask"
50
+ Provides-Extra: mysql
51
+ Requires-Dist: pymysql>=1.1.2; extra == "mysql"
52
+ Provides-Extra: postgresql
53
+ Requires-Dist: psycopg2-binary>=2.9.11; extra == "postgresql"
54
+ Provides-Extra: ldap
55
+ Requires-Dist: ldap3>=2.9.1; extra == "ldap"
56
+ Dynamic: license-file
57
+
58
+ # Alpha
59
+
60
+ Alpha is intended to be the first dependency you need to add to your Python application. It is a Python library which contains standard building blocks that can be used in applications that are used as APIs and/or make use of database interaction.
61
+
62
+ ## Badges
63
+
64
+ [![PyPI version](https://badge.fury.io/py/alpha-python.svg?icon=si%3Apython)](https://badge.fury.io/py/alpha-python)
65
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/alpha-python.svg?label=PyPI%20downloads)](https://pypistats.org/packages/alpha-python)
66
+ [![Build Status](https://github.com/breijling/alpha/actions/workflows/python-app.yml/badge.svg?branch=main)](https://github.com/breijling/alpha/actions/workflows/python-app.yml)
67
+ [![Supported Python versions](https://img.shields.io/pypi/pyversions/alpha-python.svg?color=%2334D058)](https://pypi.org/project/alpha-python)
68
+ [![Coverage Status](https://coveralls.io/repos/github/BReijling/alpha/badge.svg?branch=main)](https://coveralls.io/github/BReijling/alpha?branch=main)
69
+ [![uv](https://img.shields.io/badge/package%20manager-uv-5C4EE5)](https://docs.astral.sh/uv/)
70
+ [![mypy](https://img.shields.io/badge/type%20check-mypy-2A6DB2)](https://mypy-lang.org/)
71
+ [![Pytest](https://img.shields.io/badge/testing-pytest-0A9EDC)](https://docs.pytest.org/)
72
+ [![PEP8](https://img.shields.io/badge/code%20style-pep8-orange.svg)](https://www.python.org/dev/peps/pep-0008/)
73
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
74
+ [![Documentation Status](https://readthedocs.org/projects/alpha-python/badge/?version=latest)](https://alpha-python.readthedocs.io/en/latest/)
75
+ [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)
76
+ [![Sponsor](https://img.shields.io/badge/Sponsor-GitHub-pink?logo=github)](https://github.com/sponsors/BReijling)
77
+
78
+ ## TL;DR
79
+
80
+ Alpha provides a comprehensive set of tools for building Python applications that interact with APIs and databases, including API code generation, authentication and authorization, database access layers, error handling, logging, and more. It is designed to be the first dependency you add to your project, providing a solid foundation for your application's architecture.
81
+
82
+ ## Documentation
83
+
84
+ Full documentation is available at [alpha-python.readthedocs.io](https://alpha-python.readthedocs.io/).
85
+
86
+ ## Installation
87
+
88
+ The library is still in development, but you can already install it using pip:
89
+
90
+ ```shell
91
+ pip install alpha-python
92
+ ```
93
+
94
+ If you want to use the alpha cli for generating API code, you can install it using pip as well:
95
+
96
+ ```shell
97
+ pip install alpha-python[api-generator]
98
+ ```
99
+
100
+ If you want to add the library to your API project, you can add it to your pyproject.toml file:
101
+
102
+ ```shell
103
+ # Poetry example
104
+ poetry add alpha-python --extras "flask, postgresql"
105
+ poetry add --dev alpha-python --extras "api-generator"
106
+
107
+ # UV example
108
+ uv add alpha-python --extra flask --extra postgresql
109
+ uv add --dev alpha-python --extra api-generator
110
+ ```
111
+
112
+ ## Features
113
+
114
+ - API code generation
115
+ - Authentication and authorization
116
+ - Database interaction
117
+ - Logging
118
+ - Error handling
119
+ - And much more!
120
+
121
+ ## Usage
122
+
123
+ The library contains many components. Below are a few practical examples that map to the guides in the documentation.
124
+
125
+ ### 1) API code generation using OpenAPI spec
126
+
127
+ ```shell
128
+ alpha api gen --spec-file specification/openapi.yaml --service-package my_app
129
+
130
+ alpha api run --port 8080
131
+ ```
132
+
133
+ ### 2) Authenticate with Keycloak (OIDC)
134
+
135
+ ```python
136
+ from alpha import KeyCloakOIDCConnector, KeyCloakProvider, PasswordCredentials
137
+
138
+ keycloak_connector = KeyCloakOIDCConnector(
139
+ base_url="https://keycloak.example.com",
140
+ realm="myrealm",
141
+ client_id="myclient",
142
+ client_secret="myclientsecret",
143
+ )
144
+
145
+ keycloak_provider = KeyCloakProvider(connector=keycloak_connector)
146
+
147
+ credentials = PasswordCredentials(username="user1", password="user1_password")
148
+ identity = keycloak_provider.authenticate(credentials)
149
+ ```
150
+
151
+ ### 3) Query data using SqlAlchemyDatabase + SqlAlchemyRepository
152
+
153
+ ```python
154
+ from alpha import SqlAlchemyDatabase, SqlAlchemyRepository
155
+ from my_app import User
156
+
157
+ db = SqlAlchemyDatabase(conn_str="postgresql://user:password@localhost:5432/mydatabase")
158
+
159
+ with db.get_session() as session:
160
+ users = SqlAlchemyRepository[User](session=session, default_model=User)
161
+ user = users.get_by_id(1)
162
+ ```
163
+
164
+ ### 4) Use Unit of Work for transactional operations
165
+
166
+ ```python
167
+ from alpha import (
168
+ RepositoryModel,
169
+ SqlAlchemyDatabase,
170
+ SqlAlchemyRepository,
171
+ SqlAlchemyUnitOfWork,
172
+ )
173
+ from my_app import User, OrmMapper
174
+
175
+ db = SqlAlchemyDatabase(..., mapper=OrmMapper)
176
+ repositories = [
177
+ RepositoryModel(
178
+ name="users",
179
+ repository=SqlAlchemyRepository[User],
180
+ default_model=User,
181
+ )
182
+ ]
183
+
184
+ uow = SqlAlchemyUnitOfWork(db=db, repos=repositories)
185
+
186
+ with uow:
187
+ user = uow.users.get_by_id(1)
188
+ ```
189
+
190
+ See also:
191
+
192
+ - Design principles and patterns: https://alpha-python.readthedocs.io/en/latest/concepts/design-principles/
193
+ - Dependency injection concept: https://alpha-python.readthedocs.io/en/latest/concepts/dependency-injection/
194
+ - API code generation guide: https://alpha-python.readthedocs.io/en/latest/guides/api-generation/
195
+ - Authentication guide: https://alpha-python.readthedocs.io/en/latest/guides/authentication/
196
+ - Database interaction guide: https://alpha-python.readthedocs.io/en/latest/guides/database-interaction/
197
+
198
+ ## Contributing
199
+
200
+ If you want to contribute to the development of this library, you can fork the repository and create a pull request with your changes.
201
+
202
+ ## Support
203
+
204
+ If Alpha saves you time in production, consider supporting development by buying me a coffee! Your support helps me to continue improving the library and adding new features. Thank you!
205
+
206
+ <a href="https://www.buymeacoffee.com/breijling"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=breijling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" /></a>
207
+
208
+ ## License
209
+
210
+ This library is licensed under the MIT License. See the LICENSE file for more information.
@@ -0,0 +1,153 @@
1
+ # Alpha
2
+
3
+ Alpha is intended to be the first dependency you need to add to your Python application. It is a Python library which contains standard building blocks that can be used in applications that are used as APIs and/or make use of database interaction.
4
+
5
+ ## Badges
6
+
7
+ [![PyPI version](https://badge.fury.io/py/alpha-python.svg?icon=si%3Apython)](https://badge.fury.io/py/alpha-python)
8
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/alpha-python.svg?label=PyPI%20downloads)](https://pypistats.org/packages/alpha-python)
9
+ [![Build Status](https://github.com/breijling/alpha/actions/workflows/python-app.yml/badge.svg?branch=main)](https://github.com/breijling/alpha/actions/workflows/python-app.yml)
10
+ [![Supported Python versions](https://img.shields.io/pypi/pyversions/alpha-python.svg?color=%2334D058)](https://pypi.org/project/alpha-python)
11
+ [![Coverage Status](https://coveralls.io/repos/github/BReijling/alpha/badge.svg?branch=main)](https://coveralls.io/github/BReijling/alpha?branch=main)
12
+ [![uv](https://img.shields.io/badge/package%20manager-uv-5C4EE5)](https://docs.astral.sh/uv/)
13
+ [![mypy](https://img.shields.io/badge/type%20check-mypy-2A6DB2)](https://mypy-lang.org/)
14
+ [![Pytest](https://img.shields.io/badge/testing-pytest-0A9EDC)](https://docs.pytest.org/)
15
+ [![PEP8](https://img.shields.io/badge/code%20style-pep8-orange.svg)](https://www.python.org/dev/peps/pep-0008/)
16
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
17
+ [![Documentation Status](https://readthedocs.org/projects/alpha-python/badge/?version=latest)](https://alpha-python.readthedocs.io/en/latest/)
18
+ [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)
19
+ [![Sponsor](https://img.shields.io/badge/Sponsor-GitHub-pink?logo=github)](https://github.com/sponsors/BReijling)
20
+
21
+ ## TL;DR
22
+
23
+ Alpha provides a comprehensive set of tools for building Python applications that interact with APIs and databases, including API code generation, authentication and authorization, database access layers, error handling, logging, and more. It is designed to be the first dependency you add to your project, providing a solid foundation for your application's architecture.
24
+
25
+ ## Documentation
26
+
27
+ Full documentation is available at [alpha-python.readthedocs.io](https://alpha-python.readthedocs.io/).
28
+
29
+ ## Installation
30
+
31
+ The library is still in development, but you can already install it using pip:
32
+
33
+ ```shell
34
+ pip install alpha-python
35
+ ```
36
+
37
+ If you want to use the alpha cli for generating API code, you can install it using pip as well:
38
+
39
+ ```shell
40
+ pip install alpha-python[api-generator]
41
+ ```
42
+
43
+ If you want to add the library to your API project, you can add it to your pyproject.toml file:
44
+
45
+ ```shell
46
+ # Poetry example
47
+ poetry add alpha-python --extras "flask, postgresql"
48
+ poetry add --dev alpha-python --extras "api-generator"
49
+
50
+ # UV example
51
+ uv add alpha-python --extra flask --extra postgresql
52
+ uv add --dev alpha-python --extra api-generator
53
+ ```
54
+
55
+ ## Features
56
+
57
+ - API code generation
58
+ - Authentication and authorization
59
+ - Database interaction
60
+ - Logging
61
+ - Error handling
62
+ - And much more!
63
+
64
+ ## Usage
65
+
66
+ The library contains many components. Below are a few practical examples that map to the guides in the documentation.
67
+
68
+ ### 1) API code generation using OpenAPI spec
69
+
70
+ ```shell
71
+ alpha api gen --spec-file specification/openapi.yaml --service-package my_app
72
+
73
+ alpha api run --port 8080
74
+ ```
75
+
76
+ ### 2) Authenticate with Keycloak (OIDC)
77
+
78
+ ```python
79
+ from alpha import KeyCloakOIDCConnector, KeyCloakProvider, PasswordCredentials
80
+
81
+ keycloak_connector = KeyCloakOIDCConnector(
82
+ base_url="https://keycloak.example.com",
83
+ realm="myrealm",
84
+ client_id="myclient",
85
+ client_secret="myclientsecret",
86
+ )
87
+
88
+ keycloak_provider = KeyCloakProvider(connector=keycloak_connector)
89
+
90
+ credentials = PasswordCredentials(username="user1", password="user1_password")
91
+ identity = keycloak_provider.authenticate(credentials)
92
+ ```
93
+
94
+ ### 3) Query data using SqlAlchemyDatabase + SqlAlchemyRepository
95
+
96
+ ```python
97
+ from alpha import SqlAlchemyDatabase, SqlAlchemyRepository
98
+ from my_app import User
99
+
100
+ db = SqlAlchemyDatabase(conn_str="postgresql://user:password@localhost:5432/mydatabase")
101
+
102
+ with db.get_session() as session:
103
+ users = SqlAlchemyRepository[User](session=session, default_model=User)
104
+ user = users.get_by_id(1)
105
+ ```
106
+
107
+ ### 4) Use Unit of Work for transactional operations
108
+
109
+ ```python
110
+ from alpha import (
111
+ RepositoryModel,
112
+ SqlAlchemyDatabase,
113
+ SqlAlchemyRepository,
114
+ SqlAlchemyUnitOfWork,
115
+ )
116
+ from my_app import User, OrmMapper
117
+
118
+ db = SqlAlchemyDatabase(..., mapper=OrmMapper)
119
+ repositories = [
120
+ RepositoryModel(
121
+ name="users",
122
+ repository=SqlAlchemyRepository[User],
123
+ default_model=User,
124
+ )
125
+ ]
126
+
127
+ uow = SqlAlchemyUnitOfWork(db=db, repos=repositories)
128
+
129
+ with uow:
130
+ user = uow.users.get_by_id(1)
131
+ ```
132
+
133
+ See also:
134
+
135
+ - Design principles and patterns: https://alpha-python.readthedocs.io/en/latest/concepts/design-principles/
136
+ - Dependency injection concept: https://alpha-python.readthedocs.io/en/latest/concepts/dependency-injection/
137
+ - API code generation guide: https://alpha-python.readthedocs.io/en/latest/guides/api-generation/
138
+ - Authentication guide: https://alpha-python.readthedocs.io/en/latest/guides/authentication/
139
+ - Database interaction guide: https://alpha-python.readthedocs.io/en/latest/guides/database-interaction/
140
+
141
+ ## Contributing
142
+
143
+ If you want to contribute to the development of this library, you can fork the repository and create a pull request with your changes.
144
+
145
+ ## Support
146
+
147
+ If Alpha saves you time in production, consider supporting development by buying me a coffee! Your support helps me to continue improving the library and adding new features. Thank you!
148
+
149
+ <a href="https://www.buymeacoffee.com/breijling"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=breijling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" /></a>
150
+
151
+ ## License
152
+
153
+ This library is licensed under the MIT License. See the LICENSE file for more information.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "alpha-python"
3
- version = "0.6.0"
3
+ version = "0.6.1"
4
4
  description = "Alpha is intended to be the first dependency you need to add to your Python application. It is a Python library which contains standard building blocks that can be used in applications that are used as APIs and/or make use of database interaction."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -80,7 +80,10 @@ dev = [
80
80
  "ipykernel>=7.2.0",
81
81
  "flask<2",
82
82
  "httpx>=0.28.1",
83
- "tox>=4.53.0",
83
+ "tox>=4.0.0",
84
+ "types-ldap3",
85
+ "types-requests",
86
+ "pandas-stubs",
84
87
  ]
85
88
  # docs = [
86
89
  # "mkdocs-material>=9.5",
@@ -156,7 +159,8 @@ source = ["src"]
156
159
  omit = [
157
160
  "tests/*",
158
161
  "__init__.py",
159
- "_http_codes.py"
162
+ "_http_codes.py",
163
+ "src/alpha/utils/openapi_test/*"
160
164
  ]
161
165
 
162
166
  [tool.black]
@@ -172,10 +176,13 @@ force_grid_wrap = 0
172
176
 
173
177
  [tool.mypy]
174
178
  python_version = "3.11"
175
- exclude = ['^tests/']
179
+ exclude = ["^tests/", "src/alpha/utils/openapi_test"]
176
180
 
177
181
  [[tool.mypy.overrides]]
178
- module = ["flask", "flask.*"]
182
+ module = [
183
+ "flask",
184
+ "flask.*",
185
+ ]
179
186
  ignore_missing_imports = true
180
187
 
181
188
  [tool.ruff]
@@ -20,18 +20,18 @@ def main(sections: list[Section] = Provide[Container.sections]) -> None:
20
20
 
21
21
  # Create the main parser
22
22
  parser = argparse.ArgumentParser(
23
- description='Alpha command line interface.',
23
+ description="Alpha command line interface.",
24
24
  formatter_class=argparse.ArgumentDefaultsHelpFormatter,
25
25
  )
26
26
  subparsers = parser.add_subparsers(
27
- title='Use one of the sub categories to run commands on',
28
- dest='section',
27
+ title="Use one of the sub categories to run commands on",
28
+ dest="section",
29
29
  )
30
30
 
31
31
  # Parser dict to store in all parsers to match later on when finding a
32
32
  # handler.
33
- section_parsers = {}
34
- command_parsers = {}
33
+ section_parsers: dict[str, argparse.ArgumentParser] = {}
34
+ command_parsers: dict[str, dict[str, argparse.ArgumentParser]] = {}
35
35
 
36
36
  # Create all sections
37
37
  for section in sections:
@@ -43,7 +43,7 @@ def main(sections: list[Section] = Provide[Container.sections]) -> None:
43
43
  formatter_class=argparse.ArgumentDefaultsHelpFormatter,
44
44
  )
45
45
  section_subparser = section_parsers[section.name].add_subparsers(
46
- dest='command'
46
+ dest="command"
47
47
  )
48
48
 
49
49
  # Create all commands per section
@@ -88,8 +88,8 @@ def main(sections: list[Section] = Provide[Container.sections]) -> None:
88
88
  # Get all arguments and remove the section and command so they can be
89
89
  # 'kwarged' into the Handler set_arguments function.
90
90
  handler_args = vars(args)
91
- del handler_args['section']
92
- del handler_args['command']
91
+ del handler_args["section"]
92
+ del handler_args["command"]
93
93
 
94
94
  # Find the right handler
95
95
  for section in sections:
@@ -102,7 +102,7 @@ def main(sections: list[Section] = Provide[Container.sections]) -> None:
102
102
  command.handler.handle_command()
103
103
  return
104
104
 
105
- print('No handler found, you should never read this')
105
+ print("No handler found, you should never read this")
106
106
  return
107
107
 
108
108
 
@@ -118,53 +118,57 @@ def _guess_current_package_name() -> str:
118
118
  """
119
119
 
120
120
  cwd = os.getcwd()
121
- pyproject_path = os.path.join(cwd, 'pyproject.toml')
121
+ pyproject_path = os.path.join(cwd, "pyproject.toml")
122
122
 
123
123
  # look for pyproject.toml file in subfolders
124
124
  if not os.path.isfile(pyproject_path):
125
125
  for entry in os.scandir(cwd):
126
126
  if not entry.is_dir():
127
127
  continue
128
- possible_path = os.path.join(entry.path, 'pyproject.toml')
128
+ possible_path = os.path.join(entry.path, "pyproject.toml")
129
129
  if os.path.isfile(possible_path):
130
130
  pyproject_path = possible_path
131
131
  break
132
132
 
133
133
  if os.path.isfile(pyproject_path):
134
134
  try:
135
- with open(pyproject_path, 'rb') as f:
135
+ with open(pyproject_path, "rb") as f:
136
136
  pyproject_data = tomllib.load(f)
137
137
  name = None
138
138
  try:
139
- if 'project' in pyproject_data:
140
- name = pyproject_data['project']['name']
141
- elif 'tool' in pyproject_data and 'poetry' in pyproject_data['tool']:
142
- name = pyproject_data['tool']['poetry']['name']
139
+ if "project" in pyproject_data:
140
+ name = pyproject_data["project"]["name"]
141
+ elif (
142
+ "tool" in pyproject_data
143
+ and "poetry" in pyproject_data["tool"]
144
+ ):
145
+ name = pyproject_data["tool"]["poetry"]["name"]
143
146
  if name is not None:
144
- return name.replace('-', '_')
147
+ return name.replace("-", "_")
145
148
  except KeyError:
146
- print('Could not find project name in pyproject.toml')
149
+ print("Could not find project name in pyproject.toml")
147
150
  except Exception:
148
151
  pass
149
152
  else:
150
- print('Could not find pyproject.toml')
153
+ print("Could not find pyproject.toml")
151
154
 
152
155
  # Fallback to use the current folder name
153
- print('Guessing package name from folder')
156
+ print("Guessing package name from folder")
154
157
  return os.path.basename(cwd)
155
158
 
159
+
156
160
  def init() -> None:
157
161
  """Init the container and wire it to the main function."""
158
162
  container = Container()
159
163
  guessed_name = _guess_current_package_name()
160
164
  if guessed_name:
161
- container.config.api_package_name.from_value(f'{guessed_name}_api')
165
+ container.config.api_package_name.from_value(f"{guessed_name}_api")
162
166
  container.config.service_package_name.from_value(guessed_name)
163
167
  container.config.container_import.from_value(
164
- f'from {guessed_name}.containers.container import Container'
168
+ f"from {guessed_name}.containers.container import Container"
165
169
  )
166
170
  container.config.init_container_from.from_value(guessed_name)
167
- container.config.init_container_function.from_value('init_container')
171
+ container.config.init_container_function.from_value("init_container")
168
172
  container.wire(modules=[sys.modules[__name__]])
169
173
 
170
174
  main()
@@ -10,9 +10,10 @@ from json import encoder
10
10
  from typing import Any
11
11
  from uuid import UUID
12
12
 
13
- import numpy as np
14
- import pandas as pd
15
- import six
13
+ import numpy as np # type: ignore[import-untyped]
14
+ import pandas as pd # type: ignore[import-untyped]
15
+ import six # type: ignore[import-untyped]
16
+
16
17
 
17
18
  from alpha.interfaces.openapi_model import OpenAPIModel
18
19
 
@@ -34,7 +34,10 @@ class JWTFactory:
34
34
  Parameters
35
35
  ----------
36
36
  secret
37
- The secret key used to sign the JWT.
37
+ The secret key used to sign the JWT. A secret value should be a
38
+ minimum of 32 characters for security reasons. This value should be
39
+ kept confidential and not exposed in the source code or version
40
+ control system.
38
41
  lifetime_hours
39
42
  The lifetime of the JWT in hours, by default None. This parameter
40
43
  is ignored if lifetime_seconds is provided. The parameter is
@@ -71,13 +74,13 @@ class JWTFactory:
71
74
  stacklevel=2,
72
75
  )
73
76
 
74
- if lifetime_seconds is None and lifetime_hours is None:
75
- lifetime_seconds = (
76
- 900 # Default to 15 minutes if no lifetime is provided
77
- )
78
- elif lifetime_seconds is None and lifetime_hours is not None:
77
+ if lifetime_seconds is None and lifetime_hours is not None:
79
78
  lifetime_seconds = 3600 * int(lifetime_hours)
80
79
 
80
+ lifetime_seconds = (
81
+ 900 if lifetime_seconds is None else lifetime_seconds
82
+ ) # Default to 15 minutes if no lifetime is provided
83
+
81
84
  self.JWT_SECRET: str = secret
82
85
  self.JWT_ISSUER = issuer
83
86
  self.JWT_ALGORITHM = jwt_algorithm
@@ -113,7 +116,7 @@ class JWTFactory:
113
116
  The generated JWT token as a string.
114
117
  """
115
118
  now = datetime.now(tz=timezone.utc)
116
- exp = now + timedelta(seconds=self.JWT_LIFETIME_SECONDS)
119
+ exp = now + timedelta(seconds=float(self.JWT_LIFETIME_SECONDS))
117
120
 
118
121
  token_payload: dict[str, Any] = {
119
122
  "sub": subject,
@@ -11,6 +11,11 @@ from alpha import exceptions
11
11
  class PasswordFactory:
12
12
  """This class provides methods for hashing and verifying passwords using
13
13
  the argon2 library.
14
+
15
+ Keep in mind that changing the password hasher in a production environment
16
+ may lead to issues with existing password hashes, so it is recommended to
17
+ use the default hasher unless you have specific requirements. Or configure
18
+ the password hasher before you deploy your application to production.
14
19
  """
15
20
 
16
21
  def __init__(
@@ -22,7 +27,9 @@ class PasswordFactory:
22
27
  ----------
23
28
  password_hasher
24
29
  An optional password hasher instance. If not provided, a default
25
- argon2.PasswordHasher with a salt length of 16 will be used.
30
+ argon2.PasswordHasher with a salt length of 16 will be used. This
31
+ allows for flexibility in case you want to use a custom password
32
+ hasher.
26
33
  """
27
34
  self._password_hasher = password_hasher or argon2.PasswordHasher(
28
35
  salt_len=16
@@ -187,6 +187,11 @@ class ApiGenerateHandler(BaseHandler):
187
187
  """Copy mustache templates to the templates folder in the working
188
188
  directory
189
189
  """
190
+ if self.generator_name is None:
191
+ raise InvalidArgumentsException(
192
+ "Generator name is required to copy templates."
193
+ )
194
+
190
195
  shutil.rmtree(self.project_templates_folder, ignore_errors=True)
191
196
  shutil.copytree(
192
197
  src=os.path.join(