Handle deprecated pkg_resources
Proper fix for #32 (closed)
- remove upper version bounds for
orange-canvas-core
andorange-widget-base
- replace deprecated
importlib.resources.path
usage withimportlib.resources.files
- replace deprecated
pkg_resources
usage (the two orange base projects did this as well, Orange3 itself too but not released yet) - without
pkg_resources
it is very hard to support runtime injection of Orange add-ons. Since we only used this for the tests, I replaced this with a staticewokstest
module inorangecontrib
which is not visible by default but is enabled in a pytest fixture or when doingewoks-canvas ... --with-examples
. - implicit orangecontrib namespace package (PEP 420). This can be done for all add-ons as well (est, ewoksxrpd, tomwer, darfix, ...)
-
widget_discovery
helper function for add-ons that want to handlepkg_resources
vs.importlib
as well -
Oasys
is pinning all kinds of old versions with lots of deprecation warnings. Not worth it so disable warning raising in CI. - ignore deprecation warnings in external dependencies (next releases of
silx
andOrange3
will fix those)
Some more details below:
Removing runtime injection of Orange add-ons
Without pkg_resources
it becomes too complicated to manage orange addons that are injected at runtime.
https://stackoverflow.com/questions/57126085/how-to-use-sys-meta-path-with-python-3-x
https://github.com/python/importlib_metadata/issues/427
I tried but failed and even if we could make it work, this is very hacky and would be a hell to maintain.
So I removed support for runtime injection of Orange add-ons and replace it by adding ewokstest
which by default has a widget_discovery
that does returns nothing so the category is not visible in the canvas.
TODO: Removing support for runtime injection of Orange add-ons gets rid of lots of tricky code so that's a good thing. However currently you see an error log when ewokstest
is not enabled (which is the default) when selecting a tutorial/example workflow on the canvas. It doesn't hurt but it looks bad. Not sure how to disable tutorials in another way than raising an exception. An alternative would be to hack the distribution object and remove tutorial/example entry points. We do not want the ewokstest
examples to show up when --with-examples
is not set.
2024-03-17 13:57:06,038:ERROR:orangecanvas.application.examples: Could not load examples from <importlib.metadata.PathDistribution object at 0x71240ffbded0>
Traceback (most recent call last):
File "/home/denolf/virtualenvs/ewoks/lib/python3.10/site-packages/orangecanvas/application/examples.py", line 53, in workflows
examples = ep.load()
File "/home/denolf/.pyenv/versions/3.10.13/lib/python3.10/importlib/metadata/__init__.py", line 171, in load
module = import_module(match.group('module'))
File "/home/denolf/.pyenv/versions/3.10.13/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 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/home/denolf/projects/ewoksorange/src/orangecontrib/ewokstest/tutorials/__init__.py", line 6, in <module>
raise RuntimeError("ewokstest is disabled")
RuntimeError: ewokstest is disabled
The code that captures and prints the error is in orange-canvas-core
def workflows(config=None):
# type: (Optional[_config.Config]) -> List[ExampleWorkflow]
"""
Return all known example workflows.
"""
if config is None:
config = _config.default
workflows = [] # type: List[ExampleWorkflow]
if hasattr(config, "tutorials_entry_points") and \
callable(config.tutorials_entry_points):
# back compatibility
examples_entry_points = config.tutorials_entry_points
else:
examples_entry_points = config.examples_entry_points
for ep in examples_entry_points():
try:
examples = ep.load()
except Exception:
log.error("Could not load examples from %r",
ep.dist, exc_info=True)
continue
widget_discovery
in ewoks apps
ewoksorange
provides a helper method which needs to be used in projects like est
, tomwer
and other packages in which we want to remove the usage of the deprecated pkg_resources
, depending on the orange version.
For example in est
this
def widget_discovery(discovery):
import pkg_resources
dist = pkg_resources.get_distribution("est")
pkgs = [
"orangecontrib.est.widgets.pymca",
"orangecontrib.est.widgets.larch",
"orangecontrib.est.widgets.utils",
]
for pkg in pkgs:
discovery.process_category_package(pkg, distribution=dist)
becomes this
# Entry point for main Orange categories/widgets discovery
def widget_discovery(discovery):
from ewoksorange.discovery import widget_discovery
modules = [
"orangecontrib.est.widgets.pymca",
"orangecontrib.est.widgets.larch",
"orangecontrib.est.widgets.utils",
]
widget_discovery(discovery, "est", modules)
orangecontrib
namespace package
This
# src/orangecontrib/__init__.py
__import__("pkg_resources").declare_namespace(__name__)
together with this
# setup.cfg
[options]
packages=find:
namespace_packages =
orangecontrib
is deprecated (see setuptools docs). It can be replaced by implicit namespace packages (as specified in PEP 420).
# setup.cfg
[options]
packages=find_namespace:
In addition src/orangecontrib/__init__.py
is removed.
The same thing could be done for all orange add-ons.