2024-11-09 08:01:27 -08:00
|
|
|
|
# About this template
|
|
|
|
|
|
|
|
|
|
Hi, I created this template to help you get started with a new project.
|
|
|
|
|
|
|
|
|
|
I have created and maintained a number of python libraries, applications and
|
|
|
|
|
frameworks and during those years I have learned a lot about how to create a
|
|
|
|
|
project structure and how to structure a project to be as modular and simple
|
|
|
|
|
as possible.
|
|
|
|
|
|
|
|
|
|
Some decisions I have made while creating this template are:
|
|
|
|
|
|
|
|
|
|
- Create a project structure that is as modular as possible.
|
|
|
|
|
- Keep it simple and easy to maintain.
|
|
|
|
|
- Allow for a lot of flexibility and customizability.
|
|
|
|
|
- Low dependency (this template doesn't add dependencies)
|
|
|
|
|
|
|
|
|
|
## Structure
|
|
|
|
|
|
|
|
|
|
Lets take a look at the structure of this template:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
├── Containerfile # The file to build a container using buildah or docker
|
|
|
|
|
├── CONTRIBUTING.md # Onboarding instructions for new contributors
|
|
|
|
|
├── docs # Documentation site (add more .md files here)
|
|
|
|
|
│ └── index.md # The index page for the docs site
|
|
|
|
|
├── .gitea # Gitea metadata for repository
|
|
|
|
|
│ ├── release_message.sh # A script to generate a release message
|
|
|
|
|
│ └── workflows # The CI pipeline for Gitea Actions
|
|
|
|
|
├── .gitignore # A list of files to ignore when pushing to Gitea
|
|
|
|
|
├── HISTORY.md # Auto generated list of changes to the project
|
|
|
|
|
├── LICENSE # The license for the project
|
|
|
|
|
├── Makefile # A collection of utilities to manage the project
|
|
|
|
|
├── MANIFEST.in # A list of files to include in a package
|
|
|
|
|
├── mkdocs.yml # Configuration for documentation site
|
2024-11-09 09:05:53 -08:00
|
|
|
|
├── project_name # The main python package for the project
|
2024-11-09 08:01:27 -08:00
|
|
|
|
│ ├── base.py # The base module for the project
|
|
|
|
|
│ ├── __init__.py # This tells Python that this is a package
|
|
|
|
|
│ ├── __main__.py # The entry point for the project
|
|
|
|
|
│ └── VERSION # The version for the project is kept in a static file
|
|
|
|
|
├── README.md # The main readme for the project
|
|
|
|
|
├── setup.py # The setup.py file for installing and packaging the project
|
|
|
|
|
├── requirements.txt # An empty file to hold the requirements for the project
|
|
|
|
|
├── requirements-test.txt # List of requirements for testing and devlopment
|
|
|
|
|
├── setup.py # The setup.py file for installing and packaging the project
|
|
|
|
|
└── tests # Unit tests for the project (add mote tests files here)
|
|
|
|
|
├── conftest.py # Configuration, hooks and fixtures for pytest
|
|
|
|
|
├── __init__.py # This tells Python that this is a test package
|
|
|
|
|
└── test_base.py # The base test case for the project
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## FAQ
|
|
|
|
|
|
|
|
|
|
Frequent asked questions.
|
|
|
|
|
|
|
|
|
|
### Why this template is not using [Poetry](https://python-poetry.org/) ?
|
|
|
|
|
|
|
|
|
|
I really like Poetry and I think it is a great tool to manage your python projects,
|
|
|
|
|
if you want to switch to poetry, you can run `make switch-to-poetry`.
|
|
|
|
|
|
|
|
|
|
But for this template I wanted to keep it simple.
|
|
|
|
|
|
|
|
|
|
Setuptools is the most simple and well supported way of packaging a Python project,
|
|
|
|
|
it doesn't require extra dependencies and is the easiest way to install the project.
|
|
|
|
|
|
|
|
|
|
Also, poetry doesn't have a good support for installing projects in development mode yet.
|
|
|
|
|
|
|
|
|
|
### Why the `requirements.txt` is empty ?
|
|
|
|
|
|
|
|
|
|
This template is a low dependency project, so it doesn't have any extra dependencies.
|
|
|
|
|
You can add new dependencies as you will or you can use the `make init` command to
|
|
|
|
|
generate a `requirements.txt` file based on the template you choose `flask, fastapi, click etc`.
|
|
|
|
|
|
|
|
|
|
### Why there is a `requirements-test.txt` file ?
|
|
|
|
|
|
|
|
|
|
This file lists all the requirements for testing and development,
|
|
|
|
|
I think the development environment and testing environment should be as similar as possible.
|
|
|
|
|
|
|
|
|
|
Except those tools that are up to the developer choice (like ipython, ipdb etc).
|
|
|
|
|
|
|
|
|
|
### Why the template doesn't have a `pyproject.toml` file ?
|
|
|
|
|
|
|
|
|
|
It is possible to run `pip install https://git.disi.dev/name/repo/tarball/main` and
|
|
|
|
|
have pip to download the package direcly from Git repo.
|
|
|
|
|
|
|
|
|
|
For that to work you need to have a `setup.py` file, and `pyproject.toml` is not
|
|
|
|
|
supported for that kind of installation.
|
|
|
|
|
|
|
|
|
|
I think it is easier for example you want to install specific branch or tag you can
|
|
|
|
|
do `pip install https://git.disi.dev/name/repo/tarball/{TAG|REVISON|COMMIT}`
|
|
|
|
|
|
|
|
|
|
People automating CI for your project will be grateful for having a setup.py file
|
|
|
|
|
|
|
|
|
|
### Why isn't this template made as a cookiecutter template?
|
|
|
|
|
|
|
|
|
|
I really like [cookiecutter](https://github.com/cookiecutter/cookiecutter) and it is a great way to create new projects,
|
|
|
|
|
to use this template doesn't require to install extra tooling such as cookiecutter.
|
|
|
|
|
|
|
|
|
|
The substituions are done using gitea actions and a simple sed script.
|
|
|
|
|
|
|
|
|
|
### Why `VERSION` is kept in a static plain text file?
|
|
|
|
|
|
|
|
|
|
I used to have my version inside my main module in a `__version__` variable, then
|
|
|
|
|
I had to do some tricks to read that version variable inside the setuptools
|
|
|
|
|
`setup.py` file because that would be available only after the installation.
|
|
|
|
|
|
|
|
|
|
I decided to keep the version in a static file because it is easier to read from
|
|
|
|
|
wherever I want without the need to install the package.
|
|
|
|
|
|
2024-11-09 09:05:53 -08:00
|
|
|
|
e.g: `cat project_name/VERSION` will get the project version without harming
|
2024-11-09 08:01:27 -08:00
|
|
|
|
with module imports or anything else, it is useful for CI, logs and debugging.
|
|
|
|
|
|
|
|
|
|
### Why to include `tests`, `history` and `Containerfile` as part of the release?
|
|
|
|
|
|
|
|
|
|
The `MANIFEST.in` file is used to include the files in the release, once the
|
2024-11-10 07:37:23 -08:00
|
|
|
|
project is released to artifactory all the files listed on MANIFEST.in will be included
|
2024-11-09 08:01:27 -08:00
|
|
|
|
even if the files are static or not related to Python.
|
|
|
|
|
|
|
|
|
|
Some build systems such as RPM, DEB, AUR for some Linux distributions, and also
|
|
|
|
|
internal repackaging systems tends to run the tests before the packaging is performed.
|
|
|
|
|
|
|
|
|
|
The Containerfile can be useful to provide a safer execution environment for
|
|
|
|
|
the project when running on a testing environment.
|
|
|
|
|
|
|
|
|
|
I added those files to make it easier for packaging in different formats.
|
|
|
|
|
|
|
|
|
|
### Why conftest includes a go_to_tmpdir fixture?
|
|
|
|
|
|
|
|
|
|
When your project deals with file system operations, it is a good idea to use
|
|
|
|
|
a fixture to create a temporary directory and then remove it after the test.
|
|
|
|
|
|
|
|
|
|
Before executing each test pytest will create a temporary directory and will
|
|
|
|
|
change the working directory to that path and run the test.
|
|
|
|
|
|
|
|
|
|
So the test can create temporary artifacts isolated from other tests.
|
|
|
|
|
|
|
|
|
|
After the execution Pytest will remove the temporary directory.
|
|
|
|
|
|
|
|
|
|
### Why this template is not using [pre-commit](https://pre-commit.com/) ?
|
|
|
|
|
|
|
|
|
|
pre-commit is an excellent tool to automate checks and formatting on your code.
|
|
|
|
|
|
|
|
|
|
However I figured out that pre-commit adds extra dependency and it an entry barrier
|
|
|
|
|
for new contributors.
|
|
|
|
|
|
|
|
|
|
Having the linting, checks and formatting as simple commands on the [Makefile](Makefile)
|
|
|
|
|
makes it easier to undestand and change.
|
|
|
|
|
|
|
|
|
|
Once the project is bigger and complex, having pre-commit as a dependency can be a good idea.
|
|
|
|
|
|
|
|
|
|
### Why the CLI is not using click?
|
|
|
|
|
|
|
|
|
|
I wanted to provide a simple template for a CLI application on the project main entry point
|
|
|
|
|
click and typer are great alternatives but are external dependencies and this template
|
|
|
|
|
doesn't add dependencies besides those used for development.
|
|
|
|
|
|
|
|
|
|
### Why this doesn't provide a full example of application using Flask or Django?
|
|
|
|
|
|
|
|
|
|
as I said before, I want it to be simple and multipurpose, so I decided to not include
|
|
|
|
|
external dependencies and programming design decisions.
|
|
|
|
|
|
|
|
|
|
It is up to you to decide if you want to use Flask or Django and to create your application
|
|
|
|
|
the way you think is best.
|
|
|
|
|
|
|
|
|
|
This template provides utilities in the Makefile to make it easier to you can run:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
$ make init
|
|
|
|
|
Which template do you want to apply? [flask, fastapi, click, typer]? > flask
|
|
|
|
|
Generating a new project with Flask ...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then the above will download the Flask template and apply it to the project.
|
|
|
|
|
|
|
|
|
|
## The Makefile
|
|
|
|
|
|
|
|
|
|
All the utilities for the template and project are on the Makefile
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
❯ make
|
|
|
|
|
Usage: make <target>
|
|
|
|
|
|
|
|
|
|
Targets:
|
|
|
|
|
help: ## Show the help.
|
|
|
|
|
install: ## Install the project in dev mode.
|
|
|
|
|
fmt: ## Format code using black & isort.
|
|
|
|
|
lint: ## Run pep8, black, mypy linters.
|
|
|
|
|
test: lint ## Run tests and generate coverage report.
|
|
|
|
|
watch: ## Run tests on every change.
|
|
|
|
|
clean: ## Clean unused files.
|
|
|
|
|
virtualenv: ## Create a virtual environment.
|
|
|
|
|
release: ## Create a new tag for release.
|
|
|
|
|
docs: ## Build the documentation.
|
|
|
|
|
switch-to-poetry: ## Switch to poetry package manager.
|
|
|
|
|
init: ## Initialize the project based on an application template.
|
|
|
|
|
```
|