Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
152 lines (121 loc) · 6.03 KB
/
Copy pathMakefile
File metadata and controls
152 lines (121 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# `uv` owns the environment. `uv run` creates `.venv` and installs from `uv.lock` whenever
# it is missing or out of date, so no recipe below has to build one first and there is no
# step a contributor can forget.
UV := uv
PYTHON := $(UV) run python
# The two ends of the supported range: the oldest interpreter `requires-python` claims and the
# newest the matrix runs. Keep both in sync with `pyproject.toml`.
PYTHON_FLOOR := 3.10
PYTHON_CEIL := 3.15
# Absolute, because `api` runs its compilers from inside `compiler/`.
VENV_FLOOR := $(CURDIR)/.venv-floor
VENV_CEIL := $(CURDIR)/.venv-ceil
# The live tests take every parameter from the environment. `.env.test` is the
# git-ignored file that carries them locally; the runner loads it so nothing
# under `tests/` has to read a file of its own. Absent, the tests skip by name.
ENV_TEST := .env.test
LOAD_ENV_TEST := set -a; if [ -f $(ENV_TEST) ]; then . ./$(ENV_TEST); fi; set +a;
# `hatchling` reads `[tool.hatch.version]`, so this is the number the build backend
# stamps on the artifacts. `--no-project --with` keeps it to one ephemeral package,
# because the release jobs read the version without syncing the project.
VERSION = $(shell $(UV) run --no-project --with hatchling hatchling version)
TAG = v$(VERSION)
RM := rm -rf
GREEN := \033[0;32m
RED := \033[0;31m
YELLOW := \033[0;33m
BLUE := \033[0;34m
BOLD := \033[1m
RESET := \033[0m
.PHONY: sync version clean-venv clean-build clean-api clean-docs clean api docs-api docs docs-serve docs-archive build tag dtag lint format typecheck test test-unit test-guards test-integration test-floor test-ceil
# No other recipe needs this: they all sync on their own. It exists so CI can install in
# a step of its own, which is what makes a resolution failure read as one in the log
# instead of as whatever recipe happened to run first.
sync:
$(UV) sync
@printf "$(YELLOW)Synced .venv with %s$(RESET)\n" "$$($(PYTHON) --version)"
clean-venv:
$(RM) .venv $(VENV_FLOOR) $(VENV_CEIL)
@printf "$(YELLOW)Cleaned venv directories$(RESET)\n"
clean-build:
$(RM) *.egg-info build dist
@printf "$(YELLOW)Cleaned build directory$(RESET)\n"
clean-api:
$(RM) pyrogram/errors/exceptions pyrogram/raw/all.py pyrogram/raw/base pyrogram/raw/functions pyrogram/raw/types
@printf "$(YELLOW)Cleaned api directory$(RESET)\n"
clean-docs:
$(RM) docs/build docs/source/api/bound-methods docs/source/api/methods docs/source/api/types docs/source/api/enums docs/source/telegram
@printf "$(YELLOW)Cleaned docs directory$(RESET)\n"
clean: clean-venv clean-build clean-api clean-docs
@printf "$(GREEN)Cleaned all directories$(RESET)\n"
api:
cd compiler/api && $(PYTHON) compiler.py
cd compiler/errors && $(PYTHON) compiler.py
# Both docs recipes below build the same tree with the same builder, so the arguments and the
# page generator each have one home here rather than a copy per recipe.
SPHINX_ARGS := -b dirhtml "docs/source" "docs/build/html" -j auto
docs-api:
cd compiler/docs && $(PYTHON) compiler.py
docs: docs-api
$(UV) run --group docs sphinx-build $(SPHINX_ARGS)
# `sphinx-autobuild` runs that same build, then rebuilds only the pages an edit touched and
# reloads the browser, so a docs change costs seconds where `docs` costs minutes.
docs-serve: docs-api
$(UV) run --group docs sphinx-autobuild $(SPHINX_ARGS)
docs-archive:
cd docs/build/html && zip -r ../docs.zip ./
# `ruff` takes its rule set, its line length and its excludes from `pyproject.toml`, so the
# `lint` job and the `pre-commit` hook both run this recipe instead of spelling the checks
# out again. `format` below is the same formatter with the writing turned on.
lint:
$(UV) run ruff check
$(UV) run ruff format --check
# Rewrites the tree. The line length and the excludes live in `pyproject.toml`, the same
# configuration `lint` reads.
format:
$(UV) run ruff format
# The rule set and the excludes live in `pyproject.toml`, same as `lint`. Unlike `lint`,
# this needs `pyrogram.raw.*` to resolve, so `make api` has to have been run first.
typecheck:
$(UV) run ty check
test:
@$(LOAD_ENV_TEST) $(PYTHON) -m pytest
# `--cov` reads its source and its omit list from `[tool.coverage.run]` in `pyproject.toml`, so
# neither this recipe nor the CI job calling it restates which tree is measured. Only the offline
# selection carries it: `test` and `test-integration` stay as fast as the relay lets them.
test-unit:
$(PYTHON) -m pytest -m 'not integration' --cov
# `test-unit` selects everything that is not integration, so it runs these too. This
# target is for working on the guards alone; the two are not disjoint.
test-guards:
$(PYTHON) -m pytest -m guard
test-integration:
@$(LOAD_ENV_TEST) $(PYTHON) -m pytest -m integration
# Both recipes build a throwaway environment from `pyproject.toml`, never from `uv.lock`.
# `uv run` and `uv sync` are not usable here: asked for a resolution other than the locked
# one they rewrite `uv.lock` to match, and `--frozen` installs the locked versions instead.
# The oldest version of every dependency the declarations allow, on the oldest interpreter.
test-floor:
$(UV) venv --clear --python $(PYTHON_FLOOR) $(VENV_FLOOR)
VIRTUAL_ENV=$(VENV_FLOOR) $(UV) pip install --resolution lowest-direct --all-extras --group test -r pyproject.toml
$(MAKE) api PYTHON=$(VENV_FLOOR)/bin/python
$(MAKE) test-unit PYTHON=$(VENV_FLOOR)/bin/python
# The newest, which the matrix never sees: it installs from `uv.lock`, so a release published
# after the last `uv lock` is exercised by nothing until this runs. A fresh environment
# resolves to the newest compatible release on its own, so there is no flag to pass.
test-ceil:
$(UV) venv --clear --python $(PYTHON_CEIL) $(VENV_CEIL)
VIRTUAL_ENV=$(VENV_CEIL) $(UV) pip install --all-extras --group test -r pyproject.toml
$(MAKE) api PYTHON=$(VENV_CEIL)/bin/python
$(MAKE) test-unit PYTHON=$(VENV_CEIL)/bin/python
build:
$(UV) build
# The single place that answers "what version is this", for the release jobs as well.
version:
@printf '%s\n' "$(VERSION)"
tag:
git tag $(TAG)
git push origin $(TAG)
dtag:
git tag -d $(TAG)
git push origin -d $(TAG)