Skip to content

Commit

Permalink
add python standards: repo, tests, style
Browse files Browse the repository at this point in the history
  • Loading branch information
MathieuLamiot committed Sep 3, 2024
1 parent 9a7911f commit 4ca0341
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 1 deletion.
3 changes: 2 additions & 1 deletion technical_standards/index.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- [PHP](php/index.md)
- [PHP](php/index.md)
- [Python](python/index.md)
7 changes: 7 additions & 0 deletions technical_standards/python/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Python standards
- [Repository](repository.md)
- [Code style](style.md)
- [Tests](test.md)

## Django standards
- []
51 changes: 51 additions & 0 deletions technical_standards/python/repository.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
notion_page: https://www.notion.so/wpmedia/Python-Repository-preparation-3e292f3b1ffc4ee3adfdf1aceefa3fe2?pvs=4
title: Python - Repository preparation
---

# Python - Repository preparation

## Requirements

Dependencies for a codebase usually differ based on the environment the code is running: linters and test tools are required for development and CI, but not for production for instance. Therefore, we recommend using separate requirement files to ease dependency management and keep the footprint of the app small.

In the app repository, we use a `requirements/` directory, containing the following files:
- `base.txt`: this file lists the dependencies needed in all contexts;
- `ci.txt`: this file lists the dependencies needed in a CI context, on top of `base.txt`. It usually begins with `-r base.txt`.
- `dev.txt`: this file lists the dependencies needed in a development environment. It usually begins with `-r ci.txt`.
- `prod.txt`: this file lists the dependencies only needed in production and deployed environments. It usually begins with `-r base.txt`.

Note that those files are related to each others as some requirements include other ones. To achieve this, we use the following syntax as first line of a file, so that it includes all dependencies from the referenced file:

```
`-r base.txt`
```

To automatically generate those files, you can use:

```
mkdir requirements
touch requirements/{base.txt,ci.txt,dev.txt,prod.txt}
```

## Configuration file

As we use various tools to enhance the developer experience, it is easier to gather all configuration within a single `.toml` file.
In the project’s root directory, create a `pyproject.toml` file. This will include all the configuration for third party packages.

```bash
touch pyproject.toml
```

## Setting up a local virtual environment

As developers often switch from one repository to another, and that the environment usually differ (different dependencies, versions, etc.), it is safer to use a virtual environment per project. This will allow you to install dependencies for this repository only, and maybe use different ones on another repository without interferences.
To create and run a virtual environment, you can use the following commands in the repository:
```bash
# create the virtual env
python3 -m venv .venv
# activate the virtualenv
. .venv/bin/activate
```

## Setting up a Docker container
131 changes: 131 additions & 0 deletions technical_standards/python/style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
notion_page: https://www.notion.so/wpmedia/Python-Code-Style-81237a443b514d8dafb033efe7cdb4f1?pvs=4
title: Python - Code Style
---

# Python - Code Style

This document summarizes our standard code styling tools for Python codebases.

Our code style guidelines include linting and formatting. All the following should automatically be checked as part of the CI of all repositories.

## Linting

### pylint

For linting, we use `pylint`.

#### Install and configure

To use it, the package must be added to `requirements/ci.txt`. Note that`pylint-django` must also be added for Django projects. To do so, add the following lines to `requirements/ci.txt` and replace the targeted version with the latest one available.

```
pylint==<latest_version>
pylint-django==<latest_version>
```

Add the following lines `pyproject.toml`. Note that some lines mentioning *django* are only needed for Django projects.

```toml
[tool.pylint.MAIN]
load-plugins = ["pylint_django"]
ignore = [
"migrations",
"tests",
"test",
"venv",
".venv",
"setup.py",
"manage.py",
]
django-settings-module = "repository_name.settings.ci"

```

#### Run

Now you can run `pylint` and resolve any linting issues you will encounter ; either in a virtual environment, in your docker image or directly in the CI:

```
pylint --recursive=y .
```

## Formatting

For code formatting, we use two tools:
- [`black`](https://black.readthedocs.io/en/stable/): This tool is a code formatter. While strongly opinionated, its capacity to automatically format code and to promote small diff codebase changes makes it very useful to work on large projects.
- [`isort`](https://pycqa.github.io/isort/): This tool automatically sorts imports at the beginning of Python files, making dependency management easier and more readable.

### black

#### Install and configure

To use `black`, the package must be installed by adding the following line to `requirements/ci.txt`:

```
black==<latest_version>
```

Paste the following lines to `pyproject.toml` to configure the tool:

```toml
[tool.black]
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| venv
| \.local
| \.pytest_cache
| _build
| buck-out
| build
| dist
| migrations
)/
'''
```

#### Run

Now you can run `black .` and resolve any linting issues you will encounter ; either in a virtual environment or in your docker image.

To use `black` in a CI, you don't want the format to be enforced but just to report not compliant lines so that you can fix them. To do so, you can use the check option:

```
black --check .
```

### isort

#### Install and configure

To use `isort`, the package must be installed by adding the following line to `requirements/ci.txt`:

```
isort==<latest_version>
```

Paste the following lines to `pyproject.toml` to configure the tool:

```toml
[tool.isort]
py_version = 311
multi_line_output = 3
include_trailing_comma = true
skip_glob = ["venv/*", "**/migrations/**"]
profile = "black"
```

#### Run

Now you can run `isort .` and resolve any linting issues you will encounter ; either in a virtual environment or in your docker image.

To use `isort` in a CI, you don't want the format to be enforced but just to report not compliant lines so that you can fix them. To do so, you can use the check option:

```
isort --check .
```
70 changes: 70 additions & 0 deletions technical_standards/python/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
notion_page: https://www.notion.so/wpmedia/Python-Tests-b6d5253be84142ee87a2fd120c192ca9?pvs=4
title: Python - Tests
---

# Python - Tests

For built-in unit and integration tests of our Python projects, we use [`pytest`](https://docs.pytest.org/en/stable/).
Running `pytest` and ensuring all tests are passing must be part of the CI of all repositories.

## Setting up pytest.

To start using `pytest`, some packages must be added to `requirements/ci.txt`: `pytest` and `pytest-mock`. Note that`pytest-django` must also be added for Django projects. To do so, add the following lines to `requirements/ci.txt` and replace the targeted version with the latest one available.

```
pytest==<latest_version>
pytest-django==<latest_version>
pytest-mock==<latest_version>
```

Make sure that in `requirements/dev.txt` the first line is

```
-r ci.txt
```

For the new packages to be added to your docker image, build the image again with

```
docker-compose build
```

In your `pyproject.toml` file, add the following lines.

```toml
[tool.pytest.ini_options]
minversion = "6.0"
DJANGO_SETTINGS_MODULE = "repository_name.settings.ci"
addopts = "-x --strict-markers --ds=repository_name.settings.ci"
python_files = ["test*.py", "test_*.py"]

```

Creates a `tests.py` file and add the following code.

```python

def test_dummy(client):
result = 1+1
assert result == 2
```

Now enter the container and run the tests.

```bash
docker-compose exec app bash
pytest
```

You should see one passing test.

## Reporting test coverage

`pytest` can report test coverage after running. This is useful to understand which lines of code are covered with tests. We use this feature as part of our [automated CI](../../ways_of_working/processes/reviews.md).

To generate an XML coverage report, use the following options when running `pytest`:

```
pytest --cov=. --cov-report=xml
```

0 comments on commit 4ca0341

Please sign in to comment.