"Fossies" - the Fresh Open Source Software Archive

Member "cheetah3-3.2.6.post2/Cheetah/ImportManager.py" (20 Apr 2021, 17537 Bytes) of package /linux/www/cheetah3-3.2.6.post2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "ImportManager.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3-3.2.3_vs_3-3.2.4.

    1 """
    2 Provides an emulator/replacement for Python's standard import system.
    3 
    4 @@TR: Be warned that Import Hooks are in the deepest, darkest corner of
    5 Python's jungle.  If you need to start hacking with this, be prepared to get
    6 lost for a while. Also note, this module predates the newstyle import hooks in
    7 Python 2.3 http://www.python.org/peps/pep-0302.html.
    8 
    9 This is a hacked/documented version of Gordon McMillan's iu.py. I have:
   10 
   11   - made it a little less terse
   12 
   13   - added docstrings and explanatations
   14 
   15   - standardized the variable naming scheme
   16 
   17   - reorganized the code layout to enhance readability
   18 """
   19 
   20 import marshal
   21 import py_compile
   22 import sys
   23 from Cheetah.compat import PY2, string_type, new_module, get_suffixes, \
   24     load_module_from_file, RecursionError
   25 if PY2:
   26     import imp
   27 else:
   28     import importlib.machinery
   29 
   30 _installed = False
   31 
   32 # _globalOwnerTypes is defined at the bottom of this file
   33 
   34 _os_stat = _os_path_join = _os_getcwd = _os_path_dirname = None
   35 
   36 ##################################################
   37 # FUNCTIONS
   38 
   39 
   40 def _os_bootstrap():
   41     """
   42     Set up 'os' module replacement functions for use during import bootstrap
   43     """
   44 
   45     names = sys.builtin_module_names
   46 
   47     join = dirname = None
   48     if 'posix' in names:
   49         sep = '/'
   50         from posix import stat, getcwd
   51     elif 'nt' in names:
   52         sep = '\\'
   53         from nt import stat, getcwd
   54     elif 'dos' in names:
   55         sep = '\\'
   56         from dos import stat, getcwd
   57     elif 'os2' in names:
   58         sep = '\\'
   59         from os2 import stat, getcwd
   60     elif 'mac' in names:
   61         from mac import stat, getcwd
   62 
   63         def join(a, b):
   64             if a == '':
   65                 return b
   66             if ':' not in a:
   67                 a = ':' + a
   68             if a[-1:] != ':':
   69                 a = a + ':'
   70             return a + b
   71     else:
   72         raise ImportError('no os specific module found')
   73 
   74     if join is None:
   75         def join(a, b, sep=sep):
   76             if a == '':
   77                 return b
   78             lastchar = a[-1:]
   79             if lastchar == '/' or lastchar == sep:
   80                 return a + b
   81             return a + sep + b
   82 
   83     if dirname is None:
   84         def dirname(a, sep=sep):
   85             for i in range(len(a) - 1, -1, -1):
   86                 c = a[i]
   87                 if c == '/' or c == sep:
   88                     return a[:i]
   89             return ''
   90 
   91     global _os_stat
   92     _os_stat = stat
   93 
   94     global _os_path_join
   95     _os_path_join = join
   96 
   97     global _os_path_dirname
   98     _os_path_dirname = dirname
   99 
  100     global _os_getcwd
  101     _os_getcwd = getcwd
  102 
  103 
  104 _os_bootstrap()
  105 
  106 
  107 def packageName(s):
  108     for i in range(len(s) - 1, -1, -1):
  109         if s[i] == '.':
  110             break
  111     else:
  112         return ''
  113     return s[:i]
  114 
  115 
  116 def nameSplit(s):
  117     rslt = []
  118     i = j = 0
  119     for j in range(len(s)):
  120         if s[j] == '.':
  121             rslt.append(s[i:j])
  122             i = j + 1
  123     if i < len(s):
  124         rslt.append(s[i:])
  125     return rslt
  126 
  127 
  128 def getPathExt(fnm):
  129     for i in range(len(fnm) - 1, -1, -1):
  130         if fnm[i] == '.':
  131             return fnm[i:]
  132     return ''
  133 
  134 
  135 def pathIsDir(pathname):
  136     "Local replacement for os.path.isdir()."
  137     try:
  138         s = _os_stat(pathname)
  139     except OSError:
  140         return None
  141     return (s[0] & 0o170000) == 0o040000
  142 
  143 
  144 def getDescr(fnm):
  145     ext = getPathExt(fnm)
  146     for (suffix, mode, typ) in get_suffixes():
  147         if suffix == ext:
  148             return (suffix, mode, typ)
  149 
  150 ##################################################
  151 # CLASSES
  152 
  153 
  154 class Owner:
  155 
  156     """An Owner does imports from a particular piece of turf That is, there's
  157     an Owner for each thing on sys.path There are owners for directories and
  158     .pyz files.  There could be owners for zip files, or even URLs.  A
  159     shadowpath (a dictionary mapping the names in sys.path to their owners) is
  160     used so that sys.path (or a package's __path__) is still a bunch of
  161     strings.
  162     """
  163 
  164     def __init__(self, path):
  165         self.path = path
  166 
  167     def __str__(self):
  168         return self.path
  169 
  170     def getmod(self, nm):
  171         return None
  172 
  173 
  174 class DirOwner(Owner):
  175 
  176     def __init__(self, path):
  177         if path == '':
  178             path = _os_getcwd()
  179         if not pathIsDir(path):
  180             raise ValueError("%s is not a directory" % path)
  181         Owner.__init__(self, path)
  182 
  183     def getmod(self, nm, getsuffixes=get_suffixes,
  184                loadco=marshal.loads, newmod=new_module):
  185 
  186         pth = _os_path_join(self.path, nm)
  187 
  188         possibles = [(pth, 0, None)]
  189         if pathIsDir(pth):
  190             possibles.insert(0, (_os_path_join(pth, '__init__'), 1, pth))
  191         py = pyc = None
  192         for pth, ispkg, pkgpth in possibles:
  193             for ext, mode, typ in getsuffixes():
  194                 attempt = pth + ext
  195                 try:
  196                     st = _os_stat(attempt)
  197                 except Exception:
  198                     pass
  199                 else:
  200                     if typ == 3:  # imp.C_EXTENSION
  201                         return load_module_from_file(nm, nm, attempt)
  202                     elif typ == 1:  # imp.PY_SOURCE
  203                         py = (attempt, st)
  204                     else:
  205                         pyc = (attempt, st)
  206             if py or pyc:
  207                 break
  208         if py is None and pyc is None:
  209             return None
  210         while True:
  211             if pyc is None or py and pyc[1][8] < py[1][8]:
  212                 try:
  213                     with open(py[0], 'r') as py_code_file:
  214                         py_code = py_code_file.read()
  215                     co = compile(py_code + '\n', py[0], 'exec')
  216                     try:
  217                         py_compile.compile(py[0])
  218                     except IOError:
  219                         pass
  220                     __file__ = py[0]
  221                     break
  222                 except SyntaxError as e:
  223                     print("Invalid syntax in %s" % py[0])
  224                     print(e.args)
  225                     raise
  226             elif pyc:
  227                 with open(pyc[0], 'rb') as pyc_file:
  228                     stuff = pyc_file.read()
  229                 try:
  230                     co = loadco(stuff[8:])
  231                     __file__ = pyc[0]
  232                     break
  233                 except (ValueError, EOFError):
  234                     pyc = None
  235             else:
  236                 return None
  237         mod = newmod(nm)
  238         mod.__file__ = __file__
  239         if ispkg:
  240             mod.__path__ = [pkgpth]
  241             subimporter = PathImportDirector(mod.__path__)
  242             mod.__importsub__ = subimporter.getmod
  243         mod.__co__ = co
  244         return mod
  245 
  246 
  247 class ImportDirector(Owner):
  248     """ImportDirectors live on the metapath There's one for builtins, one for
  249     frozen modules, and one for sys.path Windows gets one for modules gotten
  250     from the Registry Mac would have them for PY_RESOURCE modules etc.  A
  251     generalization of Owner - their concept of 'turf' is broader"""
  252 
  253     pass
  254 
  255 
  256 class BuiltinImportDirector(ImportDirector):
  257     """Directs imports of builtin modules"""
  258     def __init__(self):
  259         self.path = 'Builtins'
  260 
  261     def getmod(self, nm):
  262         if nm in sys.builtin_module_names:
  263             try:
  264                 importfunc = __oldimport__
  265             except NameError:
  266                 importfunc = __import__
  267             return importfunc(nm)
  268         return None
  269 
  270 
  271 class FrozenImportDirector(ImportDirector):
  272     """Directs imports of frozen modules"""
  273 
  274     def __init__(self):
  275         self.path = 'FrozenModules'
  276 
  277     def getmod(self, nm):
  278         mod = None
  279         if PY2:
  280             if imp.is_frozen(nm):
  281                 mod = imp.load_module(nm, None, nm, ('', '', imp.PY_FROZEN))
  282         else:
  283             if importlib.machinery.FrozenImporter.find_spec(nm):
  284                 mod = importlib.machinery.FrozenImporter.load_module(nm)
  285         if mod and hasattr(mod, '__path__'):
  286             mod.__importsub__ = \
  287                 lambda name, pname=nm, owner=self: \
  288                 owner.getmod(pname + '.' + name)
  289         return mod
  290 
  291 
  292 class RegistryImportDirector(ImportDirector):
  293     """Directs imports of modules stored in the Windows Registry"""
  294 
  295     def __init__(self):
  296         self.path = "WindowsRegistry"
  297         self.map = {}
  298         try:
  299             import win32api
  300             # import win32con
  301         except ImportError:
  302             pass
  303         else:
  304             HKEY_CURRENT_USER = -2147483647
  305             HKEY_LOCAL_MACHINE = -2147483646
  306             KEY_ALL_ACCESS = 983103
  307             subkey = r"Software\Python\PythonCore\%s\Modules" % sys.winver
  308             for root in (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE):
  309                 try:
  310                     hkey = win32api.RegOpenKeyEx(root, subkey,
  311                                                  0, KEY_ALL_ACCESS)
  312                 except Exception:
  313                     pass
  314                 else:
  315                     numsubkeys, numvalues, lastmodified = \
  316                         win32api.RegQueryInfoKey(hkey)
  317                     for i in range(numsubkeys):
  318                         subkeyname = win32api.RegEnumKey(hkey, i)
  319                         hskey = win32api.RegOpenKeyEx(hkey, subkeyname,
  320                                                       0, KEY_ALL_ACCESS)
  321                         val = win32api.RegQueryValueEx(hskey, '')
  322                         desc = getDescr(val[0])
  323                         self.map[subkeyname] = (val[0], desc)
  324                         hskey.Close()
  325                     hkey.Close()
  326                     break
  327 
  328     def getmod(self, nm):
  329         stuff = self.map.get(nm)
  330         if stuff:
  331             fnm = stuff[0]
  332             return load_module_from_file(nm, nm, fnm)
  333         return None
  334 
  335 
  336 class PathImportDirector(ImportDirector):
  337     """Directs imports of modules stored on the filesystem."""
  338 
  339     def __init__(self, pathlist=None, importers=None, ownertypes=None):
  340         if pathlist is None:
  341             self.path = sys.path
  342         else:
  343             self.path = pathlist
  344         if ownertypes is None:
  345             self._ownertypes = _globalOwnerTypes
  346         else:
  347             self._ownertypes = ownertypes
  348         if importers:
  349             self._shadowPath = importers
  350         else:
  351             self._shadowPath = {}
  352         self._inMakeOwner = False
  353         self._building = {}
  354 
  355     def getmod(self, nm):
  356         mod = None
  357         for thing in self.path:
  358             if isinstance(thing, string_type):
  359                 owner = self._shadowPath.get(thing, -1)
  360                 if owner == -1:
  361                     owner = self._shadowPath[thing] = self._makeOwner(thing)
  362                 if owner:
  363                     mod = owner.getmod(nm)
  364             else:
  365                 mod = thing.getmod(nm)
  366             if mod:
  367                 break
  368         return mod
  369 
  370     def _makeOwner(self, path):
  371         if self._building.get(path):
  372             return None
  373         self._building[path] = 1
  374         owner = None
  375         for klass in self._ownertypes:
  376             try:
  377                 # this may cause an import, which may cause recursion
  378                 # hence the protection
  379                 owner = klass(path)
  380             except Exception:
  381                 pass
  382             else:
  383                 break
  384         del self._building[path]
  385         return owner
  386 
  387 # =================ImportManager============================#
  388 # The one-and-only ImportManager
  389 # ie, the builtin import
  390 
  391 
  392 UNTRIED = -1
  393 
  394 
  395 class ImportManager:
  396     # really the equivalent of builtin import
  397     def __init__(self):
  398         self.metapath = [
  399             BuiltinImportDirector(),
  400             FrozenImportDirector(),
  401             RegistryImportDirector(),
  402             PathImportDirector()
  403         ]
  404         self.threaded = 0
  405         self.rlock = None
  406         self.locker = None
  407         self.setThreaded()
  408 
  409     def setThreaded(self):
  410         thread = sys.modules.get('thread', None)
  411         if thread and not self.threaded:
  412             self.threaded = 1
  413             self.rlock = thread.allocate_lock()
  414             self._get_ident = thread.get_ident
  415 
  416     def install(self):
  417         try:
  418             import builtins as builtin
  419         except ImportError:  # PY2
  420             import __builtin__ as builtin
  421         builtin.__import__ = self.importHook
  422         builtin.reload = self.reloadHook
  423 
  424     def importHook(self, name, globals=None, locals=None,
  425                    fromlist=None, level=-1):
  426         '''
  427         NOTE: Currently importHook will accept the keyword-argument "level"
  428         but it will *NOT* use it. Details about the "level" keyword
  429         argument can be found here:
  430         https://docs.python.org/2/library/functions.html#__import__
  431         '''
  432         # first see if we could be importing a relative name
  433         _sys_modules_get = sys.modules.get
  434         contexts = [None]
  435         if globals:
  436             importernm = globals.get('__name__', '')
  437             if importernm:
  438                 if hasattr(_sys_modules_get(importernm), '__path__'):
  439                     contexts.insert(0, importernm)
  440                 else:
  441                     pkgnm = packageName(importernm)
  442                     if pkgnm:
  443                         contexts.insert(0, pkgnm)
  444         # so contexts is [pkgnm, None] or just [None]
  445         # now break the name being imported up so we get:
  446         # a.b.c -> [a, b, c]
  447         nmparts = nameSplit(name)
  448         _self_doimport = self.doimport
  449         threaded = self.threaded
  450         for context in contexts:
  451             ctx = context
  452             for i in range(len(nmparts)):
  453                 nm = nmparts[i]
  454                 if ctx:
  455                     fqname = ctx + '.' + nm
  456                 else:
  457                     fqname = nm
  458                 if threaded:
  459                     self._acquire()
  460                 mod = _sys_modules_get(fqname, UNTRIED)
  461                 if mod is UNTRIED:
  462                     mod = _self_doimport(nm, ctx, fqname)
  463                 if threaded:
  464                     self._release()
  465                 if mod:
  466                     ctx = fqname
  467                 else:
  468                     break
  469             else:
  470                 # no break, point i beyond end
  471                 i = i + 1
  472             if i:
  473                 break
  474 
  475         if i < len(nmparts):
  476             if ctx and hasattr(sys.modules[ctx], nmparts[i]):
  477                 return sys.modules[nmparts[0]]
  478             del sys.modules[fqname]
  479             raise ImportError("No module named %s" % fqname)
  480         if fromlist is None:
  481             if context:
  482                 return sys.modules[context + '.' + nmparts[0]]
  483             return sys.modules[nmparts[0]]
  484         bottommod = sys.modules[ctx]
  485         if hasattr(bottommod, '__path__'):
  486             fromlist = list(fromlist)
  487             i = 0
  488             while i < len(fromlist):
  489                 nm = fromlist[i]
  490                 if nm == '*':
  491                     fromlist[i:i+1] = list(getattr(bottommod, '__all__', []))  # noqa: E226,E501 missing whitespace around operator
  492                     if i >= len(fromlist):
  493                         break
  494                     nm = fromlist[i]
  495                 i = i + 1
  496                 if not hasattr(bottommod, nm):
  497                     if self.threaded:
  498                         self._acquire()
  499                     mod = self.doimport(nm, ctx, ctx + '.' + nm)
  500                     if self.threaded:
  501                         self._release()
  502                     if not mod:
  503                         raise ImportError("%s not found in %s" % (nm, ctx))
  504         return bottommod
  505 
  506     def doimport(self, nm, parentnm, fqname):
  507         # Not that nm is NEVER a dotted name at this point
  508         if parentnm:
  509             parent = sys.modules[parentnm]
  510             if hasattr(parent, '__path__'):
  511                 importfunc = getattr(parent, '__importsub__', None)
  512                 if not importfunc:
  513                     subimporter = PathImportDirector(parent.__path__)
  514                     importfunc = parent.__importsub__ = subimporter.getmod
  515                 mod = importfunc(nm)
  516                 if mod:
  517                     setattr(parent, nm, mod)
  518             else:
  519                 return None
  520         else:
  521             # now we're dealing with an absolute import
  522             for director in self.metapath:
  523                 try:
  524                     mod = director.getmod(nm)
  525                 except RecursionError:
  526                     mod = __oldimport__(nm)  # noqa: F821 undefined name
  527                 if mod:
  528                     break
  529         if mod:
  530             mod.__name__ = fqname
  531             sys.modules[fqname] = mod
  532             if hasattr(mod, '__co__'):
  533                 co = mod.__co__
  534                 del mod.__co__
  535                 exec(co, mod.__dict__)
  536             if fqname == 'thread' and not self.threaded:
  537                 self.setThreaded()
  538         else:
  539             sys.modules[fqname] = None
  540         return mod
  541 
  542     def reloadHook(self, mod):
  543         fqnm = mod.__name__
  544         nm = nameSplit(fqnm)[-1]
  545         parentnm = packageName(fqnm)
  546         newmod = self.doimport(nm, parentnm, fqnm)
  547         mod.__dict__.update(newmod.__dict__)
  548 #        return newmod
  549 
  550     def _acquire(self):
  551         if self.rlock.locked():
  552             if self.locker == self._get_ident():
  553                 self.lockcount = self.lockcount + 1
  554                 return
  555         self.rlock.acquire()
  556         self.locker = self._get_ident()
  557         self.lockcount = 0
  558 
  559     def _release(self):
  560         if self.lockcount:
  561             self.lockcount = self.lockcount - 1
  562         else:
  563             self.rlock.release()
  564 
  565 
  566 ##################################################
  567 # MORE CONSTANTS & GLOBALS
  568 
  569 _globalOwnerTypes = [
  570     DirOwner,
  571     Owner,
  572 ]