Initial commit
This commit is contained in:
commit
fb25d95f0c
17 changed files with 244 additions and 0 deletions
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Yehuda Deutsch
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
3
README.md
Normal file
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Ajal Template - FastAPI
|
||||||
|
|
||||||
|
An opinionated FastAPI template, managed using [copier](https://copier.readthedocs.io/)
|
||||||
68
copier.yml
Normal file
68
copier.yml
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
_subdirectory: template
|
||||||
|
|
||||||
|
_tasks:
|
||||||
|
- command: "git init"
|
||||||
|
- command: "git add ."
|
||||||
|
- command: "git commit -m 'Initial commit'"
|
||||||
|
- command: "uv venv .venv"
|
||||||
|
when: "{{ dependency_manager == 'uv' }}"
|
||||||
|
- command: "poetry env activate"
|
||||||
|
when: "{{ dependency_manager == 'poetry' }}"
|
||||||
|
|
||||||
|
# Questions
|
||||||
|
project_name:
|
||||||
|
type: str
|
||||||
|
help: What is your project name?
|
||||||
|
|
||||||
|
project_description:
|
||||||
|
type: str
|
||||||
|
help: Describe your project
|
||||||
|
default: A project based on ajal-template-fastapi
|
||||||
|
|
||||||
|
minimum_python_version:
|
||||||
|
type: str
|
||||||
|
help: Minimum python version
|
||||||
|
choices:
|
||||||
|
- "3.10"
|
||||||
|
- "3.11"
|
||||||
|
- "3.12"
|
||||||
|
- "3.13"
|
||||||
|
|
||||||
|
license:
|
||||||
|
type: str
|
||||||
|
help: A license for the project
|
||||||
|
default: MIT
|
||||||
|
choices:
|
||||||
|
- "None"
|
||||||
|
- "MIT"
|
||||||
|
|
||||||
|
dependency_manager:
|
||||||
|
type: str
|
||||||
|
help: Python dependency manager
|
||||||
|
choices:
|
||||||
|
- uv
|
||||||
|
- poetry
|
||||||
|
- hatch
|
||||||
|
- setuptools
|
||||||
|
- flit
|
||||||
|
- pdm
|
||||||
|
default: uv
|
||||||
|
|
||||||
|
user_name:
|
||||||
|
type: str
|
||||||
|
help: Author name
|
||||||
|
default: ""
|
||||||
|
|
||||||
|
user_email:
|
||||||
|
type: str
|
||||||
|
help: Author email
|
||||||
|
default: ""
|
||||||
|
|
||||||
|
container_template:
|
||||||
|
type: str
|
||||||
|
help: Choose a container template. Cached - using cache with this template can speed up subsequent builds, Uncached - will always install latest dependencies, using cache with this template will lead to outdated images
|
||||||
|
default: cached
|
||||||
|
choices:
|
||||||
|
- none
|
||||||
|
- cached
|
||||||
|
- uncached
|
||||||
1
project-name.jinja
Normal file
1
project-name.jinja
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{{ project_name | lower | replace(' ', '_') | replace('-', '_') }}
|
||||||
10
template/.gitignore
vendored
Normal file
10
template/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Python-generated files
|
||||||
|
__pycache__/
|
||||||
|
*.py[oc]
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
wheels/
|
||||||
|
*.egg-info
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv
|
||||||
1
template/.python-version.jinja
Normal file
1
template/.python-version.jinja
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{{minimum_python_version}}
|
||||||
3
template/README.md.jinja
Normal file
3
template/README.md.jinja
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# {{project_name}}
|
||||||
|
|
||||||
|
{{project_description}}
|
||||||
0
template/__init__.py
Normal file
0
template/__init__.py
Normal file
36
template/pyproject.toml.jinja
Normal file
36
template/pyproject.toml.jinja
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
[project]
|
||||||
|
name = "{{ project_name | lower | replace(' ', '-') | replace('_', '-') }}"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "{{project_description}}"
|
||||||
|
authors = [
|
||||||
|
{name = "{{user_name}}", email = "{{user_email}}"}
|
||||||
|
]
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">={{minimum_python_version}}"
|
||||||
|
dependencies = [
|
||||||
|
"aiofiles>=24.1.0",
|
||||||
|
"fastapi-jinja>=0.2.0",
|
||||||
|
"fastapi[standard]>=0.115.12",
|
||||||
|
"orjson>=3.10.16",
|
||||||
|
"pydantic-settings>=2.9.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
{%- if dependency_manager == "poetry" %}
|
||||||
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
{%- elif dependency_manager == "setuptools" %}
|
||||||
|
{%- elif dependency_manager == "hatch" %}
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
{%- elif dependency_manager == "flit" %}
|
||||||
|
requires = ["flit_core >= 3.4"]
|
||||||
|
build-backend = "flit_core.buildapi"
|
||||||
|
{%- elif dependency_manager == "pdm" %}
|
||||||
|
requires = ["pdm-backend"]
|
||||||
|
build-backend = "pdm.backend"
|
||||||
|
{%- else %}
|
||||||
|
{#- This is the default #}
|
||||||
|
requires = ["setuptools >= 61.0"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
{%- endif %}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
FROM docker.io/library/alpine:latest
|
||||||
|
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||||
|
|
||||||
|
ENV UV_LINK_MODE=copy \
|
||||||
|
UV_COMPILE_BYTECODE=1 \
|
||||||
|
PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
|
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||||
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||||
|
--mount=type=bind,source={{project_name}},target={{project_name}} \
|
||||||
|
uv sync --locked --no-editable
|
||||||
|
|
||||||
|
CMD ["fastapi", "run"]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
FROM docker.io/library/alpine:latest
|
||||||
|
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||||
|
|
||||||
|
ENV UV_LINK_MODE=copy \
|
||||||
|
UV_COMPILE_BYTECODE=1 \
|
||||||
|
PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY pyproject.toml uv.lock /app/
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
|
uv sync --locked --no-install-project --no-editable
|
||||||
|
|
||||||
|
COPY {{project_name}}/ /app/{{project_name}}/
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
|
uv sync --locked --no-editable
|
||||||
|
|
||||||
|
CMD ["fastapi", "run"]
|
||||||
21
template/{% if license == 'MIT' %}LICENSE{% endif %}.jinja
Normal file
21
template/{% if license == 'MIT' %}LICENSE{% endif %}.jinja
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 {{user_name}}
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
0
template/{% include 'project-name.jinja' %}/__init__.py
Normal file
0
template/{% include 'project-name.jinja' %}/__init__.py
Normal file
9
template/{% include 'project-name.jinja' %}/app.py
Normal file
9
template/{% include 'project-name.jinja' %}/app.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
from .settings import MainSettings
|
||||||
|
|
||||||
|
settings = MainSettings()
|
||||||
|
app = FastAPI(
|
||||||
|
title=settings.app_name,
|
||||||
|
debug=settings.debug,
|
||||||
|
)
|
||||||
22
template/{% include 'project-name.jinja' %}/settings.py
Normal file
22
template/{% include 'project-name.jinja' %}/settings.py
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
|
APP_PATH = Path(__file__).parent.absolute()
|
||||||
|
|
||||||
|
|
||||||
|
class MainSettings(BaseSettings):
|
||||||
|
debug: bool = False
|
||||||
|
verbosity: int = 1
|
||||||
|
|
||||||
|
app_name = "Ajal Template - FastAPI"
|
||||||
|
|
||||||
|
base_path: Path = APP_PATH.parent.absolute()
|
||||||
|
app_path: Path = APP_PATH
|
||||||
|
|
||||||
|
templates_dir: str = 'templates'
|
||||||
|
static_dir: str = 'static'
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
env_prefix = 'fastapi_'
|
||||||
|
env_file = '.env'
|
||||||
13
template/{% include 'project-name.jinja' %}/web.py
Normal file
13
template/{% include 'project-name.jinja' %}/web.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import fastapi_jinja
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
|
from .app import app, settings
|
||||||
|
from .views import index
|
||||||
|
|
||||||
|
fastapi_jinja.global_init(
|
||||||
|
template_folder=str(settings.app_path / settings.templates_dir),
|
||||||
|
auto_reload=settings.debug,
|
||||||
|
)
|
||||||
|
app.mount("/static", StaticFiles(directory=settings.app_path / settings.static_dir), name="static")
|
||||||
|
|
||||||
|
app.mount('/', index.router, name='index')
|
||||||
2
template/{{ _copier_conf.answers_file }}.jinja
Normal file
2
template/{{ _copier_conf.answers_file }}.jinja
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
|
||||||
|
{{ _copier_answers|to_nice_yaml -}}
|
||||||
Loading…
Add table
Reference in a new issue