instant-python 0.1.1__py3-none-any.whl → 0.3.0__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.
Files changed (55) hide show
  1. instant_python/folder_cli.py +9 -9
  2. instant_python/installer/pdm_manager.py +10 -3
  3. instant_python/installer/uv_manager.py +11 -0
  4. instant_python/project_cli.py +3 -3
  5. instant_python/project_generator/boilerplate_file.py +20 -0
  6. instant_python/project_generator/file.py +4 -8
  7. instant_python/project_generator/folder_tree.py +4 -0
  8. instant_python/project_generator/jinja_environment.py +20 -0
  9. instant_python/project_generator/{default_template_manager.py → jinja_template_manager.py} +8 -13
  10. instant_python/project_generator/node.py +1 -0
  11. instant_python/project_generator/project_generator.py +1 -1
  12. instant_python/question_prompter/question/conditional_question.py +9 -3
  13. instant_python/question_prompter/question_wizard.py +3 -3
  14. instant_python/question_prompter/{user_requirements.py → requirements_configuration.py} +3 -2
  15. instant_python/question_prompter/step/template_step.py +21 -13
  16. instant_python/templates/boilerplate/event_bus/aggregate_root.py +0 -1
  17. instant_python/templates/boilerplate/event_bus/domain_event_json_deserializer.py +3 -3
  18. instant_python/templates/boilerplate/event_bus/domain_event_subscriber.py +19 -0
  19. instant_python/templates/boilerplate/event_bus/event_bus.py +1 -1
  20. instant_python/templates/boilerplate/exceptions/domain_event_type_not_found_error.py +1 -1
  21. instant_python/templates/boilerplate/exceptions/rabbit_mq_connection_not_established_error.py +17 -0
  22. instant_python/templates/boilerplate/persistence/synchronous/sqlalchemy_repository.py +1 -1
  23. instant_python/templates/boilerplate/value_object/int_value_object.py +8 -5
  24. instant_python/templates/boilerplate/value_object/string_value_object.py +1 -1
  25. instant_python/templates/boilerplate/value_object/uuid.py +1 -1
  26. instant_python/templates/project_structure/alembic_migrator.yml.j2 +1 -1
  27. instant_python/templates/project_structure/async_alembic.yml.j2 +5 -5
  28. instant_python/templates/project_structure/async_sqlalchemy.yml.j2 +3 -3
  29. instant_python/templates/project_structure/clean_architecture/source.yml.j2 +2 -2
  30. instant_python/templates/project_structure/clean_architecture/test.yml.j2 +2 -2
  31. instant_python/templates/project_structure/domain_driven_design/source.yml.j2 +5 -3
  32. instant_python/templates/project_structure/domain_driven_design/test.yml.j2 +4 -2
  33. instant_python/templates/project_structure/event_bus_domain.yml.j2 +9 -6
  34. instant_python/templates/project_structure/event_bus_infra.yml.j2 +8 -8
  35. instant_python/templates/project_structure/fastapi_app.yml.j2 +2 -2
  36. instant_python/templates/project_structure/fastapi_infra.yml.j2 +2 -2
  37. instant_python/templates/project_structure/github_action.yml.j2 +2 -2
  38. instant_python/templates/project_structure/gitignore.yml.j2 +1 -1
  39. instant_python/templates/project_structure/license.yml.j2 +1 -1
  40. instant_python/templates/project_structure/logger.yml.j2 +2 -2
  41. instant_python/templates/project_structure/makefile.yml.j2 +10 -10
  42. instant_python/templates/project_structure/mypy.yml.j2 +1 -1
  43. instant_python/templates/project_structure/pre_commit.yml.j2 +1 -1
  44. instant_python/templates/project_structure/pyproject.yml.j2 +1 -1
  45. instant_python/templates/project_structure/pytest.yml.j2 +1 -1
  46. instant_python/templates/project_structure/python_version.yml.j2 +1 -1
  47. instant_python/templates/project_structure/standard_project/source.yml.j2 +2 -2
  48. instant_python/templates/project_structure/standard_project/test.yml.j2 +2 -2
  49. instant_python/templates/project_structure/synchronous_sqlalchemy.yml.j2 +3 -3
  50. instant_python/templates/project_structure/value_objects.yml.j2 +9 -9
  51. {instant_python-0.1.1.dist-info → instant_python-0.3.0.dist-info}/METADATA +9 -3
  52. {instant_python-0.1.1.dist-info → instant_python-0.3.0.dist-info}/RECORD +55 -52
  53. {instant_python-0.1.1.dist-info → instant_python-0.3.0.dist-info}/WHEEL +0 -0
  54. {instant_python-0.1.1.dist-info → instant_python-0.3.0.dist-info}/entry_points.txt +0 -0
  55. {instant_python-0.1.1.dist-info → instant_python-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,7 @@
1
1
  import typer
2
2
 
3
3
  from instant_python.project_generator.custom_template_manager import CustomTemplateManager
4
- from instant_python.project_generator.default_template_manager import DefaultTemplateManager
4
+ from instant_python.project_generator.jinja_template_manager import JinjaTemplateManager
5
5
  from instant_python.project_generator.folder_tree import FolderTree
6
6
  from instant_python.project_generator.project_generator import ProjectGenerator
7
7
  from instant_python.question_prompter.question.free_text_question import FreeTextQuestion
@@ -13,8 +13,8 @@ from instant_python.question_prompter.step.template_step import TemplateStep
13
13
  app = typer.Typer()
14
14
 
15
15
 
16
- @app.command("template", help="Pass a custom template folder structure", hidden=True)
17
- def create_folder_structure_from_template(template_name: str) -> None:
16
+ @app.command("template", help="Pass a custom template folder structure")
17
+ def create_folder_structure_from_template(template_path: str) -> None:
18
18
  project_name = FreeTextQuestion(
19
19
  key="project_slug",
20
20
  message="Enter the name of the project (CANNOT CONTAIN SPACES)",
@@ -22,7 +22,7 @@ def create_folder_structure_from_template(template_name: str) -> None:
22
22
  ).ask()
23
23
  project_generator = ProjectGenerator(
24
24
  folder_tree=FolderTree(project_name["project_slug"]),
25
- template_manager=CustomTemplateManager(template_name),
25
+ template_manager=CustomTemplateManager(template_path),
26
26
  )
27
27
 
28
28
  project_generator.generate()
@@ -33,17 +33,17 @@ def create_default_project_structure() -> None:
33
33
  wizard = QuestionWizard(
34
34
  steps=Steps(GeneralProjectStep(), TemplateStep())
35
35
  )
36
- user_requirements = wizard.run()
37
- user_requirements.save_in_memory()
36
+ requirements = wizard.run()
37
+ requirements.save_in_memory()
38
38
 
39
39
  project_generator = ProjectGenerator(
40
- folder_tree=FolderTree(user_requirements.project_slug),
41
- template_manager=DefaultTemplateManager(),
40
+ folder_tree=FolderTree(requirements.project_slug),
41
+ template_manager=JinjaTemplateManager(),
42
42
  )
43
43
 
44
44
  project_generator.generate()
45
45
 
46
- user_requirements.remove()
46
+ requirements.remove()
47
47
 
48
48
 
49
49
  if __name__ == "__main__":
@@ -31,6 +31,7 @@ class PdmManager(DependencyManager):
31
31
  print(f">>> Python {version} installed successfully")
32
32
 
33
33
  def install_dependencies(self, dependencies: list[str]) -> None:
34
+ self._create_virtual_environment()
34
35
  for dependency_name in dependencies:
35
36
  self._install_dependency(dependency_name)
36
37
 
@@ -67,6 +68,12 @@ class PdmManager(DependencyManager):
67
68
  group_flag += f"--group {group_name}"
68
69
  return f"{dev_flag} {group_flag}"
69
70
 
70
-
71
-
72
-
71
+ def _create_virtual_environment(self) -> None:
72
+ command = f"{self._pdm} install"
73
+ subprocess.run(
74
+ command,
75
+ shell=True,
76
+ check=True,
77
+ cwd=self._project_directory,
78
+ stdout=subprocess.DEVNULL,
79
+ )
@@ -33,6 +33,7 @@ class UvManager(DependencyManager):
33
33
  print(f">>> Python {version} installed successfully")
34
34
 
35
35
  def install_dependencies(self, dependencies: list[str]) -> None:
36
+ self._create_virtual_environment()
36
37
  for dependency_name in dependencies:
37
38
  self._install_dependency(dependency_name)
38
39
 
@@ -71,3 +72,13 @@ class UvManager(DependencyManager):
71
72
  ).ask()["group_name"]
72
73
  flag = f"--group {group_name}"
73
74
  return flag
75
+
76
+ def _create_virtual_environment(self) -> None:
77
+ command = f"{self._uv} sync"
78
+ subprocess.run(
79
+ command,
80
+ shell=True,
81
+ check=True,
82
+ cwd=self._project_directory,
83
+ stdout=subprocess.DEVNULL,
84
+ )
@@ -4,8 +4,8 @@ from instant_python.installer.dependency_manager_factory import DependencyManage
4
4
  from instant_python.installer.git_configurer import GitConfigurer
5
5
  from instant_python.installer.installer import Installer
6
6
  from instant_python.project_generator.custom_template_manager import CustomTemplateManager
7
- from instant_python.project_generator.default_template_manager import (
8
- DefaultTemplateManager,
7
+ from instant_python.project_generator.jinja_template_manager import (
8
+ JinjaTemplateManager,
9
9
  )
10
10
  from instant_python.project_generator.folder_tree import FolderTree
11
11
  from instant_python.project_generator.project_generator import ProjectGenerator
@@ -74,7 +74,7 @@ def create_full_project() -> None:
74
74
 
75
75
  project_generator = ProjectGenerator(
76
76
  folder_tree=FolderTree(user_requirements.project_slug),
77
- template_manager=DefaultTemplateManager(),
77
+ template_manager=JinjaTemplateManager(),
78
78
  )
79
79
  project_generator.generate()
80
80
 
@@ -0,0 +1,20 @@
1
+ from pathlib import Path
2
+
3
+ from instant_python.project_generator.jinja_template_manager import JinjaTemplateManager
4
+ from instant_python.project_generator.node import Node
5
+
6
+
7
+ class BoilerplateFile(Node):
8
+
9
+ def __init__(self, name: str, extension: str) -> None:
10
+ self._file_name = f"{name.split('/')[-1]}{extension}"
11
+ self._template_path = f"boilerplate/{name}{extension}"
12
+ self._template_manager = JinjaTemplateManager()
13
+
14
+ def __repr__(self) -> str:
15
+ return f"{self.__class__.__name__}(name={self._file_name})"
16
+
17
+ def create(self, base_path: Path) -> None:
18
+ file_path = base_path / self._file_name
19
+ content = self._template_manager.get_boilerplate(self._template_path)
20
+ file_path.write_text(content)
@@ -1,20 +1,16 @@
1
1
  from pathlib import Path
2
2
 
3
- from instant_python.project_generator.default_template_manager import DefaultTemplateManager
4
3
  from instant_python.project_generator.node import Node
5
4
 
6
5
 
7
6
  class File(Node):
8
-
9
7
  def __init__(self, name: str, extension: str) -> None:
10
- self._file_name = f"{name.split('/')[-1]}{extension}"
11
- self._template_path = f"boilerplate/{name}{extension}"
12
- self._template_manager = DefaultTemplateManager()
8
+ self._file_name = name
9
+ self._extension = extension
13
10
 
14
11
  def __repr__(self) -> str:
15
12
  return f"{self.__class__.__name__}(name={self._file_name})"
16
13
 
17
14
  def create(self, base_path: Path) -> None:
18
- file_path = base_path / self._file_name
19
- content = self._template_manager.get_boilerplate(self._template_path)
20
- file_path.write_text(content)
15
+ file_path = base_path / f"{self._file_name}{self._extension}"
16
+ file_path.touch(exist_ok=True)
@@ -1,6 +1,7 @@
1
1
  from pathlib import Path
2
2
 
3
3
  from instant_python.project_generator.directory import Directory
4
+ from instant_python.project_generator.boilerplate_file import BoilerplateFile
4
5
  from instant_python.project_generator.file import File
5
6
  from instant_python.project_generator.node import Node, NodeType
6
7
 
@@ -33,6 +34,9 @@ class FolderTree:
33
34
  is_python_module = node.get("python", False)
34
35
  directory_children = [self._build_tree(child) for child in children]
35
36
  return Directory(name=name, children=directory_children, python_module=is_python_module)
37
+ elif node_type == NodeType.BOILERPLATE:
38
+ extension = node.get("extension", "")
39
+ return BoilerplateFile(name=name, extension=extension)
36
40
  elif node_type == NodeType.FILE:
37
41
  extension = node.get("extension", "")
38
42
  return File(name=name, extension=extension)
@@ -0,0 +1,20 @@
1
+ from jinja2 import Environment, Template, PackageLoader
2
+
3
+ from instant_python.project_generator.jinja_custom_filters import (
4
+ is_in,
5
+ compute_base_path,
6
+ )
7
+
8
+
9
+ class JinjaEnvironment:
10
+ def __init__(self) -> None:
11
+ self._env = Environment(
12
+ loader=PackageLoader("instant_python", "templates"),
13
+ trim_blocks=True,
14
+ lstrip_blocks=True,
15
+ )
16
+ self._env.filters["is_in"] = is_in
17
+ self._env.filters["compute_base_path"] = compute_base_path
18
+
19
+ def get_template(self, name: str) -> Template:
20
+ return self._env.get_template(name)
@@ -1,22 +1,17 @@
1
1
  import yaml
2
- from jinja2 import Environment, Template, PackageLoader
2
+ from jinja2 import Template
3
3
 
4
- from instant_python.project_generator.jinja_custom_filters import is_in, compute_base_path
4
+ from instant_python.project_generator.jinja_environment import JinjaEnvironment
5
5
  from instant_python.project_generator.template_manager import TemplateManager
6
6
  from instant_python.question_prompter.template_types import TemplateTypes
7
- from instant_python.question_prompter.user_requirements import UserRequirements
7
+ from instant_python.question_prompter.requirements_configuration import RequirementsConfiguration
8
8
 
9
9
 
10
- class DefaultTemplateManager(TemplateManager):
10
+ class JinjaTemplateManager(TemplateManager):
11
11
 
12
12
  def __init__(self) -> None:
13
13
  self._requirements = self._load_memory_requirements()
14
- self._env = Environment(loader=PackageLoader("instant_python",
15
- "templates"),
16
- trim_blocks=True,
17
- lstrip_blocks=True)
18
- self._env.filters["is_in"] = is_in
19
- self._env.filters["compute_base_path"] = compute_base_path
14
+ self._env = JinjaEnvironment()
20
15
 
21
16
  def get_project(self, template_name: str) -> dict:
22
17
  template = self._get_template(
@@ -36,7 +31,7 @@ class DefaultTemplateManager(TemplateManager):
36
31
  return template.render(**self._requirements.to_dict(), template_types=TemplateTypes)
37
32
 
38
33
  @staticmethod
39
- def _load_memory_requirements() -> UserRequirements:
40
- with open("user_requirements.yml") as file:
34
+ def _load_memory_requirements() -> RequirementsConfiguration:
35
+ with open("ipy.yml") as file:
41
36
  requirements = yaml.safe_load(file)
42
- return UserRequirements(**requirements)
37
+ return RequirementsConfiguration(**requirements)
@@ -6,6 +6,7 @@ from pathlib import Path
6
6
  class NodeType(str, Enum):
7
7
  DIRECTORY = "directory"
8
8
  FILE = "file"
9
+ BOILERPLATE = "boilerplate_file"
9
10
 
10
11
 
11
12
  class Node(ABC):
@@ -1,7 +1,7 @@
1
1
  import subprocess
2
2
 
3
3
  from instant_python.project_generator.folder_tree import FolderTree
4
- from instant_python.project_generator.default_template_manager import TemplateManager
4
+ from instant_python.project_generator.jinja_template_manager import TemplateManager
5
5
 
6
6
 
7
7
  class ProjectGenerator:
@@ -1,9 +1,11 @@
1
+ from typing import Union
2
+
1
3
  from instant_python.question_prompter.question.question import Question
2
4
 
3
5
 
4
6
  class ConditionalQuestion:
5
7
  def __init__(
6
- self, base_question: Question, subquestions: list[Question], condition: str | bool
8
+ self, base_question: Question, subquestions: Union[list[Question], "ConditionalQuestion"], condition: str | bool
7
9
  ) -> None:
8
10
  self._base_question = base_question
9
11
  self._subquestions = subquestions
@@ -16,8 +18,12 @@ class ConditionalQuestion:
16
18
  return base_answer
17
19
 
18
20
  answers = base_answer
19
- for question in self._subquestions:
20
- answers.update(question.ask())
21
+
22
+ if isinstance(self._subquestions, ConditionalQuestion):
23
+ answers.update(self._subquestions.ask())
24
+ else:
25
+ for question in self._subquestions:
26
+ answers.update(question.ask())
21
27
  return answers
22
28
 
23
29
  def _base_answer_does_not_satisfies_condition(self, base_answer: dict[str, str]) -> bool:
@@ -1,5 +1,5 @@
1
1
  from instant_python.question_prompter.step.steps import Steps
2
- from instant_python.question_prompter.user_requirements import UserRequirements
2
+ from instant_python.question_prompter.requirements_configuration import RequirementsConfiguration
3
3
 
4
4
 
5
5
  class QuestionWizard:
@@ -7,9 +7,9 @@ class QuestionWizard:
7
7
  self._steps = steps
8
8
  self._answers = {}
9
9
 
10
- def run(self) -> UserRequirements:
10
+ def run(self) -> RequirementsConfiguration:
11
11
  for step in self._steps:
12
12
  answer = step.run(self._answers)
13
13
  self._answers.update(answer)
14
14
 
15
- return UserRequirements(**self._answers)
15
+ return RequirementsConfiguration(**self._answers)
@@ -6,7 +6,7 @@ import yaml
6
6
 
7
7
 
8
8
  @dataclass
9
- class UserRequirements:
9
+ class RequirementsConfiguration:
10
10
  project_slug: str
11
11
  license: str
12
12
  version: str
@@ -20,13 +20,14 @@ class UserRequirements:
20
20
  git_email: str = field(default_factory=str)
21
21
  git_user_name: str = field(default_factory=str)
22
22
  dependencies: list[str] = field(default_factory=list)
23
+ specify_bounded_context: bool = field(default=False)
23
24
  bounded_context: str = field(default_factory=str)
24
25
  aggregate_name: str = field(default_factory=str)
25
26
  built_in_features: list[str] = field(default_factory=list)
26
27
  year: int = field(default=datetime.now().year)
27
28
 
28
29
  def __post_init__(self) -> None:
29
- self._file_path = "user_requirements.yml"
30
+ self._file_path = "ipy.yml"
30
31
 
31
32
  def to_dict(self) -> dict:
32
33
  return asdict(self)
@@ -1,3 +1,4 @@
1
+ from instant_python.question_prompter.question.boolean_question import BooleanQuestion
1
2
  from instant_python.question_prompter.question.choice_question import ChoiceQuestion
2
3
  from instant_python.question_prompter.question.conditional_question import (
3
4
  ConditionalQuestion,
@@ -17,12 +18,11 @@ class TemplateStep(Step):
17
18
  self._questions = [
18
19
  MultipleChoiceQuestion(
19
20
  key="built_in_features",
20
- message="Select the built-in features you want to include (fastapi_application option requires logger)",
21
+ message="Select the built-in features you want to include",
21
22
  options=[
22
23
  "value_objects",
23
24
  "github_actions",
24
25
  "makefile",
25
- "synchronous_sqlalchemy",
26
26
  "logger",
27
27
  "event_bus",
28
28
  "async_sqlalchemy",
@@ -40,18 +40,26 @@ class TemplateStep(Step):
40
40
  "standard_project",
41
41
  ],
42
42
  ),
43
- subquestions=[
44
- FreeTextQuestion(
45
- key="bounded_context",
46
- message="Enter the bounded context name",
47
- default="backoffice",
43
+ subquestions=ConditionalQuestion(
44
+ base_question=BooleanQuestion(
45
+ key="specify_bounded_context",
46
+ message="Do you want to specify your first bounded context?",
47
+ default=True,
48
48
  ),
49
- FreeTextQuestion(
50
- key="aggregate_name",
51
- message="Enter the aggregate name",
52
- default="user",
53
- ),
54
- ],
49
+ subquestions=[
50
+ FreeTextQuestion(
51
+ key="bounded_context",
52
+ message="Enter the bounded context name",
53
+ default="backoffice",
54
+ ),
55
+ FreeTextQuestion(
56
+ key="aggregate_name",
57
+ message="Enter the aggregate name",
58
+ default="user",
59
+ ),
60
+ ],
61
+ condition=True,
62
+ ),
55
63
  condition=TemplateTypes.DDD,
56
64
  ),
57
65
  ]
@@ -1,5 +1,4 @@
1
1
  {% set template_domain_import = "shared.domain"|compute_base_path(template) %}
2
-
3
2
  from {{ source_name }}.{{ template_domain_import }}.event.domain_event import DomainEvent
4
3
 
5
4
 
@@ -5,8 +5,8 @@ from {{ source_name }}.{{ template_domain_import }}.event.domain_event import Do
5
5
  from {{ source_name }}.{{ template_domain_import }}.event.domain_event_subscriber import (
6
6
  DomainEventSubscriber,
7
7
  )
8
- from {{ source_name }}.{{ template_domain_import }}.exceptions.domain_event_type_not_found import (
9
- DomainEventTypeNotFound,
8
+ from {{ source_name }}.{{ template_domain_import }}.exceptions.domain_event_type_not_found_error import (
9
+ DomainEventTypeNotFoundError,
10
10
  )
11
11
 
12
12
 
@@ -23,6 +23,6 @@ class DomainEventJsonDeserializer:
23
23
  event_class = self._events_mapping.get(content["data"]["type"])
24
24
 
25
25
  if not event_class:
26
- raise DomainEventTypeNotFound(content["data"]["type"])
26
+ raise DomainEventTypeNotFoundError(content["data"]["type"])
27
27
 
28
28
  return event_class(**content["data"]["attributes"])
@@ -1,4 +1,5 @@
1
1
  {% set template_domain_import = "shared.domain"|compute_base_path(template) %}
2
+ {% if pythono_version in ["3.12", "3.13"] %}
2
3
  from abc import ABC, abstractmethod
3
4
 
4
5
  from {{ source_name }}.{{ template_domain_import }}.event.domain_event import DomainEvent
@@ -13,3 +14,21 @@ class DomainEventSubscriber[EventType: DomainEvent](ABC):
13
14
  @abstractmethod
14
15
  def on(self, event: EventType) -> None:
15
16
  raise NotImplementedError
17
+ {% else %}
18
+ from abc import ABC, abstractmethod
19
+ from typing import Generic, TypeVar
20
+
21
+ from {{ source_name }}.{{ template_domain_import }}.event.domain_event import DomainEvent
22
+
23
+ EventType = TypeVar("EventType", bound=DomainEvent)
24
+
25
+ class DomainEventSubscriber(Generic[EventType], ABC):
26
+ @staticmethod
27
+ @abstractmethod
28
+ def subscribed_to() -> list[type[EventType]]:
29
+ raise NotImplementedError
30
+
31
+ @abstractmethod
32
+ def on(self, event: EventType) -> None:
33
+ raise NotImplementedError
34
+ {% endif %}
@@ -6,5 +6,5 @@ from {{ source_name }}.{{ template_domain_import }}.event.domain_event import Do
6
6
 
7
7
  class EventBus(ABC):
8
8
  @abstractmethod
9
- def publish(self, events: list[DomainEvent]) -> None:
9
+ async def publish(self, events: list[DomainEvent]) -> None:
10
10
  raise NotImplementedError
@@ -2,7 +2,7 @@
2
2
  from {{ source_name }}.{{ template_domain_import }}.exceptions.domain_error import DomainError
3
3
 
4
4
 
5
- class DomainEventTypeNotFound(DomainError):
5
+ class DomainEventTypeNotFoundError(DomainError):
6
6
  def __init__(self, name: str) -> None:
7
7
  self._message = f"Event type {name} not found among subscriber."
8
8
  self._type = "domain_event_type_not_found"
@@ -0,0 +1,17 @@
1
+ {% set template_domain_import = "shared.domain"|compute_base_path(template) %}
2
+ from {{ source_name }}.{{ template_domain_import }}.exceptions.domain_error import DomainError
3
+
4
+
5
+ class RabbitMqConnectionNotEstablishedError(DomainError):
6
+ def __init__(self) -> None:
7
+ self._message = "RabbitMQ connection not established."
8
+ self._type = "rabbit_mq_connection"
9
+ super().__init__(self._message)
10
+
11
+ @property
12
+ def type(self) -> str:
13
+ return self._type
14
+
15
+ @property
16
+ def message(self) -> str:
17
+ return self._message
@@ -6,7 +6,7 @@ from typing import TypeVar
6
6
  from typing import TypeVar, Generic
7
7
  {% endif %}
8
8
 
9
- from {{ source_name }}.{{ template_domain_import }}.value_objects.uuid import Uuid
9
+ from {{ source_name }}.{{ template_domain_import }}.value_object.uuid import Uuid
10
10
  from {{ source_name }}.{{ template_infra_import }}.persistence.sqlalchemy.base import Base
11
11
  from {{ source_name }}.{{ template_infra_import }}.persistence.sqlalchemy.session_maker import (
12
12
  SessionMaker,
@@ -1,11 +1,14 @@
1
1
  {% set template_domain_import = "shared.domain"|compute_base_path(template) %}
2
2
  from {{ source_name }}.{{ template_domain_import }}.exceptions.invalid_negative_value_error import (
3
- InvalidNegativeValueError,
3
+ InvalidNegativeValueError,
4
4
  )
5
- from {{ source_name }}.{{ template_domain_import }}.value_objects.value_object import ValueObject
5
+ from {{ source_name }}.{{ template_domain_import }}.value_object.value_object import ValueObject
6
6
 
7
7
 
8
8
  class IntValueObject(ValueObject[int]):
9
- def _validate(self, value: int) -> None:
10
- if value < 0:
11
- raise InvalidNegativeValueError(value)
9
+ def __init__(self, value: int) -> None:
10
+ super().__init__(value)
11
+
12
+ def _validate(self, value: int) -> None:
13
+ if value < 0:
14
+ raise InvalidNegativeValueError(value)
@@ -5,7 +5,7 @@ from {{ source_name }}.{{ template_domain_import }}.exceptions.incorrect_value_t
5
5
  from {{ source_name }}.{{ template_domain_import }}.exceptions.required_value_error import (
6
6
  RequiredValueError,
7
7
  )
8
- from {{ source_name }}.{{ template_domain_import }}.value_objects.value_object import ValueObject
8
+ from {{ source_name }}.{{ template_domain_import }}.value_object.value_object import ValueObject
9
9
 
10
10
 
11
11
  class StringValueObject(ValueObject[str]):
@@ -4,7 +4,7 @@ from uuid import UUID
4
4
  from {{ source_name }}.{{ template_domain_import }}.exceptions.required_value_error import (
5
5
  RequiredValueError,
6
6
  )
7
- from {{ source_name }}.{{ template_domain_import }}.value_objects.value_object import ValueObject
7
+ from {{ source_name }}.{{ template_domain_import }}.value_object.value_object import ValueObject
8
8
 
9
9
 
10
10
  class Uuid(ValueObject[str]):
@@ -1,3 +1,3 @@
1
1
  - name: persistence/alembic_migrator
2
- type: file
2
+ type: boilerplate_file
3
3
  extension: .py
@@ -1,5 +1,5 @@
1
1
  - name: persistence/async/alembic
2
- type: file
2
+ type: boilerplate_file
3
3
  extension: .ini
4
4
  - name: migrations
5
5
  type: directory
@@ -7,14 +7,14 @@
7
7
  - name: versions
8
8
  type: directory
9
9
  - name: persistence/async/README
10
- type: file
10
+ type: boilerplate_file
11
11
  extension: .md
12
12
  - name: persistence/async/env
13
- type: file
13
+ type: boilerplate_file
14
14
  extension: .py
15
15
  - name: persistence/async/models_metadata
16
- type: file
16
+ type: boilerplate_file
17
17
  extension: .py
18
18
  - name: persistence/async/script
19
- type: file
19
+ type: boilerplate_file
20
20
  extension: .py.mako
@@ -7,11 +7,11 @@
7
7
  python: True
8
8
  children:
9
9
  - name: persistence/base
10
- type: file
10
+ type: boilerplate_file
11
11
  extension: .py
12
12
  - name: persistence/async/sqlalchemy_repository
13
- type: file
13
+ type: boilerplate_file
14
14
  extension: .py
15
15
  - name: persistence/async/postgres_settings
16
- type: file
16
+ type: boilerplate_file
17
17
  extension: .py
@@ -36,13 +36,13 @@
36
36
  {% if "event_bus" in built_in_features %}
37
37
  {{ macros.include_and_indent("project_structure/event_bus_infra.yml.j2", 8) }}
38
38
  {% endif %}
39
- {% if "logger" in built_in_features %}
39
+ {% if ["logger", "fastapi_application"] | is_in(built_in_features) %}
40
40
  {{ macros.include_and_indent("project_structure/logger.yml.j2", 8) }}
41
41
  {% endif %}
42
42
  {% if "async_sqlalchemy" in built_in_features %}
43
43
  {{ macros.include_and_indent("project_structure/async_sqlalchemy.yml.j2", 8) }}
44
44
  {% endif %}
45
- {% if "async_alembic" in built_in_features %}
45
+ {% if ["async_alembic", "fastapi_application"] | is_in(built_in_features) %}
46
46
  {{ macros.include_and_indent("project_structure/alembic_migrator.yml.j2", 8) }}
47
47
  {% endif %}
48
48
  {% if "fastapi_application" in built_in_features %}
@@ -9,7 +9,7 @@
9
9
  {% if "event_bus" in built_in_features %}
10
10
  children:
11
11
  - name: event_bus/mock_event_bus
12
- type: file
12
+ type: boilerplate_file
13
13
  extension: .py
14
14
  {% endif %}
15
15
  - name: integration
@@ -19,5 +19,5 @@
19
19
  type: directory
20
20
  python: True
21
21
  - name: random_generator
22
- type: file
22
+ type: boilerplate_file
23
23
  extension: .py
@@ -38,13 +38,13 @@
38
38
  {% if "event_bus" in built_in_features %}
39
39
  {{ macros.include_and_indent("project_structure/event_bus_infra.yml.j2", 12) }}
40
40
  {% endif %}
41
- {% if "logger" in built_in_features %}
41
+ {% if ["logger", "fastapi_application"] | is_in(built_in_features) %}
42
42
  {{ macros.include_and_indent("project_structure/logger.yml.j2", 12) }}
43
43
  {% endif %}
44
44
  {% if "async_sqlalchemy" in built_in_features %}
45
45
  {{ macros.include_and_indent("project_structure/async_sqlalchemy.yml.j2", 12) }}
46
46
  {% endif %}
47
- {% if "async_alembic" in built_in_features %}
47
+ {% if ["async_alembic", "fastapi_application"] | is_in(built_in_features) %}
48
48
  {{ macros.include_and_indent("project_structure/alembic_migrator.yml.j2", 12) }}
49
49
  {% endif %}
50
50
  {% if "fastapi_application" in built_in_features %}
@@ -52,4 +52,6 @@
52
52
  {% endif %}
53
53
  {% endif %}
54
54
  {% endif %}
55
- {{ macros.include_and_indent("project_structure/domain_driven_design/bounded_context.yml.j2", 4) }}
55
+ {% if specify_bounded_context %}
56
+ {{ macros.include_and_indent("project_structure/domain_driven_design/bounded_context.yml.j2", 4) }}
57
+ {% endif %}