Source code for utool.util_import

# -*- coding: utf-8 -*-
"""
SeeAlso:
    utool._internal.util_importer
"""
from __future__ import absolute_import, division, print_function, unicode_literals
from utool import util_inject
from utool import util_arg
import sys
print, rrr, profile = util_inject.inject2(__name__, '[import]')


[docs]def possible_import_patterns(modname): """ does not support from x import * does not support from x import z, y Example: >>> import utool as ut >>> modname = 'package.submod.submod2.module' >>> result = ut.repr3(ut.possible_import_patterns(modname)) >>> print(result) [ 'import package.submod.submod2.module', 'from package.submod.submod2 import module', ] """ patterns = ['import %s' % (modname,)] if '.' in modname: parts = modname.split('.') patterns += ['from %s import %s' % ( '.'.join(parts[0:-1]), parts[-1])] NONSTANDARD = False if NONSTANDARD: if '.' in modname: for i in range(1, len(parts) - 1): patterns += ['from %s import %s' % ( '.'.join(parts[i:-1]), parts[-1])] patterns += ['import %s' % (parts[-1],)] return patterns
[docs]def package_contents(package, with_pkg=False, with_mod=True, ignore_prefix=[], ignore_suffix=[]): r""" References: http://stackoverflow.com/questions/1707709/list-all-the-modules-that-are-part-of-a-python-package Args: package (?): with_pkg (bool): (default = False) with_mod (bool): (default = True) CommandLine: python -m utool.util_import --exec-package_contents Example: >>> # DISABLE_DOCTEST >>> from utool.util_import import * # NOQA >>> import ibeis >>> package = ibeis >>> ignore_prefix = ['ibeis.tests', 'ibeis.control.__SQLITE3__', >>> '_autogen_explicit_controller'] >>> ignore_suffix = ['_grave'] >>> with_pkg = False >>> with_mod = True >>> result = package_contents(package, with_pkg, with_mod, >>> ignore_prefix, ignore_suffix) >>> print(ut.list_str(result)) """ import pkgutil if not hasattr(package, '__path__'): return [package.__name__] # pass print('package = %r' % (package,)) walker = pkgutil.walk_packages(package.__path__, prefix=package.__name__ + '.', onerror=lambda x: None) module_list = [] for importer, modname, ispkg in walker: if any(modname.startswith(prefix) for prefix in ignore_prefix): continue if any(modname.endswith(suffix) for suffix in ignore_suffix): continue if not ispkg and with_mod: module_list.append(modname) if ispkg and with_pkg: module_list.append(modname) return module_list
[docs]def import_modname(modname): r""" Args: modname (str): module name Returns: module: module CommandLine: python -m utool.util_import --test-import_modname Example: >>> # ENABLE_DOCTEST >>> from utool.util_import import * # NOQA >>> modname_list = [ >>> 'utool', >>> 'utool._internal', >>> 'utool._internal.meta_util_six', >>> 'utool.util_path', >>> #'utool.util_path.checkpath', >>> ] >>> modules = [import_modname(modname) for modname in modname_list] >>> result = ([m.__name__ for m in modules]) >>> assert result == modname_list """ # The __import__ statment is weird if util_inject.PRINT_INJECT_ORDER: if modname not in sys.modules: util_inject.noinject(modname, N=2, via='ut.import_modname') if '.' in modname: fromlist = modname.split('.')[-1] fromlist_ = list(map(str, fromlist)) # needs to be ascii for python2.7 module = __import__(modname, {}, {}, fromlist_, 0) else: module = __import__(modname, {}, {}, [], 0) return module
[docs]def tryimport(modname, pipiname=None, ensure=False): """ CommandLine: python -m utool.util_import --test-tryimport Example: >>> # ENABLE_DOCTEST >>> from utool.util_tests import * # NOQA >>> import utool as ut >>> modname = 'pyfiglet' >>> pipiname = 'git+https://github.com/pwaller/pyfiglet' >>> pyfiglet = ut.tryimport(modname, pipiname) >>> assert pyfiglet is None or isinstance(pyfiglet, types.ModuleType), 'unknown error' Example2: >>> # UNSTABLE_DOCTEST >>> # disabled because not everyone has access to being a super user >>> from utool.util_tests import * # NOQA >>> import utool as ut >>> modname = 'lru' >>> pipiname = 'git+https://github.com/amitdev/lru-dict' >>> lru = ut.tryimport(modname, pipiname, ensure=True) >>> assert isinstance(lru, types.ModuleType), 'did not ensure lru' """ if pipiname is None: pipiname = modname try: if util_inject.PRINT_INJECT_ORDER: if modname not in sys.modules: util_inject.noinject(modname, N=2, via='ut.tryimport') module = __import__(modname) return module except ImportError as ex: import utool base_pipcmd = 'pip install %s' % pipiname if not utool.WIN32: pipcmd = 'sudo ' + base_pipcmd sudo = True else: pipcmd = base_pipcmd sudo = False msg = 'unable to find module %s. Please install: %s' % ((modname), (pipcmd)) print(msg) utool.printex(ex, msg, iswarning=True) if ensure: #raise NotImplementedError('not ensuring') utool.cmd(base_pipcmd, sudo=sudo) module = tryimport(modname, pipiname, ensure=False) if module is None: raise AssertionError('Cannot ensure modname=%r please install using %r' % (modname, pipcmd)) return module return None
lazy_module_attrs = ['_modname', '_module', '_load_module']
[docs]class LazyModule(object): """ Waits to import the module until it is actually used. Caveat: there is no access to module attributes used in ``lazy_module_attrs`` CommandLine: python -m utool.util_import --test-LazyModule Example: >>> # DISABLE_DOCTEST >>> from utool.util_import import * # NOQA >>> import sys >>> assert 'this' not in sys.modules, 'this was imported before test start' >>> this = LazyModule('this') >>> assert 'this' not in sys.modules, 'this should not have been imported yet' >>> assert this.i == 25 >>> assert 'this' in sys.modules, 'this should now be imported' >>> print(this) """ def __init__(self, modname): r""" Args: modname (str): module name """ self._modname = modname self._module = None def _load_module(self): if self._module is None: if util_arg.VERBOSE: print('lazy loading module module') self._module = __import__(self._modname, globals(), locals(), fromlist=[], level=0) def __str__(self): return 'LazyModule(%s)' % (self._modname,) def __dir__(self): self._load_module() return dir(self._module) def __getattr__(self, item): if item in lazy_module_attrs: return super(LazyModule, self).__getattr__(item) self._load_module() return getattr(self._module, item) def __setattr__(self, item, value): if item in lazy_module_attrs: return super(LazyModule, self).__setattr__(item, value) self._load_module() setattr(self._module, item, value)
[docs]def import_module_from_fpath(module_fpath): """ imports module from a file path Args: module_fpath (str): Returns: module: module CommandLine: python -m utool.util_import --test-import_module_from_fpath Example: >>> # DISABLE_DOCTEST >>> from utool.util_import import * # NOQA >>> module_fpath = '?' >>> module = import_module_from_fpath(module_fpath) >>> result = ('module = %s' % (str(module),)) >>> print(result) Ignore: module_fpath = '/home/joncrall/code/h5py/h5py' module_fpath = '/home/joncrall/code/h5py/build/lib.linux-x86_64-2.7/h5py' ut.ls(module_fpath) imp.find_module('h5py', '/home/joncrall/code/h5py/') # Define two temporary modules that are not in sys.path # and have the same name but different values. import sys, os, os.path def ensuredir(path): if not os.path.exists(path): os.mkdir(path) ensuredir('tmp') ensuredir('tmp/tmp1') ensuredir('tmp/tmp2') ensuredir('tmp/tmp1/testmod') ensuredir('tmp/tmp2/testmod') with open('tmp/tmp1/testmod/__init__.py', 'w') as file_: file_.write('foo = \"spam\"\nfrom . import sibling') with open('tmp/tmp1/testmod/sibling.py', 'w') as file_: file_.write('bar = \"ham\"') with open('tmp/tmp2/testmod/__init__.py', 'w') as file_: file_.write('foo = \"eggs\"\nfrom . import sibling') with open('tmp/tmp1/testmod/sibling.py', 'w') as file_: file_.write('bar = \"jam\"') # Neither module should be importable through the normal mechanism try: import testmod assert False, 'should fail' except ImportError as ex: pass # Try temporarilly adding the directory of a module to the path sys.path.insert(0, 'tmp/tmp1') testmod1 = __import__('testmod', globals(), locals(), 0) sys.path.remove('tmp/tmp1') print(testmod1.foo) print(testmod1.sibling.bar) sys.path.insert(0, 'tmp/tmp2') testmod2 = __import__('testmod', globals(), locals(), 0) sys.path.remove('tmp/tmp2') print(testmod2.foo) print(testmod2.sibling.bar) assert testmod1.foo == "spam" assert testmod1.sibling.bar == "ham" # Fails, returns spam assert testmod2.foo == "eggs" assert testmod2.sibling.bar == "jam" sys.path.append('/home/username/code/h5py') import h5py sys.path.append('/home/username/code/h5py/build/lib.linux-x86_64-2.7/') import h5py """ from os.path import basename, splitext, isdir, join, exists, dirname, split import platform if isdir(module_fpath): module_fpath = join(module_fpath, '__init__.py') print('module_fpath = %r' % (module_fpath,)) assert exists(module_fpath), 'module_fpath=%r does not exist' % (module_fpath,) python_version = platform.python_version() modname = splitext(basename(module_fpath))[0] if modname == '__init__': modname = split(dirname(module_fpath))[1] if util_inject.PRINT_INJECT_ORDER: if modname not in sys.argv: util_inject.noinject(modname, N=2, via='ut.import_module_from_fpath') if python_version.startswith('2.7'): import imp module = imp.load_source(modname, module_fpath) elif python_version.startswith('3'): import importlib.machinery loader = importlib.machinery.SourceFileLoader(modname, module_fpath) module = loader.load_module() else: raise AssertionError('invalid python version=%r' % (python_version,)) return module #modname = 'theano' #theano = LazyModule(modname)
if __name__ == '__main__': """ CommandLine: python -m utool.util_import python -m utool.util_import --allexamples python -m utool.util_import --allexamples --noface --nosrc """ import multiprocessing multiprocessing.freeze_support() # for win32 import utool as ut # NOQA ut.doctest_funcs()