Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage of scikit-surprise as a dynamic dependency is not possible #443

Open
SaschaAtOmina opened this issue Oct 24, 2022 · 1 comment
Open

Comments

@SaschaAtOmina
Copy link

Description

I need to be able to dynamically add/remove scikit-surprise (installed in advance somewhere else than in my venv) to/from my PATH to perform some processing. This cannot be done because of the __version_ variable defined here https://github.com/NicolasHug/Surprise/blob/master/surprise/__init__.py#L50
The pkg_resource does not play well with non-standard PATH apparently. The only place where this variable is used is in __main__.py, so a simple fix is to move it there, so that we can import the surprise module without any issue.

Expected Results

import surprise should just work, even if it was installed on another PATH and added dynamically.

Actual Results

env_surprise/surprise/__init__.py:50: in <module>
    __version__ = get_distribution("scikit-surprise").version
venv/lib/python3.9/site-packages/pkg_resources/__init__.py:478: in get_distribution
    dist = get_provider(dist)
venv/lib/python3.9/site-packages/pkg_resources/__init__.py:354: in get_provider
    return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
venv/lib/python3.9/site-packages/pkg_resources/__init__.py:909: in require
    needed = self.resolve(parse_requirements(requirements))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pkg_resources.WorkingSet object at 0x10087cd00>, requirements = []
env = <pkg_resources.Environment object at 0x1331c0970>, installer = None
replace_conflicting = False, extras = None

    def resolve(self, requirements, env=None, installer=None,  # noqa: C901
                replace_conflicting=False, extras=None):
        """List all distributions needed to (recursively) meet `requirements`
    
        `requirements` must be a sequence of ``Requirement`` objects.  `env`,
        if supplied, should be an ``Environment`` instance.  If
        not supplied, it defaults to all distributions available within any
        entry or distribution in the working set.  `installer`, if supplied,
        will be invoked with each requirement that cannot be met by an
        already-installed distribution; it should return a ``Distribution`` or
        ``None``.
    
        Unless `replace_conflicting=True`, raises a VersionConflict exception
        if
        any requirements are found on the path that have the correct name but
        the wrong version.  Otherwise, if an `installer` is supplied it will be
        invoked to obtain the correct version of the requirement and activate
        it.
    
        `extras` is a list of the extras to be used with these requirements.
        This is important because extra requirements may look like `my_req;
        extra = "my_extra"`, which would otherwise be interpreted as a purely
        optional requirement.  Instead, we want to be able to assert that these
        requirements are truly required.
        """
    
        # set up the stack
        requirements = list(requirements)[::-1]
        # set of processed requirements
        processed = {}
        # key -> dist
        best = {}
        to_activate = []
    
        req_extras = _ReqExtras()
    
        # Mapping of requirement to set of distributions that required it;
        # useful for reporting info about conflicts.
        required_by = collections.defaultdict(set)
    
        while requirements:
            # process dependencies breadth-first
            req = requirements.pop(0)
            if req in processed:
                # Ignore cyclic or redundant dependencies
                continue
    
            if not req_extras.markers_pass(req, extras):
                continue
    
            dist = best.get(req.key)
            if dist is None:
                # Find the best distribution and add it to the map
                dist = self.by_key.get(req.key)
                if dist is None or (dist not in req and replace_conflicting):
                    ws = self
                    if env is None:
                        if dist is None:
                            env = Environment(self.entries)
                        else:
                            # Use an empty environment and workingset to avoid
                            # any further conflicts with the conflicting
                            # distribution
                            env = Environment([])
                            ws = WorkingSet([])
                    dist = best[req.key] = env.best_match(
                        req, ws, installer,
                        replace_conflicting=replace_conflicting
                    )
                    if dist is None:
                        requirers = required_by.get(req, None)
>                       raise DistributionNotFound(req, requirers)
E                       pkg_resources.DistributionNotFound: The 'scikit-surprise' distribution was not found and is required by the application

Versions

>>> import platform; print(platform.platform())
macOS-12.6-arm64-arm-64bit
Python 3.9.13 (v3.9.13:6de2ca5339, May 17 2022, 11:37:23) 
[Clang 13.0.0 (clang-1300.0.29.30)]

surprise 1.1.3 but there is a circular import issue too ...

@NicolasHug
Copy link
Owner

The pkg_resource does not play well with non-standard PATH apparently

I'm not sure what you mean by that? What is non-standard about the PATH here?

The only place where this variable is used is in main.py, so a simple fix is to move it there, so that we can import the surprise module without any issue.

Unfortunately we still need __version__ to be in __init__.py, since this is the standard way of defining package versions in Python

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants