From 1c3a76e7df72e288be02cde549d35963d200ab21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Ram=C3=ADrez=20Mondrag=C3=B3n?= <16805946+edgarrmondragon@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:08:24 -0600 Subject: [PATCH] feat: Add `is_editable` wrapper function (#37) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ---- 📚 Documentation preview 📚: https://pep610--37.org.readthedocs.build/en/37/ --- .readthedocs.yaml | 2 +- docs/index.md | 4 ++++ src/pep610/__init__.py | 27 +++++++++++++++++++++- tests/test_parse.py | 52 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1bd401d..fd319be 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -3,7 +3,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.11" + python: "3.12" jobs: post_checkout: - git fetch --unshallow || true diff --git a/docs/index.md b/docs/index.md index e78d758..d25f743 100644 --- a/docs/index.md +++ b/docs/index.md @@ -117,3 +117,7 @@ for package in report["install"]: ```{eval-rst} .. autofunction:: pep610.read_from_distribution ``` + +```{eval-rst} +.. autofunction:: pep610.is_editable +``` diff --git a/src/pep610/__init__.py b/src/pep610/__init__.py index dee0a35..2c4ea28 100644 --- a/src/pep610/__init__.py +++ b/src/pep610/__init__.py @@ -7,7 +7,7 @@ import typing as t from dataclasses import dataclass from functools import singledispatch -from importlib.metadata import version +from importlib.metadata import distribution, version if t.TYPE_CHECKING: import sys @@ -355,6 +355,11 @@ def read_from_distribution(dist: Distribution) -> VCSData | ArchiveData | DirDat Returns: The parsed PEP 610 file. + + >>> import importlib.metadata + >>> dist = importlib.metadata.distribution("pep610") + >>> read_from_distribution(dist) # doctest: +SKIP + DirData(url='file:///home/user/pep610', dir_info=DirInfo(editable=False)) """ if contents := dist.read_text("direct_url.json"): return parse(json.loads(contents)) @@ -362,6 +367,26 @@ def read_from_distribution(dist: Distribution) -> VCSData | ArchiveData | DirDat return None +def is_editable(distribution_name: str) -> bool: + """Wrapper around :func:`read_from_distribution` to check if a distribution is editable. + + Args: + distribution_name: The distribution name. + + Returns: + Whether the distribution is editable. + + Raises: + importlib_metadata.PackageNotFoundError: If the distribution is not found. + + >>> is_editable("pep610") # doctest: +SKIP + False + """ # noqa: DAR402, RUF100 + dist = distribution(distribution_name) + data = read_from_distribution(dist) + return isinstance(data, DirData) and data.dir_info.is_editable() + + def write_to_distribution(dist: PathDistribution, data: dict) -> int: """Write the direct URL data to a distribution. diff --git a/tests/test_parse.py b/tests/test_parse.py index 9096c68..1bc3df2 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -15,6 +15,7 @@ HashData, VCSData, VCSInfo, + is_editable, parse, read_from_distribution, to_dict, @@ -347,3 +348,54 @@ def test_parse_pip_install_report(pip_install_report: dict): ), ), } + + +@pytest.mark.parametrize( + ("data", "expected"), + [ + pytest.param( + { + "url": "file:///home/user/project", + "dir_info": {"editable": True}, + }, + True, + id="editable", + ), + pytest.param( + { + "url": "file:///home/user/project", + "dir_info": {"editable": False}, + }, + False, + id="not_editable", + ), + pytest.param( + { + "url": "file:///home/user/project", + "dir_info": {}, + }, + False, + id="no_editable_info", + ), + pytest.param( + { + "url": "https://github.com/pypa/pip.git", + "vcs_info": { + "vcs": "git", + "requested_revision": "1.3.1", + "resolved_revision_type": "tag", + "commit_id": "7921be1537eac1e97bc40179a57f0349c2aee67d", + }, + }, + False, + id="vcs_git", + ), + ], +) +def test_is_editable(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, data: dict, expected: bool): # noqa: FBT001 + """Test the is_editable function.""" + dist = Distribution.at(tmp_path) + write_to_distribution(dist, data) + + monkeypatch.setattr("pep610.distribution", lambda _: dist) + assert is_editable("my_package") is expected