nocarryr/python-dispatch

python-dispatch has an implicit dependency on setuptools

enku opened this issue · 4 comments

enku commented

From line 6 of the main module pkg_resources is imported. pkg_resources is a module provided by the setuptools package. However it's not an explicit dependency defined in the package.

I have a Python package/project that uses pdm for the frontend (and backend) so doesn't automatically install setuptools. So I get a ModuleNotFoundError: No module named 'pkg_resources' when importing pydispatch.

So I think what can be done is either to explicitely depend on setuptools or to use the importlib.metadata library available in newer (3.8+) versions of Python for example (untested).

diff --git a/pydispatch/__init__.py b/pydispatch/__init__.py
index 14d017e..54e5b19 100644
--- a/pydispatch/__init__.py
+++ b/pydispatch/__init__.py
@@ -1,9 +1,9 @@
 import sys
 import warnings
-import pkg_resources
+import importlib.metadata
 
 try:
-    __version__ = pkg_resources.require('python-dispatch')[0].version
+    __version__ = importlib.metadata.version("python-dispatch")
 except: # pragma: no cover
     __version__ = 'unknown'

However importlib.metadata is not available for Python 3.6 and 3.7 however.

This is something I've been meaning to address.

Despite the amount of work and forward thinking going towards the Python packaging landscape though it always seems unclear which methods one can rely on when wanting to maintain forward and backward compatibility though. A conundrum indeed.

I've been wanting to switch to importlib.metadata but hit the same wall. Seems there's a backport for it though, but again (surprise!) that adds another dependency.

I'd be happy to accept a magic PR that covers all the bases with a simple one or two lines lol. Doesn't seem like that's possible these days.

Honestly didn't consider cases where setuptools is unavailable, but this lib is supposed to be dead simple, so I'll think on it .

edit

Would switching to a proper pyproject.toml with a setuptools dependency work in your scenario?

enku commented

Explicitly depending on setuptools would work (for me), since it already implicitly depends on it I don't see that as another dependency, rather it's just being explicit. Also I don't think you need to switch to pypproject.toml to do that, though that's where most things seem to be going these days. You should be able to get away with adding a dependencies = ["setuptools>=blahblahblah"] to setup.cfg.

As an alternative, switching to importlib.metadata is actually removing a (implicit dependency). The caveat being that it's only supported by Python 3.8+. However 3.7 is approaching end of life . I actually thought it was the end of 2022 at some point, but perhaps they changed it. Now it's the middle of 2023. One could drop support for 3.7 (in the near or distant) in the next "major") release which would alleviate the need to depend on setuptools.

Another variation of the above is to only depend on setuptools for python<3.8, but then there'd have to be some wrapper around whether setuptools is being used or not, which would likely be more than one or two lines.

@enku thanks for catching the issue.

I decided to switch to importlib.metadata and require the importlib_metadata backport for Python < 3.8.

Interestingly, I'd already run into and fixed the same issue with the sphinx plugin (pydispatch_sphinx) within this same repo 🤦

enku commented

@enku thanks for catching the issue.

I decided to switch to importlib.metadata and require the importlib_metadata backport for Python < 3.8.

Cool, that sounds like a good middle ground! And thanks a lot for the quick turn-around, too.