generate.py :  » Development » Rope » rope-0.9.2 » rope » contrib » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Rope 
Rope » rope 0.9.2 » rope » contrib » generate.py
import rope.base.evaluate
from rope.base import change,pyobjects,exceptions,pynames,worder,codeanalyze
from rope.refactor import sourceutils,importutils,functionutils,suites


def create_generate(kind, project, resource, offset):
    """A factory for creating `Generate` objects

    `kind` can be 'variable', 'function', 'class', 'module' or
    'package'.

    """
    generate = eval('Generate' + kind.title())
    return generate(project, resource, offset)


def create_module(project, name, sourcefolder=None):
    """Creates a module and returns a `rope.base.resources.File`"""
    if sourcefolder is None:
        sourcefolder = project.root
    packages = name.split('.')
    parent = sourcefolder
    for package in packages[:-1]:
        parent = parent.get_child(package)
    return parent.create_file(packages[-1] + '.py')

def create_package(project, name, sourcefolder=None):
    """Creates a package and returns a `rope.base.resources.Folder`"""
    if sourcefolder is None:
        sourcefolder = project.root
    packages = name.split('.')
    parent = sourcefolder
    for package in packages[:-1]:
        parent = parent.get_child(package)
    made_packages = parent.create_folder(packages[-1])
    made_packages.create_file('__init__.py')
    return made_packages


class _Generate(object):

    def __init__(self, project, resource, offset):
        self.project = project
        self.resource = resource
        self.info = self._generate_info(project, resource, offset)
        self.name = self.info.get_name()
        self._check_exceptional_conditions()

    def _generate_info(self, project, resource, offset):
        return _GenerationInfo(project.pycore, resource, offset)

    def _check_exceptional_conditions(self):
        if self.info.element_already_exists():
            raise exceptions.RefactoringError(
                'Element <%s> already exists.' % self.name)
        if not self.info.primary_is_found():
            raise exceptions.RefactoringError(
                'Cannot determine the scope <%s> should be defined in.' % self.name)

    def get_changes(self):
        changes = change.ChangeSet('Generate %s <%s>' %
                                   (self._get_element_kind(), self.name))
        indents = self.info.get_scope_indents()
        blanks = self.info.get_blank_lines()
        base_definition = sourceutils.fix_indentation(self._get_element(), indents)
        definition = '\n' * blanks[0] + base_definition + '\n' * blanks[1]

        resource = self.info.get_insertion_resource()
        start, end = self.info.get_insertion_offsets()

        collector = codeanalyze.ChangeCollector(resource.read())
        collector.add_change(start, end, definition)
        changes.add_change(change.ChangeContents(
                           resource, collector.get_changed()))
        return changes

    def get_location(self):
        return (self.info.get_insertion_resource(),
                self.info.get_insertion_lineno())

    def _get_element_kind(self):
        raise NotImplementedError()

    def _get_element(self):
        raise NotImplementedError()


class GenerateFunction(_Generate):

    def _generate_info(self, project, resource, offset):
        return _FunctionGenerationInfo(project.pycore, resource, offset)

    def _get_element(self):
        decorator = ''
        args = []
        if self.info.is_static_method():
            decorator = '@staticmethod\n'
        if self.info.is_method() or self.info.is_constructor() or \
           self.info.is_instance():
            args.append('self')
        args.extend(self.info.get_passed_args())
        definition = '%sdef %s(%s):\n    pass\n' % (decorator, self.name,
                                                    ', '.join(args))
        return definition

    def _get_element_kind(self):
        return 'Function'


class GenerateVariable(_Generate):

    def _get_element(self):
        return '%s = None\n' % self.name

    def _get_element_kind(self):
        return 'Variable'


class GenerateClass(_Generate):

    def _get_element(self):
        return 'class %s(object):\n    pass\n' % self.name

    def _get_element_kind(self):
        return 'Class'


class GenerateModule(_Generate):

    def get_changes(self):
        package = self.info.get_package()
        changes = change.ChangeSet('Generate Module <%s>' % self.name)
        new_resource = self.project.get_file('%s/%s.py' % (package.path, self.name))
        if new_resource.exists():
            raise exceptions.RefactoringError(
                'Module <%s> already exists' % new_resource.path)
        changes.add_change(change.CreateResource(new_resource))
        changes.add_change(_add_import_to_module(
                           self.project.pycore, self.resource, new_resource))
        return changes

    def get_location(self):
        package = self.info.get_package()
        return (package.get_child('%s.py' % self.name) , 1)


class GeneratePackage(_Generate):

    def get_changes(self):
        package = self.info.get_package()
        changes = change.ChangeSet('Generate Package <%s>' % self.name)
        new_resource = self.project.get_folder('%s/%s' % (package.path, self.name))
        if new_resource.exists():
            raise exceptions.RefactoringError(
                'Package <%s> already exists' % new_resource.path)
        changes.add_change(change.CreateResource(new_resource))
        changes.add_change(_add_import_to_module(
                           self.project.pycore, self.resource, new_resource))
        child = self.project.get_folder(package.path + '/' + self.name)
        changes.add_change(change.CreateFile(child, '__init__.py'))
        return changes

    def get_location(self):
        package = self.info.get_package()
        child = package.get_child(self.name)
        return (child.get_child('__init__.py') , 1)


def _add_import_to_module(pycore, resource, imported):
    pymodule = pycore.resource_to_pyobject(resource)
    import_tools = importutils.ImportTools(pycore)
    module_imports = import_tools.module_imports(pymodule)
    module_name = pycore.modname(imported)
    new_import = importutils.NormalImport(((module_name, None), ))
    module_imports.add_import(new_import)
    return change.ChangeContents(resource, module_imports.get_changed_source())


class _GenerationInfo(object):

    def __init__(self, pycore, resource, offset):
        self.pycore = pycore
        self.resource = resource
        self.offset = offset
        self.source_pymodule = self.pycore.resource_to_pyobject(resource)
        finder = rope.base.evaluate.ScopeNameFinder(self.source_pymodule)
        self.primary, self.pyname = finder.get_primary_and_pyname_at(offset)
        self._init_fields()

    def _init_fields(self):
        self.source_scope = self._get_source_scope()
        self.goal_scope = self._get_goal_scope()
        self.goal_pymodule = self._get_goal_module(self.goal_scope)

    def _get_goal_scope(self):
        if self.primary is None:
            return self._get_source_scope()
        pyobject = self.primary.get_object()
        if isinstance(pyobject, pyobjects.PyDefinedObject):
            return pyobject.get_scope()
        elif isinstance(pyobject.get_type(), pyobjects.PyClass):
            return pyobject.get_type().get_scope()

    def _get_goal_module(self, scope):
        if scope is None:
            return
        while scope.parent is not None:
            scope = scope.parent
        return scope.pyobject

    def _get_source_scope(self):
        module_scope = self.source_pymodule.get_scope()
        lineno = self.source_pymodule.lines.get_line_number(self.offset)
        return module_scope.get_inner_scope_for_line(lineno)

    def get_insertion_lineno(self):
        lines = self.goal_pymodule.lines
        if self.goal_scope == self.source_scope:
            line_finder = self.goal_pymodule.logical_lines
            lineno = lines.get_line_number(self.offset)
            lineno = line_finder.logical_line_in(lineno)[0]
            root = suites.ast_suite_tree(self.goal_scope.pyobject.get_ast())
            suite = root.find_suite(lineno)
            indents = sourceutils.get_indents(lines, lineno)
            while self.get_scope_indents() < indents:
                lineno = suite.get_start()
                indents = sourceutils.get_indents(lines, lineno)
                suite = suite.parent
            return lineno
        else:
            return min(self.goal_scope.get_end() + 1, lines.length())

    def get_insertion_resource(self):
        return self.goal_pymodule.get_resource()

    def get_insertion_offsets(self):
        if self.goal_scope.get_kind() == 'Class':
            start, end = sourceutils.get_body_region(self.goal_scope.pyobject)
            if self.goal_pymodule.source_code[start:end].strip() == 'pass':
                return start, end
        lines = self.goal_pymodule.lines
        start = lines.get_line_start(self.get_insertion_lineno())
        return (start, start)

    def get_scope_indents(self):
        if self.goal_scope.get_kind() == 'Module':
            return 0
        return sourceutils.get_indents(self.goal_pymodule.lines,
                                       self.goal_scope.get_start()) + 4

    def get_blank_lines(self):
        if self.goal_scope.get_kind() == 'Module':
            base_blanks = 2
            if self.goal_pymodule.source_code.strip() == '':
                base_blanks = 0
        if self.goal_scope.get_kind() == 'Class':
            base_blanks = 1
        if self.goal_scope.get_kind() == 'Function':
            base_blanks = 0
        if self.goal_scope == self.source_scope:
            return (0, base_blanks)
        return (base_blanks, 0)

    def get_package(self):
        primary = self.primary
        if self.primary is None:
            return self.pycore.get_source_folders()[0]
        if isinstance(primary.get_object(), pyobjects.PyPackage):
            return primary.get_object().get_resource()
        raise exceptions.RefactoringError(
            'A module/package can be only created in a package.')

    def primary_is_found(self):
        return self.goal_scope is not None

    def element_already_exists(self):
        if self.pyname is None or isinstance(self.pyname, pynames.UnboundName):
            return False
        return self.get_name() in self.goal_scope.get_defined_names()

    def get_name(self):
        return worder.get_name_at(self.resource, self.offset)


class _FunctionGenerationInfo(_GenerationInfo):

    def _get_goal_scope(self):
        if self.is_constructor():
            return self.pyname.get_object().get_scope()
        if self.is_instance():
            return self.pyname.get_object().get_type().get_scope()
        if self.primary is None:
            return self._get_source_scope()
        pyobject = self.primary.get_object()
        if isinstance(pyobject, pyobjects.PyDefinedObject):
            return pyobject.get_scope()
        elif isinstance(pyobject.get_type(), pyobjects.PyClass):
            return pyobject.get_type().get_scope()

    def element_already_exists(self):
        if self.pyname is None or isinstance(self.pyname, pynames.UnboundName):
            return False
        return self.get_name() in self.goal_scope.get_defined_names()

    def is_static_method(self):
        return self.primary is not None and \
               isinstance(self.primary.get_object(), pyobjects.PyClass)

    def is_method(self):
        return self.primary is not None and \
               isinstance(self.primary.get_object().get_type(), pyobjects.PyClass)

    def is_constructor(self):
        return self.pyname is not None and \
               isinstance(self.pyname.get_object(), pyobjects.PyClass)

    def is_instance(self):
        if self.pyname is None:
            return False
        pyobject = self.pyname.get_object()
        return isinstance(pyobject.get_type(), pyobjects.PyClass)

    def get_name(self):
        if self.is_constructor():
            return '__init__'
        if self.is_instance():
            return '__call__'
        return worder.get_name_at(self.resource, self.offset)

    def get_passed_args(self):
        result = []
        source = self.source_pymodule.source_code
        finder = worder.Worder(source)
        if finder.is_a_function_being_called(self.offset):
            start, end = finder.get_primary_range(self.offset)
            parens_start, parens_end = finder.get_word_parens_range(end - 1)
            call = source[start:parens_end]
            parser = functionutils._FunctionParser(call, False)
            args, keywords = parser.get_parameters()
            for arg in args:
                if self._is_id(arg):
                    result.append(arg)
                else:
                    result.append('arg%d' % len(result))
            for name, value in keywords:
                result.append(name)
        return result

    def _is_id(self, arg):
        def id_or_underline(c):
            return c.isalpha() or c == '_'
        for c in arg:
            if not id_or_underline(c) and not c.isdigit():
                return False
        return id_or_underline(arg[0])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.