Skip to content

Commit 1d46264

Browse files
committed
Update makefile, use pytest in makefile, try to run tests on 3.13 in github actions
1 parent ccb0d20 commit 1d46264

File tree

2 files changed

+121
-56
lines changed

2 files changed

+121
-56
lines changed

Diff for: .github/workflows/test.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
- "3.10"
2323
- "3.11"
2424
- "3.12"
25+
- "3.13"
2526

2627
steps:
2728
- uses: actions/checkout@v4

Diff for: Makefile

+120-56
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,39 @@ CLEAN_FS?=
3333
# Default: include.mk
3434
INCLUDE_MAKEFILE?=include.mk
3535

36+
# Optional additional directories to be added to PATH in format
37+
# `/path/to/dir/:/path/to/other/dir`. Gets inserted first, thus gets searched
38+
# first.
39+
# No default value.
40+
EXTRA_PATH?=
41+
3642
## core.mxenv
3743

38-
# Python interpreter to use.
44+
# Primary Python interpreter to use. It is used to create the
45+
# virtual environment if `VENV_ENABLED` and `VENV_CREATE` are set to `true`.
3946
# Default: python3
40-
PYTHON_BIN?=python3
47+
PRIMARY_PYTHON?=python3
4148

4249
# Minimum required Python version.
43-
# Default: 3.7
44-
PYTHON_MIN_VERSION?=3.7
50+
# Default: 3.9
51+
PYTHON_MIN_VERSION?=3.9
52+
53+
# Install packages using the given package installer method.
54+
# Supported are `pip` and `uv`. If uv is used, its global availability is
55+
# checked. Otherwise, it is installed, either in the virtual environment or
56+
# using the `PRIMARY_PYTHON`, dependent on the `VENV_ENABLED` setting. If
57+
# `VENV_ENABLED` and uv is selected, uv is used to create the virtual
58+
# environment.
59+
# Default: pip
60+
PYTHON_PACKAGE_INSTALLER?=uv
61+
62+
# Flag whether to use a global installed 'uv' or install
63+
# it in the virtual environment.
64+
# Default: false
65+
MXENV_UV_GLOBAL?=false
4566

4667
# Flag whether to use virtual environment. If `false`, the
47-
# interpreter according to `PYTHON_BIN` found in `PATH` is used.
68+
# interpreter according to `PRIMARY_PYTHON` found in `PATH` is used.
4869
# Default: true
4970
VENV_ENABLED?=true
5071

@@ -59,7 +80,7 @@ VENV_CREATE?=true
5980
# target folder for the virtual environment. If `VENV_ENABLED` is `true` and
6081
# `VENV_CREATE` is false it is expected to point to an existing virtual
6182
# environment. If `VENV_ENABLED` is `false` it is ignored.
62-
# Default: venv
83+
# Default: .venv
6384
VENV_FOLDER?=venv
6485

6586
# mxdev to install in virtual environment.
@@ -76,12 +97,19 @@ MXMAKE?=mxmake
7697
# Default: mx.ini
7798
PROJECT_CONFIG?=mx.ini
7899

100+
## core.packages
101+
102+
# Allow prerelease and development versions.
103+
# By default, the package installer only finds stable versions.
104+
# Default: false
105+
PACKAGES_ALLOW_PRERELEASES?=false
106+
79107
## qa.test
80108

81109
# The command which gets executed. Defaults to the location the
82110
# :ref:`run-tests` template gets rendered to if configured.
83111
# Default: .mxmake/files/run-tests.sh
84-
TEST_COMMAND?=$(VENV_FOLDER)/bin/python -m yafowil.tests.__init__
112+
TEST_COMMAND?=$(VENV_FOLDER)/bin/pytest src/yafowil/tests
85113

86114
# Additional Python requirements for running tests to be
87115
# installed (via pip).
@@ -100,7 +128,7 @@ TEST_DEPENDENCY_TARGETS?=
100128
COVERAGE_COMMAND?=\
101129
$(VENV_FOLDER)/bin/coverage run \
102130
--source src/yafowil \
103-
-m yafowil.tests.__init__ \
131+
-m pytest src/yafowil/tests \
104132
&& $(VENV_FOLDER)/bin/coverage report --fail-under=99
105133

106134
## i18n.gettext
@@ -127,6 +155,10 @@ LINGUA_SEARCH_PATH?=src/yafowil
127155
# No default value.
128156
LINGUA_PLUGINS?=
129157

158+
# Command line options passed to `pot-create`
159+
# No default value.
160+
LINGUA_OPTIONS?=
161+
130162
##############################################################################
131163
# END SETTINGS - DO NOT EDIT BELOW THIS LINE
132164
##############################################################################
@@ -139,6 +171,8 @@ CHECK_TARGETS?=
139171
TYPECHECK_TARGETS?=
140172
FORMAT_TARGETS?=
141173

174+
export PATH:=$(if $(EXTRA_PATH),$(EXTRA_PATH):,)$(PATH)
175+
142176
# Defensive settings for make: https://tech.davis-hansson.com/p/make/
143177
SHELL:=bash
144178
.ONESHELL:
@@ -155,48 +189,66 @@ MXMAKE_FOLDER?=.mxmake
155189
# Sentinel files
156190
SENTINEL_FOLDER?=$(MXMAKE_FOLDER)/sentinels
157191
SENTINEL?=$(SENTINEL_FOLDER)/about.txt
158-
$(SENTINEL):
192+
$(SENTINEL): $(firstword $(MAKEFILE_LIST))
159193
@mkdir -p $(SENTINEL_FOLDER)
160194
@echo "Sentinels for the Makefile process." > $(SENTINEL)
161195

162196
##############################################################################
163197
# mxenv
164198
##############################################################################
165199

166-
# Check if given Python is installed
167-
ifeq (,$(shell which $(PYTHON_BIN)))
168-
$(error "PYTHON=$(PYTHON_BIN) not found in $(PATH)")
169-
endif
200+
export OS:=$(OS)
170201

171-
# Check if given Python version is ok
172-
PYTHON_VERSION_OK=$(shell $(PYTHON_BIN) -c "import sys; print((int(sys.version_info[0]), int(sys.version_info[1])) >= tuple(map(int, '$(PYTHON_MIN_VERSION)'.split('.'))))")
173-
ifeq ($(PYTHON_VERSION_OK),0)
174-
$(error "Need Python >= $(PYTHON_MIN_VERSION)")
202+
# Determine the executable path
203+
ifeq ("$(VENV_ENABLED)", "true")
204+
export VIRTUAL_ENV=$(abspath $(VENV_FOLDER))
205+
ifeq ("$(OS)", "Windows_NT")
206+
VENV_EXECUTABLE_FOLDER=$(VIRTUAL_ENV)/Scripts
207+
else
208+
VENV_EXECUTABLE_FOLDER=$(VIRTUAL_ENV)/bin
175209
endif
176-
177-
# Check if venv folder is configured if venv is enabled
178-
ifeq ($(shell [[ "$(VENV_ENABLED)" == "true" && "$(VENV_FOLDER)" == "" ]] && echo "true"),"true")
179-
$(error "VENV_FOLDER must be configured if VENV_ENABLED is true")
210+
export PATH:=$(VENV_EXECUTABLE_FOLDER):$(PATH)
211+
MXENV_PYTHON=python
212+
else
213+
MXENV_PYTHON=$(PRIMARY_PYTHON)
180214
endif
181215

182-
# determine the executable path
183-
ifeq ("$(VENV_ENABLED)", "true")
184-
MXENV_PATH=$(VENV_FOLDER)/bin/
216+
# Determine the package installer
217+
ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv")
218+
PYTHON_PACKAGE_COMMAND=uv pip
185219
else
186-
MXENV_PATH=
220+
PYTHON_PACKAGE_COMMAND=$(MXENV_PYTHON) -m pip
187221
endif
188222

189223
MXENV_TARGET:=$(SENTINEL_FOLDER)/mxenv.sentinel
190224
$(MXENV_TARGET): $(SENTINEL)
225+
@$(PRIMARY_PYTHON) -c "import sys; vi = sys.version_info; sys.exit(1 if (int(vi[0]), int(vi[1])) >= tuple(map(int, '$(PYTHON_MIN_VERSION)'.split('.'))) else 0)" \
226+
&& echo "Need Python >= $(PYTHON_MIN_VERSION)" && exit 1 || :
227+
@[[ "$(VENV_ENABLED)" == "true" && "$(VENV_FOLDER)" == "" ]] \
228+
&& echo "VENV_FOLDER must be configured if VENV_ENABLED is true" && exit 1 || :
229+
@[[ "$(VENV_ENABLED)$(PYTHON_PACKAGE_INSTALLER)" == "falseuv" ]] \
230+
&& echo "Package installer uv does not work with a global Python interpreter." && exit 1 || :
191231
ifeq ("$(VENV_ENABLED)", "true")
192232
ifeq ("$(VENV_CREATE)", "true")
193-
@echo "Setup Python Virtual Environment under '$(VENV_FOLDER)'"
194-
@$(PYTHON_BIN) -m venv $(VENV_FOLDER)
233+
ifeq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvtrue")
234+
@echo "Setup Python Virtual Environment using package 'uv' at '$(VENV_FOLDER)'"
235+
@uv venv -p $(PRIMARY_PYTHON) --seed $(VENV_FOLDER)
236+
else
237+
@echo "Setup Python Virtual Environment using module 'venv' at '$(VENV_FOLDER)'"
238+
@$(PRIMARY_PYTHON) -m venv $(VENV_FOLDER)
239+
@$(MXENV_PYTHON) -m ensurepip -U
240+
endif
241+
endif
242+
else
243+
@echo "Using system Python interpreter"
195244
endif
245+
ifeq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvfalse")
246+
@echo "Install uv"
247+
@$(MXENV_PYTHON) -m pip install uv
196248
endif
197-
@$(MXENV_PATH)pip install -U pip setuptools wheel
198-
@$(MXENV_PATH)pip install -U $(MXDEV)
199-
@$(MXENV_PATH)pip install -U $(MXMAKE)
249+
@$(PYTHON_PACKAGE_COMMAND) install -U pip setuptools wheel
250+
@echo "Install/Update MXStack Python packages"
251+
@$(PYTHON_PACKAGE_COMMAND) install -U $(MXDEV) $(MXMAKE)
200252
@touch $(MXENV_TARGET)
201253

202254
.PHONY: mxenv
@@ -213,8 +265,8 @@ ifeq ("$(VENV_CREATE)", "true")
213265
@rm -rf $(VENV_FOLDER)
214266
endif
215267
else
216-
@$(MXENV_PATH)pip uninstall -y $(MXDEV)
217-
@$(MXENV_PATH)pip uninstall -y $(MXMAKE)
268+
@$(PYTHON_PACKAGE_COMMAND) uninstall -y $(MXDEV)
269+
@$(PYTHON_PACKAGE_COMMAND) uninstall -y $(MXMAKE)
218270
endif
219271

220272
INSTALL_TARGETS+=mxenv
@@ -233,13 +285,11 @@ MXMAKE_FILES?=$(MXMAKE_FOLDER)/files
233285

234286
# set environment variables for mxmake
235287
define set_mxfiles_env
236-
@export MXMAKE_MXENV_PATH=$(1)
237-
@export MXMAKE_FILES=$(2)
288+
@export MXMAKE_FILES=$(1)
238289
endef
239290

240291
# unset environment variables for mxmake
241292
define unset_mxfiles_env
242-
@unset MXMAKE_MXENV_PATH
243293
@unset MXMAKE_FILES
244294
endef
245295

@@ -256,9 +306,9 @@ FILES_TARGET:=requirements-mxdev.txt
256306
$(FILES_TARGET): $(PROJECT_CONFIG) $(MXENV_TARGET) $(SOURCES_TARGET) $(LOCAL_PACKAGE_FILES)
257307
@echo "Create project files"
258308
@mkdir -p $(MXMAKE_FILES)
259-
$(call set_mxfiles_env,$(MXENV_PATH),$(MXMAKE_FILES))
260-
@$(MXENV_PATH)mxdev -n -c $(PROJECT_CONFIG)
261-
$(call unset_mxfiles_env,$(MXENV_PATH),$(MXMAKE_FILES))
309+
$(call set_mxfiles_env,$(MXMAKE_FILES))
310+
@mxdev -n -c $(PROJECT_CONFIG)
311+
$(call unset_mxfiles_env)
262312
@test -e $(MXMAKE_FILES)/pip.conf && cp $(MXMAKE_FILES)/pip.conf $(VENV_FOLDER)/pip.conf || :
263313
@touch $(FILES_TARGET)
264314

@@ -287,11 +337,21 @@ ADDITIONAL_SOURCES_TARGETS?=
287337

288338
INSTALLED_PACKAGES=$(MXMAKE_FILES)/installed.txt
289339

340+
ifeq ("$(PACKAGES_ALLOW_PRERELEASES)","true")
341+
ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv")
342+
PACKAGES_PRERELEASES=--prerelease=allow
343+
else
344+
PACKAGES_PRERELEASES=--pre
345+
endif
346+
else
347+
PACKAGES_PRERELEASES=
348+
endif
349+
290350
PACKAGES_TARGET:=$(INSTALLED_PACKAGES)
291351
$(PACKAGES_TARGET): $(FILES_TARGET) $(ADDITIONAL_SOURCES_TARGETS)
292352
@echo "Install python packages"
293-
@$(MXENV_PATH)pip install -r $(FILES_TARGET)
294-
@$(MXENV_PATH)pip freeze > $(INSTALLED_PACKAGES)
353+
@$(PYTHON_PACKAGE_COMMAND) install $(PACKAGES_PRERELEASES) -r $(FILES_TARGET)
354+
@$(PYTHON_PACKAGE_COMMAND) freeze > $(INSTALLED_PACKAGES)
295355
@touch $(PACKAGES_TARGET)
296356

297357
.PHONY: packages
@@ -304,8 +364,8 @@ packages-dirty:
304364
.PHONY: packages-clean
305365
packages-clean:
306366
@test -e $(FILES_TARGET) \
307-
&& test -e $(MXENV_PATH)pip \
308-
&& $(MXENV_PATH)pip uninstall -y -r $(FILES_TARGET) \
367+
&& test -e $(MXENV_PYTHON) \
368+
&& $(MXENV_PYTHON) -m pip uninstall -y -r $(FILES_TARGET) \
309369
|| :
310370
@rm -f $(PACKAGES_TARGET)
311371

@@ -320,22 +380,22 @@ CLEAN_TARGETS+=packages-clean
320380
TEST_TARGET:=$(SENTINEL_FOLDER)/test.sentinel
321381
$(TEST_TARGET): $(MXENV_TARGET)
322382
@echo "Install $(TEST_REQUIREMENTS)"
323-
@$(MXENV_PATH)pip install $(TEST_REQUIREMENTS)
383+
@$(PYTHON_PACKAGE_COMMAND) install $(TEST_REQUIREMENTS)
324384
@touch $(TEST_TARGET)
325385

326386
.PHONY: test
327387
test: $(FILES_TARGET) $(SOURCES_TARGET) $(PACKAGES_TARGET) $(TEST_TARGET) $(TEST_DEPENDENCY_TARGETS)
328-
@echo "Run tests"
329-
@test -z "$(TEST_COMMAND)" && echo "No test command defined"
330-
@test -z "$(TEST_COMMAND)" || bash -c "$(TEST_COMMAND)"
388+
@test -z "$(TEST_COMMAND)" && echo "No test command defined" && exit 1 || :
389+
@echo "Run tests using $(TEST_COMMAND)"
390+
@/usr/bin/env bash -c "$(TEST_COMMAND)"
331391

332392
.PHONY: test-dirty
333393
test-dirty:
334394
@rm -f $(TEST_TARGET)
335395

336396
.PHONY: test-clean
337397
test-clean: test-dirty
338-
@test -e $(MXENV_PATH)pip && $(MXENV_PATH)pip uninstall -y $(TEST_REQUIREMENTS) || :
398+
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y $(TEST_REQUIREMENTS) || :
339399
@rm -rf .pytest_cache
340400

341401
INSTALL_TARGETS+=$(TEST_TARGET)
@@ -349,22 +409,22 @@ DIRTY_TARGETS+=test-dirty
349409
COVERAGE_TARGET:=$(SENTINEL_FOLDER)/coverage.sentinel
350410
$(COVERAGE_TARGET): $(TEST_TARGET)
351411
@echo "Install Coverage"
352-
@$(MXENV_PATH)pip install -U coverage
412+
@$(PYTHON_PACKAGE_COMMAND) install -U coverage
353413
@touch $(COVERAGE_TARGET)
354414

355415
.PHONY: coverage
356416
coverage: $(FILES_TARGET) $(SOURCES_TARGET) $(PACKAGES_TARGET) $(COVERAGE_TARGET)
357-
@echo "Run coverage"
358-
@test -z "$(COVERAGE_COMMAND)" && echo "No coverage command defined"
359-
@test -z "$(COVERAGE_COMMAND)" || bash -c "$(COVERAGE_COMMAND)"
417+
@test -z "$(COVERAGE_COMMAND)" && echo "No coverage command defined" && exit 1 || :
418+
@echo "Run coverage using $(COVERAGE_COMMAND)"
419+
@/usr/bin/env bash -c "$(COVERAGE_COMMAND)"
360420

361421
.PHONY: coverage-dirty
362422
coverage-dirty:
363423
@rm -f $(COVERAGE_TARGET)
364424

365425
.PHONY: coverage-clean
366426
coverage-clean: coverage-dirty
367-
@test -e $(MXENV_PATH)pip && $(MXENV_PATH)pip uninstall -y coverage || :
427+
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y coverage || :
368428
@rm -rf .coverage htmlcov
369429

370430
INSTALL_TARGETS+=$(COVERAGE_TARGET)
@@ -421,14 +481,14 @@ gettext-compile:
421481
LINGUA_TARGET:=$(SENTINEL_FOLDER)/lingua.sentinel
422482
$(LINGUA_TARGET): $(MXENV_TARGET)
423483
@echo "Install Lingua"
424-
@$(MXENV_PATH)pip install chameleon lingua $(LINGUA_PLUGINS)
484+
@$(PYTHON_PACKAGE_COMMAND) install chameleon lingua $(LINGUA_PLUGINS)
425485
@touch $(LINGUA_TARGET)
426486

427487
PHONY: lingua-extract
428488
lingua-extract: $(LINGUA_TARGET)
429489
@echo "Extract messages"
430-
@$(MXENV_PATH)pot-create \
431-
"$(LINGUA_SEARCH_PATH)" \
490+
@pot-create \
491+
"$(LINGUA_SEARCH_PATH)" $(LINGUA_OPTIONS) \
432492
-o "$(GETTEXT_LOCALES_PATH)/$(GETTEXT_DOMAIN).pot"
433493

434494
PHONY: lingua
@@ -440,13 +500,17 @@ lingua-dirty:
440500

441501
.PHONY: lingua-clean
442502
lingua-clean: lingua-dirty
443-
@test -e $(MXENV_PATH)pip && $(MXENV_PATH)pip uninstall -y \
503+
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y \
444504
chameleon lingua $(LINGUA_PLUGINS) || :
445505

446506
INSTALL_TARGETS+=$(LINGUA_TARGET)
447507
DIRTY_TARGETS+=lingua-dirty
448508
CLEAN_TARGETS+=lingua-clean
449509

510+
##############################################################################
511+
# Custom includes
512+
##############################################################################
513+
450514
-include $(INCLUDE_MAKEFILE)
451515

452516
##############################################################################

0 commit comments

Comments
 (0)