Skip to content

Handle deprecated pkg_resources

Wout De Nolf requested to merge release_orange_version_limits into main

Proper fix for #32 (closed)

  • remove upper version bounds for orange-canvas-core and orange-widget-base
  • replace deprecated importlib.resources.path usage with importlib.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 static ewokstest module in orangecontrib which is not visible by default but is enabled in a pytest fixture or when doing ewoks-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 handle pkg_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 and Orange3 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.

Edited by Wout De Nolf

Merge request reports

Loading