|
5 | 5 | import contextlib
|
6 | 6 | import types
|
7 | 7 | import importlib
|
| 8 | +import inspect |
| 9 | +import itertools |
8 | 10 |
|
9 | 11 | from typing import Union, Optional, cast
|
10 | 12 | from .abc import ResourceReader, Traversable
|
11 | 13 |
|
12 | 14 | from ._compat import wrap_spec
|
13 | 15 |
|
14 | 16 | Package = Union[types.ModuleType, str]
|
15 |
| -Anchor = Package |
| 17 | +Anchor = Union[Package, None] |
16 | 18 |
|
17 | 19 |
|
18 |
| -def files(package: Anchor) -> Traversable: |
| 20 | +def files(package: Anchor = None) -> Traversable: |
19 | 21 | """
|
20 | 22 | Get a Traversable resource for an anchor.
|
21 | 23 | """
|
@@ -48,6 +50,28 @@ def _(cand: str) -> types.ModuleType:
|
48 | 50 | return importlib.import_module(cand)
|
49 | 51 |
|
50 | 52 |
|
| 53 | +@resolve.register |
| 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 |
| 73 | + |
| 74 | + |
51 | 75 | def from_package(package: types.ModuleType):
|
52 | 76 | """
|
53 | 77 | Return a Traversable object for the given package.
|
|
0 commit comments