diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 90f8ce6..257a56c 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -13,7 +13,7 @@ jobs: - run: apk add git - run: sh bin/ci/check_versions.sh - run: uv run isort --check homely test - - run: uv run pytest test + - run: uv run pytest -W error test Mypy: runs-on: ubuntu-latest # only run on oldest supported python version diff --git a/homely/_test/system.py b/homely/_test/system.py index 7e5a116..70737d9 100644 --- a/homely/_test/system.py +++ b/homely/_test/system.py @@ -123,7 +123,8 @@ def system(cmd, cwd=None, expecterror=False, tmpdir=None): print(open(stdoutpath).read()) raise - return open(stdoutpath, 'r').read() + with open(stdoutpath, 'r') as f: + return f.read() return system diff --git a/homely/_utils.py b/homely/_utils.py index e4c420f..00ff1c8 100644 --- a/homely/_utils.py +++ b/homely/_utils.py @@ -1,13 +1,14 @@ import contextlib +import importlib.util import json import os import re import shutil import subprocess +import sys import tempfile from datetime import timedelta from functools import partial -from importlib.machinery import SourceFileLoader from itertools import chain from os.path import exists, join from typing import Any, Optional, Union @@ -17,8 +18,28 @@ from homely._vcs import Repo, fromdict -def _loadmodule(name, path): - return SourceFileLoader(name, path).load_module() +def _loadmodule(name: str, file_path: str): + spec = importlib.util.spec_from_file_location(name, file_path) + if spec is None: + raise ImportError(f"Cannot find module spec for {name} at {file_path}") + if spec.loader is None: + raise Exception(f"No loader for module {name} at {file_path}") + + module = importlib.util.module_from_spec(spec) + + # Crucial step: Register the module in sys.modules *before* execution + # This prevents issues with relative imports within the module + sys.modules[name] = module + + # Execute the module's code in its own namespace + try: + spec.loader.exec_module(module) + except Exception: + # If execution fails, remove the module from sys.modules + del sys.modules[name] + raise + + return module # for python3, we open text files with universal newline support @@ -495,8 +516,10 @@ def filereplacer(filepath): stripped = firstline.rstrip('\r\n') NL = firstline[len(stripped):] assert NL in ("\r", "\n", "\r\n"), "Bad NL %r" % NL - origlines = chain([stripped], - (line.rstrip('\r\n') for line in orig)) + origlines = chain( + [stripped], + (line.rstrip('\r\n') for line in orig), + ) yield tmp, origlines, NL else: yield tmp, None, "\n" diff --git a/pyproject.toml b/pyproject.toml index cdc748c..95b0bb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ version = "0.20.3" dependencies = [ "python-daemon>=2.3.0", "requests>=2.25.1", - "click>=7.1.2", + "click>=8.3", # tomli is required before python 3.11 "tomli>=2.3.0 ; python_full_version < '3.11'", ] diff --git a/test/tests.Dockerfile b/test/tests.Dockerfile index 190a215..da4760b 100644 --- a/test/tests.Dockerfile +++ b/test/tests.Dockerfile @@ -19,4 +19,4 @@ RUN uv venv .venv && uv pip install -e . --group=dev COPY ./test ./test COPY ./homely ./homely -RUN .venv/bin/pytest test -x +RUN .venv/bin/pytest -W error test -x diff --git a/uv.lock b/uv.lock index 1fd41df..dd9fdd2 100644 --- a/uv.lock +++ b/uv.lock @@ -299,7 +299,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -356,7 +356,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "click", specifier = ">=7.1.2" }, + { name = "click", specifier = ">=8.3" }, { name = "python-daemon", specifier = ">=2.3.0" }, { name = "requests", specifier = ">=2.25.1" }, { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.3.0" },