Exemple #1
0
    def _create_context_manager(group: str,
                                entrypoint: pkg_resources.EntryPoint,
                                working_set: pkg_resources.WorkingSet,
                                scope: str):
        name = entrypoint.name
        # We need a Distribution to register our dynamic entrypoints within.
        # We have to always instantiate it to find our key, as key can be
        # different from the project_name
        dist = pkg_resources.Distribution(location=__file__,
                                          project_name=scope)

        # Prevent creating entrypoints in distributions not created by us,
        # otherwise we could remove the distributions when cleaning up.
        if (dist.key in working_set.by_key
                and working_set.by_key[dist.key].location != __file__):
            raise ValueError(f'scope {format_scope(scope, dist)} already '
                             f'exists in working set at location '
                             f'{working_set.by_key[dist.key].location}')

        if dist.key not in working_set.by_key:
            working_set.add(dist)
        # Reference the actual registered dist if we didn't just register it
        dist = working_set.by_key[dist.key]

        # Ensure the group exists in our distribution
        group_entries = dist.get_entry_map().setdefault(group, {})

        # Create an entry for the specified entrypoint
        if name in group_entries:
            raise ValueError(f'{name!r} is already registered under {group!r} '
                             f'in scope {format_scope(scope, dist)}')

        assert entrypoint.dist is None
        entrypoint.dist = dist
        group_entries[name] = entrypoint

        # Wait for something to happen with the entrypoint...
        try:
            yield
        finally:
            # Tidy up
            del group_entries[name]
            # If we re-use this entrypoint (by re-entering the context) the
            # dist may well have changed (because it gets deleted from the
            # working set) so we shouldn't remember it.
            assert entrypoint.dist is dist
            entrypoint.dist = None
            if len(group_entries) == 0:
                del dist.get_entry_map()[group]

            if len(dist.get_entry_map()) == 0:
                del working_set.by_key[dist.key]
                working_set.entry_keys[__file__].remove(dist.key)

                if not working_set.entry_keys[__file__]:
                    del working_set.entry_keys[__file__]
                    working_set.entries.remove(__file__)