FastAPI-fastkit 1.3.0__py3-none-any.whl → 1.4.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.
- fastapi_fastkit/__init__.py +1 -1
- fastapi_fastkit/backend/inspection/__init__.py +26 -0
- fastapi_fastkit/backend/inspection/checks.py +349 -0
- fastapi_fastkit/backend/inspection/consistency.py +125 -0
- fastapi_fastkit/backend/inspection/context.py +67 -0
- fastapi_fastkit/backend/inspection/core.py +347 -0
- fastapi_fastkit/backend/inspection/docker.py +185 -0
- fastapi_fastkit/backend/inspection/freshness.py +145 -0
- fastapi_fastkit/backend/inspection/fsutils.py +139 -0
- fastapi_fastkit/backend/inspection/lint.py +89 -0
- fastapi_fastkit/backend/inspection/report.py +58 -0
- fastapi_fastkit/backend/inspection/smoke.py +327 -0
- fastapi_fastkit/backend/inspection/strategies.py +336 -0
- fastapi_fastkit/backend/inspector.py +18 -1400
- fastapi_fastkit/backend/interactive/__init__.py +6 -0
- fastapi_fastkit/backend/interactive/config_builder.py +45 -63
- fastapi_fastkit/backend/interactive/prompts.py +155 -6
- fastapi_fastkit/backend/interactive/selectors.py +18 -2
- fastapi_fastkit/backend/main.py +887 -99
- fastapi_fastkit/backend/package_managers/base.py +172 -0
- fastapi_fastkit/backend/package_managers/factory.py +5 -4
- fastapi_fastkit/backend/package_managers/pdm_manager.py +29 -82
- fastapi_fastkit/backend/package_managers/pip_manager.py +31 -85
- fastapi_fastkit/backend/package_managers/poetry_manager.py +70 -110
- fastapi_fastkit/backend/package_managers/uv_manager.py +43 -112
- fastapi_fastkit/backend/project_builder/__init__.py +8 -1
- fastapi_fastkit/backend/project_builder/config_generator.py +806 -450
- fastapi_fastkit/backend/project_builder/config_schema.py +384 -0
- fastapi_fastkit/backend/project_builder/dependency_collector.py +105 -66
- fastapi_fastkit/backend/project_builder/preset_layout.py +254 -28
- fastapi_fastkit/backend/scaffolder.py +578 -0
- fastapi_fastkit/backend/transducer.py +54 -21
- fastapi_fastkit/cli.py +434 -311
- fastapi_fastkit/core/settings.py +232 -43
- fastapi_fastkit/fastapi_project_template/README.md +26 -10
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/README.md-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/pyproject.toml-tpl +21 -22
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/requirements.txt-tpl +39 -36
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/api/routes/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/main.py-tpl +9 -1
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/.env-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/.gitignore-tpl +33 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/Dockerfile-tpl +18 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/README.md-tpl +210 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/alembic.ini-tpl +119 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/pyproject.toml-tpl +86 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/requirements.txt-tpl +23 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/format.sh-tpl +5 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/lint.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/run-server.sh-tpl +8 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/test.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/README-tpl +1 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/env.py-tpl +51 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/script.py.mako-tpl +26 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/versions/0001_initial_auth_schema.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/deps.py-tpl +91 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/health.py-tpl +11 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/router.py-tpl +17 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/core/config.py-tpl +64 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/core/security.py-tpl +100 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/db/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/db/session.py-tpl +36 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/models.py-tpl +25 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/repository.py-tpl +41 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/router.py-tpl +82 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/schemas.py-tpl +14 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/service.py-tpl +65 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/models.py-tpl +35 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/repository.py-tpl +33 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/router.py-tpl +71 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/schemas.py-tpl +29 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/service.py-tpl +55 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/main.py-tpl +69 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/template-config.yml-tpl +16 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/conftest.py-tpl +73 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/test_auth.py-tpl +201 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/test_health.py-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/test_users.py-tpl +77 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/pyproject.toml-tpl +21 -22
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/requirements.txt-tpl +39 -36
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/api/routes/items.py-tpl +3 -3
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/helper/pagination.py-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/main.py-tpl +9 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/schemas/base.py-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-default/pyproject.toml-tpl +18 -19
- fastapi_fastkit/fastapi_project_template/fastapi-default/requirements.txt-tpl +37 -34
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/api/routes/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/main.py-tpl +9 -1
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-default/tests/conftest.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-default/tests/test_items.py-tpl +0 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/Dockerfile-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/README.md-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/pyproject.toml-tpl +21 -22
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/requirements.txt-tpl +41 -36
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/api/routes/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/main.py-tpl +9 -1
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/tests/conftest.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/tests/test_items.py-tpl +0 -2
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/pyproject.toml-tpl +13 -14
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/requirements.txt-tpl +36 -10
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/api/router.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/core/config.py-tpl +4 -4
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/db/memory.py-tpl +4 -3
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/domains/items/repository.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/domains/items/router.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/domains/items/service.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/main.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/pyproject.toml-tpl +14 -15
- fastapi_fastkit/fastapi_project_template/fastapi-empty/requirements.txt-tpl +36 -10
- fastapi_fastkit/fastapi_project_template/fastapi-empty/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-empty/src/main.py-tpl +3 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/tests/test_main.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/.env-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/.gitignore-tpl +31 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/Dockerfile-tpl +18 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/README.md-tpl +193 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/pyproject.toml-tpl +76 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/requirements.txt-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/chat.sh-tpl +10 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/format.sh-tpl +5 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/lint.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/run-server.sh-tpl +8 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/test.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/chat.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/deps.py-tpl +23 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/health.py-tpl +11 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/router.py-tpl +13 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/core/config.py-tpl +67 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/agent.py-tpl +136 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/client.py-tpl +30 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/tools.py-tpl +131 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/main.py-tpl +53 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/memory/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/memory/base.py-tpl +27 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/memory/in_memory.py-tpl +32 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/schemas/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/schemas/chat.py-tpl +46 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/template-config.yml-tpl +16 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/conftest.py-tpl +158 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_chat.py-tpl +160 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_health.py-tpl +12 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_memory.py-tpl +38 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_tools.py-tpl +37 -0
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/README.md-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/pyproject.toml-tpl +25 -25
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/requirements.txt-tpl +68 -39
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/api/routes/auth.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/api/routes/items.py-tpl +3 -4
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/auth/dependencies.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/core/config.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/main.py-tpl +4 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/{mcp → mcp_server}/router.py-tpl +3 -5
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/schemas/items.py-tpl +6 -7
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/conftest.py-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/test_auth.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/test_items.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/test_mcp.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/Dockerfile-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/pyproject.toml-tpl +22 -23
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/requirements.txt-tpl +44 -41
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/env.py-tpl +1 -3
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/versions/bedcdc35b64a_first_alembic.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/api.py-tpl +2 -0
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/routes/items.py-tpl +2 -4
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/core/config.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/core/db.py-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/crud/items.py-tpl +4 -6
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/main.py-tpl +9 -0
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/schemas/items.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/tests/conftest.py-tpl +1 -5
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/tests/test_items.py-tpl +0 -2
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/.env-tpl +1 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/.gitignore-tpl +30 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/pyproject.toml-tpl +3 -4
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/requirements.txt-tpl +26 -6
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/src/main.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/.env-tpl +7 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/.gitignore-tpl +35 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/Dockerfile-tpl +18 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/README.md-tpl +166 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/alembic.ini-tpl +44 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/pyproject.toml-tpl +82 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/requirements.txt-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/format.sh-tpl +5 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/lint.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/migrate.sh-tpl +7 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/run-server.sh-tpl +8 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/test.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/README-tpl +9 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/env.py-tpl +72 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/script.py.mako-tpl +27 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/versions/0001_create_items_table.py-tpl +38 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/api/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/api/health.py-tpl +11 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/api/router.py-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/core/config.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/crud/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/crud/base.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/crud/pagination.py-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/db/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/db/base.py-tpl +12 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/db/session.py-tpl +50 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/crud.py-tpl +26 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/models.py-tpl +70 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/router.py-tpl +69 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/main.py-tpl +43 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/template-config.yml-tpl +16 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/conftest.py-tpl +60 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/test_crud_base.py-tpl +43 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/test_health.py-tpl +12 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/test_items.py-tpl +110 -0
- fastapi_fastkit/fastapi_project_template/modules/api/routes/new_route.py-tpl +2 -2
- fastapi_fastkit/fragments/README.md +90 -0
- fastapi_fastkit/fragments/auth/fastapi_users.py.j2 +8 -0
- fastapi_fastkit/fragments/auth/jwt.py.j2 +44 -0
- fastapi_fastkit/fragments/auth/oauth2.py.j2 +105 -0
- fastapi_fastkit/fragments/auth/session.py.j2 +67 -0
- fastapi_fastkit/fragments/db/mongodb.py.j2 +19 -0
- fastapi_fastkit/fragments/db/redis.py.j2 +26 -0
- fastapi_fastkit/fragments/db/sqlalchemy.py.j2 +45 -0
- fastapi_fastkit/fragments/docker/docker_compose.j2 +84 -0
- fastapi_fastkit/fragments/docker/dockerfile.j2 +19 -0
- fastapi_fastkit/fragments/features/cache.py.j2 +26 -0
- fastapi_fastkit/fragments/features/pagination.py.j2 +31 -0
- fastapi_fastkit/fragments/features/tasks_celery.py.j2 +50 -0
- fastapi_fastkit/fragments/features/tasks_dramatiq.py.j2 +59 -0
- fastapi_fastkit/fragments/features/websocket.py.j2 +66 -0
- fastapi_fastkit/fragments/header.j2 +4 -0
- fastapi_fastkit/fragments/logging/structured.py.j2 +88 -0
- fastapi_fastkit/fragments/main/imports/async_tasks.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/caching.j2 +5 -0
- fastapi_fastkit/fragments/main/imports/fastapi_users.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/jwt.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/loguru.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/mongodb.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/oauth2.j2 +4 -0
- fastapi_fastkit/fragments/main/imports/opentelemetry.j2 +6 -0
- fastapi_fastkit/fragments/main/imports/pagination.j2 +3 -0
- fastapi_fastkit/fragments/main/imports/prometheus.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/rate_limiting.j2 +3 -0
- fastapi_fastkit/fragments/main/imports/session_auth.j2 +4 -0
- fastapi_fastkit/fragments/main/imports/sqlalchemy.j2 +2 -0
- fastapi_fastkit/fragments/main/imports/structured_logging.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/websocket.j2 +1 -0
- fastapi_fastkit/fragments/main/lifespan/caching.j2 +7 -0
- fastapi_fastkit/fragments/main/lifespan/mongodb.j2 +2 -0
- fastapi_fastkit/fragments/main/lifespan/prometheus.j2 +2 -0
- fastapi_fastkit/fragments/main/lifespan/sqlalchemy.j2 +2 -0
- fastapi_fastkit/fragments/main/setup/async_tasks.j2 +1 -0
- fastapi_fastkit/fragments/main/setup/caching.j2 +1 -0
- fastapi_fastkit/fragments/main/setup/cors.j2 +8 -0
- fastapi_fastkit/fragments/main/setup/oauth2.j2 +3 -0
- fastapi_fastkit/fragments/main/setup/opentelemetry.j2 +19 -0
- fastapi_fastkit/fragments/main/setup/pagination.j2 +2 -0
- fastapi_fastkit/fragments/main/setup/rate_limiting.j2 +3 -0
- fastapi_fastkit/fragments/main/setup/session_auth.j2 +6 -0
- fastapi_fastkit/fragments/main/setup/structured_logging.j2 +2 -0
- fastapi_fastkit/fragments/main/setup/websocket.j2 +1 -0
- fastapi_fastkit/fragments/main.py.j2 +57 -0
- fastapi_fastkit/fragments/migrations/alembic_ini.j2 +42 -0
- fastapi_fastkit/fragments/migrations/env.py.j2 +76 -0
- fastapi_fastkit/fragments/migrations/initial_revision.py.j2 +27 -0
- fastapi_fastkit/fragments/migrations/migrate_sh.j2 +34 -0
- fastapi_fastkit/fragments/migrations/script.py.mako.j2 +26 -0
- fastapi_fastkit/fragments/tasks/celery_worker.py.j2 +49 -0
- fastapi_fastkit/fragments/tasks/dramatiq_worker.py.j2 +41 -0
- fastapi_fastkit/fragments/test/factories.py.j2 +68 -0
- fastapi_fastkit/fragments/test/pytest_ini.j2 +16 -0
- fastapi_fastkit/fragments/test/test_factories.py.j2 +27 -0
- fastapi_fastkit/fragments/test/test_main.py.j2 +46 -0
- fastapi_fastkit/fragments/tooling/devcontainer.j2 +26 -0
- fastapi_fastkit/fragments/tooling/github_actions.j2 +37 -0
- fastapi_fastkit/fragments/tooling/makefile.j2 +40 -0
- fastapi_fastkit/fragments/tooling/pre_commit.j2 +36 -0
- fastapi_fastkit/fragments/tooling/ruff_toml.j2 +16 -0
- fastapi_fastkit/utils/config_file.py +263 -0
- fastapi_fastkit/utils/main.py +38 -0
- {fastapi_fastkit-1.3.0.dist-info → fastapi_fastkit-1.4.0.dist-info}/METADATA +26 -2
- fastapi_fastkit-1.4.0.dist-info/RECORD +484 -0
- {fastapi_fastkit-1.3.0.dist-info → fastapi_fastkit-1.4.0.dist-info}/WHEEL +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/setup.py-tpl +0 -25
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/setup.py-tpl +0 -27
- fastapi_fastkit/fastapi_project_template/fastapi-default/setup.py-tpl +0 -22
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/setup.py-tpl +0 -22
- fastapi_fastkit/fastapi_project_template/fastapi-empty/setup.py-tpl +0 -22
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/setup.py-tpl +0 -51
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/setup.py-tpl +0 -25
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/setup.py-tpl +0 -17
- fastapi_fastkit-1.3.0.dist-info/RECORD +0 -287
- /fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/{mcp → mcp_server}/__init__.py-tpl +0 -0
- {fastapi_fastkit-1.3.0.dist-info → fastapi_fastkit-1.4.0.dist-info}/entry_points.txt +0 -0
- {fastapi_fastkit-1.3.0.dist-info → fastapi_fastkit-1.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,11 +3,32 @@
|
|
|
3
3
|
#
|
|
4
4
|
# @author bnbong bbbong9@gmail.com
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
import os
|
|
6
7
|
import subprocess
|
|
7
8
|
from abc import ABC, abstractmethod
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Any, Dict, List, Optional
|
|
10
11
|
|
|
12
|
+
from fastapi_fastkit.core.exceptions import BackendExceptions
|
|
13
|
+
from fastapi_fastkit.core.settings import settings
|
|
14
|
+
from fastapi_fastkit.utils.logging import debug_log
|
|
15
|
+
from fastapi_fastkit.utils.main import console, handle_exception, print_error
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _with_stderr_tail(message: str, stderr: str, max_lines: int = 5) -> str:
|
|
19
|
+
"""Append the last few non-empty stderr lines to an error message.
|
|
20
|
+
|
|
21
|
+
:param message: Base error message
|
|
22
|
+
:param stderr: Captured stderr of the failed command
|
|
23
|
+
:param max_lines: Maximum number of trailing stderr lines to include
|
|
24
|
+
:return: ``message`` unchanged when stderr carries nothing useful
|
|
25
|
+
"""
|
|
26
|
+
lines = [line.strip() for line in (stderr or "").splitlines()]
|
|
27
|
+
lines = [line for line in lines if line]
|
|
28
|
+
if not lines:
|
|
29
|
+
return message
|
|
30
|
+
return f"{message}: " + " | ".join(lines[-max_lines:])
|
|
31
|
+
|
|
11
32
|
|
|
12
33
|
class BasePackageManager(ABC):
|
|
13
34
|
"""
|
|
@@ -130,11 +151,162 @@ class BasePackageManager(ABC):
|
|
|
130
151
|
"capture_output": True,
|
|
131
152
|
"text": True,
|
|
132
153
|
"cwd": str(self.project_dir),
|
|
154
|
+
"timeout": settings.get_subprocess_timeout(),
|
|
133
155
|
}
|
|
134
156
|
default_kwargs.update(kwargs)
|
|
135
157
|
|
|
136
158
|
return subprocess.run(command, **default_kwargs)
|
|
137
159
|
|
|
160
|
+
def _check_command_available(self, command: List[str]) -> bool:
|
|
161
|
+
"""
|
|
162
|
+
Check whether a command can be executed on the current system.
|
|
163
|
+
|
|
164
|
+
:param command: Version probe command (e.g. ``["uv", "--version"]``)
|
|
165
|
+
:return: True if the command executed successfully
|
|
166
|
+
"""
|
|
167
|
+
try:
|
|
168
|
+
subprocess.run(
|
|
169
|
+
command,
|
|
170
|
+
check=True,
|
|
171
|
+
capture_output=True,
|
|
172
|
+
text=True,
|
|
173
|
+
timeout=settings.get_subprocess_timeout("check"),
|
|
174
|
+
)
|
|
175
|
+
return True
|
|
176
|
+
except (
|
|
177
|
+
subprocess.CalledProcessError,
|
|
178
|
+
subprocess.TimeoutExpired,
|
|
179
|
+
FileNotFoundError,
|
|
180
|
+
OSError,
|
|
181
|
+
):
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
def _run_checked(
|
|
185
|
+
self,
|
|
186
|
+
command: List[str],
|
|
187
|
+
status_msg: str,
|
|
188
|
+
error_prefix: str,
|
|
189
|
+
cwd: Optional[str] = None,
|
|
190
|
+
timeout: Optional[int] = None,
|
|
191
|
+
summarize_output: bool = False,
|
|
192
|
+
) -> subprocess.CompletedProcess[str]:
|
|
193
|
+
"""
|
|
194
|
+
Run a command with a status spinner and uniform error handling.
|
|
195
|
+
|
|
196
|
+
:param command: Command to run as list of strings
|
|
197
|
+
:param status_msg: Message shown while the command runs
|
|
198
|
+
:param error_prefix: Message used for the raised ``BackendExceptions``
|
|
199
|
+
:param cwd: Working directory (defaults to the project directory)
|
|
200
|
+
:param timeout: Timeout in seconds (defaults to the general timeout)
|
|
201
|
+
:param summarize_output: Print the tail of the command output on success
|
|
202
|
+
:return: CompletedProcess instance
|
|
203
|
+
:raises BackendExceptions: if the command fails, times out or cannot run
|
|
204
|
+
"""
|
|
205
|
+
timeout = timeout if timeout is not None else settings.get_subprocess_timeout()
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
with console.status(f"[bold green]{status_msg}"):
|
|
209
|
+
result: subprocess.CompletedProcess[str] = subprocess.run(
|
|
210
|
+
command,
|
|
211
|
+
cwd=cwd if cwd is not None else str(self.project_dir),
|
|
212
|
+
check=True,
|
|
213
|
+
capture_output=True,
|
|
214
|
+
text=True,
|
|
215
|
+
timeout=timeout,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if summarize_output:
|
|
219
|
+
self._print_output_summary(result)
|
|
220
|
+
|
|
221
|
+
return result
|
|
222
|
+
|
|
223
|
+
except subprocess.TimeoutExpired as e:
|
|
224
|
+
message = (
|
|
225
|
+
f"{error_prefix}: command timed out after {timeout}s "
|
|
226
|
+
f"({' '.join(command)}). "
|
|
227
|
+
f"Set {settings.SUBPROCESS_TIMEOUT_ENV_VAR} to raise the limit."
|
|
228
|
+
)
|
|
229
|
+
debug_log(message, "error")
|
|
230
|
+
handle_exception(e, message)
|
|
231
|
+
raise BackendExceptions(message)
|
|
232
|
+
except subprocess.CalledProcessError as e:
|
|
233
|
+
stderr = e.stderr if isinstance(e.stderr, str) else ""
|
|
234
|
+
debug_log(f"{error_prefix}: {stderr or e}", "error")
|
|
235
|
+
handle_exception(e, f"{error_prefix}: {str(e)}")
|
|
236
|
+
if stderr:
|
|
237
|
+
print_error(f"Error details: {stderr}")
|
|
238
|
+
# Carry the tail of stderr into the exception message: the raised
|
|
239
|
+
# BackendExceptions is what callers (and the CLI) surface, and a
|
|
240
|
+
# bare prefix leaves "why did it fail?" unanswerable from a log.
|
|
241
|
+
raise BackendExceptions(_with_stderr_tail(error_prefix, stderr))
|
|
242
|
+
except OSError as e:
|
|
243
|
+
debug_log(f"{error_prefix}: {e}", "error")
|
|
244
|
+
handle_exception(e, f"{error_prefix}: {str(e)}")
|
|
245
|
+
raise BackendExceptions(f"{error_prefix}: {str(e)}")
|
|
246
|
+
|
|
247
|
+
@staticmethod
|
|
248
|
+
def _print_output_summary(
|
|
249
|
+
result: subprocess.CompletedProcess[str], max_lines: int = 5
|
|
250
|
+
) -> None:
|
|
251
|
+
"""
|
|
252
|
+
Print the tail of a completed command's output.
|
|
253
|
+
|
|
254
|
+
Keeps the user informed about long running installs without dumping the
|
|
255
|
+
whole log. Silently does nothing when there is no textual output.
|
|
256
|
+
|
|
257
|
+
:param result: Completed process whose output should be summarized
|
|
258
|
+
:param max_lines: Maximum number of trailing lines to print
|
|
259
|
+
"""
|
|
260
|
+
chunks = [
|
|
261
|
+
chunk
|
|
262
|
+
for chunk in (
|
|
263
|
+
getattr(result, "stdout", None),
|
|
264
|
+
getattr(result, "stderr", None),
|
|
265
|
+
)
|
|
266
|
+
if isinstance(chunk, str)
|
|
267
|
+
]
|
|
268
|
+
lines = [line.strip() for chunk in chunks for line in chunk.splitlines()]
|
|
269
|
+
lines = [line for line in lines if line]
|
|
270
|
+
if not lines:
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
for line in lines[-max_lines:]:
|
|
274
|
+
console.print(f"[dim] {line}[/dim]")
|
|
275
|
+
|
|
276
|
+
def _ensure_venv(self, venv_path: str) -> str:
|
|
277
|
+
"""
|
|
278
|
+
Make sure a virtual environment exists, creating it when missing.
|
|
279
|
+
|
|
280
|
+
:param venv_path: Path to the virtual environment
|
|
281
|
+
:return: Path to an existing virtual environment
|
|
282
|
+
:raises BackendExceptions: if the virtual environment cannot be created
|
|
283
|
+
"""
|
|
284
|
+
if os.path.exists(venv_path):
|
|
285
|
+
return venv_path
|
|
286
|
+
|
|
287
|
+
debug_log("Virtual environment does not exist. Creating it first.", "warning")
|
|
288
|
+
print_error("Virtual environment does not exist. Creating it first.")
|
|
289
|
+
created = self.create_virtual_environment()
|
|
290
|
+
if not created:
|
|
291
|
+
raise BackendExceptions("Failed to create venv")
|
|
292
|
+
return created
|
|
293
|
+
|
|
294
|
+
def _require_dependency_file(self, error_message: Optional[str] = None) -> Path:
|
|
295
|
+
"""
|
|
296
|
+
Return the dependency file path, failing when it is missing.
|
|
297
|
+
|
|
298
|
+
:param error_message: Message used for the raised exception
|
|
299
|
+
:return: Path to the dependency file
|
|
300
|
+
:raises BackendExceptions: if the dependency file does not exist
|
|
301
|
+
"""
|
|
302
|
+
dependency_path = self.get_dependency_file_path()
|
|
303
|
+
if not dependency_path.exists():
|
|
304
|
+
file_name = self.get_dependency_file_name()
|
|
305
|
+
debug_log(f"{file_name} file not found at {dependency_path}", "error")
|
|
306
|
+
print_error(f"{file_name} file not found at {dependency_path}")
|
|
307
|
+
raise BackendExceptions(error_message or f"{file_name} file not found")
|
|
308
|
+
return dependency_path
|
|
309
|
+
|
|
138
310
|
def get_dependency_file_path(self) -> Path:
|
|
139
311
|
"""
|
|
140
312
|
Get the full path to the dependency file.
|
|
@@ -20,6 +20,10 @@ logger = get_logger(__name__)
|
|
|
20
20
|
class PackageManagerFactory:
|
|
21
21
|
"""Factory for creating package manager instances."""
|
|
22
22
|
|
|
23
|
+
# Auto-detection priority. ``uv`` wins whenever it is installed and ``pip``
|
|
24
|
+
# is only the last-resort fallback; explicit selection bypasses this order.
|
|
25
|
+
DETECTION_ORDER: List[str] = ["uv", "pdm", "poetry", "pip"]
|
|
26
|
+
|
|
23
27
|
# Registry of available package managers
|
|
24
28
|
_managers: Dict[str, Type[BasePackageManager]] = {
|
|
25
29
|
"pip": PipManager,
|
|
@@ -86,10 +90,7 @@ class PackageManagerFactory:
|
|
|
86
90
|
"""
|
|
87
91
|
exclude = exclude or []
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
detection_order = ["uv", "pdm", "poetry", "pip"]
|
|
91
|
-
|
|
92
|
-
for manager_type in detection_order:
|
|
93
|
+
for manager_type in self.DETECTION_ORDER:
|
|
93
94
|
if manager_type in exclude:
|
|
94
95
|
continue
|
|
95
96
|
|
|
@@ -3,19 +3,14 @@
|
|
|
3
3
|
#
|
|
4
4
|
# @author bnbong bbbong9@gmail.com
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
import os
|
|
7
6
|
import subprocess
|
|
8
7
|
import sys
|
|
9
8
|
from typing import List
|
|
10
9
|
|
|
11
10
|
from fastapi_fastkit.core.exceptions import BackendExceptions
|
|
11
|
+
from fastapi_fastkit.core.settings import settings
|
|
12
12
|
from fastapi_fastkit.utils.logging import debug_log, get_logger
|
|
13
|
-
from fastapi_fastkit.utils.main import
|
|
14
|
-
console,
|
|
15
|
-
handle_exception,
|
|
16
|
-
print_error,
|
|
17
|
-
print_success,
|
|
18
|
-
)
|
|
13
|
+
from fastapi_fastkit.utils.main import print_success
|
|
19
14
|
|
|
20
15
|
from .base import BasePackageManager
|
|
21
16
|
|
|
@@ -27,16 +22,7 @@ class PdmManager(BasePackageManager):
|
|
|
27
22
|
|
|
28
23
|
def is_available(self) -> bool:
|
|
29
24
|
"""Check if PDM is available on the system."""
|
|
30
|
-
|
|
31
|
-
subprocess.run(
|
|
32
|
-
["pdm", "--version"],
|
|
33
|
-
check=True,
|
|
34
|
-
capture_output=True,
|
|
35
|
-
text=True,
|
|
36
|
-
)
|
|
37
|
-
return True
|
|
38
|
-
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
39
|
-
return False
|
|
25
|
+
return self._check_command_available(["pdm", "--version"])
|
|
40
26
|
|
|
41
27
|
def get_dependency_file_name(self) -> str:
|
|
42
28
|
"""Get the dependency file name for PDM."""
|
|
@@ -51,29 +37,16 @@ class PdmManager(BasePackageManager):
|
|
|
51
37
|
"""
|
|
52
38
|
venv_path = str(self.project_dir / ".venv")
|
|
53
39
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
debug_log(f"Virtual environment created at {venv_path}", "info")
|
|
66
|
-
print_success("Virtual environment created successfully with PDM")
|
|
67
|
-
return venv_path
|
|
68
|
-
|
|
69
|
-
except subprocess.CalledProcessError as e:
|
|
70
|
-
debug_log(f"Error creating virtual environment: {e.stderr}", "error")
|
|
71
|
-
handle_exception(e, f"Error creating virtual environment: {str(e)}")
|
|
72
|
-
raise BackendExceptions("Failed to create venv with PDM")
|
|
73
|
-
except OSError as e:
|
|
74
|
-
debug_log(f"System error creating virtual environment: {e}", "error")
|
|
75
|
-
handle_exception(e, f"Error creating virtual environment: {str(e)}")
|
|
76
|
-
raise BackendExceptions(f"Failed to create venv with PDM: {str(e)}")
|
|
40
|
+
self._run_checked(
|
|
41
|
+
["pdm", "venv", "create", "--name", ".venv", sys.executable],
|
|
42
|
+
status_msg="Creating virtual environment with PDM...",
|
|
43
|
+
error_prefix="Failed to create venv with PDM",
|
|
44
|
+
timeout=settings.get_subprocess_timeout("venv"),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
debug_log(f"Virtual environment created at {venv_path}", "info")
|
|
48
|
+
print_success("Virtual environment created successfully with PDM")
|
|
49
|
+
return venv_path
|
|
77
50
|
|
|
78
51
|
def install_dependencies(self, venv_path: str) -> None:
|
|
79
52
|
"""
|
|
@@ -82,47 +55,19 @@ class PdmManager(BasePackageManager):
|
|
|
82
55
|
:param venv_path: Path to the virtual environment
|
|
83
56
|
:raises: BackendExceptions if dependency installation fails
|
|
84
57
|
"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
debug_log(
|
|
88
|
-
"Virtual environment does not exist. Creating it first.", "warning"
|
|
89
|
-
)
|
|
90
|
-
print_error("Virtual environment does not exist. Creating it first.")
|
|
91
|
-
venv_path = self.create_virtual_environment()
|
|
92
|
-
if not venv_path:
|
|
93
|
-
raise BackendExceptions("Failed to create venv")
|
|
58
|
+
venv_path = self._ensure_venv(venv_path)
|
|
59
|
+
self._require_dependency_file()
|
|
94
60
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
cwd=str(self.project_dir),
|
|
106
|
-
check=True,
|
|
107
|
-
capture_output=True,
|
|
108
|
-
text=True,
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
debug_log("Dependencies installed successfully with PDM", "info")
|
|
112
|
-
print_success("Dependencies installed successfully with PDM")
|
|
113
|
-
|
|
114
|
-
except subprocess.CalledProcessError as e:
|
|
115
|
-
debug_log(f"Error during dependency installation: {e.stderr}", "error")
|
|
116
|
-
handle_exception(e, f"Error during dependency installation: {str(e)}")
|
|
117
|
-
if hasattr(e, "stderr"):
|
|
118
|
-
print_error(f"Error details: {e.stderr}")
|
|
119
|
-
raise BackendExceptions("Failed to install dependencies with PDM")
|
|
120
|
-
except OSError as e:
|
|
121
|
-
debug_log(f"System error during dependency installation: {e}", "error")
|
|
122
|
-
handle_exception(e, f"Error during dependency installation: {str(e)}")
|
|
123
|
-
raise BackendExceptions(
|
|
124
|
-
f"Failed to install dependencies with PDM: {str(e)}"
|
|
125
|
-
)
|
|
61
|
+
self._run_checked(
|
|
62
|
+
["pdm", "install"],
|
|
63
|
+
status_msg="Installing dependencies with PDM...",
|
|
64
|
+
error_prefix="Failed to install dependencies with PDM",
|
|
65
|
+
timeout=settings.get_subprocess_timeout("install"),
|
|
66
|
+
summarize_output=True,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
debug_log("Dependencies installed successfully with PDM", "info")
|
|
70
|
+
print_success("Dependencies installed successfully with PDM")
|
|
126
71
|
|
|
127
72
|
def generate_dependency_file(
|
|
128
73
|
self,
|
|
@@ -205,6 +150,7 @@ packages = ["src"]
|
|
|
205
150
|
check=True,
|
|
206
151
|
capture_output=True,
|
|
207
152
|
text=True,
|
|
153
|
+
timeout=settings.get_subprocess_timeout("install"),
|
|
208
154
|
)
|
|
209
155
|
|
|
210
156
|
debug_log(
|
|
@@ -212,7 +158,7 @@ packages = ["src"]
|
|
|
212
158
|
"info",
|
|
213
159
|
)
|
|
214
160
|
|
|
215
|
-
except subprocess.CalledProcessError as e:
|
|
161
|
+
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
|
|
216
162
|
debug_log(f"Error adding dependency with PDM: {e}", "error")
|
|
217
163
|
raise BackendExceptions(f"Failed to add dependency with PDM: {str(e)}")
|
|
218
164
|
except OSError as e:
|
|
@@ -238,6 +184,7 @@ packages = ["src"]
|
|
|
238
184
|
check=True,
|
|
239
185
|
capture_output=True,
|
|
240
186
|
text=True,
|
|
187
|
+
timeout=settings.get_subprocess_timeout(),
|
|
241
188
|
)
|
|
242
189
|
|
|
243
190
|
# Create or update pyproject.toml with provided metadata
|
|
@@ -271,7 +218,7 @@ packages = ["src"]
|
|
|
271
218
|
|
|
272
219
|
debug_log(f"Initialized PDM project: {project_name}", "info")
|
|
273
220
|
|
|
274
|
-
except subprocess.CalledProcessError as e:
|
|
221
|
+
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
|
|
275
222
|
debug_log(f"Error initializing PDM project: {e}", "error")
|
|
276
223
|
raise BackendExceptions(f"Failed to initialize PDM project: {str(e)}")
|
|
277
224
|
except (OSError, UnicodeEncodeError) as e:
|
|
@@ -3,19 +3,13 @@
|
|
|
3
3
|
#
|
|
4
4
|
# @author bnbong bbbong9@gmail.com
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
import os
|
|
7
|
-
import subprocess
|
|
8
6
|
import sys
|
|
9
7
|
from typing import List
|
|
10
8
|
|
|
11
9
|
from fastapi_fastkit.core.exceptions import BackendExceptions
|
|
10
|
+
from fastapi_fastkit.core.settings import settings
|
|
12
11
|
from fastapi_fastkit.utils.logging import debug_log, get_logger
|
|
13
|
-
from fastapi_fastkit.utils.main import
|
|
14
|
-
console,
|
|
15
|
-
handle_exception,
|
|
16
|
-
print_error,
|
|
17
|
-
print_success,
|
|
18
|
-
)
|
|
12
|
+
from fastapi_fastkit.utils.main import print_success
|
|
19
13
|
|
|
20
14
|
from .base import BasePackageManager
|
|
21
15
|
|
|
@@ -27,16 +21,7 @@ class PipManager(BasePackageManager):
|
|
|
27
21
|
|
|
28
22
|
def is_available(self) -> bool:
|
|
29
23
|
"""Check if pip is available on the system."""
|
|
30
|
-
|
|
31
|
-
subprocess.run(
|
|
32
|
-
[sys.executable, "-m", "pip", "--version"],
|
|
33
|
-
check=True,
|
|
34
|
-
capture_output=True,
|
|
35
|
-
text=True,
|
|
36
|
-
)
|
|
37
|
-
return True
|
|
38
|
-
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
39
|
-
return False
|
|
24
|
+
return self._check_command_available([sys.executable, "-m", "pip", "--version"])
|
|
40
25
|
|
|
41
26
|
def get_dependency_file_name(self) -> str:
|
|
42
27
|
"""Get the dependency file name for pip."""
|
|
@@ -51,87 +36,48 @@ class PipManager(BasePackageManager):
|
|
|
51
36
|
"""
|
|
52
37
|
venv_path = str(self.project_dir / ".venv")
|
|
53
38
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
text=True,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
debug_log(f"Virtual environment created at {venv_path}", "info")
|
|
64
|
-
print_success("Virtual environment created successfully")
|
|
65
|
-
return venv_path
|
|
39
|
+
self._run_checked(
|
|
40
|
+
[sys.executable, "-m", "venv", venv_path],
|
|
41
|
+
status_msg="Creating virtual environment...",
|
|
42
|
+
error_prefix="Failed to create venv",
|
|
43
|
+
timeout=settings.get_subprocess_timeout("venv"),
|
|
44
|
+
)
|
|
66
45
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
raise BackendExceptions("Failed to create venv")
|
|
71
|
-
except OSError as e:
|
|
72
|
-
debug_log(f"System error creating virtual environment: {e}", "error")
|
|
73
|
-
handle_exception(e, f"Error creating virtual environment: {str(e)}")
|
|
74
|
-
raise BackendExceptions(f"Failed to create venv: {str(e)}")
|
|
46
|
+
debug_log(f"Virtual environment created at {venv_path}", "info")
|
|
47
|
+
print_success("Virtual environment created successfully")
|
|
48
|
+
return venv_path
|
|
75
49
|
|
|
76
|
-
def install_dependencies(self, venv_path: str) -> None:
|
|
50
|
+
def install_dependencies(self, venv_path: str, upgrade_pip: bool = False) -> None:
|
|
77
51
|
"""
|
|
78
52
|
Install dependencies using pip in the virtual environment.
|
|
79
53
|
|
|
80
54
|
:param venv_path: Path to the virtual environment
|
|
55
|
+
:param upgrade_pip: Upgrade pip inside the venv before installing
|
|
81
56
|
:raises: BackendExceptions if dependency installation fails
|
|
82
57
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
debug_log(
|
|
86
|
-
"Virtual environment does not exist. Creating it first.", "warning"
|
|
87
|
-
)
|
|
88
|
-
print_error("Virtual environment does not exist. Creating it first.")
|
|
89
|
-
venv_path = self.create_virtual_environment()
|
|
90
|
-
if not venv_path:
|
|
91
|
-
raise BackendExceptions("Failed to create venv")
|
|
92
|
-
|
|
93
|
-
requirements_path = self.get_dependency_file_path()
|
|
94
|
-
if not requirements_path.exists():
|
|
95
|
-
debug_log(
|
|
96
|
-
f"Requirements file not found at {requirements_path}", "error"
|
|
97
|
-
)
|
|
98
|
-
print_error(f"Requirements file not found at {requirements_path}")
|
|
99
|
-
raise BackendExceptions("Requirements file not found")
|
|
58
|
+
venv_path = self._ensure_venv(venv_path)
|
|
59
|
+
requirements_path = self._require_dependency_file("Requirements file not found")
|
|
100
60
|
|
|
101
|
-
|
|
102
|
-
pip_path = self.get_executable_path("pip", venv_path)
|
|
61
|
+
pip_path = self.get_executable_path("pip", venv_path)
|
|
103
62
|
|
|
104
|
-
|
|
105
|
-
|
|
63
|
+
if upgrade_pip:
|
|
64
|
+
self._run_checked(
|
|
106
65
|
[pip_path, "install", "--upgrade", "pip"],
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
66
|
+
status_msg="Upgrading pip...",
|
|
67
|
+
error_prefix="Failed to upgrade pip",
|
|
68
|
+
timeout=settings.get_subprocess_timeout("install"),
|
|
110
69
|
)
|
|
111
70
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
text=True,
|
|
120
|
-
)
|
|
71
|
+
self._run_checked(
|
|
72
|
+
[pip_path, "install", "-r", str(requirements_path.name)],
|
|
73
|
+
status_msg="Installing dependencies...",
|
|
74
|
+
error_prefix="Failed to install dependencies",
|
|
75
|
+
timeout=settings.get_subprocess_timeout("install"),
|
|
76
|
+
summarize_output=True,
|
|
77
|
+
)
|
|
121
78
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
except subprocess.CalledProcessError as e:
|
|
126
|
-
debug_log(f"Error during dependency installation: {e.stderr}", "error")
|
|
127
|
-
handle_exception(e, f"Error during dependency installation: {str(e)}")
|
|
128
|
-
if hasattr(e, "stderr"):
|
|
129
|
-
print_error(f"Error details: {e.stderr}")
|
|
130
|
-
raise BackendExceptions("Failed to install dependencies")
|
|
131
|
-
except OSError as e:
|
|
132
|
-
debug_log(f"System error during dependency installation: {e}", "error")
|
|
133
|
-
handle_exception(e, f"Error during dependency installation: {str(e)}")
|
|
134
|
-
raise BackendExceptions(f"Failed to install dependencies: {str(e)}")
|
|
79
|
+
debug_log("Dependencies installed successfully", "info")
|
|
80
|
+
print_success("Dependencies installed successfully")
|
|
135
81
|
|
|
136
82
|
def generate_dependency_file(
|
|
137
83
|
self,
|