instant-python 0.8.2__py3-none-any.whl → 0.9.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.
Files changed (68) hide show
  1. instant_python/cli/__init__.py +0 -0
  2. instant_python/{cli.py → cli/cli.py} +1 -1
  3. instant_python/shared/supported_built_in_features.py +4 -0
  4. instant_python/templates/boilerplate/.pre-commit-config.yml +56 -18
  5. instant_python/templates/boilerplate/CITATION.cff +13 -0
  6. instant_python/templates/boilerplate/SECURITY.md +43 -0
  7. instant_python/templates/boilerplate/event_bus/{aggregate_root.py → event_aggregate.py} +2 -1
  8. instant_python/templates/boilerplate/exceptions/domain_error.py +4 -20
  9. instant_python/templates/boilerplate/exceptions/error.py +24 -0
  10. instant_python/templates/boilerplate/fastapi/application.py +47 -10
  11. instant_python/templates/boilerplate/fastapi/error_handlers.py +64 -0
  12. instant_python/templates/boilerplate/fastapi/error_response.py +31 -0
  13. instant_python/templates/boilerplate/fastapi/fastapi_log_middleware.py +33 -0
  14. instant_python/templates/boilerplate/fastapi/success_response.py +13 -0
  15. instant_python/templates/boilerplate/github/action.yml +17 -4
  16. instant_python/templates/boilerplate/github/bug_report.yml +60 -0
  17. instant_python/templates/boilerplate/github/ci.yml +199 -0
  18. instant_python/templates/boilerplate/github/feature_request.yml +21 -0
  19. instant_python/templates/boilerplate/github/release.yml +85 -0
  20. instant_python/templates/boilerplate/logger/file_logger.py +56 -0
  21. instant_python/templates/boilerplate/logger/file_rotating_handler.py +37 -0
  22. instant_python/templates/boilerplate/logger/json_formatter.py +2 -2
  23. instant_python/templates/boilerplate/pyproject.toml +49 -3
  24. instant_python/templates/boilerplate/scripts/add_dependency.py +45 -0
  25. instant_python/templates/boilerplate/scripts/local_setup.py +12 -0
  26. instant_python/templates/boilerplate/scripts/makefile +96 -37
  27. instant_python/templates/boilerplate/scripts/post-merge.py +40 -0
  28. instant_python/templates/boilerplate/scripts/pre-commit.py +15 -0
  29. instant_python/templates/boilerplate/scripts/remove_dependency.py +40 -0
  30. instant_python/templates/boilerplate/value_object/aggregate.py +99 -0
  31. instant_python/templates/boilerplate/value_object/int_value_object.py +16 -7
  32. instant_python/templates/boilerplate/value_object/string_value_object.py +10 -12
  33. instant_python/templates/boilerplate/value_object/uuid.py +19 -11
  34. instant_python/templates/boilerplate/value_object/validation.py +7 -0
  35. instant_python/templates/boilerplate/value_object/value_object.py +88 -17
  36. instant_python/templates/project_structure/citation.yml.j2 +3 -0
  37. instant_python/templates/project_structure/clean_architecture/main_structure.yml.j2 +17 -4
  38. instant_python/templates/project_structure/domain_driven_design/main_structure.yml.j2 +17 -4
  39. instant_python/templates/project_structure/event_bus_domain.yml.j2 +20 -4
  40. instant_python/templates/project_structure/fastapi_app.yml.j2 +16 -0
  41. instant_python/templates/project_structure/fastapi_domain.yml.j2 +4 -1
  42. instant_python/templates/project_structure/fastapi_infra.yml.j2 +2 -2
  43. instant_python/templates/project_structure/github_action.yml.j2 +2 -2
  44. instant_python/templates/project_structure/github_issues_template.yml.j2 +12 -0
  45. instant_python/templates/project_structure/logger.yml.j2 +4 -1
  46. instant_python/templates/project_structure/makefile.yml.j2 +7 -16
  47. instant_python/templates/project_structure/{pre_commit.yml.j2 → precommit_hook.yml.j2} +1 -1
  48. instant_python/templates/project_structure/security.yml.j2 +3 -0
  49. instant_python/templates/project_structure/standard_project/main_structure.yml.j2 +18 -5
  50. instant_python/templates/project_structure/value_objects.yml.j2 +26 -9
  51. {instant_python-0.8.2.dist-info → instant_python-0.9.1.dist-info}/METADATA +4 -2
  52. {instant_python-0.8.2.dist-info → instant_python-0.9.1.dist-info}/RECORD +57 -43
  53. instant_python-0.9.1.dist-info/entry_points.txt +2 -0
  54. instant_python/templates/boilerplate/fastapi/http_response.py +0 -67
  55. instant_python/templates/boilerplate/fastapi/status_code.py +0 -9
  56. instant_python/templates/boilerplate/github/lint.yml +0 -30
  57. instant_python/templates/boilerplate/github/test.yml +0 -30
  58. instant_python/templates/boilerplate/logger/logger.py +0 -48
  59. instant_python/templates/boilerplate/scripts/add_dependency.sh +0 -37
  60. instant_python/templates/boilerplate/scripts/local_setup.sh +0 -15
  61. instant_python/templates/boilerplate/scripts/post-merge +0 -11
  62. instant_python/templates/boilerplate/scripts/pre-commit +0 -4
  63. instant_python/templates/boilerplate/scripts/remove_dependency.sh +0 -36
  64. instant_python-0.8.2.dist-info/entry_points.txt +0 -2
  65. /instant_python/{instant_python_typer.py → cli/instant_python_typer.py} +0 -0
  66. /instant_python/templates/boilerplate/scripts/{pre-push → pre-push.py} +0 -0
  67. {instant_python-0.8.2.dist-info → instant_python-0.9.1.dist-info}/WHEEL +0 -0
  68. {instant_python-0.8.2.dist-info → instant_python-0.9.1.dist-info}/licenses/LICENSE +0 -0
File without changes
@@ -3,7 +3,7 @@ from rich.panel import Panel
3
3
 
4
4
  from instant_python.commands import init, config
5
5
  from instant_python.shared.application_error import ApplicationError
6
- from instant_python.instant_python_typer import InstantPythonTyper
6
+ from instant_python.cli.instant_python_typer import InstantPythonTyper
7
7
 
8
8
  app = InstantPythonTyper()
9
9
  console = Console()
@@ -4,12 +4,16 @@ from enum import Enum
4
4
  class SupportedBuiltInFeatures(str, Enum):
5
5
  VALUE_OBJECTS = "value_objects"
6
6
  GITHUB_ACTIONS = "github_actions"
7
+ GITHUB_ISSUES_TEMPLATE = "github_issues_template"
7
8
  MAKEFILE = "makefile"
8
9
  LOGGER = "logger"
9
10
  EVENT_BUS = "event_bus"
10
11
  ASYNC_SQLALCHEMY = "async_sqlalchemy"
11
12
  ASYNC_ALEMBIC = "async_alembic"
12
13
  FASTAPI = "fastapi_application"
14
+ PRECOMMIT = "precommit_hook"
15
+ CITATION = "citation_file"
16
+ SECURITY = "security_file"
13
17
 
14
18
  @classmethod
15
19
  def get_supported_built_in_features(cls) -> list[str]:
@@ -1,33 +1,71 @@
1
+ fail_fast: true
2
+
3
+ default_language_version:
4
+ python: {{ general.python_version }}
5
+
1
6
  repos:
2
7
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v5.0.0
8
+ rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # v5.0.0
4
9
  hooks:
5
10
  - id: check-added-large-files
6
- - id: check-ast
11
+ name: 📦 Large Files Checker
12
+ args:
13
+ - --maxkb=100
14
+ stages:
15
+ - pre-commit
16
+
7
17
  - id: check-case-conflict
18
+ name: 🔠 Case Conflict Checker
19
+ stages:
20
+ - pre-commit
21
+
22
+ - id: check-toml
23
+ name: 📄 TOML Files Checker
24
+ files: '.*\.toml'
25
+ stages:
26
+ - pre-commit
27
+
28
+ - id: check-yaml
29
+ name: 📄 YAML Files Checker
30
+ files: '.*\.ya?ml'
31
+ args:
32
+ - --unsafe
33
+ stages:
34
+ - pre-commit
8
35
  - id: check-merge-conflict
36
+ name: 🔀 Merge Conflict Checker
37
+ stages:
38
+ - pre-commit
39
+
40
+ - repo: https://github.com/gitleaks/gitleaks
41
+ rev: 782f3104786efdce0f809bce8a9ff31f2fa1c9ed # v8.27.0
42
+ hooks:
43
+ - id: gitleaks
44
+ name: 🔍 Secrets Checker
45
+ entry: gitleaks detect --no-git --redact --verbose
46
+ stages:
47
+ - pre-commit
48
+
49
+ - repo: https://github.com/commitizen-tools/commitizen
50
+ rev: a0cc4901b0faaced74c713a9e355555fc4de0880 # v4.7.1
51
+ hooks:
52
+ - id: commitizen
53
+ name: 📝 Conventional Commit Message Checker
54
+ stages:
55
+ - commit-msg
9
56
 
10
57
  - repo: local
11
58
  hooks:
12
- - id: type-check
13
- name: check typing
14
- entry: make check-typing
15
- language: system
16
59
  - id: lint
17
- name: check for lint
18
- entry: make lint
60
+ name: 🧹 Code Linter
61
+ entry: make check-lint
19
62
  language: system
63
+ stages:
64
+ - pre-push
65
+
20
66
  - id: format
21
- name: check for code format
22
- entry: make format
23
- language: system
24
- - id: unit-test
25
- name: run all unit test
26
- entry: make all-unit
27
- language: system
28
- - id: pre-push
29
- name: run integration and acceptance test
30
- entry: make pre-push
67
+ name: 🎨 Code Formatter
68
+ entry: make check-format
31
69
  language: system
32
70
  stages:
33
71
  - pre-push
@@ -0,0 +1,13 @@
1
+ cff-version: 1.2.0
2
+ title: {{ general.slug }}
3
+ message: If you use this software, please cite it using the metadata below.
4
+ type: software
5
+ authors:
6
+ - given-names: {{ general.author }}
7
+ repository-code: https://github.com/{{ git.username }}/{{ general.slug }}/
8
+ url: https://pypi.org/project/{{ general.slug }}/
9
+ abstract: >
10
+ {{ general.description }}
11
+ keywords:
12
+ - python
13
+ license: {{ general.license }}
@@ -0,0 +1,43 @@
1
+ # Security Policy
2
+
3
+ Thank you for helping keep **{{ general.slug }}** package and its users safe.
4
+ We take security issues seriously and appreciate responsible disclosures.
5
+
6
+ ## Reporting a Vulnerability
7
+
8
+ > [!NOTE]
9
+ > **Please do NOT open public issues for security reports.**
10
+ > Use one of the private channels below so we can coordinate a safe disclosure.
11
+
12
+ | Channel | How it works |
13
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
14
+ | **GitHub Security Advisory** | 1. Navigate to the repository's **“Security → Advisories”** tab<br>2. Click **“Report a vulnerability”** and fill in the form |
15
+
16
+ Include the following, if possible:
17
+
18
+ 1. A **concise description** of the issue and its impact.
19
+ 2. **Reproduction steps** or a proof-of-concept script.
20
+ 3. Any **mitigation** ideas you've identified.
21
+
22
+ ## Our Disclosure Process
23
+
24
+ 1. **Acknowledge** report within 24–48 hours.
25
+ 2. **Triage & validate** the issue; request additional info if needed.
26
+ 3. **Fix & prepare**: develop a patch and regression tests.
27
+ 4. **Coordinate release**:
28
+ - Agree on a disclosure date with the reporter (usually ≤ 30 days).
29
+ - Publish a CVE (if applicable) and a new PyPI release.
30
+ - Post a security advisory and update CHANGELOG.
31
+ 5. **Credit** the reporter (optional & with consent).
32
+
33
+ ## Responsible Disclosure
34
+
35
+ We kindly ask you to:
36
+
37
+ - Allow us reasonable time to remediate before any public disclosure.
38
+ - Avoid violating user privacy, destroying data, or disrupting production services while researching.
39
+ - Test only on your own instances or in minimal, isolated cases.
40
+
41
+ We are committed to keeping this project and its users safe and will strive to resolve all legitimate reports swiftly and transparently.
42
+
43
+ _Thank you for keeping the **{{ general.slug }}** package community secure!_
@@ -1,8 +1,9 @@
1
1
  {% set template_domain_import = "shared.domain"|compute_base_path(template.name) %}
2
2
  from {{ general.source_name }}.{{ template_domain_import }}.event.domain_event import DomainEvent
3
+ from {{ general.source_name }}.{{ template_domain_import }}.value_objects.aggregate import Aggregate
3
4
 
4
5
 
5
- class AggregateRoot:
6
+ class EventAggregate(Aggregate):
6
7
  _domain_events: list[DomainEvent]
7
8
 
8
9
  def __init__(self) -> None:
@@ -1,22 +1,6 @@
1
- from abc import ABC
1
+ {% set template_domain_import = "shared.domain"|compute_base_path(template.name) %}
2
+ from {{ general.source_name }}.{{ template_domain_import }}.exceptions.error import Error
2
3
 
4
+ class DomainError(Error):
5
+ ...
3
6
 
4
- class DomainError(Exception, ABC):
5
- def __init__(self, message: str, error_type: str) -> None:
6
- self._message = message
7
- self._type = error_type
8
- super().__init__(self._message)
9
-
10
- @property
11
- def type(self) -> str:
12
- return self._type
13
-
14
- @property
15
- def message(self) -> str:
16
- return self._message
17
-
18
- def to_primitives(self) -> dict[str, str]:
19
- return {
20
- "type": self.type,
21
- "message": self.message,
22
- }
@@ -0,0 +1,24 @@
1
+ from abc import ABC
2
+
3
+
4
+ class BaseError(Exception, ABC):
5
+ """Base class for all controlled errors in the application."""
6
+
7
+ def __init__(self, message: str, error_type: str) -> None:
8
+ self._message = message
9
+ self._type = error_type
10
+ super().__init__(self._message)
11
+
12
+ @property
13
+ def type(self) -> str:
14
+ return self._type
15
+
16
+ @property
17
+ def message(self) -> str:
18
+ return self._message
19
+
20
+ def to_primitives(self) -> dict[str, str]:
21
+ return {
22
+ "type": self.type,
23
+ "message": self.message,
24
+ }
@@ -1,7 +1,37 @@
1
1
  {% set template_domain_import = "shared.domain"|compute_base_path(template.name) %}
2
2
  {% set template_infra_import = "shared.infra"|compute_base_path(template.name) %}
3
- from fastapi import FastAPI, Request
4
- from fastapi.responses import JSONResponse
3
+ from fastapi import FastAPI
4
+ {% if "logger" in template.built_in_features %}
5
+ from fastapi.exceptions import RequestValidationError
6
+ {% endif %}
7
+
8
+ {% if template.name == template_types.STANDARD %}
9
+ {% if "logger" in template.built_in_features %}
10
+ from {{ general.source_name }}.api.handlers.error_handlers import (
11
+ unexpected_exception_handler,
12
+ domain_error_handler,
13
+ validation_error_handler,
14
+ )
15
+ {% else %}
16
+ from {{ general.source_name }}.api.handlers.error_handlers import (
17
+ unexpected_exception_handler,
18
+ domain_error_handler,
19
+ )
20
+ {% endif %}
21
+ {% else %}
22
+ {% if "logger" in template.built_in_features %}
23
+ from {{ general.source_name }}.delivery.api.handlers.error_handlers import (
24
+ unexpected_exception_handler,
25
+ domain_error_handler,
26
+ validation_error_handler,
27
+ )
28
+ {% else %}
29
+ from {{ general.source_name }}.delivery.api.handlers.error_handlers import (
30
+ unexpected_exception_handler,
31
+ domain_error_handler,
32
+ )
33
+ {% endif %}
34
+ {% endif %}
5
35
 
6
36
  {% if ["async_alembic"] | is_in(template.built_in_features) %}
7
37
  {% if template.name == template_types.STANDARD %}
@@ -10,9 +40,15 @@ from {{ general.source_name }}.api.lifespan import lifespan
10
40
  from {{ general.source_name }}.delivery.api.lifespan import lifespan
11
41
  {% endif %}
12
42
  {% endif %}
13
- from {{ general.source_name }}.{{ template_infra_import }}.http.http_response import HttpResponse
14
- from {{ general.source_name }}.{{ template_infra_import }}.http.status_code import StatusCode
15
43
  from {{ general.source_name }}.{{ template_domain_import }}.exceptions.domain_error import DomainError
44
+ {% if "logger" in template.built_in_features %}
45
+ from {{ general.source_name }}.{{ template_infra_import }}.logger.file_logger import create_file_logger
46
+ {% if template.name == template_types.STANDARD %}
47
+ from {{ general.source_name }}.api.middleare.fast_api_log_middleware import FastapiLogMiddleware
48
+ {% else %}
49
+ from {{ general.source_name }}.delivery.api.middleare.fast_api_log_middleware import FastapiLogMiddleware
50
+ {% endif %}
51
+ {% endif %}
16
52
 
17
53
 
18
54
  {% if ["async_alembic"] | is_in(template.built_in_features) %}
@@ -21,11 +57,12 @@ app = FastAPI(lifespan=lifespan)
21
57
  app = FastAPI()
22
58
  {% endif %}
23
59
 
24
- @app.exception_handler(Exception)
25
- async def unexpected_exception_handler(_: Request, exc: Exception) -> JSONResponse:
26
- return HttpResponse.internal_error(exc)
60
+ {% if "logger" in template.built_in_features %}
61
+ logger = create_file_logger(name="{{ general.slug }}")
27
62
 
63
+ app.add_middleware(FastapiLogMiddleware, logger=logger)
64
+ app.add_exception_handler(RequestValidationError, validation_error_handler)
65
+ {% endif %}
66
+ app.add_exception_handler(Exception, unexpected_exception_handler)
67
+ app.add_exception_handler(DomainError, domain_error_handler)
28
68
 
29
- @app.exception_handler(DomainError)
30
- async def domain_error_handler(_: Request, exc: DomainError) -> JSONResponse:
31
- return HttpResponse.domain_error(exc, status_code=StatusCode.BAD_REQUEST)
@@ -0,0 +1,64 @@
1
+ {% set template_domain_import = "shared.domain"|compute_base_path(template.name) %}
2
+ {% set template_infra_import = "shared.infra"|compute_base_path(template.name) %}
3
+ from fastapi import Request
4
+ from fastapi.responses import JSONResponse
5
+ {% if "logger" in template.built_in_features %}
6
+ from fastapi.exceptions import RequestValidationError
7
+ from fastapi.exception_handlers import request_validation_exception_handler
8
+ from {{ general.source_name }}.{{ template_infra_import }}.logger.file_logger import create_file_logger
9
+ {% endif %}
10
+ from {{ general.source_name }}.{{ template_infra_import }}.http.error_response import InternalServerError, UnprocessableEntityError
11
+ from {{ general.source_name }}.{{ template_domain_import }}.exceptions.domain_error import DomainError
12
+
13
+
14
+ {% if "logger" in template.built_in_features %}
15
+ logger = create_file_logger(name="{{ general.slug }}")
16
+
17
+ async def unexpected_exception_handler(request: Request, exc: Exception) -> JSONResponse:
18
+ logger.error(
19
+ message=f"error - {request.url.path}",
20
+ details={
21
+ "error": {
22
+ "message": str(exc),
23
+ "type": "unexpected_error",
24
+ },
25
+ "method": request.method,
26
+ "source": request.url.path,
27
+ },
28
+ )
29
+ return InternalServerError().as_json()
30
+
31
+
32
+ async def domain_error_handler(request: Request, exc: DomainError) -> JSONResponse:
33
+ logger.error(
34
+ message=f"error - {request.url.path}",
35
+ details={
36
+ "error": exc.to_primitives(),
37
+ "method": request.method,
38
+ "source": request.url.path,
39
+ },
40
+ )
41
+ return UnprocessableEntityError().as_json()
42
+
43
+
44
+ async def validation_error_handler(
45
+ request: Request,
46
+ exc: RequestValidationError,
47
+ ) -> JSONResponse:
48
+ logger.error(
49
+ message=f"error - {request.url.path}",
50
+ details={
51
+ "error": {"message": str(exc), "type": "validation_error"},
52
+ "method": request.method,
53
+ "source": request.url.path,
54
+ },
55
+ )
56
+ return await request_validation_exception_handler(request, exc)
57
+ {% else %}
58
+ async def unexpected_exception_handler(_: Request, __: Exception) -> JSONResponse:
59
+ return InternalServerError().as_json()
60
+
61
+
62
+ async def domain_error_handler(_: Request, __: DomainError) -> JSONResponse:
63
+ return UnprocessableEntityError().as_json()
64
+ {% endif %}
@@ -0,0 +1,31 @@
1
+ from abc import ABC
2
+
3
+ from fastapi import status
4
+ from fastapi.responses import JSONResponse
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class ErrorResponse(ABC, BaseModel):
9
+ status_code: int
10
+ detail: str
11
+
12
+ def as_json(self) -> JSONResponse:
13
+ return JSONResponse(
14
+ content={"detail": self.detail},
15
+ status_code=self.status_code,
16
+ )
17
+
18
+
19
+ class UnprocessableEntityError(ErrorResponse):
20
+ status_code: int = Field(default=status.HTTP_422_UNPROCESSABLE_ENTITY)
21
+ detail: str = Field(default="Unprocessable Entity")
22
+
23
+
24
+ class ResourceNotFoundError(ErrorResponse):
25
+ status_code: int = Field(default=status.HTTP_404_NOT_FOUND)
26
+ detail: str = Field(default="Not Found")
27
+
28
+
29
+ class InternalServerError(ErrorResponse):
30
+ status_code: int = Field(default=status.HTTP_500_INTERNAL_SERVER_ERROR)
31
+ detail: str = Field(default="An unexpected error occurred.")
@@ -0,0 +1,33 @@
1
+ {% set template_infra_import = "shared.infra"|compute_base_path(template.name) %}
2
+ import time
3
+
4
+ from fastapi import Request, Response, FastAPI
5
+ from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
6
+
7
+ from {{ general.source_name }}.{{ template_infra_import }}.logger.file_logger import FileLogger
8
+
9
+
10
+ class FastapiLogMiddleware(BaseHTTPMiddleware):
11
+ def __init__(self, app: FastAPI, logger: FileLogger) -> None:
12
+ super().__init__(app)
13
+ self._logger = logger
14
+
15
+ async def dispatch(
16
+ self, request: Request, call_next: RequestResponseEndpoint
17
+ ) -> Response:
18
+ start_time = time.perf_counter()
19
+ response = await call_next(request)
20
+ process_time = time.perf_counter() - start_time
21
+
22
+ if response.status_code < 400:
23
+ self._logger.info(
24
+ message=f"success - {request.url.path}",
25
+ details={
26
+ "method": request.method,
27
+ "source": request.url.path,
28
+ "process_time": process_time,
29
+ "status_code": response.status_code,
30
+ },
31
+ )
32
+
33
+ return response
@@ -0,0 +1,13 @@
1
+ from pydantic import BaseModel
2
+ from starlette.responses import JSONResponse
3
+
4
+
5
+ class SuccessResponse(BaseModel):
6
+ status_code: int
7
+ data: dict
8
+
9
+ def as_json(self) -> JSONResponse:
10
+ return JSONResponse(
11
+ content=self.data,
12
+ status_code=self.status_code,
13
+ )
@@ -9,14 +9,27 @@ outputs: {}
9
9
  runs:
10
10
  using: composite
11
11
  steps:
12
- - uses: actions/setup-python@v5
12
+ - name: 🐍 Setup Python
13
+ uses: actions/setup-python@v5
13
14
  with:
14
15
  python-version: {% raw %}${{ inputs.python-version }}{% endraw %}
15
16
 
16
- - name: Install dependency manager
17
+ - name: 🔨 Install dependency manager
17
18
  run: python -m pip install {{ general.dependency_manager }}
18
19
  shell: bash
19
- - name: Install dependencies
20
- run: {% if general.dependency_manager == "uv" %}uv sync --all-groups{% elif general.dependency_manager == "pdm" %}pdm install {% endif %}
21
20
 
21
+ - name: 📦 Install dependencies
22
+ run: |
23
+ {% if general.dependency_manager == "uv" %}
24
+ uv sync --all-groups
25
+ {% elif general.dependency_manager == "pdm" %}
26
+ pdm install
27
+ {% endif %}
28
+ {% if "precommit_hook" in template.built_in_features %}
29
+ {% if general.dependency_manager == "uv" %}
30
+ uv run -m pre_commit install
31
+ {% elif general.dependency_manager == "pdm" %}
32
+ pdm run pre-commit install
33
+ {% endif %}
34
+ {% endif %}
22
35
  shell: bash
@@ -0,0 +1,60 @@
1
+ name: 🐛 Bug Report
2
+ description: Create a report to help us improve.
3
+ labels:
4
+ - bug
5
+ - pending
6
+
7
+ body:
8
+ - type: textarea
9
+ id: description
10
+ validations:
11
+ required: true
12
+ attributes:
13
+ label: ✏️ Description
14
+ description: |
15
+ Please provide a clear and concise description of the bug you are experiencing.
16
+
17
+ Specify what is the expected behavior and what is actually happening. You can add
18
+ screenshots to help illustrate the issue.
19
+
20
+ Please provide as much detail as possible to make understanding and solving your problem as quick as possible. 🙏
21
+
22
+ - type: textarea
23
+ id: reproduce
24
+ attributes:
25
+ label: ✅ Steps To Reproduce
26
+ render: Python
27
+ description: >
28
+ Please list the steps needed to reproduce the bug you are experiencing.
29
+
30
+ If applicable, please add a self-contained,
31
+ [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example)
32
+ demonstrating the bug.\
33
+
34
+ placeholder: >
35
+ # 1. Install the package using pip
36
+ # 2. Run the script with the following command:
37
+ # python script.py
38
+ # 3. Observe the output\
39
+
40
+ - type: dropdown
41
+ id: python-version
42
+ attributes:
43
+ label: 🐍 Which version of Python are you using?
44
+ options:
45
+ - 3.8
46
+ - 3.9
47
+ - 3.10
48
+ - 3.11
49
+ - 3.12
50
+ - 3.13
51
+ - other
52
+ validations:
53
+ required: true
54
+
55
+ - type: input
56
+ id: os
57
+ validations:
58
+ required: true
59
+ attributes:
60
+ label: 🖥️ Which operating system are you using?