alpha-python 0.5.1__py3-none-any.whl → 0.6.1__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.
- alpha/__init__.py +57 -5
- alpha/adapters/rest_api_unit_of_work.py +9 -3
- alpha/adapters/sqla_unit_of_work.py +23 -5
- alpha/cli.py +27 -23
- alpha/containers/container.py +52 -47
- alpha/domain/__init__.py +12 -1
- alpha/domain/models/__init__.py +12 -1
- alpha/domain/models/base_model.py +37 -1
- alpha/domain/models/group.py +51 -1
- alpha/domain/models/life_cycle_base.py +19 -0
- alpha/domain/models/role.py +127 -0
- alpha/domain/models/user.py +78 -65
- alpha/encoder.py +25 -3
- alpha/factories/class_factories.py +49 -22
- alpha/factories/default_field_factory.py +1 -0
- alpha/factories/field_iterator.py +8 -2
- alpha/factories/jwt_factory.py +59 -18
- alpha/factories/logging_handler_factory.py +7 -5
- alpha/factories/model_class_factory.py +6 -3
- alpha/factories/models/factory_classes.py +20 -1
- alpha/factories/password_factory.py +39 -15
- alpha/factories/request_factory.py +24 -13
- alpha/factories/response_factory.py +5 -2
- alpha/factories/type_factories.py +16 -2
- alpha/handlers/api_generate_handler.py +37 -33
- alpha/handlers/run-api.sh +0 -8
- alpha/handlers/templates/python-flask/__main__.mustache +26 -9
- alpha/handlers/templates/python-flask/controller.mustache +131 -30
- alpha/handlers/templates/python-flask/controller_test.mustache +1 -1
- alpha/handlers/templates/python-flask/model.mustache +7 -1
- alpha/handlers/templates/python-flask/requirements.mustache +0 -19
- alpha/handlers/templates/python-flask/setup.mustache +0 -19
- alpha/infra/__init__.py +14 -5
- alpha/infra/connectors/__init__.py +9 -4
- alpha/infra/connectors/ldap_connector.py +38 -29
- alpha/infra/connectors/oidc_connector.py +1 -1
- alpha/infra/connectors/sql_alchemy.py +166 -0
- alpha/infra/databases/sql_alchemy.py +7 -160
- alpha/infra/models/filter_operators.py +6 -1
- alpha/infra/models/json_patch.py +32 -6
- alpha/infra/models/order_by.py +78 -4
- alpha/infra/models/query_clause.py +33 -8
- alpha/infra/models/search_filter.py +96 -0
- alpha/interfaces/__init__.py +2 -2
- alpha/interfaces/api_repository.py +11 -5
- alpha/interfaces/factories.py +5 -2
- alpha/interfaces/patchable.py +17 -1
- alpha/interfaces/providers.py +4 -4
- alpha/interfaces/sql_mapper.py +6 -3
- alpha/interfaces/sql_repository.py +128 -141
- alpha/interfaces/token_factory.py +12 -10
- alpha/interfaces/unit_of_work.py +32 -15
- alpha/interfaces/updatable.py +21 -0
- alpha/mixins/__init__.py +3 -1
- alpha/mixins/group_lifecycle.py +159 -0
- alpha/mixins/user_lifecycle.py +188 -0
- alpha/providers/database_provider.py +5 -4
- alpha/providers/ldap_provider.py +82 -66
- alpha/providers/models/credentials.py +28 -6
- alpha/providers/models/identity.py +20 -11
- alpha/providers/models/token.py +56 -0
- alpha/providers/oidc_provider.py +56 -35
- alpha/repositories/rest_api_repository.py +23 -24
- alpha/repositories/sql_alchemy_repository.py +179 -133
- alpha/services/authentication_service.py +274 -51
- alpha/services/models/cookie.py +3 -49
- alpha/services/user_lifecycle_management.py +17 -285
- alpha/utils/__init__.py +2 -0
- alpha/utils/_http_codes.py +8 -0
- alpha/utils/cookie.py +51 -0
- alpha/utils/is_attrs.py +1 -1
- alpha/utils/is_pydantic.py +1 -1
- alpha/utils/logging_configurator.py +19 -17
- alpha/utils/logging_level_checker.py +3 -3
- alpha/utils/openapi_test/__init__.py +0 -0
- alpha/utils/openapi_test/container.py +181 -0
- alpha/utils/openapi_test/exceptions.py +17 -0
- alpha/utils/openapi_test/models.py +83 -0
- alpha/utils/openapi_test/orm.py +90 -0
- alpha/utils/openapi_test/response.py +12 -0
- alpha/utils/openapi_test/service.py +166 -0
- alpha/utils/request_headers.py +8 -0
- alpha/utils/response_object.py +19 -8
- alpha/utils/secret_generator.py +2 -2
- alpha/utils/verify_identity.py +7 -7
- alpha_python-0.6.1.dist-info/METADATA +210 -0
- alpha_python-0.6.1.dist-info/RECORD +144 -0
- alpha/interfaces/updateable.py +0 -7
- alpha_python-0.5.1.dist-info/METADATA +0 -100
- alpha_python-0.5.1.dist-info/RECORD +0 -132
- {alpha_python-0.5.1.dist-info → alpha_python-0.6.1.dist-info}/WHEEL +0 -0
- {alpha_python-0.5.1.dist-info → alpha_python-0.6.1.dist-info}/entry_points.txt +0 -0
- {alpha_python-0.5.1.dist-info → alpha_python-0.6.1.dist-info}/licenses/LICENSE +0 -0
- {alpha_python-0.5.1.dist-info → alpha_python-0.6.1.dist-info}/top_level.txt +0 -0
alpha/__init__.py
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
|
|
1
3
|
from alpha.adapters.rest_api_unit_of_work import RestApiUnitOfWork
|
|
2
4
|
from alpha.adapters.sqla_unit_of_work import SqlAlchemyUnitOfWork
|
|
3
5
|
from alpha.factories.jwt_factory import JWTFactory
|
|
4
6
|
from alpha.factories.logging_handler_factory import LoggingHandlerFactory
|
|
5
7
|
from alpha.factories.model_class_factory import ModelClassFactory
|
|
6
8
|
from alpha.domain.models.user import User
|
|
7
|
-
from alpha.domain.models.
|
|
9
|
+
from alpha.domain.models.group import Group
|
|
10
|
+
from alpha.domain.models.role import Role
|
|
11
|
+
from alpha.domain.models.base_model import (
|
|
12
|
+
BaseDomainModel,
|
|
13
|
+
DomainModel,
|
|
14
|
+
DomainModelCovariant,
|
|
15
|
+
DomainModelContravariant,
|
|
16
|
+
)
|
|
8
17
|
from alpha.domain.models.life_cycle_base import LifeCycleBase
|
|
9
18
|
from alpha.infra.connectors.oidc_connector import (
|
|
10
19
|
OIDCConnector,
|
|
11
20
|
KeyCloakOIDCConnector,
|
|
12
21
|
)
|
|
13
|
-
from alpha.infra.
|
|
22
|
+
from alpha.infra.connectors.sql_alchemy import SqlAlchemyDatabase
|
|
14
23
|
from alpha.infra.models.filter_operators import And, Or
|
|
15
24
|
from alpha.infra.models.json_patch import JsonPatch
|
|
16
25
|
from alpha.infra.models.order_by import OrderBy, Order
|
|
@@ -19,7 +28,7 @@ from alpha.interfaces.attrs_instance import AttrsInstance
|
|
|
19
28
|
from alpha.interfaces.dataclass_instance import DataclassInstance
|
|
20
29
|
from alpha.interfaces.pydantic_instance import PydanticInstance
|
|
21
30
|
from alpha.interfaces.openapi_model import OpenAPIModel
|
|
22
|
-
from alpha.interfaces.
|
|
31
|
+
from alpha.interfaces.updatable import Updatable
|
|
23
32
|
from alpha.interfaces.patchable import Patchable
|
|
24
33
|
from alpha.interfaces.api_repository import ApiRepository
|
|
25
34
|
from alpha.interfaces.sql_repository import SqlRepository
|
|
@@ -36,6 +45,8 @@ from alpha.interfaces.providers import (
|
|
|
36
45
|
)
|
|
37
46
|
from alpha.interfaces.token_factory import TokenFactory
|
|
38
47
|
from alpha.mixins.jwt_provider import JWTProviderMixin
|
|
48
|
+
from alpha.mixins.user_lifecycle import UserLifecycleMixin
|
|
49
|
+
from alpha.mixins.group_lifecycle import GroupLifecycleMixin
|
|
39
50
|
from alpha.providers.models.identity import (
|
|
40
51
|
Identity,
|
|
41
52
|
DEFAULT_LDAP_MAPPINGS,
|
|
@@ -44,7 +55,12 @@ from alpha.providers.models.identity import (
|
|
|
44
55
|
)
|
|
45
56
|
from alpha.providers.models.credentials import PasswordCredentials
|
|
46
57
|
from alpha.providers.models.token import Token
|
|
47
|
-
from alpha.providers.oidc_provider import
|
|
58
|
+
from alpha.providers.oidc_provider import (
|
|
59
|
+
OIDCProvider,
|
|
60
|
+
KeyCloakProvider,
|
|
61
|
+
DEFAULT_OIDC_MAPPINGS,
|
|
62
|
+
DEFAULT_KEYCLOAK_MAPPINGS,
|
|
63
|
+
)
|
|
48
64
|
from alpha.repositories.models.repository_model import RepositoryModel
|
|
49
65
|
from alpha.repositories.rest_api_repository import RestApiRepository
|
|
50
66
|
from alpha.repositories.sql_alchemy_repository import SqlAlchemyRepository
|
|
@@ -63,6 +79,7 @@ from alpha.utils.verify_identity import verify_identity
|
|
|
63
79
|
from alpha.utils.version_checker import minor_version_gte
|
|
64
80
|
from alpha.encoder import JSONEncoder
|
|
65
81
|
|
|
82
|
+
|
|
66
83
|
# Optional LDAP support - only import if ldap3 is available
|
|
67
84
|
try:
|
|
68
85
|
from alpha.infra.connectors.ldap_connector import (
|
|
@@ -77,6 +94,9 @@ try:
|
|
|
77
94
|
except ImportError:
|
|
78
95
|
_LDAP_AVAILABLE = False # type: ignore
|
|
79
96
|
|
|
97
|
+
|
|
98
|
+
__version__ = version("alpha-python")
|
|
99
|
+
|
|
80
100
|
__all__ = [
|
|
81
101
|
"RestApiUnitOfWork",
|
|
82
102
|
"SqlAlchemyUnitOfWork",
|
|
@@ -85,8 +105,12 @@ __all__ = [
|
|
|
85
105
|
"ModelClassFactory",
|
|
86
106
|
"BaseDomainModel",
|
|
87
107
|
"DomainModel",
|
|
108
|
+
"DomainModelCovariant",
|
|
109
|
+
"DomainModelContravariant",
|
|
88
110
|
"LifeCycleBase",
|
|
89
111
|
"User",
|
|
112
|
+
"Group",
|
|
113
|
+
"Role",
|
|
90
114
|
"OIDCConnector",
|
|
91
115
|
"KeyCloakOIDCConnector",
|
|
92
116
|
"SqlAlchemyDatabase",
|
|
@@ -101,7 +125,7 @@ __all__ = [
|
|
|
101
125
|
"DataclassInstance",
|
|
102
126
|
"PydanticInstance",
|
|
103
127
|
"OpenAPIModel",
|
|
104
|
-
"
|
|
128
|
+
"Updatable",
|
|
105
129
|
"Patchable",
|
|
106
130
|
"ApiRepository",
|
|
107
131
|
"SqlRepository",
|
|
@@ -116,6 +140,8 @@ __all__ = [
|
|
|
116
140
|
"TokenIssuer",
|
|
117
141
|
"TokenFactory",
|
|
118
142
|
"JWTProviderMixin",
|
|
143
|
+
"UserLifecycleMixin",
|
|
144
|
+
"GroupLifecycleMixin",
|
|
119
145
|
"Identity",
|
|
120
146
|
"DEFAULT_LDAP_MAPPINGS",
|
|
121
147
|
"DEFAULT_AD_MAPPINGS",
|
|
@@ -124,6 +150,8 @@ __all__ = [
|
|
|
124
150
|
"Token",
|
|
125
151
|
"OIDCProvider",
|
|
126
152
|
"KeyCloakProvider",
|
|
153
|
+
"DEFAULT_OIDC_MAPPINGS",
|
|
154
|
+
"DEFAULT_KEYCLOAK_MAPPINGS",
|
|
127
155
|
"RepositoryModel",
|
|
128
156
|
"RestApiRepository",
|
|
129
157
|
"SqlAlchemyRepository",
|
|
@@ -151,3 +179,27 @@ if _LDAP_AVAILABLE:
|
|
|
151
179
|
"ADProvider",
|
|
152
180
|
]
|
|
153
181
|
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _ensure_ast_str_compat() -> None:
|
|
185
|
+
"""Provide ast.Str compatibility for Python 3.14+.
|
|
186
|
+
|
|
187
|
+
Older Werkzeug versions (used by Flask 1.x) still instantiate ast.Str.
|
|
188
|
+
Python 3.14 removed that alias, so we recreate it with ast.Constant.
|
|
189
|
+
"""
|
|
190
|
+
if hasattr(ast, "Str"):
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
class _StrCompat(ast.Constant):
|
|
194
|
+
def __new__(cls, s: str = "", **kwargs): # noqa: N804
|
|
195
|
+
return ast.Constant(value=s, **kwargs)
|
|
196
|
+
|
|
197
|
+
setattr(ast, "Str", _StrCompat)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
import ast
|
|
202
|
+
|
|
203
|
+
_ensure_ast_str_compat()
|
|
204
|
+
except ImportError:
|
|
205
|
+
pass
|
|
@@ -11,7 +11,13 @@ UOW = TypeVar("UOW", bound="RestApiUnitOfWork")
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class RestApiUnitOfWork:
|
|
14
|
-
"""Unit of Work implementation for REST API interactions.
|
|
14
|
+
"""Unit of Work implementation for REST API interactions.
|
|
15
|
+
|
|
16
|
+
This class manages the lifecycle of a shared HTTP session and provides
|
|
17
|
+
access to configured repositories for API interactions. It does not support
|
|
18
|
+
transactional operations like commit, flush, rollback, or refresh, as these
|
|
19
|
+
concepts do not apply to REST API interactions.
|
|
20
|
+
"""
|
|
15
21
|
|
|
16
22
|
def __init__(
|
|
17
23
|
self,
|
|
@@ -22,9 +28,9 @@ class RestApiUnitOfWork:
|
|
|
22
28
|
|
|
23
29
|
Parameters
|
|
24
30
|
----------
|
|
25
|
-
repos
|
|
31
|
+
repos
|
|
26
32
|
The list of repository models to use.
|
|
27
|
-
session
|
|
33
|
+
session
|
|
28
34
|
The requests session (or compatible HTTP client, e.g., httpx) to
|
|
29
35
|
use for context management, by default None
|
|
30
36
|
|
|
@@ -12,7 +12,12 @@ UOW = TypeVar("UOW", bound="SqlAlchemyUnitOfWork")
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class SqlAlchemyUnitOfWork:
|
|
15
|
-
"""Unit of Work implementation for SQLAlchemy databases.
|
|
15
|
+
"""Unit of Work implementation for SQLAlchemy databases.
|
|
16
|
+
|
|
17
|
+
This class manages the lifecycle of a SQLAlchemy session and provides
|
|
18
|
+
access to configured repositories for database interactions. It supports
|
|
19
|
+
transactional operations such as commit, flush, rollback, and refresh.
|
|
20
|
+
"""
|
|
16
21
|
|
|
17
22
|
def __init__(
|
|
18
23
|
self,
|
|
@@ -23,9 +28,9 @@ class SqlAlchemyUnitOfWork:
|
|
|
23
28
|
|
|
24
29
|
Parameters
|
|
25
30
|
----------
|
|
26
|
-
db
|
|
31
|
+
db
|
|
27
32
|
The database instance to use.
|
|
28
|
-
repos
|
|
33
|
+
repos
|
|
29
34
|
The list of repository models to use.
|
|
30
35
|
|
|
31
36
|
Raises
|
|
@@ -45,6 +50,7 @@ class SqlAlchemyUnitOfWork:
|
|
|
45
50
|
|
|
46
51
|
Returns
|
|
47
52
|
-------
|
|
53
|
+
UOW
|
|
48
54
|
The Unit of Work instance.
|
|
49
55
|
|
|
50
56
|
Raises
|
|
@@ -107,7 +113,13 @@ class SqlAlchemyUnitOfWork:
|
|
|
107
113
|
self._session.rollback()
|
|
108
114
|
|
|
109
115
|
def refresh(self, obj: object) -> None:
|
|
110
|
-
"""Refresh the state of a given object.
|
|
116
|
+
"""Refresh the state of a given object.
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
obj
|
|
121
|
+
The object to refresh.
|
|
122
|
+
"""
|
|
111
123
|
if not self._session:
|
|
112
124
|
raise exceptions.DatabaseSessionError(
|
|
113
125
|
"No active database session is defined"
|
|
@@ -116,5 +128,11 @@ class SqlAlchemyUnitOfWork:
|
|
|
116
128
|
|
|
117
129
|
@property
|
|
118
130
|
def session(self) -> Session | None:
|
|
119
|
-
"""Get the current database session.
|
|
131
|
+
"""Get the current database session.
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
Session | None
|
|
136
|
+
The current database session.
|
|
137
|
+
"""
|
|
120
138
|
return self._session
|
alpha/cli.py
CHANGED
|
@@ -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=
|
|
23
|
+
description="Alpha command line interface.",
|
|
24
24
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
25
25
|
)
|
|
26
26
|
subparsers = parser.add_subparsers(
|
|
27
|
-
title=
|
|
28
|
-
dest=
|
|
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=
|
|
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[
|
|
92
|
-
del handler_args[
|
|
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(
|
|
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,
|
|
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,
|
|
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,
|
|
135
|
+
with open(pyproject_path, "rb") as f:
|
|
136
136
|
pyproject_data = tomllib.load(f)
|
|
137
137
|
name = None
|
|
138
138
|
try:
|
|
139
|
-
if
|
|
140
|
-
name = pyproject_data[
|
|
141
|
-
elif
|
|
142
|
-
|
|
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(
|
|
149
|
+
print("Could not find project name in pyproject.toml")
|
|
147
150
|
except Exception:
|
|
148
151
|
pass
|
|
149
152
|
else:
|
|
150
|
-
print(
|
|
153
|
+
print("Could not find pyproject.toml")
|
|
151
154
|
|
|
152
155
|
# Fallback to use the current folder name
|
|
153
|
-
print(
|
|
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
|
|
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
|
|
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(
|
|
171
|
+
container.config.init_container_function.from_value("init_container")
|
|
168
172
|
container.wire(modules=[sys.modules[__name__]])
|
|
169
173
|
|
|
170
174
|
main()
|
alpha/containers/container.py
CHANGED
|
@@ -8,13 +8,18 @@ from alpha.handlers.models.argument import Argument
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Container(containers.DeclarativeContainer):
|
|
11
|
-
"""Dependency injection container for the alpha package.
|
|
11
|
+
"""Dependency injection container for the alpha package.
|
|
12
|
+
|
|
13
|
+
The container is used to manage the dependencies of the alpha package,
|
|
14
|
+
including the API generation and running commands. It allows for easy
|
|
15
|
+
configuration and extension of the commands and their dependencies.
|
|
16
|
+
"""
|
|
12
17
|
|
|
13
18
|
config = providers.Configuration()
|
|
14
19
|
|
|
15
20
|
api_gen_command = providers.Factory(
|
|
16
21
|
Command,
|
|
17
|
-
name=
|
|
22
|
+
name="gen",
|
|
18
23
|
help=(
|
|
19
24
|
"Generate the API code and watch OpenAPI spec file. The API code "
|
|
20
25
|
"will be generated into the ./api folder."
|
|
@@ -23,46 +28,46 @@ class Container(containers.DeclarativeContainer):
|
|
|
23
28
|
arguments=providers.List(
|
|
24
29
|
providers.Factory(
|
|
25
30
|
Argument,
|
|
26
|
-
default=
|
|
27
|
-
name=
|
|
28
|
-
help=
|
|
31
|
+
default="specification/openapi.yaml",
|
|
32
|
+
name="--spec-file",
|
|
33
|
+
help="Path to the specification file",
|
|
29
34
|
args={
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
"type": str,
|
|
36
|
+
"nargs": "?",
|
|
32
37
|
},
|
|
33
38
|
),
|
|
34
39
|
providers.Factory(
|
|
35
40
|
Argument,
|
|
36
41
|
default=config.api_package_name,
|
|
37
|
-
name=
|
|
42
|
+
name="--api-package",
|
|
38
43
|
help=(
|
|
39
44
|
"Name of the API package to generate. Automatically "
|
|
40
45
|
"determined or guessed. If incorrect, "
|
|
41
46
|
"just use this argument."
|
|
42
47
|
),
|
|
43
48
|
args={
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
"type": str,
|
|
50
|
+
"nargs": "?",
|
|
46
51
|
},
|
|
47
52
|
),
|
|
48
53
|
providers.Factory(
|
|
49
54
|
Argument,
|
|
50
55
|
default=config.service_package_name,
|
|
51
|
-
name=
|
|
56
|
+
name="--service-package",
|
|
52
57
|
help=(
|
|
53
58
|
"Name of the service package to use. Automatically "
|
|
54
59
|
"determined or guessed. If incorrect, "
|
|
55
60
|
"just use this argument."
|
|
56
61
|
),
|
|
57
62
|
args={
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
"type": str,
|
|
64
|
+
"nargs": "?",
|
|
60
65
|
},
|
|
61
66
|
),
|
|
62
67
|
providers.Factory(
|
|
63
68
|
Argument,
|
|
64
69
|
default=config.container_import,
|
|
65
|
-
name=
|
|
70
|
+
name="--container-import",
|
|
66
71
|
help=(
|
|
67
72
|
"Name of the container to use. Automatically "
|
|
68
73
|
"determined or guessed. If incorrect, "
|
|
@@ -70,76 +75,76 @@ class Container(containers.DeclarativeContainer):
|
|
|
70
75
|
"use empty string for this variable"
|
|
71
76
|
),
|
|
72
77
|
args={
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
"type": str,
|
|
79
|
+
"nargs": "?",
|
|
75
80
|
},
|
|
76
81
|
),
|
|
77
82
|
providers.Factory(
|
|
78
83
|
Argument,
|
|
79
84
|
default=config.init_container_from,
|
|
80
|
-
name=
|
|
85
|
+
name="--init-container-from",
|
|
81
86
|
help=(
|
|
82
87
|
"Location of where the container initialize function "
|
|
83
88
|
"should be imported from."
|
|
84
89
|
),
|
|
85
90
|
args={
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
"type": str,
|
|
92
|
+
"nargs": "?",
|
|
88
93
|
},
|
|
89
94
|
),
|
|
90
95
|
providers.Factory(
|
|
91
96
|
Argument,
|
|
92
97
|
default=config.init_container_function,
|
|
93
|
-
name=
|
|
98
|
+
name="--init-container-function",
|
|
94
99
|
help="Name of the container initialize function.",
|
|
95
100
|
args={
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
"type": str,
|
|
102
|
+
"nargs": "?",
|
|
98
103
|
},
|
|
99
104
|
),
|
|
100
105
|
providers.Factory(
|
|
101
106
|
Argument,
|
|
102
|
-
default=
|
|
103
|
-
name=
|
|
107
|
+
default="post_process.py",
|
|
108
|
+
name="--post-process-file",
|
|
104
109
|
help="Path to the post process file to use after generation",
|
|
105
110
|
args={
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
"type": str,
|
|
112
|
+
"nargs": "?",
|
|
108
113
|
},
|
|
109
114
|
),
|
|
110
115
|
providers.Factory(
|
|
111
116
|
Argument,
|
|
112
|
-
default=
|
|
113
|
-
name=
|
|
117
|
+
default="python-flask",
|
|
118
|
+
name="--generator-name",
|
|
114
119
|
help="Name of the openapi generator to use",
|
|
115
120
|
args={
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
"type": str,
|
|
122
|
+
"nargs": "?",
|
|
118
123
|
},
|
|
119
124
|
),
|
|
120
125
|
providers.Factory(
|
|
121
126
|
Argument,
|
|
122
127
|
default=False,
|
|
123
|
-
name=
|
|
128
|
+
name="--no-watch",
|
|
124
129
|
help=(
|
|
125
130
|
"To prevent watching the spec file for changes and only "
|
|
126
131
|
"run the generation once."
|
|
127
132
|
),
|
|
128
133
|
args={
|
|
129
|
-
|
|
134
|
+
"action": "store_true",
|
|
130
135
|
},
|
|
131
136
|
),
|
|
132
137
|
providers.Factory(
|
|
133
138
|
Argument,
|
|
134
139
|
default=False,
|
|
135
|
-
name=
|
|
140
|
+
name="--templates-only",
|
|
136
141
|
help=(
|
|
137
142
|
"Only create a templates folder containing openapi "
|
|
138
143
|
"mustache templates in the current working directory. "
|
|
139
144
|
"Skip generation of API code."
|
|
140
145
|
),
|
|
141
146
|
args={
|
|
142
|
-
|
|
147
|
+
"action": "store_true",
|
|
143
148
|
},
|
|
144
149
|
),
|
|
145
150
|
),
|
|
@@ -147,28 +152,28 @@ class Container(containers.DeclarativeContainer):
|
|
|
147
152
|
|
|
148
153
|
api_run_command = providers.Factory(
|
|
149
154
|
Command,
|
|
150
|
-
name=
|
|
151
|
-
help=
|
|
155
|
+
name="run",
|
|
156
|
+
help="Run API in development mode",
|
|
152
157
|
handler=providers.Factory(ApiRunHandler),
|
|
153
158
|
arguments=providers.List(
|
|
154
159
|
providers.Factory(
|
|
155
160
|
Argument,
|
|
156
161
|
default=config.api_package_name,
|
|
157
|
-
name=
|
|
158
|
-
help=
|
|
162
|
+
name="--api-package",
|
|
163
|
+
help="Name of the API package to generate",
|
|
159
164
|
args={
|
|
160
|
-
|
|
161
|
-
|
|
165
|
+
"type": str,
|
|
166
|
+
"nargs": "?",
|
|
162
167
|
},
|
|
163
168
|
),
|
|
164
169
|
providers.Factory(
|
|
165
170
|
Argument,
|
|
166
|
-
default=
|
|
167
|
-
name=
|
|
168
|
-
help=
|
|
171
|
+
default="8080",
|
|
172
|
+
name="--port",
|
|
173
|
+
help="Port to run server on",
|
|
169
174
|
args={
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
"type": str,
|
|
176
|
+
"nargs": "?",
|
|
172
177
|
},
|
|
173
178
|
),
|
|
174
179
|
),
|
|
@@ -176,8 +181,8 @@ class Container(containers.DeclarativeContainer):
|
|
|
176
181
|
|
|
177
182
|
api_section = providers.Factory(
|
|
178
183
|
Section,
|
|
179
|
-
name=
|
|
180
|
-
description=
|
|
184
|
+
name="api",
|
|
185
|
+
description="OpenAPI development commands.",
|
|
181
186
|
help=(
|
|
182
187
|
"All commands for generating and developing an API using the "
|
|
183
188
|
"OpenAPI standards"
|
alpha/domain/__init__.py
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
from alpha.domain.models.user import User
|
|
2
|
-
from alpha.domain.models.
|
|
2
|
+
from alpha.domain.models.group import Group
|
|
3
|
+
from alpha.domain.models.role import Role
|
|
4
|
+
from alpha.domain.models.base_model import (
|
|
5
|
+
BaseDomainModel,
|
|
6
|
+
DomainModel,
|
|
7
|
+
DomainModelCovariant,
|
|
8
|
+
DomainModelContravariant,
|
|
9
|
+
)
|
|
3
10
|
from alpha.domain.models.life_cycle_base import LifeCycleBase
|
|
4
11
|
|
|
5
12
|
__all__ = [
|
|
6
13
|
"BaseDomainModel",
|
|
7
14
|
"DomainModel",
|
|
15
|
+
"DomainModelCovariant",
|
|
16
|
+
"DomainModelContravariant",
|
|
8
17
|
"LifeCycleBase",
|
|
9
18
|
"User",
|
|
19
|
+
"Group",
|
|
20
|
+
"Role",
|
|
10
21
|
]
|
alpha/domain/models/__init__.py
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
from alpha.domain.models.user import User
|
|
2
|
-
from alpha.domain.models.
|
|
2
|
+
from alpha.domain.models.group import Group
|
|
3
|
+
from alpha.domain.models.role import Role
|
|
4
|
+
from alpha.domain.models.base_model import (
|
|
5
|
+
BaseDomainModel,
|
|
6
|
+
DomainModel,
|
|
7
|
+
DomainModelCovariant,
|
|
8
|
+
DomainModelContravariant,
|
|
9
|
+
)
|
|
3
10
|
from alpha.domain.models.life_cycle_base import LifeCycleBase
|
|
4
11
|
|
|
5
12
|
__all__ = [
|
|
6
13
|
"BaseDomainModel",
|
|
7
14
|
"DomainModel",
|
|
15
|
+
"DomainModelCovariant",
|
|
16
|
+
"DomainModelContravariant",
|
|
8
17
|
"LifeCycleBase",
|
|
9
18
|
"User",
|
|
19
|
+
"Group",
|
|
20
|
+
"Role",
|
|
10
21
|
]
|