简体   繁体   中英

Python/Django: setuptools/flit entry_point module path not found?

I have a problem that I can't solve since days. I created a python module "medux_timetracker" packaged as GDAPS plugin, details below, using an entry point. But the entry point is not recognized - and I'm stuck. The module is installed using flit install --symlink. from within the medux-timetracker directory, using the venv of the main project.

pyproject.toml

[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"

[project]
name = "medux_timetracker"
# ...

[tool.flit.module]
name="medux.plugins.timetracker:apps.TimeTrackerConfig"
# medux.plugins are namespace modules.

[project.entry-points."medux.plugins"]
timetracker = "medux.plugins.timetracker"

The class TimeTrackerConfig in this module is basically a Django app, inheriting AppConfig .

# settings.py

INSTALLED_APPS = [
# ...
]
INSTALLED_APPS += PluginManager.find_plugins("medux.plugins")

Here the installed apps are dynamically appended by the PluginManager's method which is this (the relevant part where GDAPS/Django loads the entry_point):

    @classmethod
    def find_plugins(cls, group: str) -> List[str]:
        """Finds plugins from setuptools entry points.

        This function is supposed to be called in settings.py after the
        INSTALLED_APPS variable....

        :param group: a dotted path where to find plugin apps. This is used as
            'group' for setuptools' entry points.
        :returns: A list of dotted app_names, which can be appended to
            INSTALLED_APPS.
        """
        # ...

        cls.group = group # ="medux.plugins"
        installed_plugin_apps = []

        # here iter_entry_points returns nothing, so the for loop does never execute:
        for entry_point in iter_entry_points(group=group, name=None):  
            appname = entry_point.module_name 
            if entry_point.attrs:
                appname += "." + ".".join(entry_point.attrs)

            installed_plugin_apps.append(appname)
            logger.info("Found plugin '{}'.".format(appname))

        return installed_plugin_apps

The error message when I start the Django server:

  File "/home/christian/Projekte/medux/.venv/lib/python3.10/site-packages/django/apps/config.py", line 193, in create
    import_module(entry)
  File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'medux.plugins.timetracker'

So, GDAPS finds the entry point from pyproject.toml , "medux.plugins.timetracker" is appended to INSTALLED_APPS correctly, but this module is not found. I suppose it's a PYTHONPATH problem, but can't find out why.

in the venv, under.../lib/python3.10/site-packages, I have:

medux/
  plugins/
    timetracker -> /home/christian/Projekte/medux-timetracker # symlink
medux_timetracker-0.0.1.dist-info/
  direct_url.json
  entry_points.txt
  INSTALLER
  METADATA
  RECORD
  REQUESTED

So the symlink to the package is there. I don't know further.

AAARGH.Why is it always the same? after searching for days, I post on stackoverflow, and one hour later I find the answer by accident.

So at least, if anyone reads this, maybe it helps to know how I solved it:

plugin package:

medux/
  plugins/
    timetracker/
      __init__.py
      apps.py
      ...

main package:

...
medux/
  __init__.py
  plugins/
  core/
  contrib/
  ...

So in the main package medux was a real package (no namespace package), and import medux.plugins would import the main packages module, overriding the plugins', and medux.plugins.timetracker was never found.

launching a python interpreter from another directory worked and brought me to the solution:

I just deleted the init .py in the main repo, hence making a namespace package of medux here too, and it worked at once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM