예제 #1
0
 def testAnalyzeFile(self):
     path = os.path.abspath('File.py')
     source = dedent("""\
         CONSTANT = 1
     """)
     expectedDict = ModuleDict()
     expectedDict.enterModule('File')
     expectedDict.addProperty(None, 'CONSTANT')
     outDict = analyzeFile(path, getSafeTree(source, 1))
     self.assertEqual(outDict, expectedDict, '%r != %r' % (outDict._modules, expectedDict._modules))
예제 #2
0
 def testAnalyzeFile(self):
     path = os.path.abspath('File.py')
     source = dedent("""\
         CONSTANT = 1
     """)
     expectedDict = ModuleDict()
     expectedDict.enterModule('File')
     expectedDict.addProperty(None, 'CONSTANT')
     outDict = analyzeFile(path, getSafeTree(source, 1))
     self.assertEquals(outDict, expectedDict, '%r != %r' % (outDict._modules, expectedDict._modules))
예제 #3
0
    def testGetNames(self):
        source = dedent("""\
            from something import Class

            a = Class()

            class D(object):
                pass

        """)

        expectedNames = {'Class': 'something.Class', 'a': 'Class()'}
        self.assertEquals(getNames(getSafeTree(source, 3)), (expectedNames, ['D']))
예제 #4
0
    def testInferParentsTricky(self):
        source = dedent("""\
            from something.this import other as another
            class AClass(another.bother):
                def amethod(self, other):
                    other.do_something()
                    self.

                def another(self):
                    pass""")
        klass, parents = getClassAndParents(getSafeTree(source, 5), 5)
        self.assertEquals(klass, 'AClass')
        self.assertEquals(parents, ['something.this.other.bother'])
예제 #5
0
    def testGetNames(self):
        source = dedent("""\
            from something import Class

            a = Class()

            class D(object):
                pass

        """).replace('\n', '\r\n')

        expectedNames = {'Class': 'something.Class', 'a': 'Class()'}
        self.assertEqual(getNames(getSafeTree(source, 3)), (expectedNames, ['D']))
예제 #6
0
    def testInferParentsTricky(self):
        source = dedent("""\
            from something.this import other as another
            class AClass(another.bother):
                def amethod(self, other):
                    other.do_something()
                    self.

                def another(self):
                    pass""")
        klass, parents = getClassAndParents(getSafeTree(source, 5), 5)
        self.assertEqual(klass, 'AClass')
        self.assertEqual(parents, ['something.this.other.bother'])
예제 #7
0
    def testInferSelfMultipleClasses(self):
        
        source = dedent("""\
            import something
            class AClass(object):
                def amethod(self, other):
                    other.do_something()
                    class Sneak(object):
                        def sth(self):
                            class EvenSneakier(object):
                                pass
                            pass
                    pass

                def another(self):
                    pass



            class BClass(object):
                def newmethod(self, something):
                    wibble = [i for i in self.a]
                    pass

                def newerMethod(self, somethingelse):
                    if Bugger:
                        self.ass
        """)
        
        self.assertEquals(getClassAndParents(getSafeTree(source, 1), 1)[0], None, 'no class yet!')
        for line in range(2, 5):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEquals(klass, 'AClass', 'wrong class %s in line %d' % (klass, line))

        for line in range(5, 7):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEquals(klass, 'Sneak', 'wrong class %s in line %d' % (klass, line))

        for line in range(7, 9):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEquals(klass, 'EvenSneakier', 'wrong class %s in line %d' % (klass, line))

        line = 9
        klass, _ = getClassAndParents(getSafeTree(source, line), line)
        self.assertEquals(klass, 'Sneak', 'wrong class %s in line %d' % (klass, line))

        for line in range(10, 17):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEquals(klass, 'AClass', 'wrong class %s in line %d' % (klass, line))

        for line in range(17, 51):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEquals(klass, 'BClass', 'wrong class %s in line %d' % (klass, line))
예제 #8
0
    def testInferSelfMultipleClasses(self):
        
        source = dedent("""\
            import something
            class AClass(object):
                def amethod(self, other):
                    other.do_something()
                    class Sneak(object):
                        def sth(self):
                            class EvenSneakier(object):
                                pass
                            pass
                    pass

                def another(self):
                    pass



            class BClass(object):
                def newmethod(self, something):
                    wibble = [i for i in self.a]
                    pass

                def newerMethod(self, somethingelse):
                    if Bugger:
                        self.ass
        """)
        
        self.assertEqual(getClassAndParents(getSafeTree(source, 1), 1)[0], None, 'no class yet!')
        for line in range(2, 5):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEqual(klass, 'AClass', 'wrong class %s in line %d' % (klass, line))

        for line in range(5, 7):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEqual(klass, 'Sneak', 'wrong class %s in line %d' % (klass, line))

        for line in range(7, 9):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEqual(klass, 'EvenSneakier', 'wrong class %s in line %d' % (klass, line))

        line = 9
        klass, _ = getClassAndParents(getSafeTree(source, line), line)
        self.assertEqual(klass, 'Sneak', 'wrong class %s in line %d' % (klass, line))

        for line in range(10, 17):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEqual(klass, 'AClass', 'wrong class %s in line %d' % (klass, line))

        for line in range(17, 51):
            klass, _ = getClassAndParents(getSafeTree(source, line), line)
            self.assertEqual(klass, 'BClass', 'wrong class %s in line %d' % (klass, line))
예제 #9
0
    def testInferSelfSimple(self):
        source = dedent("""\
            import something
            class AClass(object):
                def amethod(self, other):
                    other.do_something()
                    self.

                def another(self):
                    pass
        """)
        klass, parents = getClassAndParents(getSafeTree(source, 5), 5)
        self.assertEquals(klass, 'AClass')
        self.assertEquals(parents, ['object'])
예제 #10
0
    def testInferSelfSimple(self):
        source = dedent("""\
            import something
            class AClass(object):
            \tdef amethod(self, other):
            \t\tother.do_something()
            \t\tself.

            \tdef another(self):
            \t\tpass
        """)
        klass, parents = getClassAndParents(getSafeTree(source, 5), 5)
        self.assertEqual(klass, 'AClass')
        self.assertEqual(parents, ['object'])
예제 #11
0
    def testInferParents(self):
        source = dedent("""\
            import something
            from something import father as stepfather
            class AClass(something.mother, stepfather):
                def amethod(self, other):
                    other.do_something()
                    self.

                def another(self):
                    pass
        """)
        klass, parents = getClassAndParents(getSafeTree(source, 6), 6)
        self.assertEquals(klass, 'AClass')
        self.assertEquals(parents, ['something.mother', 'something.father'])
예제 #12
0
    def testInferParents(self):
        source = dedent("""\
            import something
            from something import father as stepfather
            class AClass(something.mother, stepfather):
                def amethod(self, other):
                    other.do_something()
                    self.

                def another(self):
                    pass
        """)
        klass, parents = getClassAndParents(getSafeTree(source, 6), 6)
        self.assertEqual(klass, 'AClass')
        self.assertEqual(parents, ['something.mother', 'something.father'])
예제 #13
0
def detectCompletionType(fullPath, origSource, lineNo, origCol, base, PYSMELLDICT, update=True):
    """
    Return a CompletionOptions instance describing the type of the completion, along with extra parameters.
    
    args: fullPath -> The full path and filename of the file that is edited
          origSource -> The source of the edited file (it's probably not saved)
          lineNo -> The line number the cursor is in, 1-based
          origCol -> The column number the cursor is in, 0-based
          base -> The string that will be replaced when the completion is inserted
          PYSMELLDICT -> The loaded PYSMELLDICT

    Note that Vim deletes the "base" when a completion is requested so extra trickery must be performed to get it from the source.

    """
    AST = getSafeTree(origSource, lineNo)
    if update:
        currentDict = analyzeFile(fullPath, AST)
        if currentDict is not None:
            updatePySmellDict(PYSMELLDICT, currentDict)
    origLineText = origSource.splitlines()[lineNo - 1] # lineNo is 1 based
    leftSide, rightSide = origLineText[:origCol], origLineText[origCol:]
    leftSideStripped = leftSide.lstrip()

    isImportCompletion = (leftSideStripped.startswith("from ") or leftSideStripped.startswith("import "))
    if isImportCompletion:
        module = leftSideStripped.split(" ")[1]
        if "." in module and " import " not in leftSideStripped:
            module, _ = module.rsplit(".", 1)
        showMembers = False
        if " import " in leftSide:
            showMembers = True
        return CompletionOptions(Types.MODULE, module=module, showMembers=showMembers)

    isAttrLookup = "." in leftSide and not isImportCompletion
    isArgCompletion = base.endswith('(') and leftSide.endswith(base)

    if isArgCompletion:
        rindex = None
        if rightSide.startswith(')'):
            rindex = -1
        funcName = None
        lindex = leftSide.rfind('.') + 1 #rfind will return -1, so with +1 it will be zero
        funcName = leftSide[lindex:-1].lstrip()
        if isAttrLookup:
            return CompletionOptions(Types.METHOD, parents=[], klass=None, name=funcName, rindex=rindex)
        else:
            return CompletionOptions(Types.FUNCTION, name=funcName, rindex=rindex)

    if isAttrLookup and AST is not None:
        var = leftSideStripped[:leftSideStripped.rindex('.')]
        isClassLookup = var == 'self'
        if isClassLookup:
            klass, parents = inferClass(fullPath, AST, lineNo, PYSMELLDICT)
            return CompletionOptions(Types.INSTANCE, klass=klass, parents=parents)
        else:
            chain = getChain(leftSideStripped)[:-1] # strip dot
            possibleModule = inferModule(chain, AST, lineNo)
            if possibleModule is not None:
                return CompletionOptions(Types.MODULE, module=possibleModule, showMembers=True)
        klass, parents = inferInstance(fullPath, AST, lineNo, var, PYSMELLDICT)
        return CompletionOptions(Types.INSTANCE, klass=klass, parents=parents)
        

    return CompletionOptions(Types.TOPLEVEL)
예제 #14
0
def detectCompletionType(fullPath,
                         origSource,
                         lineNo,
                         origCol,
                         base,
                         PYSMELLDICT,
                         update=True):
    """
    Return a CompletionOptions instance describing the type of the completion, along with extra parameters.
    
    args: fullPath -> The full path and filename of the file that is edited
          origSource -> The source of the edited file (it's probably not saved)
          lineNo -> The line number the cursor is in, 1-based
          origCol -> The column number the cursor is in, 0-based
          base -> The string that will be replaced when the completion is inserted
          PYSMELLDICT -> The loaded PYSMELLDICT

    Note that Vim deletes the "base" when a completion is requested so extra trickery must be performed to get it from the source.

    """
    AST = getSafeTree(origSource, lineNo)
    if update:
        currentDict = analyzeFile(fullPath, AST)
        if currentDict is not None:
            updatePySmellDict(PYSMELLDICT, currentDict)
    origLineText = origSource.splitlines()[lineNo - 1]  # lineNo is 1 based
    leftSide, rightSide = origLineText[:origCol], origLineText[origCol:]
    leftSideStripped = leftSide.lstrip()

    isImportCompletion = (leftSideStripped.startswith("from ")
                          or leftSideStripped.startswith("import "))
    if isImportCompletion:
        module = leftSideStripped.split(" ")[1]
        if "." in module and " import " not in leftSideStripped:
            module, _ = module.rsplit(".", 1)
        showMembers = False
        if " import " in leftSide:
            showMembers = True
        return CompletionOptions(Types.MODULE,
                                 module=module,
                                 showMembers=showMembers)

    isAttrLookup = "." in leftSide and not isImportCompletion
    isArgCompletion = base.endswith('(') and leftSide.endswith(base)

    if isArgCompletion:
        rindex = None
        if rightSide.startswith(')'):
            rindex = -1
        funcName = None
        lindex = leftSide.rfind(
            '.') + 1  #rfind will return -1, so with +1 it will be zero
        funcName = leftSide[lindex:-1].lstrip()
        if isAttrLookup:
            return CompletionOptions(Types.METHOD,
                                     parents=[],
                                     klass=None,
                                     name=funcName,
                                     rindex=rindex)
        else:
            return CompletionOptions(Types.FUNCTION,
                                     name=funcName,
                                     rindex=rindex)

    if isAttrLookup and AST is not None:
        var = leftSideStripped[:leftSideStripped.rindex('.')]
        isClassLookup = var == 'self'
        if isClassLookup:
            klass, parents = inferClass(fullPath, AST, lineNo, PYSMELLDICT)
            return CompletionOptions(Types.INSTANCE,
                                     klass=klass,
                                     parents=parents)
        else:
            chain = getChain(leftSideStripped)  # strip dot
            if base and chain.endswith(base):
                chain = chain[:-len(base)]
            if chain.endswith('.'):
                chain = chain[:-1]
            possibleModule = inferModule(chain, AST, lineNo)
            if possibleModule is not None:
                return CompletionOptions(Types.MODULE,
                                         module=possibleModule,
                                         showMembers=True)
        klass, parents = inferInstance(fullPath, AST, lineNo, var, PYSMELLDICT)
        return CompletionOptions(Types.INSTANCE, klass=klass, parents=parents)

    return CompletionOptions(Types.TOPLEVEL)