Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/pyobjects.py
1415 views
from rope.base.fscommands import _decode_data1from rope.base import ast, exceptions, utils234class PyObject(object):56def __init__(self, type_):7if type_ is None:8type_ = self9self.type = type_1011def get_attributes(self):12if self.type is self:13return {}14return self.type.get_attributes()1516def get_attribute(self, name):17if name not in self.get_attributes():18raise exceptions.AttributeNotFoundError(19'Attribute %s not found' % name)20return self.get_attributes()[name]2122def get_type(self):23return self.type2425def __getitem__(self, key):26"""The same as ``get_attribute(key)``"""27return self.get_attribute(key)2829def __contains__(self, key):30"""The same as ``key in self.get_attributes()``"""31return key in self.get_attributes()3233def __eq__(self, obj):34"""Check the equality of two `PyObject`\s3536Currently it is assumed that instances (the direct instances37of `PyObject`, not the instances of its subclasses) are equal38if their types are equal. For every other object like39defineds or builtins rope assumes objects are reference40objects and their identities should match.4142"""43if self.__class__ != obj.__class__:44return False45if type(self) == PyObject:46if self is not self.type:47return self.type == obj.type48else:49return self.type is obj.type50return self is obj5152def __ne__(self, obj):53return not self.__eq__(obj)5455def __hash__(self):56"""See docs for `__eq__()` method"""57if type(self) == PyObject and self != self.type:58return hash(self.type) + 159else:60return super(PyObject, self).__hash__()6162def __iter__(self):63"""The same as ``iter(self.get_attributes())``"""64return iter(self.get_attributes())6566_types = None67_unknown = None6869@staticmethod70def _get_base_type(name):71if PyObject._types is None:72PyObject._types = {}73base_type = PyObject(None)74PyObject._types['Type'] = base_type75PyObject._types['Module'] = PyObject(base_type)76PyObject._types['Function'] = PyObject(base_type)77PyObject._types['Unknown'] = PyObject(base_type)78return PyObject._types[name]798081def get_base_type(name):82"""Return the base type with name `name`.8384The base types are 'Type', 'Function', 'Module' and 'Unknown'. It85was used to check the type of a `PyObject` but currently its use86is discouraged. Use classes defined in this module instead.87For example instead of88``pyobject.get_type() == get_base_type('Function')`` use89``isinstance(pyobject, AbstractFunction)``.9091You can use `AbstractClass` for classes, `AbstractFunction` for92functions, and `AbstractModule` for modules. You can also use93`PyFunction` and `PyClass` for testing if an object is94defined somewhere and rope can access its source. These classes95provide more methods.9697"""98return PyObject._get_base_type(name)99100101def get_unknown():102"""Return a pyobject whose type is unknown103104Note that two unknown objects are equal. So for example you can105write::106107if pyname.get_object() == get_unknown():108print 'cannot determine what this pyname holds'109110Rope could have used `None` for indicating unknown objects but111we had to check that in many places. So actually this method112returns a null object.113114"""115if PyObject._unknown is None:116PyObject._unknown = PyObject(get_base_type('Unknown'))117return PyObject._unknown118119120class AbstractClass(PyObject):121122def __init__(self):123super(AbstractClass, self).__init__(get_base_type('Type'))124125def get_name(self):126pass127128def get_doc(self):129pass130131def get_superclasses(self):132return []133134135class AbstractFunction(PyObject):136137def __init__(self):138super(AbstractFunction, self).__init__(get_base_type('Function'))139140def get_name(self):141pass142143def get_doc(self):144pass145146def get_param_names(self, special_args=True):147return []148149def get_returned_object(self, args):150return get_unknown()151152153class AbstractModule(PyObject):154155def __init__(self, doc=None):156super(AbstractModule, self).__init__(get_base_type('Module'))157158def get_doc(self):159pass160161def get_resource(self):162pass163164165class PyDefinedObject(object):166"""Python defined names that rope can access their sources"""167168def __init__(self, pycore, ast_node, parent):169self.pycore = pycore170self.ast_node = ast_node171self.scope = None172self.parent = parent173self.structural_attributes = None174self.concluded_attributes = self.get_module()._get_concluded_data()175self.attributes = self.get_module()._get_concluded_data()176self.defineds = None177178visitor_class = None179180@utils.prevent_recursion(lambda: {})181def _get_structural_attributes(self):182if self.structural_attributes is None:183self.structural_attributes = self._create_structural_attributes()184return self.structural_attributes185186@utils.prevent_recursion(lambda: {})187def _get_concluded_attributes(self):188if self.concluded_attributes.get() is None:189self._get_structural_attributes()190self.concluded_attributes.set(self._create_concluded_attributes())191return self.concluded_attributes.get()192193def get_attributes(self):194if self.attributes.get() is None:195result = dict(self._get_concluded_attributes())196result.update(self._get_structural_attributes())197self.attributes.set(result)198return self.attributes.get()199200def get_attribute(self, name):201if name in self._get_structural_attributes():202return self._get_structural_attributes()[name]203if name in self._get_concluded_attributes():204return self._get_concluded_attributes()[name]205raise exceptions.AttributeNotFoundError('Attribute %s not found' %206name)207208def get_scope(self):209if self.scope is None:210self.scope = self._create_scope()211return self.scope212213def get_module(self):214current_object = self215while current_object.parent is not None:216current_object = current_object.parent217return current_object218219def get_doc(self):220if len(self.get_ast().body) > 0:221expr = self.get_ast().body[0]222if isinstance(expr, ast.Expr) and \223isinstance(expr.value, ast.Str):224docstring = expr.value.s225coding = self.get_module().coding226return _decode_data(docstring, coding)227228def _get_defined_objects(self):229if self.defineds is None:230self._get_structural_attributes()231return self.defineds232233def _create_structural_attributes(self):234if self.visitor_class is None:235return {}236new_visitor = self.visitor_class(self.pycore, self)237for child in ast.get_child_nodes(self.ast_node):238ast.walk(child, new_visitor)239self.defineds = new_visitor.defineds240return new_visitor.names241242def _create_concluded_attributes(self):243return {}244245def get_ast(self):246return self.ast_node247248def _create_scope(self):249pass250251252class PyFunction(PyDefinedObject, AbstractFunction):253"""Only a placeholder"""254255256class PyClass(PyDefinedObject, AbstractClass):257"""Only a placeholder"""258259260class _ConcludedData(object):261262def __init__(self):263self.data_ = None264265def set(self, data):266self.data_ = data267268def get(self):269return self.data_270271data = property(get, set)272273def _invalidate(self):274self.data = None275276def __str__(self):277return '<' + str(self.data) + '>'278279280class _PyModule(PyDefinedObject, AbstractModule):281282def __init__(self, pycore, ast_node, resource):283self.resource = resource284self.concluded_data = []285AbstractModule.__init__(self)286PyDefinedObject.__init__(self, pycore, ast_node, None)287288def _get_concluded_data(self):289new_data = _ConcludedData()290self.concluded_data.append(new_data)291return new_data292293def _forget_concluded_data(self):294for data in self.concluded_data:295data._invalidate()296297def get_resource(self):298return self.resource299300301class PyModule(_PyModule):302"""Only a placeholder"""303304305class PyPackage(_PyModule):306"""Only a placeholder"""307308309class IsBeingInferredError(exceptions.RopeError):310pass311312313