Skip to content

Commit 4561cd8

Browse files
committed
Move caller inference to its own function. Removes hard-coded distance to caller by finding the first caller not in this file. Avoids expensive use of inspect when package is specified.
1 parent e285509 commit 4561cd8

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

importlib_resources/_common.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,22 @@
66
import types
77
import importlib
88
import inspect
9+
import itertools
910

10-
from typing import Union, Optional, cast, Dict
11+
from typing import Union, Optional, cast
1112
from .abc import ResourceReader, Traversable
1213

1314
from ._compat import wrap_spec
1415

1516
Package = Union[types.ModuleType, str]
1617
Anchor = Union[Package, None]
17-
ModuleContext = Dict[str, str]
1818

1919

2020
def files(package: Anchor = None) -> Traversable:
2121
"""
2222
Get a Traversable resource for an anchor.
2323
"""
24-
context = inspect.stack()[1].frame.f_globals # type: ignore
25-
return from_package(resolve(package, context))
24+
return from_package(resolve(package))
2625

2726

2827
def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:
@@ -42,18 +41,35 @@ def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:
4241

4342

4443
@functools.singledispatch
45-
def resolve(cand: Anchor, context) -> types.ModuleType:
44+
def resolve(cand: Anchor) -> types.ModuleType:
4645
return cast(types.ModuleType, cand)
4746

4847

4948
@resolve.register
50-
def _(cand: str, context) -> types.ModuleType:
49+
def _(cand: str) -> types.ModuleType:
5150
return importlib.import_module(cand)
5251

5352

5453
@resolve.register
55-
def _(cand: None, context: ModuleContext) -> types.ModuleType:
56-
return resolve(context['__name__'], context)
54+
def _(cand: None) -> types.ModuleType:
55+
return resolve(_infer_caller().f_globals['__name__'])
56+
57+
58+
def _infer_caller():
59+
"""
60+
Walk the stack and find the frame of the first caller not in this module.
61+
"""
62+
63+
def is_this_file(frame_info):
64+
return frame_info.filename == __file__
65+
66+
def is_wrapper(frame_info):
67+
return frame_info.function == 'wrapper'
68+
69+
not_this_file = itertools.filterfalse(is_this_file, inspect.stack())
70+
# also exclude 'wrapper' due to singledispatch in the call stack
71+
callers = itertools.filterfalse(is_wrapper, not_this_file)
72+
return next(callers).frame
5773

5874

5975
def from_package(package: types.ModuleType):

0 commit comments

Comments
 (0)