Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a7723c8

Browse files
committed
Key the root modules cache by sys.path entries.
Instead of a single root modules cache, cache in a dict the list of modules associated with each sys.path entries (except $PWD). On future import completions, create the list of completions by merging the appropriate cache entries (while updating the cache if sys.path changed) and adding in the modules in $PWD as well. This allows the completer to keep up with multiple Python installations, virtualenvs, etc. Right now the root modules cache grows indefinitely. It may be worth implementing a LRU cache, a la functools.lru_cache.
1 parent 8bb3f53 commit a7723c8

2 files changed

Lines changed: 30 additions & 25 deletions

File tree

IPython/core/completerlib.py

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -98,39 +98,44 @@ def module_list(path):
9898
modules.append(m.group('name'))
9999
return list(set(modules))
100100

101+
101102
def get_root_modules():
102103
"""
103104
Returns a list containing the names of all the modules available in the
104105
folders of the pythonpath.
106+
107+
ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
105108
"""
106109
ip = get_ipython()
107-
108-
if 'rootmodules' in ip.db:
109-
return ip.db['rootmodules']
110-
111-
t = time()
110+
rootmodules_cache = ip.db.get('rootmodules_cache', {})
111+
rootmodules = list(sys.builtin_module_names)
112+
start_time = time()
112113
store = False
113-
modules = list(sys.builtin_module_names)
114114
for path in sys.path:
115-
modules += module_list(path)
116-
if time() - t >= TIMEOUT_STORAGE and not store:
117-
store = True
118-
print("\nCaching the list of root modules, please wait!")
119-
print("(This will only be done once - type '%rehashx' to "
120-
"reset cache!)\n")
121-
sys.stdout.flush()
122-
if time() - t > TIMEOUT_GIVEUP:
123-
print("This is taking too long, we give up.\n")
124-
ip.db['rootmodules'] = []
125-
return []
126-
127-
modules = set(modules)
128-
if '__init__' in modules:
129-
modules.remove('__init__')
130-
modules = list(modules)
115+
try:
116+
modules = rootmodules_cache[path]
117+
except KeyError:
118+
modules = module_list(path)
119+
try:
120+
modules.remove('__init__')
121+
except ValueError:
122+
pass
123+
if path not in ('', '.'): # cwd modules should not be cached
124+
rootmodules_cache[path] = modules
125+
if time() - start_time > TIMEOUT_STORAGE and not store:
126+
store = True
127+
print("\nCaching the list of root modules, please wait!")
128+
print("(This will only be done once - type '%rehashx' to "
129+
"reset cache!)\n")
130+
sys.stdout.flush()
131+
if time() - start_time > TIMEOUT_GIVEUP:
132+
print("This is taking too long, we give up.\n")
133+
return []
134+
rootmodules.extend(modules)
131135
if store:
132-
ip.db['rootmodules'] = modules
133-
return modules
136+
ip.db['rootmodules_cache'] = rootmodules_cache
137+
rootmodules = list(set(rootmodules))
138+
return rootmodules
134139

135140

136141
def is_importable(module, attr, only_modules):

IPython/core/magics/osm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def rehashx(self, parameter_s=''):
148148
from IPython.core.alias import InvalidAliasError
149149

150150
# for the benefit of module completer in ipy_completers.py
151-
del self.shell.db['rootmodules']
151+
del self.shell.db['rootmodules_cache']
152152

153153
path = [os.path.abspath(os.path.expanduser(p)) for p in
154154
os.environ.get('PATH','').split(os.pathsep)]

0 commit comments

Comments
 (0)