architectonics 0.0.27__tar.gz → 0.0.29__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 (26) hide show
  1. {architectonics-0.0.27 → architectonics-0.0.29}/PKG-INFO +1 -1
  2. architectonics-0.0.29/architectonics/core/result/error_message.py +6 -0
  3. architectonics-0.0.29/architectonics/core/result/service_result.py +71 -0
  4. architectonics-0.0.29/architectonics/core/services/base_schemas.py +21 -0
  5. architectonics-0.0.29/architectonics/core/services/base_service.py +114 -0
  6. architectonics-0.0.29/architectonics/core/validation/base_model_validation_errors.py +14 -0
  7. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/repositories/base_repository.py +6 -6
  8. {architectonics-0.0.27 → architectonics-0.0.29}/pyproject.toml +1 -1
  9. {architectonics-0.0.27 → architectonics-0.0.29}/setup.py +4 -1
  10. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/__init__.py +0 -0
  11. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/common/__init__.py +0 -0
  12. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/common/utils/utils.py +0 -0
  13. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/__init__.py +0 -0
  14. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/config/__init__.py +0 -0
  15. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/config/application_settings.py +0 -0
  16. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/factory/__init__.py +0 -0
  17. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/factory/factory.py +0 -0
  18. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/models/__init__.py +0 -0
  19. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/core/models/base_model.py +0 -0
  20. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/__init__.py +0 -0
  21. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/config/__init__.py +0 -0
  22. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/config/database.py +0 -0
  23. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/config/database_settings.py +0 -0
  24. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/entities/base_entity.py +0 -0
  25. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/repositories/__init__.py +0 -0
  26. {architectonics-0.0.27 → architectonics-0.0.29}/architectonics/infrastructure/repositories/base_exceptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: architectonics
3
- Version: 0.0.27
3
+ Version: 0.0.29
4
4
  Summary:
5
5
  Author: Your Name
6
6
  Author-email: you@example.com
@@ -0,0 +1,6 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass(frozen=True)
5
+ class ErrorMessage:
6
+ message: str
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Generic, TypeVar
4
+
5
+ from architectonics.core.result.error_message import ErrorMessage
6
+
7
+ TValue = TypeVar("TValue")
8
+ TValidationErrors = TypeVar("TValidationErrors")
9
+
10
+
11
+ class ServiceResult(
12
+ Generic[
13
+ TValue,
14
+ TValidationErrors,
15
+ ],
16
+ ):
17
+ __slots__ = (
18
+ "_value",
19
+ "_validation_errors",
20
+ "_error_message",
21
+ )
22
+
23
+ def __init__(
24
+ self,
25
+ value: TValue | None = None,
26
+ validation_errors: TValidationErrors | None = None,
27
+ error_message: ErrorMessage | None = None,
28
+ ) -> None:
29
+ self._value = value
30
+ self._validation_errors = validation_errors
31
+ self._error_message = error_message
32
+
33
+ @property
34
+ def value(self) -> TValue | None:
35
+ return self._value
36
+
37
+ @property
38
+ def validation_errors(self) -> TValidationErrors | None:
39
+ return self._validation_errors
40
+
41
+ @property
42
+ def error_message(self) -> ErrorMessage | None:
43
+ return self._error_message
44
+
45
+ @property
46
+ def is_validation_error(self) -> bool:
47
+ return self._validation_errors is not None
48
+
49
+ @property
50
+ def is_success(self) -> bool:
51
+ return self._value is not None and self._validation_errors is None and self._error_message is None
52
+
53
+ @classmethod
54
+ def success(cls, value: TValue) -> ServiceResult[TValue, TValidationErrors]:
55
+ return cls(
56
+ value=value,
57
+ )
58
+
59
+ @classmethod
60
+ def validation_failure(cls, validation_errors: TValidationErrors) -> ServiceResult[TValue, TValidationErrors]:
61
+ return cls(
62
+ validation_errors=validation_errors,
63
+ )
64
+
65
+ @classmethod
66
+ def failure(cls, error_message: str) -> ServiceResult[TValue, TValidationErrors]:
67
+ return cls(
68
+ error_message=ErrorMessage(
69
+ message=error_message,
70
+ ),
71
+ )
@@ -0,0 +1,21 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class BaseModelCreateSchema(BaseModel):
5
+ pass
6
+
7
+
8
+ class BaseModelCreateErrorsSchema(BaseModel):
9
+ pass
10
+
11
+
12
+ class BaseModelGetSchema(BaseModel):
13
+ pass
14
+
15
+
16
+ class BaseModelUpdateSchema(BaseModel):
17
+ pass
18
+
19
+
20
+ class BaseModelUpdateErrorsSchema(BaseModel):
21
+ pass
@@ -0,0 +1,114 @@
1
+ from starlette.status import (
2
+ HTTP_200_OK,
3
+ HTTP_404_NOT_FOUND,
4
+ HTTP_409_CONFLICT,
5
+ HTTP_422_UNPROCESSABLE_CONTENT,
6
+ )
7
+
8
+ from architectonics.core.models.base_model import BaseModel
9
+ from architectonics.core.result.service_result import ServiceResult
10
+ from architectonics.core.services.base_schemas import (
11
+ BaseModelCreateSchema,
12
+ BaseModelUpdateSchema,
13
+ )
14
+ from architectonics.core.validation.base_model_validation_errors import BaseModelValidationErrors
15
+ from architectonics.infrastructure.repositories.base_exceptions import (
16
+ IntegrityErrorException,
17
+ ObjectAlreadyExistsException,
18
+ ObjectNotFoundException,
19
+ )
20
+ from architectonics.infrastructure.repositories.base_repository import BaseRepository
21
+
22
+
23
+ class BaseService:
24
+ _repository: BaseRepository = NotImplemented
25
+
26
+ async def get_models_list(
27
+ self,
28
+ ) -> ServiceResult[list[BaseModel], BaseModelValidationErrors]:
29
+
30
+ models = await self._repository.get_models_list()
31
+
32
+ return ServiceResult[list[BaseModel], BaseModelValidationErrors].success(models)
33
+
34
+ """async def validate(self, model: BaseModel) -> BaseModelValidationErrors:
35
+
36
+ errors = BaseModelValidationErrors()
37
+
38
+ return errors
39
+
40
+ async def create_model(
41
+ self,
42
+ model: BaseModel,
43
+ ) -> ServiceResult[BaseModel, BaseModelValidationErrors]:
44
+
45
+ model_errors = await self.validate(model)
46
+
47
+ if model_errors.has_errors():
48
+ return None, model_errors, HTTP_422_UNPROCESSABLE_CONTENT
49
+
50
+ try:
51
+ model = await self._repository.create_model(
52
+ values=values,
53
+ )
54
+ except ObjectAlreadyExistsException:
55
+ return None, "object_already_exist", HTTP_409_CONFLICT
56
+
57
+ return model, None, HTTP_200_OK
58
+
59
+ async def get_model(
60
+ self,
61
+ model_id: str,
62
+ ) -> tuple[BaseModel | None, str | None, int]:
63
+
64
+ try:
65
+ model = await self._repository.get_model(
66
+ model_id=model_id,
67
+ )
68
+ except ObjectNotFoundException:
69
+ return None, "object_not_found", HTTP_404_NOT_FOUND
70
+
71
+ return model, None, HTTP_200_OK
72
+
73
+ async def update_model(
74
+ self,
75
+ model_id: str,
76
+ update_schema: BaseModelUpdateSchema,
77
+ ) -> tuple[BaseModel | None, str | dict[str, list[str]] | None, int]:
78
+
79
+ schema_dict = update_schema.model_dump(by_alias=False)
80
+
81
+ attrs, errors = await self._validate_values(**schema_dict)
82
+
83
+ if errors:
84
+ return None, errors, HTTP_422_UNPROCESSABLE_CONTENT
85
+
86
+ try:
87
+ model = await self._repository.update_model(
88
+ model_id=model_id,
89
+ values=attrs,
90
+ )
91
+ except IntegrityErrorException as e:
92
+ return None, f"{e}", HTTP_404_NOT_FOUND
93
+ except ObjectNotFoundException:
94
+ return None, "object_not_found", HTTP_404_NOT_FOUND
95
+
96
+ return model, None, HTTP_200_OK
97
+
98
+ async def delete_model(
99
+ self,
100
+ model_id: str,
101
+ ) -> tuple[None | str, str | dict[str, list[str]] | None, int]:
102
+
103
+ _, errors, status_code = await self.get_model(
104
+ model_id=model_id,
105
+ )
106
+
107
+ if errors:
108
+ return None, errors, status_code
109
+
110
+ await self._repository.delete_model(
111
+ model_id=model_id,
112
+ )
113
+
114
+ return "object_deleted", None, HTTP_200_OK"""
@@ -0,0 +1,14 @@
1
+ from dataclasses import dataclass, fields
2
+
3
+
4
+ @dataclass
5
+ class BaseModelValidationErrors:
6
+
7
+ def has_errors(self) -> bool:
8
+ for f in fields(self):
9
+ value = getattr(self, f.name)
10
+
11
+ if isinstance(value, list) and len(value) > 0:
12
+ return True
13
+
14
+ return False
@@ -2,17 +2,17 @@ from abc import ABC
2
2
  from typing import Callable
3
3
 
4
4
  from asyncpg.exceptions import ForeignKeyViolationError
5
+ from architectonics.infrastructure.entities.base_entity import BaseEntity
6
+ from architectonics.infrastructure.repositories.base_exceptions import (
7
+ IntegrityErrorException,
8
+ ObjectAlreadyExistsException,
9
+ ObjectNotFoundException,
10
+ )
5
11
  from sqlalchemy import delete, select, update
6
12
  from sqlalchemy.exc import IntegrityError
7
13
  from sqlalchemy.ext.asyncio import AsyncSession
8
14
 
9
15
  from architectonics.core.models.base_model import BaseModel
10
- from infrastructure.entities.base_entity import BaseEntity
11
- from infrastructure.repositories.base_exceptions import (
12
- IntegrityErrorException,
13
- ObjectAlreadyExistsException,
14
- ObjectNotFoundException,
15
- )
16
16
 
17
17
 
18
18
  class BaseRepository(ABC):
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "architectonics"
3
- version = "0.0.27"
3
+ version = "0.0.29"
4
4
  description = ""
5
5
  authors = ["Your Name <you@example.com>"]
6
6
 
@@ -9,6 +9,9 @@ packages = \
9
9
  'architectonics.core.config',
10
10
  'architectonics.core.factory',
11
11
  'architectonics.core.models',
12
+ 'architectonics.core.result',
13
+ 'architectonics.core.services',
14
+ 'architectonics.core.validation',
12
15
  'architectonics.infrastructure',
13
16
  'architectonics.infrastructure.config',
14
17
  'architectonics.infrastructure.entities',
@@ -29,7 +32,7 @@ install_requires = \
29
32
 
30
33
  setup_kwargs = {
31
34
  'name': 'architectonics',
32
- 'version': '0.0.27',
35
+ 'version': '0.0.29',
33
36
  'description': '',
34
37
  'long_description': None,
35
38
  'author': 'Your Name',