5
5
import contextlib
6
6
import types
7
7
import importlib
8
+ import inspect
8
9
import warnings
10
+ import itertools
9
11
10
12
from typing import Union , Optional , cast
11
13
from .abc import ResourceReader , Traversable
@@ -50,7 +52,7 @@ def wrapper(anchor=undefined, package=undefined):
50
52
51
53
52
54
@package_to_anchor
53
- def files (anchor : Anchor ) -> Traversable :
55
+ def files (package : Optional [ Anchor ] = None ) -> Traversable :
54
56
"""
55
57
Get a Traversable resource for an anchor.
56
58
"""
@@ -74,7 +76,7 @@ def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:
74
76
75
77
76
78
@functools .singledispatch
77
- def resolve (cand : Anchor ) -> types .ModuleType :
79
+ def resolve (cand : Optional [ Anchor ] ) -> types .ModuleType :
78
80
return cast (types .ModuleType , cand )
79
81
80
82
@@ -83,6 +85,28 @@ def _(cand: str) -> types.ModuleType:
83
85
return importlib .import_module (cand )
84
86
85
87
88
+ @resolve .register
89
+ def _ (cand : None ) -> types .ModuleType :
90
+ return resolve (_infer_caller ().f_globals ['__name__' ])
91
+
92
+
93
+ def _infer_caller ():
94
+ """
95
+ Walk the stack and find the frame of the first caller not in this module.
96
+ """
97
+
98
+ def is_this_file (frame_info ):
99
+ return frame_info .filename == __file__
100
+
101
+ def is_wrapper (frame_info ):
102
+ return frame_info .function == 'wrapper'
103
+
104
+ not_this_file = itertools .filterfalse (is_this_file , inspect .stack ())
105
+ # also exclude 'wrapper' due to singledispatch in the call stack
106
+ callers = itertools .filterfalse (is_wrapper , not_this_file )
107
+ return next (callers ).frame
108
+
109
+
86
110
def from_package (package : types .ModuleType ):
87
111
"""
88
112
Return a Traversable object for the given package.
0 commit comments