alpha-python 0.7.7__py3-none-any.whl → 0.7.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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()}\'')
@@ -175,6 +175,7 @@ def init_container():
175
175
  },
176
176
  "cors": {
177
177
  "origins": ["*"],
178
+ "supports_credentials": True,
178
179
  },
179
180
  "jwt": {
180
181
  "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
@@ -119,3 +122,66 @@ class TestToken(BaseDomainModel):
119
122
  obj["expires_at"] = self.expires_at.isoformat()
120
123
 
121
124
  return obj
125
+
126
+
127
+ P = TypeVar("P", bound="Pet")
128
+
129
+
130
+ class PetType(Enum):
131
+ NONE = 0
132
+ DOG = auto()
133
+ CAT = auto()
134
+ RABBIT = auto()
135
+
136
+
137
+ @dataclass
138
+ class Pet:
139
+ name: str
140
+ pet_type: PetType
141
+ date_of_birth: date
142
+ weight: Optional[float] = None
143
+ good_boy: Optional[bool] = None
144
+ id: int = field(default=1)
145
+
146
+ @property
147
+ def age(self) -> int:
148
+ delta = date(2022, 2, 2) - self.date_of_birth
149
+ return delta.days // 365
150
+
151
+ def to_dict(self) -> dict[str, Any]:
152
+ return {
153
+ "id": 1,
154
+ "name": self.name,
155
+ "pet_type": self.pet_type.name,
156
+ "age": self.age,
157
+ "weight": self.weight,
158
+ "good_boy": self.good_boy,
159
+ }
160
+
161
+ @classmethod
162
+ def factory(cls: Type[P], **kwargs) -> P:
163
+ return cls(
164
+ name=kwargs["name"],
165
+ pet_type=PetType[kwargs["pet_type"]],
166
+ date_of_birth=kwargs["date_of_birth"],
167
+ good_boy=kwargs["good_boy"],
168
+ )
169
+
170
+
171
+ @define
172
+ class AttrsPet:
173
+ name: str
174
+ pet_type: PetType
175
+ date_of_birth: date
176
+ weight: Optional[float] = None
177
+ good_boy: Optional[bool] = None
178
+ id: int = 1
179
+
180
+
181
+ class PydanticPet(BaseModel):
182
+ name: str
183
+ pet_type: PetType
184
+ date_of_birth: date
185
+ weight: Optional[float] = None
186
+ good_boy: Optional[bool] = None
187
+ 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.8
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
@@ -21,12 +21,12 @@ alpha/factories/_type_conversion_matrix.py,sha256=mhMYpus6OFE0sZB0gQ-b1ndIOhiA1S
21
21
  alpha/factories/_type_mapping.py,sha256=f8cRfu8KUfw1ggY0Txs6fEX2e6GaXrsNcc2SCeYFRHM,789
22
22
  alpha/factories/class_factories.py,sha256=e0NCQDU1qCOQxoApICjZi3dnLLZ85Py5JOHqzLRbOSQ,17131
23
23
  alpha/factories/default_field_factory.py,sha256=J8fM48Yar1KpXX8SR1iB3buGr1hkYeayH5IYWoBqaHk,1770
24
- alpha/factories/field_iterator.py,sha256=q4B1bUuY1ZCWdS0F5mRGfaYcbKM-WlPUNixRzk6yAS8,6305
24
+ alpha/factories/field_iterator.py,sha256=PlExqVAmeYmlnE_iJ-tcAuIHiIgwwmqmlX-vYrkTAQY,6406
25
25
  alpha/factories/jwt_factory.py,sha256=ZuamKmi12uZve-TQByppeMlH1aiBNWraejd2wpZuB3k,8429
26
26
  alpha/factories/logging_handler_factory.py,sha256=ZoVkD2S3Pl7NMMfhcFF8k76BlKTsvis75udLX-JqQ30,3063
27
27
  alpha/factories/model_class_factory.py,sha256=VK80vLHGF-XdlW3aln5C9tHSQv81NLxz5ti5jYxdv4w,5862
28
28
  alpha/factories/password_factory.py,sha256=uK8X5bNvlyUtxvJXH7MXmYLiaM4jmsS6sZrx7Ew07kM,5031
29
- alpha/factories/request_factory.py,sha256=jyMOtya6ppe6gZuauLzCArk6PAYx6oT9RGXUUhKS3aI,7504
29
+ alpha/factories/request_factory.py,sha256=qDAiMvPmH-YcG7fAIRE5vjgnw-26MmbB16DV7-6s-bY,7615
30
30
  alpha/factories/response_factory.py,sha256=du2tqJdqzTSIpWeC3z8LmVKKZHqrLZ-1G42TBLbIQG4,6749
31
31
  alpha/factories/type_factories.py,sha256=3MCSQ1g1neBVPk0cSbhmGED7O4AQNMmBK8OmTLwuaGM,6478
32
32
  alpha/factories/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -47,7 +47,7 @@ alpha/handlers/templates/python-flask/Dockerfile.mustache,sha256=nyginFsU-nKyq0b
47
47
  alpha/handlers/templates/python-flask/README.mustache,sha256=X-giJMN_juUrVoW2mj_2Npw6q1s8NGsAgToK2um3NLQ,1368
48
48
  alpha/handlers/templates/python-flask/__init__model.mustache,sha256=JRwyJmOCAD8nskG1DnYjt7orBTmza8qPQ2N24JaPcuY,209
49
49
  alpha/handlers/templates/python-flask/__init__test.mustache,sha256=wUxDXcyE4rPh3sDp8MvR5m8vqzoU25Fw1bo_xh6InnY,438
50
- alpha/handlers/templates/python-flask/__main__.mustache,sha256=D11Z_bhka_NsK3EP8iSzV8_Hcc15L-uOntH2IbzrKng,2942
50
+ alpha/handlers/templates/python-flask/__main__.mustache,sha256=LN4FxQyvsCGAYQlD2ccdYIY0hyY1DBi-3Apncia350w,3847
51
51
  alpha/handlers/templates/python-flask/base_model.mustache,sha256=B--jl9LmfiHACq9n1kDxm6YTi6tb1oSUFnZya_IKOhU,2184
52
52
  alpha/handlers/templates/python-flask/controller.mustache,sha256=PoQ1nOa7wjqH1KEuWSIyC0XZlcz0iqBf9aEHTbPFEuo,18721
53
53
  alpha/handlers/templates/python-flask/controller_test.mustache,sha256=2i2cwgQonT1RMJQwdxeq8B3x8-hLjpK7YkI--LkKLOI,2848
@@ -138,15 +138,15 @@ alpha/utils/secret_generator.py,sha256=LjsKb8oDfsfmCCcTKrqtw_duqJ7u3V_o6zGGuG26_
138
138
  alpha/utils/verify_identity.py,sha256=Y1pdcVl8Z_I4ibw2KY7i5QwTQrY29WwpBOJ6j0YOAow,2271
139
139
  alpha/utils/version_checker.py,sha256=W8v69hDbrr0VvJ40gpFmXMtVawrDmUz_YGWssKUTmVE,380
140
140
  alpha/utils/openapi_test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
- alpha/utils/openapi_test/container.py,sha256=znO38IeidIEc_Ylemq0cmfSOgGANKdmMxvLMTKHB8KY,6592
141
+ alpha/utils/openapi_test/container.py,sha256=5QRfRl4S3KiPjvsu4zOro5swlFAS8O3ZSSmkAT6_IRU,6638
142
142
  alpha/utils/openapi_test/exceptions.py,sha256=FfVodhZrajSGQEZngKZRmlJCxjQP502OqQgu3qdtuN4,298
143
- alpha/utils/openapi_test/models.py,sha256=POqDD2v2VqPmVLnbvgZ0kVlVzL9Are1oFHmuyyKWR3Y,3549
143
+ alpha/utils/openapi_test/models.py,sha256=n5KCwdlpOiFcgvYlmFl-cMrvoOhmClodVC4hKH4fOvo,4996
144
144
  alpha/utils/openapi_test/orm.py,sha256=Py95GV_0e7wI1MYDZR1_EHkvTgev6eNo70SVmnD7kGc,3045
145
145
  alpha/utils/openapi_test/response.py,sha256=IxbQ6Nw258LLViHkgfjOpc7zWGTP8ofVOX1zrwDoR50,270
146
- alpha/utils/openapi_test/service.py,sha256=ycrEUlQmygKthnOhEiir-wtbPFi5cT-bepVclaL9FAk,5003
147
- alpha_python-0.7.7.dist-info/licenses/LICENSE,sha256=5KwEqC3KUoH4lVXgZ9tGriKOl-LGxHkXBWo16mFmAYM,1070
148
- alpha_python-0.7.7.dist-info/METADATA,sha256=GdYSiVbPsISAEo1L9Z-nai_ow77gC5R7urY5YKUV8VQ,8639
149
- alpha_python-0.7.7.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
150
- alpha_python-0.7.7.dist-info/entry_points.txt,sha256=LBEXdcofOugYYdZ46nz5Dxj_aj1QbRBkumfPGhy-GXI,41
151
- alpha_python-0.7.7.dist-info/top_level.txt,sha256=tqmNnOmi2RSSiPo99C03fD5Cc3r9za9xTjPAoQC1EGA,6
152
- alpha_python-0.7.7.dist-info/RECORD,,
146
+ alpha/utils/openapi_test/service.py,sha256=WWR33FYr76zV7CD8OWYc1B0zofv3_DDo0jnRPV6uJuM,4948
147
+ alpha_python-0.7.8.dist-info/licenses/LICENSE,sha256=5KwEqC3KUoH4lVXgZ9tGriKOl-LGxHkXBWo16mFmAYM,1070
148
+ alpha_python-0.7.8.dist-info/METADATA,sha256=viK-l1AufOomnXyFtAicy4gy9qDSOBNnj8pdXCeBnvg,8639
149
+ alpha_python-0.7.8.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
150
+ alpha_python-0.7.8.dist-info/entry_points.txt,sha256=LBEXdcofOugYYdZ46nz5Dxj_aj1QbRBkumfPGhy-GXI,41
151
+ alpha_python-0.7.8.dist-info/top_level.txt,sha256=tqmNnOmi2RSSiPo99C03fD5Cc3r9za9xTjPAoQC1EGA,6
152
+ alpha_python-0.7.8.dist-info/RECORD,,