|
3 | 3 | Nick Mathewson |
4 | 4 | ''' |
5 | 5 |
|
| 6 | +import importlib.machinery |
6 | 7 | import sys |
| 8 | +from contextlib import contextmanager |
7 | 9 | from textwrap import dedent |
8 | 10 | from types import FunctionType, MethodType, BuiltinFunctionType |
9 | 11 | import pyclbr |
|
22 | 24 | # is imperfect (as designed), testModule is called with a set of |
23 | 25 | # members to ignore. |
24 | 26 |
|
| 27 | + |
| 28 | +@contextmanager |
| 29 | +def temporary_main_spec(): |
| 30 | + """ |
| 31 | + A context manager that temporarily sets the `__spec__` attribute |
| 32 | + of the `__main__` module if it's missing. |
| 33 | + """ |
| 34 | + main_mod = sys.modules.get("__main__") |
| 35 | + if main_mod is None: |
| 36 | + yield # Do nothing if __main__ is not present |
| 37 | + return |
| 38 | + |
| 39 | + original_spec = getattr(main_mod, "__spec__", None) |
| 40 | + if original_spec is None: |
| 41 | + main_mod.__spec__ = importlib.machinery.ModuleSpec( |
| 42 | + name="__main__", loader=None, origin="built-in" |
| 43 | + ) |
| 44 | + try: |
| 45 | + yield |
| 46 | + finally: |
| 47 | + main_mod.__spec__ = original_spec |
| 48 | + |
| 49 | + |
25 | 50 | class PyclbrTest(TestCase): |
26 | 51 |
|
27 | 52 | def assertListEq(self, l1, l2, ignore): |
@@ -145,8 +170,9 @@ def test_easy(self): |
145 | 170 | self.checkModule('pyclbr') |
146 | 171 | # XXX: Metaclasses are not supported |
147 | 172 | # self.checkModule('ast') |
148 | | - self.checkModule('doctest', ignore=("TestResults", "_SpoofOut", |
149 | | - "DocTestCase", '_DocTestSuite')) |
| 173 | + with temporary_main_spec(): |
| 174 | + self.checkModule('doctest', ignore=("TestResults", "_SpoofOut", |
| 175 | + "DocTestCase", '_DocTestSuite')) |
150 | 176 | self.checkModule('difflib', ignore=("Match",)) |
151 | 177 |
|
152 | 178 | def test_cases(self): |
@@ -223,12 +249,13 @@ def test_others(self): |
223 | 249 | with warnings.catch_warnings(): |
224 | 250 | warnings.simplefilter('ignore', DeprecationWarning) |
225 | 251 | cm('sre_parse', ignore=('dump', 'groups', 'pos')) # from sre_constants import *; property |
226 | | - cm( |
227 | | - 'pdb', |
228 | | - # pyclbr does not handle elegantly `typing` or properties |
229 | | - ignore=('Union', '_ModuleTarget', '_ScriptTarget', '_ZipTarget', 'curframe_locals'), |
230 | | - ) |
231 | | - cm('pydoc', ignore=('input', 'output',)) # properties |
| 252 | + with temporary_main_spec(): |
| 253 | + cm( |
| 254 | + 'pdb', |
| 255 | + # pyclbr does not handle elegantly `typing` or properties |
| 256 | + ignore=('Union', '_ModuleTarget', '_ScriptTarget', '_ZipTarget', 'curframe_locals'), |
| 257 | + ) |
| 258 | + cm('pydoc', ignore=('input', 'output',)) # properties |
232 | 259 |
|
233 | 260 | # Tests for modules inside packages |
234 | 261 | cm('email.parser') |
|
0 commit comments