diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 56f7d83..896e9d8 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -74,7 +74,7 @@ jobs: - run: | mk python-release owner=vkottler \ - repo=vmklib version=2.0.3 + repo=vmklib version=2.0.4 if: | matrix.python-version == '3.12' && matrix.system == 'ubuntu-latest' diff --git a/README.md b/README.md index fb0bfbb..fb7508c 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ ===================================== generator=datazen version=3.1.4 - hash=c9f109357706db34fbe6c3c4b3b9d9a2 + hash=43e9f25280d496418215c22cd0c49c7f ===================================== --> -# vmklib ([2.0.3](https://pypi.org/project/vmklib/)) +# vmklib ([2.0.4](https://pypi.org/project/vmklib/)) [![python](https://img.shields.io/pypi/pyversions/vmklib.svg)](https://pypi.org/project/vmklib/) ![Build Status](https://github.com/vkottler/vmklib/workflows/Python%20Package/badge.svg) diff --git a/local/variables/package.yaml b/local/variables/package.yaml index 7b343eb..d5ede4e 100644 --- a/local/variables/package.yaml +++ b/local/variables/package.yaml @@ -1,5 +1,5 @@ --- major: 2 minor: 0 -patch: 3 +patch: 4 entry: mk diff --git a/pyproject.toml b/pyproject.toml index af606d2..125b736 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__" [project] name = "vmklib" -version = "2.0.3" +version = "2.0.4" description = "Simplify project workflows by standardizing use of GNU Make." readme = "README.md" requires-python = ">=3.10" diff --git a/tests/__init__.py b/tests/__init__.py index d26e15b..9037516 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -4,14 +4,11 @@ # built-in from contextlib import contextmanager -import os +from pathlib import Path from shutil import rmtree import tempfile from typing import Iterator, List -# third-party -import pkg_resources - # module under test from vmklib import PKG_NAME @@ -30,9 +27,7 @@ def get_args() -> Iterator[List[str]]: def get_resource(resource_name: str) -> str: """Locate the path to a test resource.""" - - resource_path = os.path.join("data", resource_name) - return pkg_resources.resource_filename(__name__, resource_path) + return str(Path(__file__).parent.joinpath("data", resource_name)) @contextmanager @@ -42,19 +37,21 @@ def build_cleaned_resource(resource_name: str) -> Iterator[str]: is cleaned up before and after providing it. """ - path = get_resource(resource_name) + path = Path(get_resource(resource_name)) # Try our best to clean up virtual environments. - to_clean = ["build", "venv"] + [ - f"venv3.{x}" for x in [6, 7, 8, 9, 10, 11, 12] - ] + to_clean = ["build", "venv"] + [f"venv3.{x}" for x in range(6, 6 + 20)] for clean in to_clean: - clean_path = os.path.join(path, clean) + clean_path = path.joinpath(clean) rmtree(clean_path, ignore_errors=True) + if clean_path.is_file(): + clean_path.unlink() - yield path + yield str(path) for clean in to_clean: - clean_path = os.path.join(path, clean) + clean_path = path.joinpath(clean) rmtree(clean_path, ignore_errors=True) + if clean_path.is_file(): + clean_path.unlink() diff --git a/tests/test_entry.py b/tests/test_entry.py index 364f97d..43d8886 100644 --- a/tests/test_entry.py +++ b/tests/test_entry.py @@ -113,6 +113,8 @@ def target_tests( def test_entry_python_tasks(): """Ensure that we can run Python-based tasks.""" + scenario = "python-tasks" + passes = [ ( "python-lint python-sa" @@ -124,11 +126,9 @@ def test_entry_python_tasks(): "python-test-add", "dz-sync", ] - fails = ["python-deps", "python-editable"] + fails = ["python-deps", "python-editable", f"python-install-{scenario}"] - with target_tests( - "python-tasks", passes, fails, {"python-deps", "python-editable"} - ) as test_dir: + with target_tests(scenario, passes, fails, set(fails)) as test_dir: for _ in range(2): assert mk_main([PKG_NAME, "-C", test_dir, "-d", "venv"]) == 0 diff --git a/vmklib/__init__.py b/vmklib/__init__.py index f020895..2633837 100644 --- a/vmklib/__init__.py +++ b/vmklib/__init__.py @@ -1,7 +1,7 @@ # ===================================== # generator=datazen # version=3.1.4 -# hash=a5d53b6399d66ef76c6e395d072c6018 +# hash=54451b981a0a3faef0b7641dd6877695 # ===================================== """ @@ -10,4 +10,4 @@ DESCRIPTION = "Simplify project workflows by standardizing use of GNU Make." PKG_NAME = "vmklib" -VERSION = "2.0.3" +VERSION = "2.0.4" diff --git a/vmklib/app.py b/vmklib/app.py index c26ae47..07146ab 100644 --- a/vmklib/app.py +++ b/vmklib/app.py @@ -24,6 +24,7 @@ # internal from vmklib import PKG_NAME +from vmklib.util import to_slug LOG = logging.getLogger(__name__) DEFAULT_FILE = Path("Makefile") @@ -36,7 +37,7 @@ def project(path: Path, name: str = None) -> str: """ path = path.resolve() if name is None: - parent_slug = path.name.replace("-", "_") + parent_slug = to_slug(path.name) if path.joinpath(parent_slug).is_dir(): name = parent_slug else: diff --git a/vmklib/tasks/python/package.py b/vmklib/tasks/python/package.py index ab64f92..c5e23cd 100644 --- a/vmklib/tasks/python/package.py +++ b/vmklib/tasks/python/package.py @@ -14,6 +14,7 @@ # internal from vmklib.tasks.mixins.concrete import ConcreteOnceMixin from vmklib.tasks.python import PREFIX +from vmklib.util import to_slug class PythonPackage(ConcreteOnceMixin, SubprocessLogMixin): @@ -24,11 +25,22 @@ class PythonPackage(ConcreteOnceMixin, SubprocessLogMixin): async def run(self, inbox: Inbox, outbox: Outbox, *args, **kwargs) -> bool: """Create or update a project's virtual environment.""" + install_args = [*args] + + to_install = kwargs["package"] + project = kwargs.get("project") + + # Perform an editable install if we're the install target. + if project and to_slug(project) == to_slug(to_install): + install_args.append("-e") + to_install = "." + + install_args.append(to_install) + return await self.exec( str(inbox["venv"]["venv{python_version}"]["pip"]), "install", - *args, - kwargs["package"], + *install_args, ) @@ -40,19 +52,24 @@ def register( ) -> bool: """Register Python package tasks to the manager.""" - del project del cwd del substitutions # A target that installs a package. manager.register( - PythonPackage("python{python_version}-install-{package}"), [] + PythonPackage( + "python{python_version}-install-{package}", project=project + ), + [], ) # A target that attempts to upgrade a package. manager.register( PythonPackage( - "python{python_version}-upgrade-{package}", "--upgrade", once=False + "python{python_version}-upgrade-{package}", + "--upgrade", + once=False, + project=project, ), [], ) diff --git a/vmklib/util.py b/vmklib/util.py new file mode 100644 index 0000000..08dcd19 --- /dev/null +++ b/vmklib/util.py @@ -0,0 +1,8 @@ +""" +An interface exposing miscellaneous utilities. +""" + + +def to_slug(data: str) -> str: + """Convert a string to an import slug.""" + return data.replace("-", "_")