forked from astropy/astropy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmisc.py
More file actions
92 lines (80 loc) · 3.47 KB
/
Copy pathmisc.py
File metadata and controls
92 lines (80 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
Simple utility functions and bug fixes for compatibility with all supported
versions of Python. This module should generally not be used directly, as
everything in `__all__` will be imported into `astropy.utils.compat` and can
be accessed from there.
Includes the following fixes:
* The `inspect.getmodule` function does not always work in Python 3.1 and 3.2.
This package includes a function `inspect_getmodule` that will simply be an
alias to `inspect.getmodule` if the stdlib version is correct, but for
versions of python with the bug, it uses an internal patched version.
"""
from __future__ import absolute_import
from sys import version_info
__all__ = ['inspect_getmodule']
def _patched_getmodule(object, _filename=None):
"""Return the module an object was defined in, or None if not found.
This replicates the functionality of the stdlib `inspect.getmodule`
function but includes a fix for a bug present in Python 3.1 and 3.2.
"""
#these imports mock up what would otherwise have been in inspect
import sys
import os
from inspect import modulesbyfile, _filesbymodname, getabsfile, ismodule
if ismodule(object):
return object
if hasattr(object, '__module__'):
return sys.modules.get(object.__module__)
# Try the filename to modulename cache
if _filename is not None and _filename in modulesbyfile:
return sys.modules.get(modulesbyfile[_filename])
# Try the cache again with the absolute file name
try:
file = getabsfile(object, _filename)
except TypeError:
return None
if file in modulesbyfile:
return sys.modules.get(modulesbyfile[file])
# Update the filename to module name cache and check yet again
# Copy sys.modules in order to cope with changes while iterating
# This is where the fix is made - the adding of the "list" call:
for modname, module in list(sys.modules.items()):
if ismodule(module) and hasattr(module, '__file__'):
f = module.__file__
if f == _filesbymodname.get(modname, None):
# Have already mapped this module, so skip it
continue
_filesbymodname[modname] = f
f = getabsfile(module)
# Always map to the name the module knows itself by
modulesbyfile[f] = modulesbyfile[
os.path.realpath(f)] = module.__name__
if file in modulesbyfile:
return sys.modules.get(modulesbyfile[file])
# Check the main module
main = sys.modules['__main__']
if not hasattr(object, '__name__'):
return None
if hasattr(main, object.__name__):
mainobject = getattr(main, object.__name__)
if mainobject is object:
return main
# Check builtins
builtin = sys.modules['builtins']
if hasattr(builtin, object.__name__):
builtinobject = getattr(builtin, object.__name__)
if builtinobject is object:
return builtin
inspect_getmodule = None
"""
An alias to `inspect.getmodule`, or a patched version that replicates the
functionality with a bugfix for Python 3.1 and 3.2.
"""
#This assigns the stdlib inspect.getmodule to the variable name
#`inspect_getmodule` if it's not buggy, and uses the matched version if it is.
if version_info[0]<3 or version_info[1]>2:
#in 2.x everythig is fine, as well as >=3.3
from inspect import getmodule as inspect_getmodule
else:
inspect_getmodule = _patched_getmodule