Changeset 526

Show
Ignore:
Timestamp:
Tue Aug 5 12:31:49 2008
Author:
htgoebel
Message:

Added support for relative import (new in Python2.5)

Files:

Legend:

Unmodified
Added
Removed
Modified
  • trunk/mf.py

    r520 r526  
    400 400                 if mod:  
    401 401                     mod.xref(importer)  
    402                       for name, isdelayed, isconditional in mod.imports:  
      402                     for name, isdelayed, isconditional, level in mod.imports:  
    402 402                         imptyp = isdelayed * 2 + isconditional  
    403                           newnms = self.analyze_one(name, nm, imptyp)  
      403                         newnms = self.analyze_one(name, nm, imptyp, level)  
    403 403                         newnms = map(None, newnms, [nm]*len(newnms))  
    404 404                         nms[j:j] = newnms  
     
    408 408         return map(lambda a: a[0], nms)  
    409 409  
    410       def analyze_one(self, nm, importernm=None, imptyp=0):  
    411           # first see if we could be importing a relative name  
    412           contexts = [None]  
      410     def analyze_one(self, nm, importernm=None, imptyp=0, level=-1):  
      411         #print '## analyze_one', nm, importernm, imptyp, level  
      412         # break the name being imported up so we get:  
      413         # a.b.c -> [a, b, c] ; ..z -> ['', '', z]  
      414         if not nm:  
      415             nm = importernm  
      416             importernm = None  
      417             level = 0  
      418         nmparts = string.split(nm, '.')  
      419  
      420         if level < 0:  
      421             # behaviour up to Python 2.4 (and default in Python 2.5)  
      422             # first see if we could be importing a relative name  
      423             contexts = [None]  
      424             if importernm:  
      425                 if self.ispackage(importernm):  
      426                     contexts.insert(0, importernm)  
      427                 else:  
      428                     pkgnm = string.join(string.split(importernm, '.')[:-1], '.')  
      429                     if pkgnm:  
      430                         contexts.insert(0, pkgnm)  
      431         elif level == 0:  
      432             # absolute import, do not try relative  
      433             importernm = None  
      434             contexts = [None]  
      435         elif level > 0:  
      436             # relative import, do not try absolute  
      437             contexts = [string.join(string.split(importernm, '.')[:-level], '.')]  
      438             importernm = None  
      439  
    413 440         _all = None  
    414           if importernm:  
    415               if self.ispackage(importernm):  
    416                   contexts.insert(0,importernm)  
    417               else:  
    418                   pkgnm = string.join(string.split(importernm, '.')[:-1], '.')  
    419                   if pkgnm:  
    420                       contexts.insert(0,pkgnm)  
      441  
      442         assert contexts  
    421 443         # so contexts is [pkgnm, None] or just [None]  
    422           # now break the name being imported up so we get:  
    423           # a.b.c -> [a, b, c]  
    424           nmparts = string.split(nm, '.')  
    425 444         if nmparts[-1] == '*':  
    426 445             del nmparts[-1]  
     
    535 554                 if hasattr(hook, 'hiddenimports'):  
    536 555                     for impnm in hook.hiddenimports:  
    537                           mod.imports.append((impnm, 0, 0))  
      556                         mod.imports.append((impnm, 0, 0, -1))  
    537 556                 if hasattr(hook, 'attrs'):  
    538 557                     for attr, val in hook.attrs:  
     
    704 723 BUILD_LIST = dis.opname.index('BUILD_LIST')  
    705 724 LOAD_CONST = dis.opname.index('LOAD_CONST')  
      725 if getattr(sys, 'version_info', (0,0,0)) > (2,5,0):  
      726     LOAD_CONST_level = LOAD_CONST  
      727 else:  
      728     LOAD_CONST_level = 999  
    706 729 JUMP_IF_FALSE = dis.opname.index('JUMP_IF_FALSE')  
    707 730 JUMP_IF_TRUE = dis.opname.index('JUMP_IF_TRUE')  
     
    753 776     all = None  
    754 777     lastname = None  
      778     level = -1 # import-level, same behaviour as up to Python 2.4  
    755 779     for i in range(len(instrs)):  
    756 780         op, oparg, conditional, curline = instrs[i]  
    757 781         if op == IMPORT_NAME:  
    758               name = lastname = co.co_names[oparg]  
    759               m.append((name, nested, conditional))  
      782             if level <= 0:  
      783                 name = lastname = co.co_names[oparg]  
      784             else:  
      785                 name = lastname = co.co_names[oparg]  
      786             #print 'import_name', name, `lastname`, level  
      787             m.append((name, nested, conditional, level))  
    760 788         elif op == IMPORT_FROM:  
    761 789             name = co.co_names[oparg]  
    762               m.append((lastname+'.'+name, nested, conditional))  
      790             #print 'import_from', name, `lastname`, level,  
      791             if level > 0 and (not lastname or lastname[-1:] == '.'):  
      792                 name = lastname + name  
      793             else:  
      794                 name = lastname + '.' + name  
      795             #print name  
      796             m.append((name, nested, conditional, level))  
    763 797             assert lastname is not None  
    764 798         elif op == IMPORT_STAR:  
    765               m.append((lastname+'.*', nested, conditional))  
      799             m.append((lastname+'.*', nested, conditional, level))  
    765 799         elif op == STORE_NAME:  
    766 800             if co.co_names[oparg] == "__all__":  
     
    781 815         elif op in STORE_OPS:  
    782 816             pass  
      817         elif op == LOAD_CONST_level:  
      818             # starting with Python 2.5, _each_ import is preceeded with a  
      819             # LOAD_CONST to indicate the relative level.  
      820             if isinstance(co.co_consts[oparg], (int, long)):  
      821                 level = co.co_consts[oparg]  
    783 822         elif op == LOAD_GLOBAL:  
    784 823             name = co.co_names[oparg]  
  • trunk/iu.py

    r520 r526  
    343 343         #print "importHook(%s, %s, locals, %s)" % (name, getattr(globals, '__name__', None), fromlist)  
    344 344         _sys_modules_get = sys.modules.get  
    345           contexts = [None]  
    346           if globals and level == -1:  
    347               # The level indicates we should attempt relative imports, add the  
    348               # package to searched contexts  
      345         _self_doimport = self.doimport  
      346         threaded = self.threaded  
      347  
      348         # break the name being imported up so we get:  
      349         # a.b.c -> [a, b, c]  
      350         nmparts = namesplit(name)  
      351  
      352         if not globals:  
      353             contexts = [None]  
      354             if level >= 0:  
      355                 raise ImportError("Relative import requires 'globals'")  
      356         elif level == 0:  
      357             # absolute import, do not try relative  
      358             contexts = [None]  
      359         else: # level != 0  
    349 360             importernm = globals.get('__name__', '')  
      361             if level < 0:  
      362                 # behaviour up to Python 2.4 (and default in Python 2.5)  
      363                 # add the package to searched contexts  
      364                 contexts = [None]  
      365             else:  
      366                 # relative import, do not try absolute  
      367                 if not importernm:  
      368                     raise ImportError("Relative import requires package")  
      369                 importernm = _string_split(importernm, '.')[:-level]  
      370                 importernm = _string_join('.', importernm)  
      371                 contexts = []  
    350 372             if importernm:  
    351 373                 if hasattr(_sys_modules_get(importernm), '__path__'):  
     
    358 380                     pkgnm = packagename(importernm)  
    359 381                     if pkgnm:  
    360                           contexts.insert(0,pkgnm)  
    361           # so contexts is [pkgnm, None] or just [None]  
    362           # now break the name being imported up so we get:  
    363           # a.b.c -> [a, b, c]  
    364           nmparts = namesplit(name)  
    365           _self_doimport = self.doimport  
    366           threaded = self.threaded  
      382                         contexts.insert(0, pkgnm)  
      383              
      384         # so contexts is [pkgnm, None], [pkgnm] or just [None]  
    367 385         for context in contexts:  
    368 386             ctx = context  
      387             i = 0  
    369 388             for i in range(len(nmparts)):  
    370 389                 nm = nmparts[i]