Skip to content

Commit

Permalink
Merge branch 'maint/3.8.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco committed Mar 27, 2021
2 parents 703a29b + d84930c commit 61fcac1
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
13 changes: 8 additions & 5 deletions importlib_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
import contextlib
import collections

from ._collections import freezable_defaultdict
from ._compat import (
NullFinder,
Protocol,
PyPy_repr,
install,
Protocol,
)

from ._functools import method_cache
from ._itertools import unique_everseen

Expand Down Expand Up @@ -710,8 +710,8 @@ class Lookup:
def __init__(self, path: FastPath):
base = os.path.basename(path.root).lower()
base_is_egg = base.endswith(".egg")
self.infos = collections.defaultdict(list)
self.eggs = collections.defaultdict(list)
self.infos = freezable_defaultdict(list)
self.eggs = freezable_defaultdict(list)

for child in path.children():
low = child.lower()
Expand All @@ -725,6 +725,9 @@ def __init__(self, path: FastPath):
legacy_normalized = Prepared.legacy_normalize(name)
self.eggs[legacy_normalized].append(path.joinpath(child))

self.infos.freeze()
self.eggs.freeze()

def search(self, prepared):
infos = (
self.infos[prepared.normalized]
Expand All @@ -736,7 +739,7 @@ def search(self, prepared):
if prepared
else itertools.chain.from_iterable(self.eggs.values())
)
return list(itertools.chain(infos, eggs))
return itertools.chain(infos, eggs)


class Prepared:
Expand Down
21 changes: 21 additions & 0 deletions importlib_metadata/_collections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import collections


class freezable_defaultdict(collections.defaultdict):
"""
Mix-in to freeze a defaultdict.
>>> dd = freezable_defaultdict(list)
>>> dd[0].append('1')
>>> dd.freeze()
>>> dd[1]
[]
>>> len(dd)
1
"""

def __missing__(self, key):
return getattr(self, '_frozen', super().__missing__)(key)

def freeze(self):
self._frozen = lambda key: self.default_factory()
14 changes: 14 additions & 0 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Distribution,
MetadataPathFinder,
_compat,
distributions,
version,
)

Expand Down Expand Up @@ -59,3 +60,16 @@ def test_search_dist_dirs(self):
"""
res = MetadataPathFinder._search_paths('any-name', [])
assert list(res) == []

def test_interleaved_discovery(self):
"""
When the search is cached, it is
possible for searches to be interleaved, so make sure
those use-cases are safe.
Ref #293
"""
dists = distributions()
next(dists)
version('importlib_metadata')
next(dists)

0 comments on commit 61fcac1

Please sign in to comment.