instant-python 0.20.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.
- instant_python/__init__.py +1 -0
- instant_python/cli/__init__.py +0 -0
- instant_python/cli/cli.py +58 -0
- instant_python/cli/instant_python_typer.py +35 -0
- instant_python/config/__init__.py +0 -0
- instant_python/config/application/__init__.py +0 -0
- instant_python/config/application/config_generator.py +23 -0
- instant_python/config/delivery/__init__.py +0 -0
- instant_python/config/delivery/cli.py +19 -0
- instant_python/config/domain/__init__.py +0 -0
- instant_python/config/domain/question_wizard.py +7 -0
- instant_python/config/infra/__init__.py +0 -0
- instant_python/config/infra/question_wizard/__init__.py +0 -0
- instant_python/config/infra/question_wizard/questionary_console_wizard.py +25 -0
- instant_python/config/infra/question_wizard/step/__init__.py +0 -0
- instant_python/config/infra/question_wizard/step/dependencies_step.py +64 -0
- instant_python/config/infra/question_wizard/step/general_step.py +81 -0
- instant_python/config/infra/question_wizard/step/git_step.py +41 -0
- instant_python/config/infra/question_wizard/step/questionary.py +17 -0
- instant_python/config/infra/question_wizard/step/steps.py +21 -0
- instant_python/config/infra/question_wizard/step/template_step.py +63 -0
- instant_python/initialize/__init__.py +0 -0
- instant_python/initialize/application/__init__.py +0 -0
- instant_python/initialize/application/project_initializer.py +47 -0
- instant_python/initialize/delivery/__init__.py +0 -0
- instant_python/initialize/delivery/cli.py +48 -0
- instant_python/initialize/domain/__init__.py +0 -0
- instant_python/initialize/domain/env_manager.py +9 -0
- instant_python/initialize/domain/node.py +73 -0
- instant_python/initialize/domain/project_formatter.py +7 -0
- instant_python/initialize/domain/project_renderer.py +10 -0
- instant_python/initialize/domain/project_structure.py +77 -0
- instant_python/initialize/domain/project_writer.py +20 -0
- instant_python/initialize/domain/version_control_configurer.py +9 -0
- instant_python/initialize/infra/__init__.py +0 -0
- instant_python/initialize/infra/env_manager/__init__.py +0 -0
- instant_python/initialize/infra/env_manager/env_manager_factory.py +27 -0
- instant_python/initialize/infra/env_manager/pdm_env_manager.py +66 -0
- instant_python/initialize/infra/env_manager/system_console.py +65 -0
- instant_python/initialize/infra/env_manager/uv_env_manager.py +74 -0
- instant_python/initialize/infra/formatter/__init__.py +0 -0
- instant_python/initialize/infra/formatter/ruff_project_formatter.py +10 -0
- instant_python/initialize/infra/renderer/__init__.py +0 -0
- instant_python/initialize/infra/renderer/jinja_environment.py +71 -0
- instant_python/initialize/infra/renderer/jinja_project_renderer.py +57 -0
- instant_python/initialize/infra/version_control/__init__.py +0 -0
- instant_python/initialize/infra/version_control/git_configurer.py +29 -0
- instant_python/initialize/infra/writer/__init__.py +0 -0
- instant_python/initialize/infra/writer/file_system_project_writer.py +23 -0
- instant_python/shared/__init__.py +0 -0
- instant_python/shared/application_error.py +8 -0
- instant_python/shared/domain/__init__.py +0 -0
- instant_python/shared/domain/config_repository.py +18 -0
- instant_python/shared/domain/config_schema.py +113 -0
- instant_python/shared/domain/dependency_config.py +41 -0
- instant_python/shared/domain/general_config.py +71 -0
- instant_python/shared/domain/git_config.py +32 -0
- instant_python/shared/domain/template_config.py +76 -0
- instant_python/shared/infra/__init__.py +0 -0
- instant_python/shared/infra/persistence/__init__.py +0 -0
- instant_python/shared/infra/persistence/yaml_config_repository.py +39 -0
- instant_python/shared/supported_built_in_features.py +20 -0
- instant_python/shared/supported_licenses.py +11 -0
- instant_python/shared/supported_managers.py +10 -0
- instant_python/shared/supported_python_versions.py +12 -0
- instant_python/shared/supported_templates.py +12 -0
- instant_python/templates/boilerplate/.gitignore +164 -0
- instant_python/templates/boilerplate/.pre-commit-config.yml +73 -0
- instant_python/templates/boilerplate/.python-version +1 -0
- instant_python/templates/boilerplate/CITATION.cff +13 -0
- instant_python/templates/boilerplate/LICENSE +896 -0
- instant_python/templates/boilerplate/README.md +8 -0
- instant_python/templates/boilerplate/SECURITY.md +43 -0
- instant_python/templates/boilerplate/event_bus/__init__.py +0 -0
- instant_python/templates/boilerplate/event_bus/domain_event.py +15 -0
- instant_python/templates/boilerplate/event_bus/domain_event_json_deserializer.py +25 -0
- instant_python/templates/boilerplate/event_bus/domain_event_json_serializer.py +16 -0
- instant_python/templates/boilerplate/event_bus/domain_event_subscriber.py +33 -0
- instant_python/templates/boilerplate/event_bus/event_aggregate.py +19 -0
- instant_python/templates/boilerplate/event_bus/event_bus.py +9 -0
- instant_python/templates/boilerplate/event_bus/exchange_type.py +14 -0
- instant_python/templates/boilerplate/event_bus/mock_event_bus.py +16 -0
- instant_python/templates/boilerplate/event_bus/rabbit_mq_configurer.py +45 -0
- instant_python/templates/boilerplate/event_bus/rabbit_mq_connection.py +71 -0
- instant_python/templates/boilerplate/event_bus/rabbit_mq_consumer.py +56 -0
- instant_python/templates/boilerplate/event_bus/rabbit_mq_event_bus.py +26 -0
- instant_python/templates/boilerplate/event_bus/rabbit_mq_queue_formatter.py +21 -0
- instant_python/templates/boilerplate/event_bus/rabbit_mq_settings.py +8 -0
- instant_python/templates/boilerplate/exceptions/__init__.py +0 -0
- instant_python/templates/boilerplate/exceptions/base_error.py +13 -0
- instant_python/templates/boilerplate/exceptions/domain_error.py +6 -0
- instant_python/templates/boilerplate/exceptions/domain_event_type_not_found_error.py +6 -0
- instant_python/templates/boilerplate/exceptions/rabbit_mq_connection_not_established_error.py +7 -0
- instant_python/templates/boilerplate/exceptions/required_value_error.py +6 -0
- instant_python/templates/boilerplate/fastapi/__init__.py +0 -0
- instant_python/templates/boilerplate/fastapi/application.py +74 -0
- instant_python/templates/boilerplate/fastapi/error_handlers.py +88 -0
- instant_python/templates/boilerplate/fastapi/error_response.py +31 -0
- instant_python/templates/boilerplate/fastapi/fastapi_log_middleware.py +32 -0
- instant_python/templates/boilerplate/fastapi/lifespan.py +13 -0
- instant_python/templates/boilerplate/fastapi/success_response.py +13 -0
- instant_python/templates/boilerplate/github/action.yml +35 -0
- instant_python/templates/boilerplate/github/bug_report.yml +60 -0
- instant_python/templates/boilerplate/github/ci.yml +199 -0
- instant_python/templates/boilerplate/github/feature_request.yml +21 -0
- instant_python/templates/boilerplate/github/release.yml +94 -0
- instant_python/templates/boilerplate/logger/__init__.py +0 -0
- instant_python/templates/boilerplate/logger/file_logger.py +55 -0
- instant_python/templates/boilerplate/logger/file_rotating_handler.py +36 -0
- instant_python/templates/boilerplate/logger/json_formatter.py +16 -0
- instant_python/templates/boilerplate/mypy.ini +41 -0
- instant_python/templates/boilerplate/persistence/__init__.py +0 -0
- instant_python/templates/boilerplate/persistence/alembic_migrator.py +19 -0
- instant_python/templates/boilerplate/persistence/async/README.md +1 -0
- instant_python/templates/boilerplate/persistence/async/__init__.py +0 -0
- instant_python/templates/boilerplate/persistence/async/alembic.ini +124 -0
- instant_python/templates/boilerplate/persistence/async/async_engine_fixture.py +20 -0
- instant_python/templates/boilerplate/persistence/async/async_session.py +20 -0
- instant_python/templates/boilerplate/persistence/async/env.py +94 -0
- instant_python/templates/boilerplate/persistence/async/models_metadata.py +10 -0
- instant_python/templates/boilerplate/persistence/async/postgres_settings.py +15 -0
- instant_python/templates/boilerplate/persistence/async/script.py.mako +26 -0
- instant_python/templates/boilerplate/persistence/async/sqlalchemy_repository.py +28 -0
- instant_python/templates/boilerplate/persistence/base.py +4 -0
- instant_python/templates/boilerplate/persistence/synchronous/__init__.py +0 -0
- instant_python/templates/boilerplate/persistence/synchronous/session_maker.py +21 -0
- instant_python/templates/boilerplate/persistence/synchronous/sqlalchemy_repository.py +40 -0
- instant_python/templates/boilerplate/pyproject.toml +134 -0
- instant_python/templates/boilerplate/pytest.ini +10 -0
- instant_python/templates/boilerplate/scripts/add_dependency.py +45 -0
- instant_python/templates/boilerplate/scripts/create_aggregate.py +33 -0
- instant_python/templates/boilerplate/scripts/insert_template.py +90 -0
- instant_python/templates/boilerplate/scripts/integration.sh +39 -0
- instant_python/templates/boilerplate/scripts/local_setup.py +12 -0
- instant_python/templates/boilerplate/scripts/makefile +184 -0
- instant_python/templates/boilerplate/scripts/post-merge.py +40 -0
- instant_python/templates/boilerplate/scripts/pre-commit.py +15 -0
- instant_python/templates/boilerplate/scripts/pre-push.py +6 -0
- instant_python/templates/boilerplate/scripts/remove_dependency.py +40 -0
- instant_python/templates/boilerplate/scripts/unit.sh +40 -0
- instant_python/templates/project_structure/clean_architecture/layers/application.yml +3 -0
- instant_python/templates/project_structure/clean_architecture/layers/delivery.yml +8 -0
- instant_python/templates/project_structure/clean_architecture/layers/domain.yml +10 -0
- instant_python/templates/project_structure/clean_architecture/layers/infra.yml +12 -0
- instant_python/templates/project_structure/clean_architecture/layers/test_application.yml +3 -0
- instant_python/templates/project_structure/clean_architecture/layers/test_delivery.yml +3 -0
- instant_python/templates/project_structure/clean_architecture/layers/test_domain.yml +3 -0
- instant_python/templates/project_structure/clean_architecture/layers/test_infra.yml +9 -0
- instant_python/templates/project_structure/clean_architecture/main_structure.yml +38 -0
- instant_python/templates/project_structure/clean_architecture/source.yml +9 -0
- instant_python/templates/project_structure/clean_architecture/test.yml +9 -0
- instant_python/templates/project_structure/config_files/gitignore.yml +3 -0
- instant_python/templates/project_structure/config_files/mypy.yml +4 -0
- instant_python/templates/project_structure/config_files/pyproject.yml +4 -0
- instant_python/templates/project_structure/config_files/pytest.yml +4 -0
- instant_python/templates/project_structure/config_files/python_version.yml +3 -0
- instant_python/templates/project_structure/documentation/citation.yml +4 -0
- instant_python/templates/project_structure/documentation/license.yml +3 -0
- instant_python/templates/project_structure/documentation/readme.yml +4 -0
- instant_python/templates/project_structure/documentation/security.yml +4 -0
- instant_python/templates/project_structure/domain_driven_design/layers/bounded_context.yml +17 -0
- instant_python/templates/project_structure/domain_driven_design/layers/delivery.yml +8 -0
- instant_python/templates/project_structure/domain_driven_design/layers/shared.yml +18 -0
- instant_python/templates/project_structure/domain_driven_design/layers/shared_domain.yml +10 -0
- instant_python/templates/project_structure/domain_driven_design/layers/shared_infra.yml +12 -0
- instant_python/templates/project_structure/domain_driven_design/layers/test_shared.yml +8 -0
- instant_python/templates/project_structure/domain_driven_design/layers/test_shared_delivery.yml +3 -0
- instant_python/templates/project_structure/domain_driven_design/layers/test_shared_domain.yml +3 -0
- instant_python/templates/project_structure/domain_driven_design/layers/test_shared_infra.yml +9 -0
- instant_python/templates/project_structure/domain_driven_design/main_structure.yml +38 -0
- instant_python/templates/project_structure/domain_driven_design/source.yml +10 -0
- instant_python/templates/project_structure/domain_driven_design/test.yml +9 -0
- instant_python/templates/project_structure/errors.yml +12 -0
- instant_python/templates/project_structure/events/event_bus_domain.yml +48 -0
- instant_python/templates/project_structure/events/event_bus_infra.yml +40 -0
- instant_python/templates/project_structure/events/mock_event_bus.yml +4 -0
- instant_python/templates/project_structure/fastapi/fastapi_app.yml +32 -0
- instant_python/templates/project_structure/fastapi/fastapi_domain.yml +12 -0
- instant_python/templates/project_structure/fastapi/fastapi_infra.yml +12 -0
- instant_python/templates/project_structure/github/github_action.yml +24 -0
- instant_python/templates/project_structure/github/github_issues_template.yml +14 -0
- instant_python/templates/project_structure/github/makefile.yml +3 -0
- instant_python/templates/project_structure/github/precommit_hook.yml +4 -0
- instant_python/templates/project_structure/logger.yml +16 -0
- instant_python/templates/project_structure/macros.j2 +73 -0
- instant_python/templates/project_structure/persistence/alembic_migrator.yml +6 -0
- instant_python/templates/project_structure/persistence/async_alembic.yml +27 -0
- instant_python/templates/project_structure/persistence/async_engine_conftest.yml +4 -0
- instant_python/templates/project_structure/persistence/async_sqlalchemy.yml +14 -0
- instant_python/templates/project_structure/persistence/persistence.yml +8 -0
- instant_python/templates/project_structure/persistence/synchronous_sqlalchemy.yml +20 -0
- instant_python/templates/project_structure/standard_project/layers/source_features.yml +13 -0
- instant_python/templates/project_structure/standard_project/layers/test_event_bus.yml +6 -0
- instant_python/templates/project_structure/standard_project/layers/test_features.yml +6 -0
- instant_python/templates/project_structure/standard_project/main_structure.yml +38 -0
- instant_python/templates/project_structure/standard_project/source.yml +5 -0
- instant_python/templates/project_structure/standard_project/test.yml +5 -0
- instant_python-0.20.0.dist-info/METADATA +318 -0
- instant_python-0.20.0.dist-info/RECORD +202 -0
- instant_python-0.20.0.dist-info/WHEEL +4 -0
- instant_python-0.20.0.dist-info/entry_points.txt +2 -0
- instant_python-0.20.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from scripts.templates.aggregate_root_template import aggregate_root_template
|
|
6
|
+
from scripts.templates.errors.incorrect_value_error_template import incorrect_value_type_error_template
|
|
7
|
+
from scripts.templates.errors.required_value_error_template import required_value_error_template
|
|
8
|
+
from scripts.templates.errors.invalid_negative_value_error_template import invalid_negative_value_error_template
|
|
9
|
+
from scripts.templates.value_objects.string_value_object_template import string_value_object_template
|
|
10
|
+
from scripts.templates.value_objects.uuid_template import uuid_template
|
|
11
|
+
from scripts.templates.value_objects.value_object_template import value_object_template
|
|
12
|
+
from scripts.templates.value_objects.int_value_object_template import int_value_object_template
|
|
13
|
+
from scripts.templates.events.domain_event_template import domain_event_template
|
|
14
|
+
from scripts.templates.events.domain_event_subscriber_template import domain_event_subscriber_template
|
|
15
|
+
from scripts.templates.events.event_bus_template import event_bus_template
|
|
16
|
+
from scripts.templates.events.exchange_type_template import exchange_type_template
|
|
17
|
+
from scripts.templates.events.rabbit_mq_configurer_template import rabbit_mq_configurer_template
|
|
18
|
+
from scripts.templates.events.rabbit_mq_connection_template import rabbit_mq_connection_template
|
|
19
|
+
from scripts.templates.events.rabbit_mq_consumer_template import rabbit_mq_consumer_template
|
|
20
|
+
from scripts.templates.events.rabbit_mq_event_bus_template import rabbit_mq_event_bus_template
|
|
21
|
+
from scripts.templates.events.rabbit_mq_queue_formatter_template import rabbit_mq_queue_formatter_template
|
|
22
|
+
from scripts.templates.events.rabbit_mq_settings_template import rabbit_mq_settings_template
|
|
23
|
+
from scripts.templates.events.domain_event_json_deserializer_template import domain_event_json_deserializer_template
|
|
24
|
+
from scripts.templates.events.domain_event_json_serializer_template import domain_event_json_serializer_template
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
TEMPLATES = {
|
|
28
|
+
"value_object": value_object_template,
|
|
29
|
+
"string_value_object": string_value_object_template,
|
|
30
|
+
"int_value_object": int_value_object_template,
|
|
31
|
+
"uuid": uuid_template,
|
|
32
|
+
"incorrect_value": incorrect_value_type_error_template,
|
|
33
|
+
"required_value": required_value_error_template,
|
|
34
|
+
"invalid_negative_value": invalid_negative_value_error_template,
|
|
35
|
+
"domain_event": domain_event_template,
|
|
36
|
+
"domain_event_subscriber": domain_event_subscriber_template,
|
|
37
|
+
"event_bus": event_bus_template,
|
|
38
|
+
"exchange_type": exchange_type_template,
|
|
39
|
+
"aggregate_root": aggregate_root_template,
|
|
40
|
+
"rabbit_mq_configurer": rabbit_mq_configurer_template,
|
|
41
|
+
"rabbit_mq_connection": rabbit_mq_connection_template,
|
|
42
|
+
"rabbit_mq_consumer": rabbit_mq_consumer_template,
|
|
43
|
+
"rabbit_mq_event_bus": rabbit_mq_event_bus_template,
|
|
44
|
+
"rabbit_mq_queue_formatter": rabbit_mq_queue_formatter_template,
|
|
45
|
+
"rabbit_mq_settings": rabbit_mq_settings_template,
|
|
46
|
+
"domain_event_json_deserializer": domain_event_json_deserializer_template,
|
|
47
|
+
"domain_event_json_serializer": domain_event_json_serializer_template,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def main() -> None:
|
|
52
|
+
list_available_templates()
|
|
53
|
+
template_name = input("Enter the name of the template you want to insert: ")
|
|
54
|
+
ensure_template_exists(template_name)
|
|
55
|
+
|
|
56
|
+
user_path = input("Enter the path where template should be created: ")
|
|
57
|
+
folder_path = generate_folder_path(Path(user_path))
|
|
58
|
+
write_content_at(folder_path, template_name)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def list_available_templates() -> None:
|
|
62
|
+
print(f"Available templates: {', '.join(TEMPLATES.keys())}")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def ensure_template_exists(template_name: str) -> None:
|
|
66
|
+
if template_name not in TEMPLATES:
|
|
67
|
+
print(f"Error: Template '{template_name}' not found.")
|
|
68
|
+
list_available_templates()
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def write_content_at(folder_path: Path, template_name: str) -> None:
|
|
73
|
+
file_name = f"{template_name.replace('_template', '')}.py"
|
|
74
|
+
file_path = folder_path / file_name
|
|
75
|
+
|
|
76
|
+
with open(file_path, "w") as file:
|
|
77
|
+
file.write(TEMPLATES[template_name])
|
|
78
|
+
print(f"Template {template_name} created at {file_path}")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def generate_folder_path(user_path: Path) -> Path:
|
|
82
|
+
project_root = Path(__file__).resolve().parents[1]
|
|
83
|
+
folder_path = project_root / user_path
|
|
84
|
+
folder_path.mkdir(parents=True, exist_ok=True)
|
|
85
|
+
print(f"Folder created at: {folder_path}")
|
|
86
|
+
return folder_path
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == "__main__":
|
|
90
|
+
main()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
function get_bounded_contexts_with_changes {
|
|
4
|
+
changed_files=$(git diff --name-only HEAD)
|
|
5
|
+
bounded_contexts=$(echo "$changed_files" | grep -E 'instant_python/contexts/([^/]*/)*(infra)' | sed -E 's|instant_python/contexts/([^/]*)/.*|\1|' | sort -u)
|
|
6
|
+
echo "$bounded_contexts"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function has_bounded_contexts {
|
|
10
|
+
local contexts="$1"
|
|
11
|
+
|
|
12
|
+
if [[ -z "$contexts" ]]; then
|
|
13
|
+
echo "No changes detected in infra folder of any bounded context."
|
|
14
|
+
return 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
return 0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function run_tests {
|
|
21
|
+
local contexts="$1"
|
|
22
|
+
|
|
23
|
+
for context in $contexts; do
|
|
24
|
+
echo "Running integration tests for bounded context: $context"
|
|
25
|
+
infra_folders=$(find tests/contexts/"$context" -type d -name "infra")
|
|
26
|
+
{{ general.dependency_manager }} run pytest $infra_folders -ra
|
|
27
|
+
done
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function main {
|
|
31
|
+
local bounded_contexts
|
|
32
|
+
bounded_contexts=$(get_bounded_contexts_with_changes)
|
|
33
|
+
|
|
34
|
+
if has_bounded_contexts "$bounded_contexts"; then
|
|
35
|
+
run_tests "$bounded_contexts"
|
|
36
|
+
fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
main
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import subprocess
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main() -> None:
|
|
6
|
+
print("Installing git hooks...")
|
|
7
|
+
subprocess.run(["git", "config", "core.hooksPath", "scripts/hooks"], check=True)
|
|
8
|
+
print("Git hooks installed.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
if __name__ == "__main__":
|
|
12
|
+
main()
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
{% set has_uv = general.dependency_manager == "uv" %}
|
|
2
|
+
{% set has_pdm = general.dependency_manager == "pdm" %}
|
|
3
|
+
{% set has_pre_commit_hooks = "precommit_hook" in template.built_in_features %}
|
|
4
|
+
{% set has_github_actions_or_makefile = ["github_actions", "makefile"] | is_in(template.built_in_features) %}
|
|
5
|
+
.DEFAULT_GOAL := help
|
|
6
|
+
|
|
7
|
+
.PHONY: help
|
|
8
|
+
help: ## Show this help.
|
|
9
|
+
@grep -E '^[a-zA-Z_-]+:.*?## ' $(firstword $(MAKEFILE_LIST)) | \
|
|
10
|
+
awk 'BEGIN {FS = ":.*## "}; {printf "%-30s %s\n", $$1, $$2}'
|
|
11
|
+
|
|
12
|
+
.PHONY: local-setup
|
|
13
|
+
local-setup: ## Setup git hooks and install dependencies.
|
|
14
|
+
@echo "⌛ Setting up the project...\n"
|
|
15
|
+
@make install
|
|
16
|
+
{% if has_pre_commit_hooks %}
|
|
17
|
+
@{{ general.dependency_manager }} run -m pre_commit install --hook-type pre-commit --hook-type commit-msg --hook-type pre-push
|
|
18
|
+
{% endif %}
|
|
19
|
+
|
|
20
|
+
.PHONY: install
|
|
21
|
+
install: ## Install dependencies.
|
|
22
|
+
@echo "⌛ Installing dependencies...\n"
|
|
23
|
+
{% if has_uv %}
|
|
24
|
+
@uv sync --all-groups
|
|
25
|
+
{% elif has_pdm %}
|
|
26
|
+
@pdm install
|
|
27
|
+
{% endif %}
|
|
28
|
+
|
|
29
|
+
.PHONY: update
|
|
30
|
+
update: ## Update dependencies.
|
|
31
|
+
@echo "⌛ Updating dependencies...\n"
|
|
32
|
+
{% if has_uv %}
|
|
33
|
+
@uv sync --upgrade
|
|
34
|
+
{% elif has_pdm %}
|
|
35
|
+
@pdm update
|
|
36
|
+
{% endif %}
|
|
37
|
+
|
|
38
|
+
.PHONY: add-dep
|
|
39
|
+
add-dep: ## Add a new dependency
|
|
40
|
+
@{{ general.dependency_manager }} add $(dep)
|
|
41
|
+
|
|
42
|
+
.PHONY: remove-dep
|
|
43
|
+
remove-dep: ## Remove a dependency
|
|
44
|
+
@{{ general.dependency_manager }} remove $(dep)
|
|
45
|
+
|
|
46
|
+
{% if dependencies | has_dependency("pytest") or has_github_actions_or_makefile %}
|
|
47
|
+
.PHONY: test
|
|
48
|
+
test: ## Run all test.
|
|
49
|
+
@echo "⌛ Running tests...\n"
|
|
50
|
+
@{{ general.dependency_manager }} run pytest test -ra
|
|
51
|
+
|
|
52
|
+
.PHONY: unit
|
|
53
|
+
unit: ## Run all unit test.
|
|
54
|
+
@echo "⌛ Running unit tests...\n"
|
|
55
|
+
@{{ general.dependency_manager }} run pytest -m "unit" -ra
|
|
56
|
+
|
|
57
|
+
.PHONY: integration
|
|
58
|
+
integration: ## Run all integration test.
|
|
59
|
+
@echo "⌛ Running integration tests...\n"
|
|
60
|
+
@{{ general.dependency_manager }} run pytest -m "integration" -ra
|
|
61
|
+
|
|
62
|
+
.PHONY: acceptance
|
|
63
|
+
acceptance: ## Run all acceptance test.
|
|
64
|
+
@echo "⌛ Running acceptance tests...\n"
|
|
65
|
+
@{{ general.dependency_manager }} run pytest -m "acceptance" -ra
|
|
66
|
+
|
|
67
|
+
.PHONY: coverage
|
|
68
|
+
coverage: ## Run all test with coverage.
|
|
69
|
+
@echo "⌛ Running tests with coverage...\n"
|
|
70
|
+
@{{ general.dependency_manager }} run coverage run --branch -m pytest test
|
|
71
|
+
@{{ general.dependency_manager }} run coverage html
|
|
72
|
+
@$(BROWSER) htmlcov/index.html
|
|
73
|
+
{% endif %}
|
|
74
|
+
{% if dependencies | has_dependency("pytest-watch") %}
|
|
75
|
+
.PHONY: watch
|
|
76
|
+
watch: ## Run all test with every change.
|
|
77
|
+
@echo "⌛ Running test in watch mode...\n"
|
|
78
|
+
@{{ general.dependency_manager }} run ptw --runner "pytest test -ra"
|
|
79
|
+
{% endif %}
|
|
80
|
+
|
|
81
|
+
.PHONY: check-typing
|
|
82
|
+
check-typing: ## Run mypy type checking.
|
|
83
|
+
@echo "⌛ Running type checking...\n"
|
|
84
|
+
{% if dependencies | has_dependency("mypy") or has_github_actions_or_makefile %}
|
|
85
|
+
@{{ general.dependency_manager }} run mypy
|
|
86
|
+
{% elif dependencies | has_dependency("ty") or has_github_actions_or_makefile %}
|
|
87
|
+
@{{ general.dependency_manager }} run ty
|
|
88
|
+
{% elif dependencies | has_dependency("pyright") or has_github_actions_or_makefile %}
|
|
89
|
+
@{{ general.dependency_manager }} run pyright
|
|
90
|
+
{% elif dependencies | has_dependency("pyrefly") or has_github_actions_or_makefile %}
|
|
91
|
+
@{{ general.dependency_manager }} run pyrefly
|
|
92
|
+
{% endif %}
|
|
93
|
+
|
|
94
|
+
{% if dependencies | has_dependency("ruff") or has_github_actions_or_makefile %}
|
|
95
|
+
.PHONY: check-lint
|
|
96
|
+
check-lint: ## Run ruff linting check.
|
|
97
|
+
@echo "⌛ Running linting check...\n"
|
|
98
|
+
{% if has_pdm %}
|
|
99
|
+
@pdm run ruff check src test
|
|
100
|
+
{% elif has_uv %}
|
|
101
|
+
@uvx ruff check src test
|
|
102
|
+
{% endif %}
|
|
103
|
+
|
|
104
|
+
.PHONY: lint
|
|
105
|
+
lint: ## Apply ruff linting fix.
|
|
106
|
+
@echo "\n⌛ Applying linting fixes...\n"
|
|
107
|
+
{% if has_pdm %}
|
|
108
|
+
@pdm run ruff check --fix src test
|
|
109
|
+
{% elif has_uv %}
|
|
110
|
+
@uvx ruff check --fix src test
|
|
111
|
+
{% endif %}
|
|
112
|
+
|
|
113
|
+
.PHONY: check-format
|
|
114
|
+
check-format: ## Run ruff format check.
|
|
115
|
+
@echo "⌛ Checking code formatting...\n"
|
|
116
|
+
{% if has_pdm %}
|
|
117
|
+
@pdm run ruff format --check src test
|
|
118
|
+
{% elif has_uv %}
|
|
119
|
+
@uvx ruff format --check src test
|
|
120
|
+
{% endif %}
|
|
121
|
+
|
|
122
|
+
.PHONY: format
|
|
123
|
+
format: ## Apply ruff format fix.
|
|
124
|
+
@echo "⌛ Formatting project code...\n"
|
|
125
|
+
{% if has_pdm %}
|
|
126
|
+
@pdm run ruff format src test
|
|
127
|
+
{% elif has_uv %}
|
|
128
|
+
@uvx ruff format src test
|
|
129
|
+
{% endif %}
|
|
130
|
+
|
|
131
|
+
.PHONY: autostyle
|
|
132
|
+
autostyle: ## Apply all code style fixes.
|
|
133
|
+
@echo "\n⌛ Applying all code style fixes...\n"
|
|
134
|
+
@make format
|
|
135
|
+
@make lint
|
|
136
|
+
@git add . && git commit -m "style: apply code style fixes"
|
|
137
|
+
{% endif %}
|
|
138
|
+
{% if has_pre_commit_hooks %}
|
|
139
|
+
.PHONY: secrets
|
|
140
|
+
secrets: # Check for secrets in the source code
|
|
141
|
+
@echo "⌛ Checking secrets...\n"
|
|
142
|
+
@{{ general.dependency_manager }} run -m pre_commit run gitleaks --all-files
|
|
143
|
+
{% endif %}
|
|
144
|
+
|
|
145
|
+
{% if "github_actions" in template.built_in_features %}
|
|
146
|
+
.PHONY: audit
|
|
147
|
+
audit: # It audits dependencies and source code
|
|
148
|
+
@echo "⌛ Checking for vulnerabilities in dependencies...\n"
|
|
149
|
+
@{{ general.dependency_manager }} run -m pip_audit --progress-spinner off
|
|
150
|
+
{% endif %}
|
|
151
|
+
|
|
152
|
+
.PHONY: clean
|
|
153
|
+
clean: # Clean up the project, removing the virtual environment and some files
|
|
154
|
+
@echo "\n⌛ Cleaning up the project...\n"
|
|
155
|
+
|
|
156
|
+
@{{ general.dependency_manager }} run -m pre_commit clean)
|
|
157
|
+
@{{ general.dependency_manager }} run -m pre_commit uninstall --hook-type pre-commit --hook-type commit-msg)
|
|
158
|
+
@rm --force --recursive .venv
|
|
159
|
+
@rm --force --recursive `find . -type f -name '*.py[co]'`
|
|
160
|
+
@rm --force --recursive `find . -name __pycache__`
|
|
161
|
+
@rm --force --recursive `find . -name .ruff_cache`
|
|
162
|
+
@rm --force --recursive `find . -name .mypy_cache`
|
|
163
|
+
@rm --force --recursive `find . -name .pytest_cache`
|
|
164
|
+
@rm --force --recursive .coverage
|
|
165
|
+
@rm --force --recursive .coverage.*
|
|
166
|
+
@rm --force --recursive coverage.xml
|
|
167
|
+
@rm --force --recursive htmlcov
|
|
168
|
+
|
|
169
|
+
.PHONY: show
|
|
170
|
+
show: ## Show installed dependencies.
|
|
171
|
+
{% if has_pdm %}
|
|
172
|
+
@pdm list
|
|
173
|
+
{% elif has_uv %}
|
|
174
|
+
@uv tree
|
|
175
|
+
{% endif %}
|
|
176
|
+
|
|
177
|
+
.PHONY: search
|
|
178
|
+
search: ## Show package details.
|
|
179
|
+
@read -p "Enter package name to search: " package;\
|
|
180
|
+
{% if has_pdm %}
|
|
181
|
+
@pdm show $$package
|
|
182
|
+
{% elif has_uv %}
|
|
183
|
+
@uv pip show $$package
|
|
184
|
+
{% endif %}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> None:
|
|
7
|
+
try:
|
|
8
|
+
changed_files = _get_changed_files_between_last_two_heads()
|
|
9
|
+
changed_files = changed_files.stdout.splitlines()
|
|
10
|
+
files_to_search = ["Dockerfile", "pyproject.toml", "poetry.lock"]
|
|
11
|
+
if any(f in changed_files for f in files_to_search):
|
|
12
|
+
print(" * changes detected in tracked files")
|
|
13
|
+
print(" * running make build and make install")
|
|
14
|
+
subprocess.run(["make", "build"], check=True)
|
|
15
|
+
subprocess.run(["make", "install"], check=True)
|
|
16
|
+
except subprocess.CalledProcessError as e:
|
|
17
|
+
print(f"post-merge hook failed: {e}")
|
|
18
|
+
sys.exit(e.returncode)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _get_changed_files_between_last_two_heads():
|
|
22
|
+
result = subprocess.run(
|
|
23
|
+
[
|
|
24
|
+
"git",
|
|
25
|
+
"diff-tree",
|
|
26
|
+
"-r",
|
|
27
|
+
"--name-only",
|
|
28
|
+
"--no-commit-id",
|
|
29
|
+
"HEAD@{1}",
|
|
30
|
+
"HEAD",
|
|
31
|
+
],
|
|
32
|
+
capture_output=True,
|
|
33
|
+
text=True,
|
|
34
|
+
check=True,
|
|
35
|
+
)
|
|
36
|
+
return result
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> None:
|
|
7
|
+
try:
|
|
8
|
+
subprocess.run(["make", "pre-commit"], check=True)
|
|
9
|
+
except subprocess.CalledProcessError as e:
|
|
10
|
+
print(f"pre-commit hook failed: {e}")
|
|
11
|
+
sys.exit(e.returncode)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import subprocess
|
|
3
|
+
|
|
4
|
+
{% if general.dependency_manager == "pdm" -%}
|
|
5
|
+
def main() -> None:
|
|
6
|
+
dependency = input("Dependency to remove: ")
|
|
7
|
+
is_dev = input(f"Is {dependency} a dev dependency? (y/n): ")
|
|
8
|
+
belongs_to_group = input(f"Does {dependency} belong to a group? (y/n): ")
|
|
9
|
+
|
|
10
|
+
dev_flag=""
|
|
11
|
+
group_flag=""
|
|
12
|
+
if is_dev.lower() == "y":
|
|
13
|
+
dev_flag = "-d"
|
|
14
|
+
if belongs_to_group.lower() == "y":
|
|
15
|
+
group_name = input("Group name: ")
|
|
16
|
+
group_flag = f"-G {group_name}"
|
|
17
|
+
|
|
18
|
+
cmd = f"pdm remove {dev_flag} {group_flag} {dependency}".strip()
|
|
19
|
+
subprocess.run(cmd, shell=True, check=True)
|
|
20
|
+
|
|
21
|
+
{%- elif general.dependency_manager == "uv" -%}
|
|
22
|
+
def main() -> None:
|
|
23
|
+
dependency = input("Dependency to remove: ")
|
|
24
|
+
is_dev = input(f"Is {dependency} a dev dependency? (y/n): ")
|
|
25
|
+
belongs_to_group = input(f"Does {dependency} belong to a group? (y/n): ")
|
|
26
|
+
|
|
27
|
+
flag = ""
|
|
28
|
+
if is_dev.lower() == "y":
|
|
29
|
+
flag = "--dev"
|
|
30
|
+
if belongs_to_group.lower() == "y":
|
|
31
|
+
group_name = input("Group name: ")
|
|
32
|
+
flag = f"--group {group_name}"
|
|
33
|
+
|
|
34
|
+
cmd = f"uv remove {flag} {dependency}".strip()
|
|
35
|
+
subprocess.run(cmd, shell=True, check=True)
|
|
36
|
+
{% endif %}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
function get_bounded_contexts_with_changes {
|
|
4
|
+
changed_files=$(git diff --name-only HEAD)
|
|
5
|
+
bounded_contexts=$(echo "$changed_files" | grep -E 'instant_python/contexts/([^/]*/)*(application|domain)' | sed -E 's|instant_python/contexts/([^/]*)/.*|\1|' | sort -u)
|
|
6
|
+
echo "$bounded_contexts"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function has_bounded_contexts {
|
|
10
|
+
local contexts="$1"
|
|
11
|
+
|
|
12
|
+
if [[ -z "$contexts" ]]; then
|
|
13
|
+
echo "No changes detected in application or domain folders of any bounded context."
|
|
14
|
+
return 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
return 0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function run_tests {
|
|
21
|
+
local contexts="$1"
|
|
22
|
+
|
|
23
|
+
for context in $contexts; do
|
|
24
|
+
echo "Running application and domain tests for: $context"
|
|
25
|
+
application_folders=$(find tests/contexts/"$context" -type d -name "application")
|
|
26
|
+
domain_folders=$(find tests/contexts/"$context" -type d -name "domain")
|
|
27
|
+
{{ general.dependency_manager }} run pytest -n auto $application_folders $domain_folders -ra
|
|
28
|
+
done
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function main {
|
|
32
|
+
local bounded_contexts
|
|
33
|
+
bounded_contexts=$(get_bounded_contexts_with_changes)
|
|
34
|
+
|
|
35
|
+
if has_bounded_contexts "$bounded_contexts"; then
|
|
36
|
+
run_tests "$bounded_contexts"
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
{%- set delivery_features = [
|
|
3
|
+
{"feature": "fastapi_application", "template": "fastapi/fastapi_app.yml"}
|
|
4
|
+
] %}
|
|
5
|
+
- name: delivery
|
|
6
|
+
type: directory
|
|
7
|
+
python: True
|
|
8
|
+
{{ macros.render_children_for(delivery_features, 2) }}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
{%- set domain_features = [
|
|
3
|
+
{"feature": "value_objects", "template": "errors.yml"},
|
|
4
|
+
{"feature": "event_bus", "template": "events/event_bus_domain.yml"},
|
|
5
|
+
{"feature": "fastapi_application", "template": "fastapi/fastapi_domain.yml"}
|
|
6
|
+
] %}
|
|
7
|
+
- name: domain
|
|
8
|
+
type: directory
|
|
9
|
+
python: True
|
|
10
|
+
{{ macros.render_children_for(domain_features, 2) }}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
{%- set infra_features = [
|
|
3
|
+
{"feature": "event_bus", "template": "events/event_bus_infra.yml"},
|
|
4
|
+
{"feature": "logger", "template": "logger.yml"},
|
|
5
|
+
{"feature": "async_sqlalchemy", "template": "persistence/async_sqlalchemy.yml"},
|
|
6
|
+
{"feature": "async_alembic", "template": "persistence/alembic_migrator.yml"},
|
|
7
|
+
{"feature": "fastapi_application", "template": "fastapi/fastapi_infra.yml"}
|
|
8
|
+
] %}
|
|
9
|
+
- name: infra
|
|
10
|
+
type: directory
|
|
11
|
+
python: True
|
|
12
|
+
{{ macros.render_children_for(infra_features, 2) }}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
{%- set infra_features = [
|
|
3
|
+
{"feature": "event_bus", "template": "events/mock_event_bus.yml"},
|
|
4
|
+
{"feature": "async_sqlalchemy", "template": "persistence/async_engine_conftest.yml"},
|
|
5
|
+
] %}
|
|
6
|
+
- name: infra
|
|
7
|
+
type: directory
|
|
8
|
+
python: True
|
|
9
|
+
{{ macros.render_children_for(infra_features, 2) }}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
{# === Core Project Structure === #}
|
|
3
|
+
{{ macros.include_block("clean_architecture/source.yml", 0) }}
|
|
4
|
+
{{ macros.include_block("clean_architecture/test.yml", 0) }}
|
|
5
|
+
{# === Base Configuration Files === #}
|
|
6
|
+
{{ macros.include_block("config_files/pyproject.yml", 0) }}
|
|
7
|
+
{{ macros.include_block("config_files/python_version.yml", 0) }}
|
|
8
|
+
{{ macros.include_block("documentation/license.yml", 0) }}
|
|
9
|
+
{# === CI/CD and Automation Features === #}
|
|
10
|
+
{% set ci_cd_features = [
|
|
11
|
+
{"feature": "github_actions", "template": "github/github_action.yml"},
|
|
12
|
+
{"feature": "github_actions", "template": "github/makefile.yml"},
|
|
13
|
+
{"feature": "github_issues_template", "template": "github/github_issues_template.yml"},
|
|
14
|
+
{"feature": "makefile", "template": "github/makefile.yml"},
|
|
15
|
+
{"feature": "precommit_hook", "template": "github/precommit_hook.yml"},
|
|
16
|
+
{"feature": "precommit_hook", "template": "github/makefile.yml"}
|
|
17
|
+
] %}
|
|
18
|
+
{{ macros.render_features(ci_cd_features, 0) }}
|
|
19
|
+
{# === Git Features === #}
|
|
20
|
+
{% if git.initialize %}
|
|
21
|
+
{{ macros.include_block("config_files/gitignore.yml", 0) }}
|
|
22
|
+
{{ macros.include_block("documentation/readme.yml", 0) }}
|
|
23
|
+
{% endif %}
|
|
24
|
+
{# === Testing and Type Checking === #}
|
|
25
|
+
{% if dependencies | has_dependency("pytest") %}
|
|
26
|
+
{{ macros.include_block("config_files/pytest.yml", 0) }}
|
|
27
|
+
{% endif %}
|
|
28
|
+
{% if dependencies | has_dependency("mypy") %}
|
|
29
|
+
{{ macros.include_block("config_files/mypy.yml", 0) }}
|
|
30
|
+
{% endif %}
|
|
31
|
+
{# === Database Migration === #}
|
|
32
|
+
{{ macros.render_feature_if_enabled("async_alembic", "persistence/async_alembic.yml", 0) }}
|
|
33
|
+
{# === Documentation and Metadata === #}
|
|
34
|
+
{% set doc_features = [
|
|
35
|
+
{"feature": "citation_file", "template": "documentation/citation.yml"},
|
|
36
|
+
{"feature": "security_file", "template": "documentation/security.yml"}
|
|
37
|
+
] %}
|
|
38
|
+
{{ macros.render_features(doc_features, 0) }}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
- name: {{ general.source_name }}
|
|
3
|
+
type: directory
|
|
4
|
+
python: True
|
|
5
|
+
children:
|
|
6
|
+
{{ macros.include_block("clean_architecture/layers/delivery.yml", 4) }}
|
|
7
|
+
{{ macros.include_block("clean_architecture/layers/domain.yml", 4) }}
|
|
8
|
+
{{ macros.include_block("clean_architecture/layers/application.yml", 4) }}
|
|
9
|
+
{{ macros.include_block("clean_architecture/layers/infra.yml", 4) }}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{% import "macros.j2" as macros with context %}
|
|
2
|
+
- name: test
|
|
3
|
+
type: directory
|
|
4
|
+
python: True
|
|
5
|
+
children:
|
|
6
|
+
{{ macros.include_block("clean_architecture/layers/test_delivery.yml", 4) }}
|
|
7
|
+
{{ macros.include_block("clean_architecture/layers/test_domain.yml", 4) }}
|
|
8
|
+
{{ macros.include_block("clean_architecture/layers/test_application.yml", 4) }}
|
|
9
|
+
{{ macros.include_block("clean_architecture/layers/test_infra.yml", 4) }}
|