alpha-python 0.7.7__tar.gz → 0.7.9__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 (159) hide show
  1. {alpha_python-0.7.7 → alpha_python-0.7.9}/PKG-INFO +1 -1
  2. {alpha_python-0.7.7 → alpha_python-0.7.9}/pyproject.toml +1 -1
  3. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/user.py +13 -0
  4. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/field_iterator.py +3 -0
  5. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/request_factory.py +6 -2
  6. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/__main__.mustache +31 -10
  7. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/connectors/sql_alchemy.py +2 -2
  8. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/models/identity.py +13 -6
  9. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/services/authentication_service.py +2 -1
  10. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/container.py +4 -1
  11. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/models.py +72 -3
  12. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/service.py +34 -50
  13. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha_python.egg-info/PKG-INFO +1 -1
  14. {alpha_python-0.7.7 → alpha_python-0.7.9}/LICENSE +0 -0
  15. {alpha_python-0.7.7 → alpha_python-0.7.9}/README.md +0 -0
  16. {alpha_python-0.7.7 → alpha_python-0.7.9}/setup.cfg +0 -0
  17. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/__init__.py +0 -0
  18. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/adapters/__init__.py +0 -0
  19. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/adapters/rest_api_unit_of_work.py +0 -0
  20. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/adapters/sqla_unit_of_work.py +0 -0
  21. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/cli.py +0 -0
  22. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/containers/__init__.py +0 -0
  23. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/containers/container.py +0 -0
  24. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/__init__.py +0 -0
  25. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/__init__.py +0 -0
  26. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/base_model.py +0 -0
  27. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/group.py +0 -0
  28. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/life_cycle_base.py +0 -0
  29. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/permission.py +0 -0
  30. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/domain/models/role.py +0 -0
  31. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/encoder.py +0 -0
  32. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/exceptions.py +0 -0
  33. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/__init__.py +0 -0
  34. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/_type_conversion_matrix.py +0 -0
  35. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/_type_mapping.py +0 -0
  36. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/class_factories.py +0 -0
  37. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/default_field_factory.py +0 -0
  38. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/jwt_factory.py +0 -0
  39. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/logging_handler_factory.py +0 -0
  40. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/model_class_factory.py +0 -0
  41. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/models/__init__.py +0 -0
  42. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/models/factory_classes.py +0 -0
  43. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/password_factory.py +0 -0
  44. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/response_factory.py +0 -0
  45. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/factories/type_factories.py +0 -0
  46. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/__init__.py +0 -0
  47. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/api_generate_handler.py +0 -0
  48. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/api_run_handler.py +0 -0
  49. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/base_handler.py +0 -0
  50. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/gen-code.sh +0 -0
  51. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/models/__init__.py +0 -0
  52. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/models/argument.py +0 -0
  53. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/models/command.py +0 -0
  54. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/models/section.py +0 -0
  55. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/models/subparser.py +0 -0
  56. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/run-api.sh +0 -0
  57. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/__init__.py +0 -0
  58. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/Dockerfile.mustache +0 -0
  59. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/README.mustache +0 -0
  60. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/__init__model.mustache +0 -0
  61. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/__init__test.mustache +0 -0
  62. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/base_model.mustache +0 -0
  63. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/controller.mustache +0 -0
  64. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/controller_test.mustache +0 -0
  65. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/dockerignore.mustache +0 -0
  66. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/encoder.mustache +0 -0
  67. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/git_push.sh.mustache +0 -0
  68. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/gitignore.mustache +0 -0
  69. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/model.mustache +0 -0
  70. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/openapi.mustache +0 -0
  71. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/param_type.mustache +0 -0
  72. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/requirements.mustache +0 -0
  73. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/security_controller_.mustache +0 -0
  74. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/setup.mustache +0 -0
  75. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/test-requirements.mustache +0 -0
  76. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/tox.mustache +0 -0
  77. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/travis.mustache +0 -0
  78. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/typing_utils.mustache +0 -0
  79. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/handlers/templates/python-flask/util.mustache +0 -0
  80. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/__init__.py +0 -0
  81. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/connectors/__init__.py +0 -0
  82. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/connectors/ldap_connector.py +0 -0
  83. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/connectors/oidc_connector.py +0 -0
  84. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/databases/__init__.py +0 -0
  85. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/databases/sql_alchemy.py +0 -0
  86. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/models/__init__.py +0 -0
  87. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/models/filter_operators.py +0 -0
  88. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/models/json_patch.py +0 -0
  89. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/models/order_by.py +0 -0
  90. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/models/query_clause.py +0 -0
  91. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/infra/models/search_filter.py +0 -0
  92. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/__init__.py +0 -0
  93. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/api_repository.py +0 -0
  94. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/attrs_instance.py +0 -0
  95. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/dataclass_instance.py +0 -0
  96. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/factories.py +0 -0
  97. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/handler.py +0 -0
  98. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/http_client.py +0 -0
  99. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/openapi_model.py +0 -0
  100. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/patchable.py +0 -0
  101. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/providers.py +0 -0
  102. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/pydantic_instance.py +0 -0
  103. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/refresh_repository.py +0 -0
  104. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/sql_database.py +0 -0
  105. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/sql_mapper.py +0 -0
  106. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/sql_repository.py +0 -0
  107. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/token_factory.py +0 -0
  108. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/unit_of_work.py +0 -0
  109. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/interfaces/updatable.py +0 -0
  110. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/mixins/__init__.py +0 -0
  111. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/mixins/group_lifecycle.py +0 -0
  112. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/mixins/jwt_provider.py +0 -0
  113. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/mixins/user_lifecycle.py +0 -0
  114. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/__init__.py +0 -0
  115. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/api_key_provider.py +0 -0
  116. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/database_provider.py +0 -0
  117. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/ldap_provider.py +0 -0
  118. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/models/__init__.py +0 -0
  119. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/models/credentials.py +0 -0
  120. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/models/token.py +0 -0
  121. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/providers/oidc_provider.py +0 -0
  122. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/py.typed +0 -0
  123. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/__init__.py +0 -0
  124. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/models/__init__.py +0 -0
  125. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/models/repository_model.py +0 -0
  126. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/refresh/__init__.py +0 -0
  127. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/refresh/cache_repository.py +0 -0
  128. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/refresh/database_repository.py +0 -0
  129. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/refresh/file_repository.py +0 -0
  130. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/refresh/memory_repository.py +0 -0
  131. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/rest_api_repository.py +0 -0
  132. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/repositories/sql_alchemy_repository.py +0 -0
  133. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/services/__init__.py +0 -0
  134. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/services/models/__init__.py +0 -0
  135. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/services/models/cookie.py +0 -0
  136. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/services/user_lifecycle_management.py +0 -0
  137. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/__init__.py +0 -0
  138. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/_http_codes.py +0 -0
  139. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/cookie.py +0 -0
  140. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/is_attrs.py +0 -0
  141. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/is_pydantic.py +0 -0
  142. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/logging_configurator.py +0 -0
  143. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/logging_level_checker.py +0 -0
  144. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/__init__.py +0 -0
  145. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/exceptions.py +0 -0
  146. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/orm.py +0 -0
  147. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/openapi_test/response.py +0 -0
  148. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/request_headers.py +0 -0
  149. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/response_object.py +0 -0
  150. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/secret_generator.py +0 -0
  151. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/verify_identity.py +0 -0
  152. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha/utils/version_checker.py +0 -0
  153. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha_python.egg-info/SOURCES.txt +0 -0
  154. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha_python.egg-info/dependency_links.txt +0 -0
  155. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha_python.egg-info/entry_points.txt +0 -0
  156. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha_python.egg-info/requires.txt +0 -0
  157. {alpha_python-0.7.7 → alpha_python-0.7.9}/src/alpha_python.egg-info/top_level.txt +0 -0
  158. {alpha_python-0.7.7 → alpha_python-0.7.9}/tests/test_cli.py +0 -0
  159. {alpha_python-0.7.7 → alpha_python-0.7.9}/tests/test_encoder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alpha-python
3
- Version: 0.7.7
3
+ Version: 0.7.9
4
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
5
  Author-email: Bart Reijling <bart@reijling.eu>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "alpha-python"
3
- version = "0.7.7"
3
+ version = "0.7.9"
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 = [
@@ -205,3 +205,16 @@ class User(LifeCycleBase, BaseDomainModel):
205
205
  self.admin = obj.admin
206
206
 
207
207
  return cast(DomainModel, self)
208
+
209
+ def update_from_identity(self, identity: Identity) -> Self:
210
+ """Update the User instance with data from an Identity instance. Only
211
+ the email and display name are updated.
212
+
213
+ Parameters
214
+ ----------
215
+ identity
216
+ Identity object to update from.
217
+ """
218
+ self.email = identity.email
219
+ self.display_name = identity.display_name
220
+ return self
@@ -131,6 +131,8 @@ class Field:
131
131
 
132
132
  Parameters
133
133
  ----------
134
+ key
135
+ Name of the pydantic field
134
136
  obj
135
137
  pydantic Field
136
138
 
@@ -140,6 +142,7 @@ class Field:
140
142
  Field object
141
143
  """
142
144
  init = getattr(obj, "init", True)
145
+ init = init if init is not None else True
143
146
  type = getattr(obj, "annotation", None)
144
147
  default = getattr(obj, "default", MISSING)
145
148
 
@@ -160,7 +160,9 @@ class RequestFactory:
160
160
  for item in value
161
161
  ]
162
162
 
163
- if isinstance(cls, DataclassInstance):
163
+ if isinstance(
164
+ cls, (DataclassInstance | AttrsInstance | PydanticInstance)
165
+ ):
164
166
  return self._to_dataclass(value=value, cls=cls)
165
167
 
166
168
  if isinstance(cls, type(Enum)):
@@ -181,7 +183,9 @@ class RequestFactory:
181
183
  return value
182
184
 
183
185
  def _to_dataclass(
184
- self, value: OpenAPIModel | Any, cls: DataclassInstance
186
+ self,
187
+ value: OpenAPIModel | Any,
188
+ cls: DataclassInstance | AttrsInstance | PydanticInstance,
185
189
  ) -> (
186
190
  DataclassInstance
187
191
  | AttrsInstance
@@ -36,9 +36,6 @@ if os.getenv('FLASK_ENV') != 'production':
36
36
 
37
37
  app = connexion.App(__name__, specification_dir='./openapi/')
38
38
  app.app.json_encoder = JSONEncoder
39
- app.add_api('openapi.yaml',
40
- arguments={'title': '{{appName}}'},
41
- pythonic_params=True)
42
39
 
43
40
  compress = Compress()
44
41
  compress.init_app(app.app)
@@ -57,19 +54,37 @@ LoggingConfigurator(
57
54
  )
58
55
  {{/disableLoggingConfigurator}}
59
56
  {{#featureCORS}}
60
- cors_origins = container.config.cors.origins()
61
- if cors_origins is None:
57
+ origins = container.config.cors.origins()
58
+ supports_credentials = container.config.cors.supports_credentials()
59
+
60
+ if origins is None:
62
61
  logging.info(
63
62
  "CORS origins not configured, defaulting to allow all origins"
64
63
  )
65
- cors_origins = ["*"]
66
- logging.info(f"Enabling CORS for origins: {cors_origins}")
67
- CORS(app.app, origins=cors_origins)
64
+ origins = ["*"]
65
+ logging.info(f"Enabling CORS for origins: {origins}")
66
+ CORS(
67
+ app.app,
68
+ origins=origins,
69
+ supports_credentials=supports_credentials or False,
70
+ resources=container.config.cors.resources() or r"/*",
71
+ methods=container.config.cors.methods() or ["GET", "HEAD", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"],
72
+ allow_headers=container.config.cors.allow_headers() or "*",
73
+ expose_headers=container.config.cors.expose_headers(),
74
+ max_age=container.config.cors.max_age(),
75
+ vary_header=container.config.cors.vary_header() or True,
76
+ send_wildcard=container.config.cors.send_wildcard() or False,
77
+ )
68
78
  {{/featureCORS}}
69
-
70
- app.container = container
71
79
  {{/initContainerFunction}}
72
80
 
81
+ app.add_api(
82
+ 'openapi.yaml',
83
+ arguments={'title': '{{appName}}'},
84
+ pythonic_params=True
85
+ )
86
+ {{#initContainerFunction}}app.container = container{{/initContainerFunction}}
87
+
73
88
 
74
89
  @app.app.after_request
75
90
  def add_headers(response: Response):
@@ -93,6 +108,12 @@ def add_headers(response: Response):
93
108
  ):
94
109
  continue
95
110
  response.headers[header] = value
111
+ {{#featureCORS}}
112
+ request_origin = request.headers.get("Origin", None)
113
+ if supports_credentials and request_origin:
114
+ response.headers["Access-Control-Allow-Origin"] = request_origin
115
+ response.headers["Access-Control-Allow-Credentials"] = "true"
116
+ {{/featureCORS}}
96
117
  return response
97
118
 
98
119
  logging.info(f'Started {{servicePackage}} API on \'{socket.gethostname()}\'')
@@ -32,7 +32,7 @@ class SqlAlchemyDatabase:
32
32
  db_name
33
33
  Database name, by default ""
34
34
  db_type
35
- Database type, by default "postgresql"
35
+ Database type and driver, by default "postgresql+psycopg2"
36
36
  conn_str
37
37
  Connection string. Can be used instead of host, port, username,
38
38
  password, and db_name, by default None
@@ -55,7 +55,7 @@ class SqlAlchemyDatabase:
55
55
  username: str = "",
56
56
  password: str = "",
57
57
  db_name: str = "",
58
- db_type: str = "postgresql",
58
+ db_type: str = "postgresql+psycopg2",
59
59
  conn_str: str | None = None,
60
60
  schema_name: str = "public",
61
61
  create_schema: bool = True,
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
+ from enum import Enum
4
5
  from typing import Mapping, Any, Self, Sequence, TYPE_CHECKING, cast
5
6
  from datetime import datetime, timezone
6
7
 
@@ -321,18 +322,24 @@ class Identity:
321
322
  User object to update from.
322
323
  """
323
324
  self.username = user.username
324
- if not self.email:
325
- self.email = user.email
326
- if not self.display_name:
327
- self.display_name = user.display_name
325
+ self.role = (
326
+ user.role.name if isinstance(user.role, Enum) else user.role
327
+ )
328
+ self.admin = user.admin
328
329
  for permission in user.permissions or []:
329
330
  self.permissions = self._append_on_sequence(
330
331
  self.permissions, str(permission)
331
332
  )
332
333
  for group in user.groups or []:
333
334
  self.groups = self._append_on_sequence(self.groups, str(group))
334
- self.role = user.role # type: ignore
335
- self.admin = user.admin
335
+
336
+ # Update email and display name only if they are not already set. This
337
+ # ensures that existing values which are provided by an identity
338
+ # provider are not overwritten.
339
+ if not self.email:
340
+ self.email = user.email
341
+ if not self.display_name:
342
+ self.display_name = user.display_name
336
343
 
337
344
  def update_from_groups(self, groups: list[Group]) -> None:
338
345
  """Update the Identity permissions with data from a list of Group
@@ -622,12 +622,13 @@ class AuthenticationService:
622
622
  )
623
623
  if user:
624
624
  identity.update_from_user(user)
625
+ user.update_from_identity(identity)
625
626
 
626
627
  else:
627
628
  # Create new user from identity if not found in database
628
629
  user = self._user_model.from_identity(identity)
629
630
  users.add(user)
630
- self.uow.commit()
631
+ self.uow.commit()
631
632
 
632
633
  return identity
633
634
 
@@ -147,7 +147,9 @@ def init_container():
147
147
  "username": os.getenv("TEST_PSQL_USERNAME", "postgres"),
148
148
  "password": os.getenv("TEST_PSQL_PASSWORD", "postgres"),
149
149
  "db_name": os.getenv("TEST_PSQL_DB_NAME", "postgres"),
150
- "db_type": os.getenv("TEST_PSQL_DB_TYPE", "postgresql"),
150
+ "db_type": os.getenv(
151
+ "TEST_PSQL_DB_TYPE", "postgresql+psycopg2"
152
+ ),
151
153
  },
152
154
  "authentication": {
153
155
  "use_cookies": True,
@@ -175,6 +177,7 @@ def init_container():
175
177
  },
176
178
  "cors": {
177
179
  "origins": ["*"],
180
+ "supports_credentials": True,
178
181
  },
179
182
  "jwt": {
180
183
  "secret": "supersecretkey0123456789",
@@ -1,7 +1,10 @@
1
- from dataclasses import dataclass
2
- from datetime import datetime, timedelta, timezone
3
- from typing import Any, Literal, Self, Sequence
1
+ from datetime import datetime, timedelta, timezone, date
2
+ from typing import Any, Literal, Self, Sequence, Optional, Type, TypeVar
4
3
  from uuid import UUID
4
+ from dataclasses import dataclass, field
5
+ from attrs import define
6
+ from pydantic import BaseModel
7
+ from enum import Enum, auto
5
8
 
6
9
  from alpha.domain.models.base_model import BaseDomainModel
7
10
  from alpha.providers.models.identity import Identity
@@ -59,6 +62,9 @@ class TestUser(LifeCycleBase, BaseDomainModel):
59
62
  display_name=identity.display_name,
60
63
  )
61
64
 
65
+ def update_from_identity(self, identity: Identity) -> None:
66
+ return None
67
+
62
68
 
63
69
  @dataclass
64
70
  class TestToken(BaseDomainModel):
@@ -119,3 +125,66 @@ class TestToken(BaseDomainModel):
119
125
  obj["expires_at"] = self.expires_at.isoformat()
120
126
 
121
127
  return obj
128
+
129
+
130
+ P = TypeVar("P", bound="Pet")
131
+
132
+
133
+ class PetType(Enum):
134
+ NONE = 0
135
+ DOG = auto()
136
+ CAT = auto()
137
+ RABBIT = auto()
138
+
139
+
140
+ @dataclass
141
+ class Pet:
142
+ name: str
143
+ pet_type: PetType
144
+ date_of_birth: date
145
+ weight: Optional[float] = None
146
+ good_boy: Optional[bool] = None
147
+ id: int = field(default=1)
148
+
149
+ @property
150
+ def age(self) -> int:
151
+ delta = date(2022, 2, 2) - self.date_of_birth
152
+ return delta.days // 365
153
+
154
+ def to_dict(self) -> dict[str, Any]:
155
+ return {
156
+ "id": 1,
157
+ "name": self.name,
158
+ "pet_type": self.pet_type.name,
159
+ "age": self.age,
160
+ "weight": self.weight,
161
+ "good_boy": self.good_boy,
162
+ }
163
+
164
+ @classmethod
165
+ def factory(cls: Type[P], **kwargs) -> P:
166
+ return cls(
167
+ name=kwargs["name"],
168
+ pet_type=PetType[kwargs["pet_type"]],
169
+ date_of_birth=kwargs["date_of_birth"],
170
+ good_boy=kwargs["good_boy"],
171
+ )
172
+
173
+
174
+ @define
175
+ class AttrsPet:
176
+ name: str
177
+ pet_type: PetType
178
+ date_of_birth: date
179
+ weight: Optional[float] = None
180
+ good_boy: Optional[bool] = None
181
+ id: int = 1
182
+
183
+
184
+ class PydanticPet(BaseModel):
185
+ name: str
186
+ pet_type: PetType
187
+ date_of_birth: date
188
+ weight: Optional[float] = None
189
+ good_boy: Optional[bool] = None
190
+ id: int = 1
@@ -1,9 +1,6 @@
1
1
  from copy import deepcopy
2
2
  import datetime
3
- from dataclasses import dataclass, field
4
- from enum import Enum, auto
5
- from typing import Any, Optional, Type, TypeVar
6
-
3
+ from typing import Any
7
4
  import dateutil
8
5
  from werkzeug.datastructures import FileStorage
9
6
 
@@ -23,52 +20,10 @@ from alpha.exceptions import (
23
20
  UnauthorizedException,
24
21
  UnprocessableContentException,
25
22
  )
23
+ from alpha.utils.openapi_test.models import AttrsPet, Pet, PetType, PydanticPet
26
24
 
27
25
  from . import exceptions
28
26
 
29
- P = TypeVar("P", bound="Pet")
30
-
31
-
32
- class PetType(Enum):
33
- NONE = 0
34
- DOG = auto()
35
- CAT = auto()
36
- RABBIT = auto()
37
-
38
-
39
- @dataclass
40
- class Pet:
41
- name: str
42
- pet_type: PetType
43
- date_of_birth: datetime.date
44
- weight: Optional[float] = None
45
- good_boy: Optional[bool] = None
46
- id: int = field(default=1)
47
-
48
- @property
49
- def age(self) -> int:
50
- delta = datetime.date(2022, 2, 2) - self.date_of_birth
51
- return delta.days // 365
52
-
53
- def to_dict(self) -> dict[str, Any]:
54
- return {
55
- "id": 1,
56
- "name": self.name,
57
- "pet_type": self.pet_type.name,
58
- "age": self.age,
59
- "weight": self.weight,
60
- "good_boy": self.good_boy,
61
- }
62
-
63
- @classmethod
64
- def factory(cls: Type[P], **kwargs) -> P:
65
- return cls(
66
- name=kwargs["name"],
67
- pet_type=PetType[kwargs["pet_type"]],
68
- date_of_birth=kwargs["date_of_birth"],
69
- good_boy=kwargs["good_boy"],
70
- )
71
-
72
27
 
73
28
  class TestService:
74
29
  @staticmethod
@@ -103,15 +58,44 @@ class TestService:
103
58
  "The object is not an instance of Pet"
104
59
  )
105
60
 
61
+ def check_attrs_class(self, pet: AttrsPet) -> AttrsPet:
62
+ if isinstance(pet, AttrsPet):
63
+ return pet
64
+ raise exceptions.InvalidInstance(
65
+ "The object is not an instance of AttrsPet; received type: "
66
+ f"{type(pet)}"
67
+ )
68
+
69
+ def check_pydantic_class(self, pet: PydanticPet) -> PydanticPet:
70
+ if isinstance(pet, PydanticPet):
71
+ return pet
72
+ raise exceptions.InvalidInstance(
73
+ "The object is not an instance of PydanticPet; received type: "
74
+ f"{type(pet)}"
75
+ )
76
+
106
77
  def check_dataclass_return_list(self, pet: Pet) -> list[Pet]:
107
78
  if isinstance(pet, Pet):
108
79
  pet2 = deepcopy(pet)
109
80
  pet2.id = 2
110
81
  pet2.name = "Dug"
111
82
  return [pet, pet2]
112
- # raise exceptions.InvalidInstance(
113
- # "The object is not an instance of Pet"
114
- # )
83
+
84
+ def check_attrs_class_return_list(self, pet: AttrsPet) -> list[AttrsPet]:
85
+ if isinstance(pet, AttrsPet):
86
+ pet2 = deepcopy(pet)
87
+ pet2.id = 2
88
+ pet2.name = "Dug"
89
+ return [pet, pet2]
90
+
91
+ def check_pydantic_class_return_list(
92
+ self, pet: PydanticPet
93
+ ) -> list[PydanticPet]:
94
+ if isinstance(pet, PydanticPet):
95
+ pet2 = deepcopy(pet)
96
+ pet2.id = 2
97
+ pet2.name = "Dug"
98
+ return [pet, pet2]
115
99
 
116
100
  def handle4xx(self, pet: Pet) -> Any:
117
101
  if pet.weight and pet.weight < 0:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alpha-python
3
- Version: 0.7.7
3
+ Version: 0.7.9
4
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
5
  Author-email: Bart Reijling <bart@reijling.eu>
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes