-
Notifications
You must be signed in to change notification settings - Fork 61
/
Makefile
224 lines (189 loc) · 7.25 KB
/
Makefile
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#-------------------- ONLY MODIFY CODE IN THIS SECTION --------------------#
PACKAGE_DIR := androidtv
TEST_DIR := tests
DOCS_DIR := docs
# Change to false if you don't want to use pytest
USE_PYTEST := true
# Change this to false if you don't want to run linting checks on the tests
LINT_TEST_DIR := false
#-------------------- DO NOT MODIFY CODE BELOW!!!!!!!! --------------------#
export PATH := $(abspath venv)/bin:${PATH}
# Binaries to run
BLACK := $(abspath venv)/bin/black
COVERAGE := $(abspath venv)/bin/coverage
FLAKE8 := $(abspath venv)/bin/flake8
PIP := $(abspath venv)/bin/pip3
PYLINT := $(abspath venv)/bin/pylint
PYTEST := $(abspath venv)/bin/pytest
PYTHON := $(abspath venv)/bin/python
SPHINX_APIDOC := $(abspath venv)/bin/sphinx-apidoc
TWINE := $(abspath venv)/bin/twine
# Whether to include "*_async.py" files
INCLUDE_ASYNC = $(shell $(PYTHON) --version | grep -q "Python 3.[7891]" && echo "true" || echo "false")
# Async vs. Sync files
PACKAGE_ASYNC_FILES = $(shell ls -m $(PACKAGE_DIR)/*_async.py 2>/dev/null)
TEST_ASYNC_FILES = $(shell ls -m $(TEST_DIR)/*_async.py 2>/dev/null)
TEST_SYNC_FILES = $(shell cd $(TEST_DIR) && ls test*.py | grep -v async)
# Target prerequisites that may or may not exist
VENV_REQUIREMENTS_TXT := $(wildcard venv_requirements.txt)
SETUP_PY := $(wildcard setup.py)
# A prerequisite for forcing targets to run
FORCE:
# Help!
help: ## Show this help menu
@echo "\n\033[1mUsage:\033[0m"; \
awk -F ':|##' '/^[^\t].+?:.*?##/ { printf "\033[36m make %-20s\033[0m %s\n", $$1, $$NF }' $(MAKEFILE_LIST) | grep -v "make venv/\." | sort
@echo ""
@echo "NOTES:"
@echo "- The 'venv/.bin' target may fail because newer Python versions include the 'venv' package. Follow the instructions to create the virtual environment manually."
ifneq ("$(wildcard scripts/pre-commit.sh)", "")
@echo "- To install the git pre-commit hook:\n\n scripts/pre-commit.sh\n"
endif
@echo "- You may need to activate the virtual environment prior to running any Make commands:\n\n source venv/bin/activate\n"
# Virtual environment targets
.PHONY: clean-venv
clean-venv: ## Remove the virtual environment
rm -rf venv
venv: venv/.bin venv/.requirements venv/.setup .git/hooks/pre-commit ## Create the virtual environment and install all necessary packages
venv/.bin: ## Create the virtual environment
if [ -z "$$ENV_GITHUB_ACTIONS" ]; then \
echo -e "If this target fails, you can perform this action manually via:\n\n make clean-venv && python3 -m venv venv && source venv/bin/activate && pip install -U setuptools && echo -e '*.*\\\n**/' > venv/.gitignore && touch venv/.bin\n\n"; \
apt list -a --installed python3-venv 2>&1 | grep -q installed || sudo apt update && sudo apt install python3-venv; \
python3 -m venv venv; \
$(PIP) install -U setuptools; \
else \
mkdir -p venv/bin; \
ln -s $$(which pip) $(PIP); \
ln -s $$(which python) $(PYTHON); \
fi
mkdir -p venv/bin
echo '*.*\n**/' > venv/.gitignore
touch venv/.bin
venv/.requirements: venv/.bin $(VENV_REQUIREMENTS_TXT) ## Install the requirements from 'venv_requirements.txt' in the virtual environment
ifneq ("$(wildcard venv_requirements.txt)", "")
$(PIP) install -U -r venv_requirements.txt
if ! [ -z "$$ENV_GITHUB_ACTIONS" ]; then \
ln -s $$(which black) $(BLACK); \
ln -s $$(which coverage) $(COVERAGE); \
ln -s $$(which flake8) $(FLAKE8); \
ln -s $$(which pylint) $(PYLINT); \
ln -s $$(which pytest) $(PYTEST); \
ln -s $$(which sphinx-apidoc) $(SPHINX_APIDOC); \
ln -s $$(which twine) $(TWINE); \
fi
endif
touch venv/.requirements
# Install the package in the virtual environment
venv/.setup: venv/.bin $(SETUP_PY)
ifneq ("$(wildcard setup.py)", "")
$(PIP) install .
endif
touch venv/.setup
.PHONY: uninstall
uninstall:
rm -f venv/.setup
.PHONY: install
install: uninstall venv/.setup ## Install the package in the virtual environment
# Create the pre-commit hook
.git/hooks/pre-commit:
./scripts/pre-commit.sh MAKE_PRECOMMIT_HOOK
.PHONY: pre-commit
pre-commit: .git/hooks/pre-commit ## Create the pre-commit hook
# Linting and code analysis
.PHONY: black
black: venv ## Format the code using black
$(BLACK) --safe --line-length 120 --target-version py35 $(PACKAGE_DIR)
$(BLACK) --safe --line-length 120 --target-version py35 $(TEST_DIR)
ifneq ("$(wildcard setup.py)", "")
$(BLACK) --safe --line-length 120 --target-version py35 setup.py
endif
.PHONY: lint-black
lint-black: venv ## Check that the code is formatted using black
$(BLACK) --check --line-length 120 --safe --target-version py35 $(PACKAGE_DIR)
$(BLACK) --check --line-length 120 --safe --target-version py35 $(TEST_DIR)
ifneq ("$(wildcard setup.py)", "")
$(BLACK) --check --line-length 120 --safe --target-version py35 setup.py
endif
.PHONY: lint-flake8
lint-flake8: venv ## Check the code using flake8
ifeq ($(INCLUDE_ASYNC), true)
$(FLAKE8) $(PACKAGE_DIR)
ifeq ($(LINT_TEST_DIR), true)
$(FLAKE8) $(TEST_DIR)
endif
else
$(FLAKE8) $(PACKAGE_DIR) --exclude="$(PACKAGE_ASYNC_FILES)"
ifeq ($(LINT_TEST_DIR), true)
$(FLAKE8) $(TEST_DIR) --exclude="$(TEST_ASYNC_FILES)"
endif
endif
ifneq ("$(wildcard setup.py)", "")
$(FLAKE8) setup.py
endif
.PHONY: lint-pylint
lint-pylint: venv ## Check the code using pylint
ifeq ($(INCLUDE_ASYNC), true)
$(PYLINT) $(PACKAGE_DIR)
ifeq ($(LINT_TEST_DIR), true)
$(PYLINT) $(TEST_DIR)
endif
else
$(PYLINT) $(PACKAGE_DIR) --ignore="$(PACKAGE_ASYNC_FILES)"
ifeq ($(LINT_TEST_DIR), true)
$(PYLINT) $(TEST_DIR) --ignore="$(TEST_ASYNC_FILES)"
endif
endif
ifneq ("$(wildcard setup.py)", "")
$(PYLINT) setup.py
endif
.PHONY: lint
lint: lint-black lint-flake8 lint-pylint ## Run all linting checks on the code
# Testing and coverage.
.PHONY: test
test: venv ## Run the unit tests
ifeq ($(INCLUDE_ASYNC), true)
ifeq ($(USE_PYTEST), true)
$(PYTEST) $(TEST_DIR)
else
$(PYTHON) -m unittest discover -s $(TEST_DIR)/ -t .
endif
else
ifeq ($(USE_PYTEST), true)
$(PYTEST) $(TEST_DIR) --ignore-glob="*async.py"
else
for synctest in $(TEST_SYNC_FILES); do echo "\033[1;32m$(TEST_DIR)/$$synctest\033[0m" && $(PYTHON) -m unittest "$(TEST_DIR)/$$synctest"; done
endif
endif
.PHONY: coverage
coverage: venv ## Run the unit tests and produce coverage info
ifeq ($(INCLUDE_ASYNC), true)
ifeq ($(USE_PYTEST), true)
$(COVERAGE) run --source $(PACKAGE_DIR) -m pytest $(TEST_DIR)/ && $(COVERAGE) report -m
else
$(COVERAGE) run --source $(PACKAGE_DIR) -m unittest discover -s $(TEST_DIR) -t . && $(COVERAGE) report -m
endif
else
ifeq ($(USE_PYTEST), true)
$(COVERAGE) run --source $(PACKAGE_DIR) -m pytest $(TEST_DIR)/ --ignore-glob="*async.py" && $(COVERAGE) report -m
else
for synctest in $(TEST_SYNC_FILES); do echo "\033[1;32m$(TEST_DIR)/$$synctest\033[0m" && $(COVERAGE) run --source $(PACKAGE_DIR) -m unittest "$(TEST_DIR)/$$synctest"; done
$(COVERAGE) report -m
endif
endif
.PHONY: htmlcov
htmlcov: coverage ## Produce a coverage report
$(COVERAGE) html
# Documentation
.PHONY: docs
docs: venv ## Build the documentation
rm -rf $(DOCS_DIR)/build
@cd $(DOCS_DIR) && $(SPHINX_APIDOC) -f -e -o source/ $(CURDIR)/$(PACKAGE_DIR)/
@cd $(DOCS_DIR) && make html && make html
.PHONY: release
release: ## Make a release and upload it to pypi
rm -rf dist
scripts/git_tag.sh
$(PYTHON) setup.py sdist bdist_wheel
$(TWINE) upload dist/*
.PHONY: all
all: lint htmlcov ## Run all linting checks and unit tests and produce a coverage report