Mercurial > hg
view hgdemandimport/demandimportpy3.py @ 36174:b42c47b8c9d4
treemanifest: add an optimized __nonzero__()
We use bool(manifest) in at least some places:
localrepo.py:1730
hgweb/webcommands.py:524
Since the treemanifest class doesn't define __nonzero__() (before this
patch), bool(manifest) will instead call __len__(), which can be slow
for treemanifests. This patch may make a noticeable difference in the
localrepo case above, but that only happens when committing a merge
and I haven't timed it.
Note that Durham already added a __nonzero__ implementation to
manifestdict in b19291e5d506 (manifest: add __nonzero__ method,
2016-11-03).
Differential Revision: https://phab.mercurial-scm.org/D2232
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Tue, 13 Feb 2018 13:23:18 -0800 |
parents | fcb1ecf2bef7 |
children | 670eb4fa1b86 |
line wrap: on
line source
# demandimportpy3 - global demand-loading of modules for Mercurial # # Copyright 2017 Facebook Inc. # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. """Lazy loading for Python 3.6 and above. This uses the new importlib finder/loader functionality available in Python 3.5 and up. The code reuses most of the mechanics implemented inside importlib.util, but with a few additions: * Allow excluding certain modules from lazy imports. * Expose an interface that's substantially the same as demandimport for Python 2. This also has some limitations compared to the Python 2 implementation: * Much of the logic is per-package, not per-module, so any packages loaded before demandimport is enabled will not be lazily imported in the future. In practice, we only expect builtins to be loaded before demandimport is enabled. """ # This line is unnecessary, but it satisfies test-check-py3-compat.t. from __future__ import absolute_import import contextlib import importlib.abc import importlib.machinery import importlib.util import sys _deactivated = False class _lazyloaderex(importlib.util.LazyLoader): """This is a LazyLoader except it also follows the _deactivated global and the ignore list. """ def exec_module(self, module): """Make the module load lazily.""" if _deactivated or module.__name__ in ignore: self.loader.exec_module(module) else: super().exec_module(module) # This is 3.6+ because with Python 3.5 it isn't possible to lazily load # extensions. See the discussion in https://bugs.python.org/issue26186 for more. _extensions_loader = _lazyloaderex.factory( importlib.machinery.ExtensionFileLoader) _bytecode_loader = _lazyloaderex.factory( importlib.machinery.SourcelessFileLoader) _source_loader = _lazyloaderex.factory(importlib.machinery.SourceFileLoader) def _makefinder(path): return importlib.machinery.FileFinder( path, # This is the order in which loaders are passed in in core Python. (_extensions_loader, importlib.machinery.EXTENSION_SUFFIXES), (_source_loader, importlib.machinery.SOURCE_SUFFIXES), (_bytecode_loader, importlib.machinery.BYTECODE_SUFFIXES), ) ignore = [] def init(ignorelist): global ignore ignore = ignorelist def isenabled(): return _makefinder in sys.path_hooks and not _deactivated def disable(): try: while True: sys.path_hooks.remove(_makefinder) except ValueError: pass def enable(): sys.path_hooks.insert(0, _makefinder) @contextlib.contextmanager def deactivated(): # This implementation is a bit different from Python 2's. Python 3 # maintains a per-package finder cache in sys.path_importer_cache (see # PEP 302). This means that we can't just call disable + enable. # If we do that, in situations like: # # demandimport.enable() # ... # from foo.bar import mod1 # with demandimport.deactivated(): # from foo.bar import mod2 # # mod2 will be imported lazily. (The converse also holds -- whatever finder # first gets cached will be used.) # # Instead, have a global flag the LazyLoader can use. global _deactivated demandenabled = isenabled() if demandenabled: _deactivated = True try: yield finally: if demandenabled: _deactivated = False