Commit a08d2d04 authored by Stefan Behnel's avatar Stefan Behnel

add tests for JediTyper (includes disabled tests for things that currently do not work but should)

parent 6f930abe
# -*- coding: utf-8 -*-
# tag: jedi
from __future__ import absolute_import
import unittest
from textwrap import dedent
from contextlib import contextmanager
from tempfile import NamedTemporaryFile
from ..ParseTreeTransforms import NormalizeTree, InterpretCompilerDirectives
from .. import Main, Symtab, Visitor
from ...TestUtils import TransformTest
@contextmanager
def _tempfile(code):
code = dedent(code)
if isinstance(code, unicode):
code = code.encode('utf8')
with NamedTemporaryFile(suffix='.py') as f:
f.write(code)
f.seek(0)
yield f
def _test_typing(code, inject=False):
from ..JediTyper import analyse, inject_types
lines = []
with _tempfile(code) as f:
types = analyse(f.name)
if inject:
lines = inject_types(f.name, types)
return types, lines
class DeclarationsFinder(Visitor.VisitorTransform):
directives = None
visit_Node = Visitor.VisitorTransform.recurse_to_children
def visit_CompilerDirectivesNode(self, node):
if not self.directives:
self.directives = []
self.directives.append(node)
self.visitchildren(node)
return node
class TestJediTyper(TransformTest):
def _test(self, code):
return _test_typing(code)[0]
def test_typing_global_int_loop(self):
code = '''\
for i in range(10):
a = i + 1
'''
types = self._test(code)
self.assertIn((None, (1, 0)), types)
variables = types.pop((None, (1, 0)))
self.assertFalse(types)
self.assertEqual({'a': set(['int']), 'i': set(['int'])}, variables)
def test_typing_function_int_loop(self):
code = '''\
def func(x):
for i in range(x):
a = i + 1
return a
'''
types = self._test(code)
self.assertIn(('func', (1, 0)), types)
variables = types.pop(('func', (1, 0)))
self.assertFalse(types)
self.assertEqual({'a': set(['int']), 'i': set(['int'])}, variables)
def _test_conflicting_types_in_function(self):
code = '''\
def func(a, b):
print(a)
a = 1
b += a
a = 'abc'
return a, str(b)
print(func(1.5, 2))
'''
types = self._test(code)
self.assertIn(('func', (1, 0)), types)
variables = types.pop(('func', (1, 0)))
self.assertFalse(types)
self.assertEqual({'a': set(['int', 'str']), 'i': set(['int'])}, variables)
def _test_typing_function_char_loop(self):
code = '''\
def func(x):
l = []
for c in x:
l.append(c)
return l
print(func('abcdefg'))
'''
types = self._test(code)
self.assertIn(('func', (1, 0)), types)
variables = types.pop(('func', (1, 0)))
self.assertFalse(types)
self.assertEqual({'a': set(['int']), 'i': set(['int'])}, variables)
class TestTypeInjection(TestJediTyper):
"""
Subtype of TestJediTyper that additionally tests type injection and compilation.
"""
def setUp(self):
super(TestTypeInjection, self).setUp()
compilation_options = Main.CompilationOptions(Main.default_options)
ctx = compilation_options.create_context()
transform = InterpretCompilerDirectives(ctx, ctx.compiler_directives)
transform.module_scope = Symtab.ModuleScope('__main__', None, ctx)
self.declarations_finder = DeclarationsFinder()
self.pipeline = [NormalizeTree(None), transform, self.declarations_finder]
def _test(self, code):
types, lines = _test_typing(code, inject=True)
tree = self.run_pipeline(self.pipeline, ''.join(lines))
directives = self.declarations_finder.directives
# TODO: validate directives
return types
...@@ -95,7 +95,8 @@ EXT_DEP_MODULES = { ...@@ -95,7 +95,8 @@ EXT_DEP_MODULES = {
'tag:pstats': 'pstats', 'tag:pstats': 'pstats',
'tag:posix' : 'posix', 'tag:posix' : 'posix',
'tag:array' : 'array', 'tag:array' : 'array',
'tag:ipython': 'IPython' 'tag:ipython': 'IPython',
'tag:jedi': 'jedi',
} }
def patch_inspect_isfunction(): def patch_inspect_isfunction():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment