diff --git a/i18n/si/msgs.jaml b/i18n/si/msgs.jaml index ff037cc6..ff13f181 100644 --- a/i18n/si/msgs.jaml +++ b/i18n/si/msgs.jaml @@ -2436,7 +2436,6 @@ help/manager.py: data: false URL: false DEVELOP_ROOT: false - .: false def `create_intersphinx_provider`: objects.inv: false Local doc root '%s' does not exist.: false @@ -3515,11 +3514,19 @@ utils/pkgmeta.py: parse_meta: false get_dist_meta: false get_distribution: false + develop_root: false + get_dist_url: false def `normalize_name`: [-_.]+: false -: false _: false - def `is_develop_egg`: + def `_direct_url`: + direct_url.json: false + def `develop_root`: + dir_info: false + editable: false + url: false + file: false {normalize_name(dist.name)}.egg-info/: false setup.py: false def `trim`: diff --git a/orangecanvas/help/manager.py b/orangecanvas/help/manager.py index 7db9227a..a0d80bd7 100644 --- a/orangecanvas/help/manager.py +++ b/orangecanvas/help/manager.py @@ -15,7 +15,7 @@ from AnyQt.QtCore import QObject, QUrl, QDir -from ..utils.pkgmeta import get_dist_url, is_develop_egg, get_distribution +from ..utils.pkgmeta import get_dist_url, get_distribution, develop_root from . import provider if typing.TYPE_CHECKING: @@ -154,8 +154,8 @@ def _replacements_for_dist(dist): except KeyError: pass - if is_develop_egg(dist): - replacements["DEVELOP_ROOT"] = str(dist.locate_file(".")) + if develop_root(dist) is not None: + replacements["DEVELOP_ROOT"] = develop_root(dist) return replacements diff --git a/orangecanvas/utils/pkgmeta.py b/orangecanvas/utils/pkgmeta.py index e49e1d0f..c7f9dc34 100644 --- a/orangecanvas/utils/pkgmeta.py +++ b/orangecanvas/utils/pkgmeta.py @@ -1,8 +1,12 @@ +from __future__ import annotations import os import sys import re +import json import email from operator import itemgetter +from urllib.parse import urlparse +from urllib.request import url2pathname from typing import List, Dict, Optional, Union, cast import packaging.version @@ -16,7 +20,7 @@ __all__ = [ "Distribution", "EntryPoint", "entry_points", "normalize_name", "trim", "trim_leading_lines", "trim_trailing_lines", "parse_meta", "get_dist_meta", - "get_distribution" + "get_distribution", "develop_root", "get_dist_url" ] @@ -27,13 +31,43 @@ def normalize_name(name: str) -> str: return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_') -def is_develop_egg(dist: Distribution) -> bool: +def _direct_url(dist: Distribution) -> dict | None: """ - Is the distribution installed in development mode (setup.py develop) + Return PEP-0610 direct_url dict. """ + direct_url_content = dist.read_text("direct_url.json") + if direct_url_content: + try: + return json.loads(direct_url_content) + except (json.JSONDecodeError, UnicodeDecodeError): + return None + return None + + +def develop_root(dist: Distribution) -> str | None: + """ + Return the distribution's editable root path if applicable (pip install -e). + """ + direct_url = _direct_url(dist) + if direct_url is not None and direct_url.get("dir_info", {}).get("editable", False): + url = direct_url.get("url", None) + if url is not None: + url = urlparse(url) + if url.scheme == "file": + return url2pathname(url.path) + egg_info_dir = dist.locate_file(f"{normalize_name(dist.name)}.egg-info/") setup = dist.locate_file("setup.py") - return os.path.isdir(egg_info_dir) and os.path.isfile(setup) + if os.path.isdir(egg_info_dir) and os.path.isfile(setup): + return os.path.dirname(setup) + return None + + +def is_develop_egg(dist: Distribution) -> bool: + """ + Is the distribution installed in development mode (setup.py develop) + """ + return develop_root(dist) is not None def left_trim_lines(lines: List[str]) -> List[str]: diff --git a/orangecanvas/utils/tests/test_pkgmeta.py b/orangecanvas/utils/tests/test_pkgmeta.py index 52610150..65bbccf3 100644 --- a/orangecanvas/utils/tests/test_pkgmeta.py +++ b/orangecanvas/utils/tests/test_pkgmeta.py @@ -1,8 +1,9 @@ +import os from unittest import TestCase from orangecanvas.utils.pkgmeta import ( Distribution, normalize_name, is_develop_egg, get_dist_meta, parse_meta, - trim, + trim, develop_root, ) @@ -20,6 +21,20 @@ def test_is_develop_egg(self): else: is_develop_egg(d) + def test_develop_root(self): + d = Distribution.from_name("AnyQt") + path = develop_root(d) + if path is not None: + self.assertTrue(os.path.isfile(d.locate_file("setup.py"))) + try: + d = Distribution.from_name("orange-canvas-core") + except Exception: + pass + else: + path = develop_root(d) + if path is not None: + self.assertTrue(os.path.isfile(d.locate_file("setup.py"))) + def test_get_dist_meta(self): d = Distribution.from_name("AnyQt") meta = get_dist_meta(d)