2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00

Plugin meta detection improvements (#3516)

* refactor entrypoint into helpers

* Add lookup by metadata
This is geared towards plugins packaged in pkgs that differ in name from their top module

* Make module lookup predictable in changing pkg-envs
This commit is contained in:
Matthias Mair 2022-08-11 04:02:06 +02:00 committed by GitHub
parent 4ae3cf9a9c
commit 1010a6296f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 7 deletions

View File

@ -7,6 +7,9 @@ import pkgutil
import subprocess import subprocess
import sysconfig import sysconfig
import traceback import traceback
from importlib.metadata import (PackageNotFoundError, distributions,
entry_points)
from importlib.util import find_spec
from django import template from django import template
from django.conf import settings from django.conf import settings
@ -92,6 +95,11 @@ def handle_error(error, do_raise: bool = True, do_log: bool = True, log_name: st
if settings.TESTING_ENV and package_name != 'integration.broken_sample' and isinstance(error, IntegrityError): if settings.TESTING_ENV and package_name != 'integration.broken_sample' and isinstance(error, IntegrityError):
raise error # pragma: no cover raise error # pragma: no cover
raise IntegrationPluginError(package_name, str(error)) raise IntegrationPluginError(package_name, str(error))
def get_entrypoints():
"""Returns list for entrypoints for InvenTree plugins."""
return entry_points().get('inventree_plugins', [])
# endregion # endregion
@ -223,6 +231,34 @@ def get_plugins(pkg, baseclass, path=None):
plugins.append(plugin) plugins.append(plugin)
return plugins return plugins
def get_module_meta(mdl_name):
"""Return distribution for module.
Modified form source: https://stackoverflow.com/a/60975978/17860466
"""
# Get spec for module
spec = find_spec(mdl_name)
# Try to get specific package for the module
result = None
for dist in distributions():
try:
relative = pathlib.Path(spec.origin).relative_to(dist.locate_file(''))
except ValueError:
pass
else:
if relative in dist.files:
result = dist
# Check if a distribution was found
# A no should not be possible here as a call can only be made on a discovered module but better save then sorry
if not result:
raise PackageNotFoundError(mdl_name)
# Return metadata
return result.metadata
# endregion # endregion

View File

@ -6,7 +6,7 @@ import os
import pathlib import pathlib
import warnings import warnings
from datetime import datetime from datetime import datetime
from importlib.metadata import metadata from importlib.metadata import PackageNotFoundError, metadata
from django.conf import settings from django.conf import settings
from django.db.utils import OperationalError, ProgrammingError from django.db.utils import OperationalError, ProgrammingError
@ -14,7 +14,7 @@ from django.urls.base import reverse
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from plugin.helpers import GitStatus, get_git_log from plugin.helpers import GitStatus, get_git_log, get_module_meta
logger = logging.getLogger("inventree") logger = logging.getLogger("inventree")
@ -294,7 +294,13 @@ class InvenTreePlugin(MixinBase, MetaBase):
@classmethod @classmethod
def _get_package_metadata(cls): def _get_package_metadata(cls):
"""Get package metadata for plugin.""" """Get package metadata for plugin."""
meta = metadata(cls.__name__)
# Try simple metadata lookup
try:
meta = metadata(cls.__name__)
# Simpel lookup did not work - get data from module
except PackageNotFoundError:
meta = get_module_meta(cls.__module__)
return { return {
'author': meta['Author-email'], 'author': meta['Author-email'],

View File

@ -8,7 +8,7 @@ import importlib
import logging import logging
import os import os
import subprocess import subprocess
from importlib import metadata, reload from importlib import reload
from pathlib import Path from pathlib import Path
from typing import OrderedDict from typing import OrderedDict
@ -24,8 +24,8 @@ from maintenance_mode.core import (get_maintenance_mode, maintenance_mode_on,
from InvenTree.config import get_setting from InvenTree.config import get_setting
from .helpers import (IntegrationPluginError, get_plugins, handle_error, from .helpers import (IntegrationPluginError, get_entrypoints, get_plugins,
log_error) handle_error, log_error)
from .plugin import InvenTreePlugin from .plugin import InvenTreePlugin
logger = logging.getLogger('inventree') logger = logging.getLogger('inventree')
@ -266,7 +266,7 @@ class PluginsRegistry:
# Check if not running in testing mode and apps should be loaded from hooks # Check if not running in testing mode and apps should be loaded from hooks
if (not settings.PLUGIN_TESTING) or (settings.PLUGIN_TESTING and settings.PLUGIN_TESTING_SETUP): if (not settings.PLUGIN_TESTING) or (settings.PLUGIN_TESTING and settings.PLUGIN_TESTING_SETUP):
# Collect plugins from setup entry points # Collect plugins from setup entry points
for entry in metadata.entry_points().get('inventree_plugins', []): # pragma: no cover for entry in get_entrypoints(): # pragma: no cover
try: try:
plugin = entry.load() plugin = entry.load()
plugin.is_package = True plugin.is_package = True