Skip to content

Commit

Permalink
Project's development setup described (#297)
Browse files Browse the repository at this point in the history
  • Loading branch information
francis-clairicia authored Jun 15, 2024
1 parent 70652f0 commit 70ce604
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
src/easynetwork/version.py

# Benchmark reports
.benchmarks
benchmark_reports
benchmark*.json
benchmark*.html
Expand Down
44 changes: 0 additions & 44 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ default_language_version:
minimum_pre_commit_version: '2.20.0'

ci:
skip: [mypy]
autoupdate_branch: 'pre-commit/autoupdate'
autoupdate_schedule: quarterly

Expand Down Expand Up @@ -68,46 +67,3 @@ repos:
- id: check-json
- id: check-toml
- id: check-yaml
- repo: local
hooks:
- id: mypy
name: mypy (project)
entry: tox run -q -e mypy-full
language: system
files: ^(src/)
types_or: [python, pyi]
require_serial: true
pass_filenames: false
- id: mypy
name: mypy (tests)
files: ^((src|tests)/)
entry: tox run -q -e mypy-test
language: system
types_or: [python, pyi]
require_serial: true
pass_filenames: false
- id: mypy
name: mypy (docs)
files: ^((src|docs/source)/)
exclude: ^(docs/source/conf.py)$
entry: tox run -q -e mypy-docs
language: system
types_or: [python, pyi]
require_serial: true
pass_filenames: false
- id: mypy
name: mypy (benchmark/servers)
files: ^((src|benchmark_server)/)
entry: tox run -q -e mypy-benchmark_server
language: system
types_or: [python, pyi]
require_serial: true
pass_filenames: false
- id: mypy
name: mypy (benchmark/micro-benchs)
files: ^((src|micro_benchmarks)/)
entry: tox run -q -e mypy-micro_benchmarks
language: system
types_or: [python, pyi]
require_serial: true
pass_filenames: false
10 changes: 10 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"recommendations": [
"ms-python.black-formatter",
"ms-python.flake8",
"ms-python.isort",
"ms-python.mypy-type-checker",
"ms-python.python",
"ms-python.vscode-pylance"
]
}
86 changes: 86 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Development Environment

## Project Setup

### System Requirements

- CPython >= 3.11.0
- [PDM](https://pdm-project.org/latest/#installation) >= 2.15

### Virtual environment

#### Option 1: Use an already created virtual environment via `pyenv-virtualenv`

```sh
# Create the virtual environment
pyenv virtualenv 3.11 easynetwork-3.11

# Set the local python (3.12 and upward are still needed for tox)
pyenv local "easynetwork-3.11" 3.12

# Tell pdm to use your virtualenv
pdm use -f $VIRTUAL_ENV
# -> Using Python interpreter: /path/to/.pyenv/versions/3.11.x/envs/easynetwork-3.11/bin/python3 (3.11)
```

#### Option 2: Let `pdm` create a `.venv` folder

0. For the `pyenv` users, set the local python :
```sh
pyenv local 3.11 3.12
```

1. Create the virtual environment :
```sh
# Creates the virtual environment ( in .venv directory )
pdm venv create 3.11

# Tell pdm to use this virtualenv
pdm use --venv in-project
```

2. Activate the virtual environment in the current shell using either :
- the [manual way](https://docs.python.org/3.11/library/venv.html#how-venvs-work)
- the [pdm venv CLI tool](https://pdm-project.org/latest/usage/venv/#activate-a-virtualenv)

### Installation

1. Install the project with its dependencies and development tools :
```sh
pdm install -G:all
```

2. If it is a clone of the `git` project, run :
```sh
pre-commit install
```

3. Check the installation :
```sh
# Run pre-commit hooks
pre-commit run --all-files

# Run mypy against all the project
tox run -q -f mypy
```

### Configure the IDE

#### Visual Studio Code

1. The recommended extensions are in [.vscode/extensions.json](.vscode/extensions.json)

2. Copy [.vscode/settings.example.json](.vscode/settings.example.json) to `.vscode/settings.json`

3. (Optional) To enable VS code's integrated testing tool, add this in your `settings.json`:
```json
{
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": [
"-n",
"auto"
]
}
```
> :warning: **NEVER** run all the test suite with VS code integrated testing tool ! There are 8000+ tests.
6 changes: 6 additions & 0 deletions benchmark_server/run_benchmark
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,12 @@ def main() -> None:
html_output_file: Path | None = args.save_html
json_output_file: Path | None = args.save_json
report_file_with_date: bool = args.report_file_with_date
if html_output_file:
html_output_file = html_output_file.absolute()
html_output_file.parent.mkdir(parents=True, exist_ok=True)
if json_output_file:
json_output_file = json_output_file.absolute()
json_output_file.parent.mkdir(parents=True, exist_ok=True)

variations: list[_BenchmarkVariationDef] = [
{
Expand Down
5 changes: 5 additions & 0 deletions pdm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[python]
use_venv = true

[venv]
backend = "venv"
4 changes: 1 addition & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ classifiers = [
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: BSD",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand Down Expand Up @@ -227,7 +225,7 @@ ignore_missing_imports = true

[tool.pytest.ini_options]
asyncio_mode = "strict" # Avoid some unwanted behaviour
addopts = "--strict-markers -p 'no:anyio' -p 'no:benchmark'" # hatch CLI dependencies installs anyio
addopts = "--dist=worksteal --strict-markers -p 'no:anyio' -p 'no:benchmark'" # hatch CLI dependencies installs anyio
minversion = "7.1.2"
testpaths = ["tests"]
norecursedirs = ["scripts"]
Expand Down
15 changes: 11 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
import random
from typing import TYPE_CHECKING

import pytest

random.seed(42) # Fully deterministic random output


def pytest_report_header() -> list[str]:
def pytest_report_header(config: pytest.Config) -> list[str]:
headers: list[str] = []
addopts: str = os.environ.get("PYTEST_ADDOPTS", "")
if not addopts:
return []
return [f"PYTEST_ADDOPTS: {addopts}"]
if addopts:
headers.append(f"PYTEST_ADDOPTS: {addopts}")
if config.pluginmanager.has_plugin("xdist") and config.getoption("numprocesses", 0):
headers.append(f"distribution: {config.getoption('dist', 'no')}")
return headers


PYTEST_PLUGINS_PACKAGE = f"{__package__}.pytest_plugins"
Expand All @@ -23,6 +28,7 @@ def pytest_report_header() -> list[str]:
f"{PYTEST_PLUGINS_PACKAGE}.auto_markers",
f"{PYTEST_PLUGINS_PACKAGE}.extra_features",
f"{PYTEST_PLUGINS_PACKAGE}.ssl_module",
f"{PYTEST_PLUGINS_PACKAGE}.xdist_for_vscode",
]

if TYPE_CHECKING:
Expand All @@ -34,4 +40,5 @@ def pytest_report_header() -> list[str]:
auto_markers as auto_markers,
extra_features as extra_features,
ssl_module as ssl_module,
xdist_for_vscode as xdist_for_vscode,
)
18 changes: 18 additions & 0 deletions tests/pytest_plugins/xdist_for_vscode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import annotations

from collections.abc import Generator

import pytest


@pytest.hookimpl(wrapper=True)
def pytest_xdist_auto_num_workers(config: pytest.Config) -> Generator[None, int, int]:
"""determine how many workers to use based on how many tests were selected in the test explorer"""
num_workers = yield
if "vscode_pytest" in config.option.plugins:
nb_launched_tests = len(config.option.file_or_dir)
if nb_launched_tests == 1:
# "0" means no workers
return 0
return min(num_workers, nb_launched_tests)
return num_workers
22 changes: 10 additions & 12 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ envlist =
build
# Tests (3.11)
py311-other-{tests,docstrings}
py311-{unit,functional}-{__standard__,cbor,msgpack}
py311-{unit,functional}-{standard,cbor,msgpack}
py311-functional-{sniffio,asyncio_proactor,uvloop}
# Tests (3.12)
py312-{unit,functional}-{__standard__,cbor,msgpack}
py312-{unit,functional}-{standard,cbor,msgpack}
py312-functional-{sniffio,asyncio_proactor,uvloop}
# Report
coverage
Expand All @@ -37,7 +37,6 @@ setenv =
addopts = -p "no:cacheprovider" {tty:--color=yes}
unit_tests_rootdir = tests{/}unit_test
functional_tests_rootdir = tests{/}functional_test
xdist_dist = worksteal
cov_opts = --cov --cov-report=''

[testenv:py311-other-{tests,docstrings}]
Expand All @@ -58,7 +57,7 @@ commands =
docstrings: pytest --doctest-modules {posargs} {[docs]examples_dir}{/}tutorials{/}ftp_server
docstrings: pytest --doctest-glob="*.rst" {posargs} {[docs]source_dir}

[testenv:{py311,py312}-{unit,functional}-{__standard__,cbor,msgpack}]
[testenv:{py311,py312}-{unit,functional}-{standard,cbor,msgpack}]
package = wheel
wheel_build_env = {[base]wheel_build_env}
groups =
Expand All @@ -78,7 +77,7 @@ setenv =
passenv =
PYTEST_MAX_WORKERS
commands =
__standard__: pytest -n "{env:PYTEST_MAX_WORKERS:auto}" --dist={[pytest-conf]xdist_dist} -m "not feature" {posargs} {env:TESTS_ROOTDIR}
standard: pytest -n "{env:PYTEST_MAX_WORKERS:auto}" -m "not feature" {posargs} {env:TESTS_ROOTDIR}
cbor: pytest -m "feature_cbor" {posargs} {env:TESTS_ROOTDIR}
msgpack: pytest -m "feature_msgpack" {posargs} {env:TESTS_ROOTDIR}

Expand Down Expand Up @@ -123,12 +122,12 @@ setenv =
passenv =
PYTEST_MAX_WORKERS
commands =
pytest -n "{env:PYTEST_MAX_WORKERS:auto}" --dist={[pytest-conf]xdist_dist} --asyncio-event-loop="{env:ASYNCIO_EVENTLOOP}" -m "asyncio and not feature" {posargs} {env:TESTS_ROOTDIR}
pytest -n "{env:PYTEST_MAX_WORKERS:auto}" --asyncio-event-loop="{env:ASYNCIO_EVENTLOOP}" -m "asyncio and not feature" {posargs} {env:TESTS_ROOTDIR}

[testenv:coverage]
skip_install = true
depends =
{py311,py312}-{unit,functional}-{__standard__,cbor,msgpack}
{py311,py312}-{unit,functional}-{standard,cbor,msgpack}
{py311,py312}-functional-{sniffio,asyncio_proactor,uvloop}
parallel_show_output = True
groups =
Expand Down Expand Up @@ -202,7 +201,6 @@ groups =
pre-commit
setenv =
{[base]setenv}
SKIP=mypy
passenv =
PRE_COMMIT_HOME
XDG_CACHE_HOME
Expand All @@ -213,7 +211,7 @@ commands =
package = wheel
wheel_build_env = {[base]wheel_build_env}
groups =
micro-benchmarks
micro-benchmark
cbor
msgpack
setenv =
Expand All @@ -222,7 +220,7 @@ setenv =
PYTHONHASHSEED = 0
PYTEST_ADDOPTS = {[pytest-conf]addopts}
commands =
pytest -c pytest-benchmark.ini {posargs:--benchmark-histogram=benchmark_reports{/}benchmark}
pytest -c pytest-benchmark.ini {posargs:--benchmark-histogram=benchmark_reports{/}micro_benches{/}benchmark}

[testenv:benchmark-server-{tcpecho,sslecho,readline,udpecho}]
skip_install = true
Expand All @@ -244,8 +242,8 @@ setenv =
readline: BENCHMARK_PATTERN = ^readline

# Report files
BENCHMARK_REPORT_JSON = {toxinidir}{/}benchmark_reports{/}{envname}-{env:BENCHMARK_PYTHON_VERSION}-report.json
BENCHMARK_REPORT_HTML = {toxinidir}{/}benchmark_reports{/}{envname}-{env:BENCHMARK_PYTHON_VERSION}-report.html
BENCHMARK_REPORT_JSON = {toxinidir}{/}benchmark_reports{/}json{/}{envname}-{env:BENCHMARK_PYTHON_VERSION}-report.json
BENCHMARK_REPORT_HTML = {toxinidir}{/}benchmark_reports{/}html{/}{envname}-{env:BENCHMARK_PYTHON_VERSION}-report.html
passenv =
BENCHMARK_PYTHON_VERSION
DOCKER_HOST
Expand Down

0 comments on commit 70ce604

Please sign in to comment.