Skip to content

Commit dcdaa00

Browse files
authored
Merge branch 'main' into feature/hatch-vcs-versioning
2 parents a55933b + 4425500 commit dcdaa00

File tree

9 files changed

+242
-76
lines changed

9 files changed

+242
-76
lines changed

.github/workflows/variants.yml

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ jobs:
3030
run: |
3131
make VENV_ENABLED=true VENV_CREATE=true PRIMARY_PYTHON=python3 PYTHON_PACKAGE_INSTALLER=pip test
3232
make clean
33-
- name: VENV to be created with uv to be installed
33+
- name: VENV to be created with uv (local install, no global UV)
3434
run: |
35-
make VENV_ENABLED=true VENV_CREATE=true PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=python3 MXENV_UV_GLOBAL=false test
35+
make VENV_ENABLED=true VENV_CREATE=true PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=python3 test
3636
make clean
37-
- name: VENV to be created with uv globally pre-installed
37+
- name: VENV to be created with uv (global UV auto-detected)
3838
run: |
3939
pip install uv
40-
make VENV_ENABLED=true VENV_CREATE=true PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=${{ matrix.python-version }} MXENV_UV_GLOBAL=true test
40+
make VENV_ENABLED=true VENV_CREATE=true PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=${{ matrix.python-version }} test
4141
make clean
4242
pip uninstall -y uv
4343
- name: VENV pre-installed with pip
@@ -46,20 +46,26 @@ jobs:
4646
make VENV_ENABLED=true VENV_CREATE=false VENV_FOLDER=existingvenv PRIMARY_PYTHON=python3 PYTHON_PACKAGE_INSTALLER=pip test
4747
make clean
4848
rm -r existingvenv
49-
- name: VENV pre-installed with uv to be installed
49+
- name: VENV pre-installed with uv (local install, no global UV)
5050
run: |
5151
python -m venv existingvenv
52-
make VENV_ENABLED=true VENV_CREATE=false VENV_FOLDER=existingvenv PRIMARY_PYTHON=python3 PYTHON_PACKAGE_INSTALLER=uv MXENV_UV_GLOBAL=false test
52+
make VENV_ENABLED=true VENV_CREATE=false VENV_FOLDER=existingvenv PRIMARY_PYTHON=python3 PYTHON_PACKAGE_INSTALLER=uv test
5353
make clean
5454
rm -r existingvenv
55-
- name: VENV pre-installed with uv globally pre-installed
55+
- name: VENV pre-installed with uv (global UV auto-detected)
5656
run: |
5757
python -m venv existingvenv
5858
pip install uv
59-
make VENV_ENABLED=true VENV_CREATE=false VENV_FOLDER=existingvenv PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=python3 MXENV_UV_GLOBAL=true test
59+
make VENV_ENABLED=true VENV_CREATE=false VENV_FOLDER=existingvenv PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=python3 test
6060
make clean
6161
pip uninstall -y uv
6262
rm -r existingvenv
63+
- name: VENV with global UV using different UV_PYTHON
64+
run: |
65+
pip install uv
66+
make VENV_ENABLED=true VENV_CREATE=true PYTHON_PACKAGE_INSTALLER=uv PRIMARY_PYTHON=python3 UV_PYTHON=${{ matrix.python-version }} test
67+
make clean
68+
pip uninstall -y uv
6369
- name: Global Python with pip
6470
run: |
6571
make VENV_ENABLED=false VENV_CREATE=false PRIMARY_PYTHON=python3 PYTHON_PACKAGE_INSTALLER=pip test

CHANGES.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## 1.4.0 (unreleased)
3+
## 2.0.0 (unreleased)
44

55
- **Breaking**: Drop Python 3.9 support. Minimum Python version is now 3.10.
66
- Feature: Modernize codebase to use Python 3.10+ features (PEP 604 union types, built-in generic types).
@@ -11,7 +11,25 @@
1111
- Fix: theme for newer Sphinx 7.x.
1212
- Fix: interactive uv venv, use --allow-existing instead.
1313
- Feature: Add support for Python 3.14.
14-
- Feature: Add `docs-linkcheck` to check for broken links in the sphinx documentation.
14+
- Breaking: Removed `MXENV_UV_GLOBAL` setting in favor of automatic UV detection.
15+
When `PYTHON_PACKAGE_INSTALLER=uv`, mxmake now automatically detects and uses
16+
a globally installed `uv` if available. To force local installation of uv,
17+
simply don't install it globally or remove it from PATH.
18+
- Feature: Add `UV_PYTHON` setting to specify Python version for UV-managed virtual
19+
environments. Defaults to `PRIMARY_PYTHON` for backward compatibility. This
20+
provides semantic clarity: `PRIMARY_PYTHON` is the system interpreter path
21+
(e.g., `python3.11`), while `UV_PYTHON` is the version spec for UV
22+
(e.g., `3.14`, `cpython@3.14`).
23+
- Feature: Automatic detection of global UV installation using simple shell check.
24+
No manual configuration required.
25+
- Feature: All UV commands now run with `--quiet --no-progress` flags for better
26+
CI/CD compatibility and cleaner log output.
27+
- Feature: When using global UV, mxmake checks if updates are available using
28+
`uv self update --dry-run` and displays a helpful non-blocking warning if a
29+
newer version is available.
30+
- Improvement: Simplified mxenv.mk logic from 3+ nesting levels to 1-2 levels
31+
using computed intermediate variables (`USE_GLOBAL_UV`, `USE_LOCAL_UV`).
32+
Code is now more maintainable and easier to extend.
1533
- Chore: Migrate to hatch-vcs for automated versioning from git tags.
1634

1735
## 1.3.0 (2025-09-03)

Makefile

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,19 @@ PRIMARY_PYTHON?=3.14
5757
PYTHON_MIN_VERSION?=3.9
5858

5959
# Install packages using the given package installer method.
60-
# Supported are `pip` and `uv`. If uv is used, its global availability is
61-
# checked. Otherwise, it is installed, either in the virtual environment or
62-
# using the `PRIMARY_PYTHON`, dependent on the `VENV_ENABLED` setting. If
63-
# `VENV_ENABLED` and uv is selected, uv is used to create the virtual
64-
# environment.
60+
# Supported are `pip` and `uv`. When `uv` is selected, a global installation
61+
# is auto-detected and used if available. Otherwise, uv is installed in the
62+
# virtual environment or using `PRIMARY_PYTHON`, depending on the
63+
# `VENV_ENABLED` setting.
6564
# Default: pip
6665
PYTHON_PACKAGE_INSTALLER?=uv
6766

68-
# Flag whether to use a global installed 'uv' or install
69-
# it in the virtual environment.
70-
# Default: false
71-
MXENV_UV_GLOBAL?=true
67+
# Python version for UV to install/use when creating virtual
68+
# environments with global UV. Passed to `uv venv -p VALUE`. Supports version
69+
# specs like `3.11`, `3.14`, `cpython@3.14`. Defaults to PRIMARY_PYTHON value
70+
# for backward compatibility.
71+
# Default: $(PRIMARY_PYTHON)
72+
UV_PYTHON?=$(PRIMARY_PYTHON)
7273

7374
# Flag whether to use virtual environment. If `false`, the
7475
# interpreter according to `PRIMARY_PYTHON` found in `PATH` is used.
@@ -233,30 +234,57 @@ else
233234
MXENV_PYTHON=$(PRIMARY_PYTHON)
234235
endif
235236

236-
# Determine the package installer
237+
# Determine the package installer with non-interactive flags
237238
ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv")
238-
PYTHON_PACKAGE_COMMAND=uv pip
239+
PYTHON_PACKAGE_COMMAND=uv pip --quiet --no-progress
239240
else
240241
PYTHON_PACKAGE_COMMAND=$(MXENV_PYTHON) -m pip
241242
endif
242243

244+
# Auto-detect global uv availability (simple existence check)
245+
ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv")
246+
UV_AVAILABLE:=$(shell command -v uv >/dev/null 2>&1 && echo "true" || echo "false")
247+
else
248+
UV_AVAILABLE:=false
249+
endif
250+
251+
# Determine installation strategy
252+
USE_GLOBAL_UV:=$(shell [[ "$(PYTHON_PACKAGE_INSTALLER)" == "uv" && "$(UV_AVAILABLE)" == "true" ]] && echo "true" || echo "false")
253+
USE_LOCAL_UV:=$(shell [[ "$(PYTHON_PACKAGE_INSTALLER)" == "uv" && "$(UV_AVAILABLE)" == "false" ]] && echo "true" || echo "false")
254+
255+
# Check if global UV is outdated (non-blocking warning)
256+
ifeq ("$(USE_GLOBAL_UV)","true")
257+
UV_OUTDATED:=$(shell uv self update --dry-run 2>&1 | grep -q "Would update" && echo "true" || echo "false")
258+
else
259+
UV_OUTDATED:=false
260+
endif
261+
243262
MXENV_TARGET:=$(SENTINEL_FOLDER)/mxenv.sentinel
244263
$(MXENV_TARGET): $(SENTINEL)
245-
ifneq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvfalse")
264+
# Validation: Check Python version if not using global uv
265+
ifneq ("$(USE_GLOBAL_UV)","true")
246266
@$(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)" \
247267
&& echo "Need Python >= $(PYTHON_MIN_VERSION)" && exit 1 || :
248268
else
249-
@echo "Use Python $(PYTHON_MIN_VERSION) over uv"
269+
@echo "Using global uv for Python $(UV_PYTHON)"
250270
endif
271+
# Validation: Check VENV_FOLDER is set if venv enabled
251272
@[[ "$(VENV_ENABLED)" == "true" && "$(VENV_FOLDER)" == "" ]] \
252273
&& echo "VENV_FOLDER must be configured if VENV_ENABLED is true" && exit 1 || :
253-
@[[ "$(VENV_ENABLED)$(PYTHON_PACKAGE_INSTALLER)" == "falseuv" ]] \
274+
# Validation: Check uv not used with system Python
275+
@[[ "$(VENV_ENABLED)" == "false" && "$(PYTHON_PACKAGE_INSTALLER)" == "uv" ]] \
254276
&& echo "Package installer uv does not work with a global Python interpreter." && exit 1 || :
277+
# Warning: Notify if global UV is outdated
278+
ifeq ("$(UV_OUTDATED)","true")
279+
@echo "WARNING: A newer version of uv is available. Run 'uv self update' to upgrade."
280+
endif
281+
282+
# Create virtual environment
255283
ifeq ("$(VENV_ENABLED)", "true")
256284
ifeq ("$(VENV_CREATE)", "true")
257-
ifeq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvtrue")
258-
@echo "Setup Python Virtual Environment using package 'uv' at '$(VENV_FOLDER)'"
259-
@uv venv -p $(PRIMARY_PYTHON) --seed $(VENV_FOLDER)
285+
ifeq ("$(USE_GLOBAL_UV)","true")
286+
@echo "Setup Python Virtual Environment using global uv at '$(VENV_FOLDER)'"
287+
@uv venv --quiet --no-progress -p $(UV_PYTHON) --seed $(VENV_FOLDER)
260288
else
261289
@echo "Setup Python Virtual Environment using module 'venv' at '$(VENV_FOLDER)'"
262290
@$(PRIMARY_PYTHON) -m venv $(VENV_FOLDER)
@@ -266,10 +294,14 @@ endif
266294
else
267295
@echo "Using system Python interpreter"
268296
endif
269-
ifeq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvfalse")
270-
@echo "Install uv"
297+
298+
# Install uv locally if needed
299+
ifeq ("$(USE_LOCAL_UV)","true")
300+
@echo "Install uv in virtual environment"
271301
@$(MXENV_PYTHON) -m pip install uv
272302
endif
303+
304+
# Install/upgrade core packages
273305
@$(PYTHON_PACKAGE_COMMAND) install -U pip setuptools wheel
274306
@echo "Install/Update MXStack Python packages"
275307
@$(PYTHON_PACKAGE_COMMAND) install -U $(MXDEV) $(MXMAKE)

docs/source/getting-started.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ For details read the chapter [on topics and it's domains](topics-and-domains).
6363
Do not add custom settings to settings section.
6464
They will be lost on next `mxmake init` respective `mxmake update` run.
6565

66+
### Python Package Installer
67+
68+
By default, mxmake uses `pip` as the package installer. You can switch to [UV](https://docs.astral.sh/uv/) by setting `PYTHON_PACKAGE_INSTALLER=uv` in the settings section.
69+
70+
When using UV, mxmake automatically detects if UV is installed globally or installs it locally in the virtual environment.
71+
72+
```{note}
73+
When using UV, you should explicitly set `UV_PYTHON` to specify which Python version UV should use. While `UV_PYTHON` currently defaults to `PRIMARY_PYTHON` for backward compatibility, this default may change in future versions. Set `UV_PYTHON` explicitly to avoid surprises.
74+
```
75+
76+
Example:
77+
```makefile
78+
PRIMARY_PYTHON?=python3
79+
PYTHON_PACKAGE_INSTALLER?=uv
80+
UV_PYTHON?=3.14
81+
```
82+
6683
## How to use on the Windows operating system
6784

6885
mxmake works excellent on Windows!

docs/source/preseeds.md

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ topics:
1515
core:
1616
# include domain mxenv
1717
mxenv:
18-
# set PYTHON_MIN_VERSION and PYTHON_PACKAGE_INSTALLER
19-
PYTHON_MIN_VERSION: 3.10
18+
# set PYTHON_MIN_VERSION, PYTHON_PACKAGE_INSTALLER and UV_PYTHON
19+
PYTHON_MIN_VERSION: 3.14
2020
PYTHON_PACKAGE_INSTALLER: uv
21+
UV_PYTHON: "3.14"
2122
qa:
2223
# include domains from qa topic but do not override default settings
2324
ruff:
@@ -36,6 +37,26 @@ Now initialize the project with the preseeds:
3637
$ mxmake init -p preseeds.yaml
3738
```
3839

40+
## UV Package Installer
41+
42+
When `PYTHON_PACKAGE_INSTALLER` is set to `uv`, mxmake automatically detects whether UV is installed globally on your system.
43+
44+
```{important}
45+
When using UV, you should explicitly set `UV_PYTHON` to specify which Python version UV should use. While `UV_PYTHON` currently defaults to `PRIMARY_PYTHON` for backward compatibility, relying on this default is not recommended and may change in future versions.
46+
```
47+
48+
The `UV_PYTHON` setting accepts version specs like `3.13`, `3.14`, or `cpython@3.14`:
49+
50+
```yaml
51+
topics:
52+
core:
53+
mxenv:
54+
PYTHON_MIN_VERSION: "3.14"
55+
PRIMARY_PYTHON: python3
56+
PYTHON_PACKAGE_INSTALLER: uv
57+
UV_PYTHON: "3.14" # Explicitly specify Python version for UV
58+
```
59+
3960
## Examples
4061
4162
### Create a simple Python project
@@ -56,9 +77,9 @@ Enter the `hello-world-` directory and create a file `preseed.yaml`:
5677
topics:
5778
core:
5879
mxenv:
59-
PYTHON_MIN_VERSION: "3.10"
80+
PYTHON_MIN_VERSION: "3.14"
6081
PYTHON_PACKAGE_INSTALLER: uv
61-
MXENV_UV_GLOBAL: true
82+
UV_PYTHON: "3.14"
6283
sources:
6384
qa:
6485
ruff
@@ -103,9 +124,9 @@ topics:
103124
base:
104125
RUN_TARGET: zope-start
105126
mxenv:
106-
PYTHON_MIN_VERSION: "3.10"
127+
PYTHON_MIN_VERSION: "3.13"
107128
PYTHON_PACKAGE_INSTALLER: uv
108-
MXENV_UV_GLOBAL: true
129+
UV_PYTHON: "3.13"
109130
applications:
110131
zope:
111132
plone:

0 commit comments

Comments
 (0)