mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
lazy load modules
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import contextlib
|
||||
import codecs
|
||||
import os
|
||||
@@ -10,6 +11,15 @@ import tempfile
|
||||
from glob import glob
|
||||
import json as simplejson
|
||||
|
||||
import lazyload
|
||||
for module in [
|
||||
'urllib3', 'background', 'dotenv', 'delegator', 'pexpect',
|
||||
'requests', 'pip', 'pipfile', 'pipdeptree', 'requirements',
|
||||
'semver', 'flake8', 'pipreqs', 'blindspin', 'click_didyoumean',
|
||||
'.project', '.utils'
|
||||
]:
|
||||
lazyload.make_lazy(module)
|
||||
|
||||
import urllib3
|
||||
import background
|
||||
import click
|
||||
|
||||
Vendored
+61
@@ -0,0 +1,61 @@
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
|
||||
class _LazyModuleMarker(object):
|
||||
"""
|
||||
A marker to indicate a LazyModule type.
|
||||
Allows us to check module's with `isinstance(mod, _LazyModuleMarker)`
|
||||
to know if the module is lazy.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NonLocal(object):
|
||||
"""
|
||||
Simulates nonlocal keyword in Python 2
|
||||
"""
|
||||
__slots__ = ['value']
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
||||
def make_lazy(module_path):
|
||||
"""
|
||||
Mark that this module should not be imported until an
|
||||
attribute is needed off of it.
|
||||
"""
|
||||
sys_modules = sys.modules # cache in the locals
|
||||
|
||||
# store our 'instance' data in the closure.
|
||||
module = NonLocal(None)
|
||||
|
||||
class LazyModule(_LazyModuleMarker):
|
||||
"""
|
||||
A standin for a module to prevent it from being imported
|
||||
"""
|
||||
def __mro__(self):
|
||||
"""
|
||||
Override the __mro__ to fool `isinstance`.
|
||||
"""
|
||||
# We don't use direct subclassing because `ModuleType` has an
|
||||
# incompatible metaclass base with object (they are both in c)
|
||||
# and we are overridding __getattribute__.
|
||||
# By putting a __mro__ method here, we can pass `isinstance`
|
||||
# checks without ever invoking our __getattribute__ function.
|
||||
return (LazyModule, ModuleType)
|
||||
|
||||
def __getattribute__(self, attr):
|
||||
"""
|
||||
Override __getattribute__ to hide the implementation details.
|
||||
"""
|
||||
if module.value is None:
|
||||
del sys_modules[module_path]
|
||||
module.value = __import__(module_path)
|
||||
|
||||
sys_modules[module_path] = __import__(module_path)
|
||||
|
||||
return getattr(module.value, attr)
|
||||
|
||||
sys_modules[module_path] = LazyModule()
|
||||
Reference in New Issue
Block a user