import rope.base.codeanalyze
import rope.base.evaluate
import rope.base.builtins
import rope.base.oi.soi
import rope.base.pyscopes
from rope.base import (pynamesdef
astutils, pyobjects, fscommands, arguments, utils)
from rope.base.pyobjects import *
class PyFunction(pyobjects.PyFunction):
def __init__(self, pycore, ast_node, parent):
AbstractFunction.__init__(self)
PyDefinedObject.__init__(self, pycore, ast_node, parent)
self.arguments = self.ast_node.args
self.parameter_pyobjects = pynames._Inferred(
self._infer_parameters, self.get_module()._get_concluded_data())
self.returned = pynames._Inferred(self._infer_returned)
self.parameter_pynames = None
def _create_structural_attributes(self):
return {}
def _create_concluded_attributes(self):
return {}
def _create_scope(self):
return rope.base.pyscopes.FunctionScope(self.pycore, self,
_FunctionVisitor)
def _infer_parameters(self):
pyobjects = rope.base.oi.soi.infer_parameter_objects(self)
self._handle_special_args(pyobjects)
return pyobjects
def _infer_returned(self, args=None):
return rope.base.oi.soi.infer_returned_object(self, args)
def _handle_special_args(self, pyobjects):
if len(pyobjects) == len(self.arguments.args):
if self.arguments.vararg:
pyobjects.append(rope.base.builtins.get_list())
if self.arguments.kwarg:
pyobjects.append(rope.base.builtins.get_dict())
def _set_parameter_pyobjects(self, pyobjects):
if pyobjects is not None:
self._handle_special_args(pyobjects)
self.parameter_pyobjects.set(pyobjects)
def get_parameters(self):
if self.parameter_pynames is None:
result = {}
for index, name in enumerate(self.get_param_names()):
# TODO: handle tuple parameters
result[name] = pynames.ParameterName(self, index)
self.parameter_pynames = result
return self.parameter_pynames
def get_parameter(self, index):
if index < len(self.parameter_pyobjects.get()):
return self.parameter_pyobjects.get()[index]
def get_returned_object(self, args):
return self.returned.get(args)
def get_name(self):
return self.get_ast().name
def get_param_names(self, special_args=True):
# TODO: handle tuple parameters
result = [node.id for node in self.arguments.args
if isinstance(node, ast.Name)]
if special_args:
if self.arguments.vararg:
result.append(self.arguments.vararg)
if self.arguments.kwarg:
result.append(self.arguments.kwarg)
return result
def get_kind(self):
"""Get function type
It returns one of 'function', 'method', 'staticmethod' or
'classmethod' strs.
"""
scope = self.parent.get_scope()
if isinstance(self.parent, PyClass):
for decorator in self.decorators:
pyname = rope.base.evaluate.eval_node(scope, decorator)
if pyname == rope.base.builtins.builtins['staticmethod']:
return 'staticmethod'
if pyname == rope.base.builtins.builtins['classmethod']:
return 'classmethod'
return 'method'
return 'function'
@property
def decorators(self):
try:
return getattr(self.ast_node, 'decorator_list')
except AttributeError:
return getattr(self.ast_node, 'decorators', None)
class PyClass(pyobjects.PyClass):
def __init__(self, pycore, ast_node, parent):
self.visitor_class = _ClassVisitor
AbstractClass.__init__(self)
PyDefinedObject.__init__(self, pycore, ast_node, parent)
self.parent = parent
self._superclasses = self.get_module()._get_concluded_data()
def get_superclasses(self):
if self._superclasses.get() is None:
self._superclasses.set(self._get_bases())
return self._superclasses.get()
def get_name(self):
return self.get_ast().name
def _create_concluded_attributes(self):
result = {}
for base in reversed(self.get_superclasses()):
result.update(base.get_attributes())
return result
def _get_bases(self):
result = []
for base_name in self.ast_node.bases:
base = rope.base.evaluate.eval_node(self.parent.get_scope(),
base_name)
if base is not None and \
base.get_object().get_type() == get_base_type('Type'):
result.append(base.get_object())
return result
def _create_scope(self):
return rope.base.pyscopes.ClassScope(self.pycore, self)
class PyModule(pyobjects.PyModule):
def __init__(self, pycore, source=None,
resource=None, force_errors=False):
ignore = pycore.project.prefs.get('ignore_syntax_errors', False)
syntax_errors = force_errors or not ignore
try:
source, node = self._init_source(pycore, source, resource)
except exceptions.ModuleSyntaxError:
if syntax_errors:
raise
else:
source = '\n'
node = ast.parse('\n')
self.source_code = source
self.star_imports = []
self.visitor_class = _GlobalVisitor
super(PyModule, self).__init__(pycore, node, resource)
def _init_source(self, pycore, source_code, resource):
filename = 'string'
if resource:
filename = resource.path
try:
if source_code is None:
source_bytes = resource.read_bytes()
source_code = fscommands.file_data_to_unicode(source_bytes)
else:
if isinstance(source_code, unicode):
source_bytes = fscommands.unicode_to_file_data(source_code)
else:
source_bytes = source_code
ast_node = ast.parse(source_bytes, filename=filename)
except SyntaxError, e:
raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg)
except UnicodeDecodeError, e:
raise exceptions.ModuleSyntaxError(filename, 1, '%s' % (e.reason))
return source_code, ast_node
@utils.prevent_recursion(lambda: {})
def _create_concluded_attributes(self):
result = {}
for star_import in self.star_imports:
result.update(star_import.get_names())
return result
def _create_scope(self):
return rope.base.pyscopes.GlobalScope(self.pycore, self)
@property
@utils.saveit
def lines(self):
"""A `SourceLinesAdapter`"""
return rope.base.codeanalyze.SourceLinesAdapter(self.source_code)
@property
@utils.saveit
def logical_lines(self):
"""A `LogicalLinesFinder`"""
return rope.base.codeanalyze.CachingLogicalLineFinder(self.lines)
class PyPackage(pyobjects.PyPackage):
def __init__(self, pycore, resource=None, force_errors=False):
self.resource = resource
init_dot_py = self._get_init_dot_py()
if init_dot_py is not None:
ast_node = pycore.resource_to_pyobject(
init_dot_py, force_errors=force_errors).get_ast()
else:
ast_node = ast.parse('\n')
super(PyPackage, self).__init__(pycore, ast_node, resource)
def _create_structural_attributes(self):
result = {}
modname = self.pycore.modname(self.resource)
extension_submodules = self.pycore._builtin_submodules(modname)
for name, module in extension_submodules.iteritems():
result[name] = rope.base.builtins.BuiltinName(module)
if self.resource is None:
return result
for name, resource in self._get_child_resources().items():
result[name] = pynames.ImportedModule(self, resource=resource)
return result
def _create_concluded_attributes(self):
result = {}
init_dot_py = self._get_init_dot_py()
if init_dot_py:
init_object = self.pycore.resource_to_pyobject(init_dot_py)
result.update(init_object.get_attributes())
return result
def _get_child_resources(self):
result = {}
for child in self.resource.get_children():
if child.is_folder():
result[child.name] = child
elif child.name.endswith('.py') and \
child.name != '__init__.py':
name = child.name[:-3]
result[name] = child
return result
def _get_init_dot_py(self):
if self.resource is not None and self.resource.has_child('__init__.py'):
return self.resource.get_child('__init__.py')
else:
return None
def _create_scope(self):
return self.get_module().get_scope()
def get_module(self):
init_dot_py = self._get_init_dot_py()
if init_dot_py:
return self.pycore.resource_to_pyobject(init_dot_py)
return self
class _AssignVisitor(object):
def __init__(self, scope_visitor):
self.scope_visitor = scope_visitor
self.assigned_ast = None
def _Assign(self, node):
self.assigned_ast = node.value
for child_node in node.targets:
ast.walk(child_node, self)
def _assigned(self, name, assignment=None):
self.scope_visitor._assigned(name, assignment)
def _Name(self, node):
assignment = None
if self.assigned_ast is not None:
assignment = pynames.AssignmentValue(self.assigned_ast)
self._assigned(node.id, assignment)
def _Tuple(self, node):
names = astutils.get_name_levels(node)
for name, levels in names:
assignment = None
if self.assigned_ast is not None:
assignment = pynames.AssignmentValue(self.assigned_ast, levels)
self._assigned(name, assignment)
def _Attribute(self, node):
pass
def _Subscript(self, node):
pass
def _Slice(self, node):
pass
class _ScopeVisitor(object):
def __init__(self, pycore, owner_object):
self.pycore = pycore
self.owner_object = owner_object
self.names = {}
self.defineds = []
def get_module(self):
if self.owner_object is not None:
return self.owner_object.get_module()
else:
return None
def _ClassDef(self, node):
pyclass = PyClass(self.pycore, node, self.owner_object)
self.names[node.name] = pynames.DefinedName(pyclass)
self.defineds.append(pyclass)
def _FunctionDef(self, node):
pyfunction = PyFunction(self.pycore, node, self.owner_object)
for decorator in pyfunction.decorators:
if isinstance(decorator, ast.Name) and decorator.id == 'property':
if isinstance(self, _ClassVisitor):
type_ = rope.base.builtins.Property(pyfunction)
arg = pynames.UnboundName(PyObject(self.owner_object))
def _eval(type_=type_, arg=arg):
return type_.get_property_object(
arguments.ObjectArguments([arg]))
self.names[node.name] = pynames.EvaluatedName(
_eval, module=self.get_module(), lineno=node.lineno)
break
else:
self.names[node.name] = pynames.DefinedName(pyfunction)
self.defineds.append(pyfunction)
def _Assign(self, node):
ast.walk(node, _AssignVisitor(self))
def _AugAssign(self, node):
pass
def _For(self, node):
names = self._update_evaluated(node.target, node.iter,
'.__iter__().next()')
for child in node.body + node.orelse:
ast.walk(child, self)
def _assigned(self, name, assignment):
pyname = self.names.get(name, None)
if pyname is None:
pyname = pynames.AssignedName(module=self.get_module())
if isinstance(pyname, pynames.AssignedName):
if assignment is not None:
pyname.assignments.append(assignment)
self.names[name] = pyname
def _update_evaluated(self, targets, assigned,
evaluation= '', eval_type=False):
result = {}
names = astutils.get_name_levels(targets)
for name, levels in names:
assignment = pynames.AssignmentValue(assigned, levels,
evaluation, eval_type)
self._assigned(name, assignment)
return result
def _With(self, node):
if node.optional_vars:
self._update_evaluated(node.optional_vars,
node.context_expr, '.__enter__()')
for child in node.body:
ast.walk(child, self)
def _excepthandler(self, node):
if node.name is not None and isinstance(node.name, ast.Name):
type_node = node.type
if isinstance(node.type, ast.Tuple) and type_node.elts:
type_node = type_node.elts[0]
self._update_evaluated(node.name, type_node, eval_type=True)
for child in node.body:
ast.walk(child, self)
def _ExceptHandler(self, node):
self._excepthandler(node)
def _Import(self, node):
for import_pair in node.names:
module_name = import_pair.name
alias = import_pair.asname
first_package = module_name.split('.')[0]
if alias is not None:
imported = pynames.ImportedModule(self.get_module(),
module_name)
if not self._is_ignored_import(imported):
self.names[alias] = imported
else:
imported = pynames.ImportedModule(self.get_module(),
first_package)
if not self._is_ignored_import(imported):
self.names[first_package] = imported
def _ImportFrom(self, node):
level = 0
if node.level:
level = node.level
imported_module = pynames.ImportedModule(self.get_module(),
node.module, level)
if self._is_ignored_import(imported_module):
return
if len(node.names) == 1 and node.names[0].name == '*':
if isinstance(self.owner_object, PyModule):
self.owner_object.star_imports.append(
StarImport(imported_module))
else:
for imported_name in node.names:
imported = imported_name.name
alias = imported_name.asname
if alias is not None:
imported = alias
self.names[imported] = pynames.ImportedName(imported_module,
imported_name.name)
def _is_ignored_import(self, imported_module):
if not self.pycore.project.prefs.get('ignore_bad_imports', False):
return False
return not isinstance(imported_module.get_object(), AbstractModule)
def _Global(self, node):
module = self.get_module()
for name in node.names:
if module is not None:
try:
pyname = module[name]
except exceptions.AttributeNotFoundError:
pyname = pynames.AssignedName(node.lineno)
self.names[name] = pyname
class _GlobalVisitor(_ScopeVisitor):
def __init__(self, pycore, owner_object):
super(_GlobalVisitor, self).__init__(pycore, owner_object)
class _ClassVisitor(_ScopeVisitor):
def __init__(self, pycore, owner_object):
super(_ClassVisitor, self).__init__(pycore, owner_object)
def _FunctionDef(self, node):
_ScopeVisitor._FunctionDef(self, node)
if len(node.args.args) > 0:
first = node.args.args[0]
if isinstance(first, ast.Name):
new_visitor = _ClassInitVisitor(self, first.id)
for child in ast.get_child_nodes(node):
ast.walk(child, new_visitor)
class _FunctionVisitor(_ScopeVisitor):
def __init__(self, pycore, owner_object):
super(_FunctionVisitor, self).__init__(pycore, owner_object)
self.returned_asts = []
self.generator = False
def _Return(self, node):
if node.value is not None:
self.returned_asts.append(node.value)
def _Yield(self, node):
if node.value is not None:
self.returned_asts.append(node.value)
self.generator = True
class _ClassInitVisitor(_AssignVisitor):
def __init__(self, scope_visitor, self_name):
super(_ClassInitVisitor, self).__init__(scope_visitor)
self.self_name = self_name
def _Attribute(self, node):
if not isinstance(node.ctx, ast.Store):
return
if isinstance(node.value, ast.Name) and \
node.value.id == self.self_name:
if node.attr not in self.scope_visitor.names:
self.scope_visitor.names[node.attr] = pynames.AssignedName(
lineno=node.lineno, module=self.scope_visitor.get_module())
if self.assigned_ast is not None:
pyname = self.scope_visitor.names[node.attr]
if isinstance(pyname, pynames.AssignedName):
pyname.assignments.append(
pynames.AssignmentValue(self.assigned_ast))
def _Tuple(self, node):
if not isinstance(node.ctx, ast.Store):
return
for child in ast.get_child_nodes(node):
ast.walk(child, self)
def _Name(self, node):
pass
def _FunctionDef(self, node):
pass
def _ClassDef(self, node):
pass
def _For(self, node):
pass
def _With(self, node):
pass
class StarImport(object):
def __init__(self, imported_module):
self.imported_module = imported_module
def get_names(self):
result = {}
imported = self.imported_module.get_object()
for name in imported:
if not name.startswith('_'):
result[name] = pynames.ImportedName(self.imported_module, name)
return result
|