diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e71fb7ab..aee8b302 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,10 +4,10 @@ "name": "pygls", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile "build": { - "dockerfile": "Dockerfile" + "dockerfile": "Dockerfile" }, "containerEnv": { - "TZ": "UTC" + "TZ": "UTC" }, // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, @@ -17,13 +17,12 @@ // "postCreateCommand": "uname -a", // Configure tool-specific properties. "customizations": { - "vscode": { - "extensions": [ - "charliermarsh.ruff", - "ms-python.python", - ] - } - + "vscode": { + "extensions": [ + "charliermarsh.ruff", + "ms-python.python" + ] + } } // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" diff --git a/.devcontainer/tools.mk b/.devcontainer/tools.mk index 8de2aeac..4134793a 100644 --- a/.devcontainer/tools.mk +++ b/.devcontainer/tools.mk @@ -5,8 +5,8 @@ ifeq ($(strip $(ARCH)),) $(error Unable to determine platform architecture) endif -NODE_VERSION := 20.19.2 -UV_VERSION := 0.7.9 +NODE_VERSION := 20.19.3 +UV_VERSION := 0.7.16 UV ?= $(shell command -v uv) UVX ?= $(shell command -v uvx) @@ -31,64 +31,6 @@ $(UV): endif -# The versions of Python we support -PYXX_versions := 3.10 3.11 3.12 3.13 3.14 - -# Our default Python version -PY_VERSION := 3.13 - -# This effectively defines a function `PYXX` that takes a Python version number -# (e.g. 3.8) and expands it out into a common block of code that will ensure a -# verison of that interpreter is available to be used. -# -# This is perhaps a bit more complicated than I'd like, but it should mean that -# the project's makefiles are useful both inside and outside of a devcontainer. -# -# `PYXX` has the following behavior: -# - If possible, it will reuse the user's existing version of Python -# i.e. $(shell command -v pythonX.X) -# -# - The user may force a specific interpreter to be used by setting the -# variable when running make e.g. PYXX=/path/to/pythonX.X make ... -# -# - Otherwise, `make` will use `$(UV)` to install the given version of -# Python under `$(BIN)` -# -# See: https://www.gnu.org/software/make/manual/html_node/Eval-Function.html -define PYXX = - -PY$(subst .,,$1) ?= $$(shell command -v python$1) - -ifeq ($$(strip $$(PY$(subst .,,$1))),) - -PY$(subst .,,$1) := $$(BIN)/python$1 - -$$(PY$(subst .,,$1)): | $$(UV) - $$(UV) python find $1 || $$(UV) python install $1 - ln -s $$$$($$(UV) python find $1) $$@ - - $$@ --version - -endif - -endef - -# Uncomment the following line to see what this expands into. -#$(foreach version,$(PYXX_versions),$(info $(call PYXX,$(version)))) -$(foreach version,$(PYXX_versions),$(eval $(call PYXX,$(version)))) - -# Set a default `python` command if there is not one already -PY ?= $(shell command -v python) - -ifeq ($(strip $(PY)),) -PY := $(BIN)/python - -$(PY): | $(UV) - $(UV) python install $(PY_VERSION) - ln -s $$($(UV) python find $(PY_VERSION)) $@ - $@ --version -endif - # Node JS NPM ?= $(shell command -v npm) NPX ?= $(shell command -v npx) @@ -121,5 +63,5 @@ endif # One command to bootstrap all tools and check their versions .PHONY: tools -tools: $(UV) $(PY) $(NPM) $(NPX) +tools: $(UV) $(NPM) $(NPX) for prog in $^ ; do echo -n "$${prog}\t" ; PATH=$(BIN) $${prog} --version; done diff --git a/Makefile b/Makefile index 2aa95085..56b01738 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +PY ?= 3.13 + .PHONY: dist dist: | $(UV) git describe --tags --abbrev=0 @@ -9,17 +11,16 @@ lint: | $(UV) .PHONY: test test: | $(UV) - $(UV) run --all-extras poe test + $(UV) run --managed-python --python $(PY) --group test --all-extras poe test .PHONY: test-pyodide test-pyodide: dist | $(NPM) $(UV) - $(UV) sync --group test cd tests/pyodide && $(NPM) ci - $(UV) run poe test-pyodide + $(UV) run --managed-python --python $(PY) --group test poe test-pyodide .PHONY: pygls-playground pygls-playground: | $(NPM) $(UV) - $(UV) sync --all-extras + $(UV) sync --managed-python --python $(PY) --all-extras cd .vscode/extensions/pygls-playground && $(NPM) install --no-save cd .vscode/extensions/pygls-playground && $(NPM) run compile diff --git a/pyproject.toml b/pyproject.toml index 318c7f7d..0dc5f50f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,9 @@ docs = [ [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" +markers = [ + "e2e: tests that run a language server in a subprocess", +] [tool.poe.tasks] test-pyodide = "pytest tests/e2e --lsp-runtime pyodide" diff --git a/tests/conftest.py b/tests/conftest.py index 40b7ae42..32f956d1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -111,6 +111,26 @@ def pytest_addoption(parser): ) +def pytest_collection_modifyitems(items): + """Re-order tests so that end-to-end tests are run last. + + Idea taken from: + https://timonweb.com/django/optimizing-test-execution-running-live_server-tests-last-with-pytest + """ + e2e_tests = [] + other_tests = [] + + for item in items: + if "get_client_for" in getattr(item, "fixturenames", ()): + item.add_marker("e2e") + e2e_tests.append(item) + else: + other_tests.append(item) + + # Modify the items list to run end-to-end tests last + items[:] = other_tests + e2e_tests + + @pytest.fixture(scope="session") def runtime(request): """This fixture is the source of truth as to which environment we should run the @@ -131,7 +151,12 @@ def pytest_report_header(config: pytest.Config): runtime = config.getoption("lsp_runtime") transport = config.getoption("lsp_transport") - return [f"pygls: {runtime=}, {transport=}"] + try: + gil_enabled = "enabled" if sys._is_gil_enabled() else "disabled" + except AttributeError: + gil_enabled = "enabled" + + return [f"pygls: {runtime=}, {transport=}", f"GIL: {gil_enabled}"] @pytest.fixture(scope="session")