forked from donnemartin/gitsome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimphooks.py
85 lines (74 loc) · 2.59 KB
/
imphooks.py
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
"""Import hooks for importing xonsh source files. This module registers
the hooks it defines when it is imported.
"""
import os
import sys
import builtins
from importlib.machinery import ModuleSpec
from importlib.abc import MetaPathFinder, SourceLoader
from xonsh.tools import string_types
from xonsh.execer import Execer
class XonshImportHook(MetaPathFinder, SourceLoader):
"""Implements the import hook for xonsh source files."""
def __init__(self, *args, **kwargs):
super(XonshImportHook, self).__init__(*args, **kwargs)
self._filenames = {}
self._execer = None
@property
def execer(self):
if hasattr(builtins, '__xonsh_execer__'):
execer = builtins.__xonsh_execer__
if self._execer is not None:
self._execer = None
elif self._execer is None:
self._execer = execer = Execer(unload=False)
else:
execer = self._execer
return execer
#
# MetaPathFinder methods
#
def find_spec(self, fullname, path, target=None):
"""Finds the spec for a xonsh module if it exists."""
dot = '.'
spec = None
path = sys.path if path is None else path
if dot not in fullname and dot not in path:
path = [dot] + path
name = fullname.rsplit(dot, 1)[-1]
fname = name + '.xsh'
for p in path:
if not isinstance(p, string_types):
continue
if not os.path.isdir(p):
continue
if fname not in os.listdir(p):
continue
spec = ModuleSpec(fullname, self)
self._filenames[fullname] = os.path.join(p, fname)
break
return spec
#
# SourceLoader methods
#
def get_filename(self, fullname):
"""Returns the filename for a module's fullname."""
return self._filenames[fullname]
def get_data(self, path):
"""Gets the bytes for a path."""
raise NotImplementedError
def get_code(self, fullname):
"""Gets the code object for a xonsh file."""
filename = self._filenames.get(fullname, None)
if filename is None:
msg = "xonsh file {0!r} could not be found".format(fullname)
raise ImportError(msg)
with open(filename, 'r') as f:
src = f.read()
src = src if src.endswith('\n') else src + '\n'
execer = self.execer
execer.filename = filename
ctx = {} # dummy for modules
code = execer.compile(src, glbs=ctx, locs=ctx)
return code
sys.meta_path.append(XonshImportHook())