Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/oi/transform.py
1421 views
"""Provides classes for persisting `PyObject`\s"""1import os2import re34import rope.base.builtins5from rope.base import exceptions678class PyObjectToTextual(object):9"""For transforming `PyObject` to textual form1011This can be used for storing `PyObjects` in files. Use12`TextualToPyObject` for converting back.1314"""1516def __init__(self, project):17self.project = project1819def transform(self, pyobject):20"""Transform a `PyObject` to textual form"""21if pyobject is None:22return ('none',)23object_type = type(pyobject)24try:25method = getattr(self, object_type.__name__ + '_to_textual')26return method(pyobject)27except AttributeError:28return ('unknown',)2930def __call__(self, pyobject):31return self.transform(pyobject)3233def PyObject_to_textual(self, pyobject):34if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass):35result = self.transform(pyobject.get_type())36if result[0] == 'defined':37return ('instance', result)38return result39return ('unknown',)4041def PyFunction_to_textual(self, pyobject):42return self._defined_to_textual(pyobject)4344def PyClass_to_textual(self, pyobject):45return self._defined_to_textual(pyobject)4647def _defined_to_textual(self, pyobject):48address = []49while pyobject.parent is not None:50address.insert(0, pyobject.get_name())51pyobject = pyobject.parent52return ('defined', self._get_pymodule_path(pyobject.get_module()),53'.'.join(address))5455def PyModule_to_textual(self, pyobject):56return ('defined', self._get_pymodule_path(pyobject))5758def PyPackage_to_textual(self, pyobject):59return ('defined', self._get_pymodule_path(pyobject))6061def List_to_textual(self, pyobject):62return ('builtin', 'list', self.transform(pyobject.holding))6364def Dict_to_textual(self, pyobject):65return ('builtin', 'dict', self.transform(pyobject.keys),66self.transform(pyobject.values))6768def Tuple_to_textual(self, pyobject):69objects = [self.transform(holding)70for holding in pyobject.get_holding_objects()]71return tuple(['builtin', 'tuple'] + objects)7273def Set_to_textual(self, pyobject):74return ('builtin', 'set', self.transform(pyobject.holding))7576def Iterator_to_textual(self, pyobject):77return ('builtin', 'iter', self.transform(pyobject.holding))7879def Generator_to_textual(self, pyobject):80return ('builtin', 'generator', self.transform(pyobject.holding))8182def Str_to_textual(self, pyobject):83return ('builtin', 'str')8485def File_to_textual(self, pyobject):86return ('builtin', 'file')8788def BuiltinFunction_to_textual(self, pyobject):89return ('builtin', 'function', pyobject.get_name())9091def _get_pymodule_path(self, pymodule):92return self.resource_to_path(pymodule.get_resource())9394def resource_to_path(self, resource):95if resource.project == self.project:96return resource.path97else:98return resource.real_path99100101class TextualToPyObject(object):102"""For transforming textual form to `PyObject`"""103104def __init__(self, project, allow_in_project_absolutes=False):105self.project = project106107def __call__(self, textual):108return self.transform(textual)109110def transform(self, textual):111"""Transform an object from textual form to `PyObject`"""112if textual is None:113return None114type = textual[0]115try:116method = getattr(self, type + '_to_pyobject')117return method(textual)118except AttributeError:119return None120121def builtin_to_pyobject(self, textual):122name = textual[1]123method = getattr(self, 'builtin_%s_to_pyobject' % textual[1], None)124if method is not None:125return method(textual)126127def builtin_str_to_pyobject(self, textual):128return rope.base.builtins.get_str()129130def builtin_list_to_pyobject(self, textual):131holding = self.transform(textual[2])132return rope.base.builtins.get_list(holding)133134def builtin_dict_to_pyobject(self, textual):135keys = self.transform(textual[2])136values = self.transform(textual[3])137return rope.base.builtins.get_dict(keys, values)138139def builtin_tuple_to_pyobject(self, textual):140objects = []141for holding in textual[2:]:142objects.append(self.transform(holding))143return rope.base.builtins.get_tuple(*objects)144145def builtin_set_to_pyobject(self, textual):146holding = self.transform(textual[2])147return rope.base.builtins.get_set(holding)148149def builtin_iter_to_pyobject(self, textual):150holding = self.transform(textual[2])151return rope.base.builtins.get_iterator(holding)152153def builtin_generator_to_pyobject(self, textual):154holding = self.transform(textual[2])155return rope.base.builtins.get_generator(holding)156157def builtin_file_to_pyobject(self, textual):158return rope.base.builtins.get_file()159160def builtin_function_to_pyobject(self, textual):161if textual[2] in rope.base.builtins.builtins:162return rope.base.builtins.builtins[textual[2]].get_object()163164def unknown_to_pyobject(self, textual):165return None166167def none_to_pyobject(self, textual):168return None169170def _module_to_pyobject(self, textual):171path = textual[1]172return self._get_pymodule(path)173174def _hierarchical_defined_to_pyobject(self, textual):175path = textual[1]176names = textual[2].split('.')177pymodule = self._get_pymodule(path)178pyobject = pymodule179for name in names:180if pyobject is None:181return None182if isinstance(pyobject, rope.base.pyobjects.PyDefinedObject):183try:184pyobject = pyobject.get_scope()[name].get_object()185except exceptions.NameNotFoundError:186return None187else:188return None189return pyobject190191def defined_to_pyobject(self, textual):192if len(textual) == 2 or textual[2] == '':193return self._module_to_pyobject(textual)194else:195return self._hierarchical_defined_to_pyobject(textual)196197def instance_to_pyobject(self, textual):198type = self.transform(textual[1])199if type is not None:200return rope.base.pyobjects.PyObject(type)201202def _get_pymodule(self, path):203resource = self.path_to_resource(path)204if resource is not None:205return self.project.pycore.resource_to_pyobject(resource)206207def path_to_resource(self, path):208try:209root = self.project.address210if not os.path.isabs(path):211return self.project.get_resource(path)212if path == root or path.startswith(root + os.sep):213# INFO: This is a project file; should not be absolute214return None215import rope.base.project216return rope.base.project.get_no_project().get_resource(path)217except exceptions.ResourceNotFoundError:218return None219220221class DOITextualToPyObject(TextualToPyObject):222"""For transforming textual form to `PyObject`223224The textual form DOI uses is different from rope's standard225textual form. The reason is that we cannot find the needed226information by analyzing live objects. This class can be227used to transform DOI textual form to `PyObject` and later228we can convert it to standard textual form using229`TextualToPyObject` class.230231"""232233def _function_to_pyobject(self, textual):234path = textual[1]235lineno = int(textual[2])236pymodule = self._get_pymodule(path)237if pymodule is not None:238scope = pymodule.get_scope()239inner_scope = scope.get_inner_scope_for_line(lineno)240return inner_scope.pyobject241242def _class_to_pyobject(self, textual):243path, name = textual[1:]244pymodule = self._get_pymodule(path)245if pymodule is None:246return None247module_scope = pymodule.get_scope()248suspected = None249if name in module_scope.get_names():250suspected = module_scope[name].get_object()251if suspected is not None and \252isinstance(suspected, rope.base.pyobjects.PyClass):253return suspected254else:255lineno = self._find_occurrence(name, pymodule.get_resource().read())256if lineno is not None:257inner_scope = module_scope.get_inner_scope_for_line(lineno)258return inner_scope.pyobject259260def defined_to_pyobject(self, textual):261if len(textual) == 2:262return self._module_to_pyobject(textual)263else:264if textual[2].isdigit():265result = self._function_to_pyobject(textual)266else:267result = self._class_to_pyobject(textual)268if not isinstance(result, rope.base.pyobjects.PyModule):269return result270271def _find_occurrence(self, name, source):272pattern = re.compile(r'^\s*class\s*' + name + r'\b')273lines = source.split('\n')274for i in range(len(lines)):275if pattern.match(lines[i]):276return i + 1277278def path_to_resource(self, path):279import rope.base.libutils280root = self.project.address281relpath = rope.base.libutils.relative(root, path)282if relpath is not None:283path = relpath284return super(DOITextualToPyObject, self).path_to_resource(path)285286287