Skip to content

Commit

Permalink
addons: Make sure to iterate over valid entry points
Browse files Browse the repository at this point in the history
I.e. cast pkg_resources.EntryPoint to corresponding
importlib.metadata.EntryPoint because the source of these are from
downstream clients which might still construct them.
  • Loading branch information
ales-erjavec committed Nov 3, 2023
1 parent 02a4aa8 commit 904fdea
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 7 deletions.
7 changes: 3 additions & 4 deletions orangecanvas/application/addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,7 @@ def start(self, config):
self.__config = config

if self.__packages is not None:
# method_queued(self.setItems, (object,))(self.__packages)
installed = [ep.dist for ep in config.addon_entry_points()
installed = [ep.dist for ep in config._ensure_valid_entry_points()
if ep.dist is not None]
items = installable_items(self.__packages, installed)
self.setItems(items)
Expand Down Expand Up @@ -548,7 +547,7 @@ def network_warning(exc):
network_warning(exc[0])
assert all(isinstance(p, Installable) for p in packages)
AddonManagerDialog.__packages = packages
installed = [ep.dist for ep in config.addon_entry_points()
installed = [ep.dist for ep in config._ensure_valid_entry_points()
if ep.dist is not None]
items = installable_items(packages, installed)
core_constraints = {
Expand Down Expand Up @@ -675,7 +674,7 @@ def addInstallable(self, installable):
installable: Installable
"""
items = self.items()
installed = [ep.dist for ep in self.config().addon_entry_points()]
installed = [ep.dist for ep in self.config()._ensure_valid_entry_points()]
new_ = installable_items([installable], filter(None, installed))

def match(item):
Expand Down
2 changes: 1 addition & 1 deletion orangecanvas/application/utils/addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def getname(item):

# query pypi.org for installed add-ons that are not in the defaults
# list
installed = [ep.dist for ep in config.addon_entry_points()
installed = [ep.dist for ep in config._ensure_valid_entry_points()
if ep.dist is not None]
missing = {dist.name.casefold() for dist in installed} - \
{name.casefold() for name in defaults_names}
Expand Down
7 changes: 6 additions & 1 deletion orangecanvas/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
from .gui.utils import windows_set_current_process_app_user_model_id
from .gui.svgiconengine import SvgIconEngine
from .utils.settings import Settings, config_slot
from .utils.pkgmeta import EntryPoint, Distribution, entry_points
from .utils.pkgmeta import (
EntryPoint, Distribution, entry_points, ensure_valid_entry_point
)

if typing.TYPE_CHECKING:
import requests
Expand Down Expand Up @@ -135,6 +137,9 @@ def addon_entry_points(self):
# type: () -> Iterable[EntryPoint]
return iter(())

def _ensure_valid_entry_points(self):
return map(ensure_valid_entry_point, self.addon_entry_points())

def addon_pypi_search_spec(self):
return {}

Expand Down
26 changes: 25 additions & 1 deletion orangecanvas/utils/pkgmeta.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@

__all__ = [
"Distribution", "EntryPoint", "entry_points", "normalize_name", "trim",
"trim_leading_lines", "trim_trailing_lines", "get_distribution"
"trim_leading_lines", "trim_trailing_lines", "get_distribution",
"ensure_valid_entry_point"
]


Expand Down Expand Up @@ -140,3 +141,26 @@ def get_distribution(name: str) -> Optional[Distribution]:
return Distribution.from_name(name)
except PackageNotFoundError:
return None


def ensure_valid_entry_point(ep) -> EntryPoint:
if isinstance(ep, EntryPoint):
return ep
try:
# importlib_metadata.EntryPoint
group = ep.group
name = ep.name
value = ep.value
dist_name = ep.dist.name if ep.dist is not None else None
except AttributeError:
# pkg_resources.EntryPoint
group = "unknown" # does not record the group
name = ep.name
value = ep.module_name
if ep.attrs:
value += ":" + ".".join(ep.attrs)
dist_name = ep.dist.project_name if ep.dist is not None else None
dist = get_distribution(dist_name) if dist_name is not None else None
ep_ = EntryPoint(name, value, group)
vars(ep_).update(dist=dist) # EntryPoint is "immutable"
return ep_
27 changes: 27 additions & 0 deletions orangecanvas/utils/tests/test_pkgmeta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from types import SimpleNamespace
from unittest import TestCase

from ..pkgmeta import ensure_valid_entry_point, EntryPoint


class TestPkgmeta(TestCase):
def test_ensure_valid_entry_point(self):
ep = ensure_valid_entry_point(EntryPoint("a", "b", "c"))
self.assertIsInstance(ep, EntryPoint)
self.assertEqual(ep.name, "a")
self.assertEqual(ep.value, "b")
self.assertEqual(ep.group, "c")
ep = ensure_valid_entry_point(
SimpleNamespace(name="a", value="b", group="c", dist=None)
)
self.assertEqual(ep.name, "a")
self.assertEqual(ep.value, "b")
self.assertEqual(ep.group, "c")

try:
from pkg_resources import EntryPoint as PREntryPoint
except ImportError:
return
ep = ensure_valid_entry_point(PREntryPoint("a", "b"))
self.assertEqual(ep.name, "a")
self.assertEqual(ep.value, "b")

0 comments on commit 904fdea

Please sign in to comment.