python.py :  » IDE » PIDA » pida-0.6beta3 » pida-plugins » python » 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 » IDE » PIDA 
PIDA » pida 0.6beta3 » pida plugins » python » python.py
# -*- coding: utf-8 -*- 

# Copyright (c) 2007 The PIDA Project

#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:

#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.

# stdlib
import sys, compiler, os.path, keyword, re

# gtk
import gtk

# PIDA Imports

# core
from pida.core.service import Service
from pida.core.events import EventsConfig
from pida.core.actions import ActionsConfig,TYPE_NORMAL
from pida.core.options import OptionsConfig
from pida.core.languages import (LanguageService,Outliner,Validator
    Completer, LanguageServiceFeaturesConfig, LanguageInfo, Definer, 
    Documentator, External)

from pida.utils.languages import (LANG_COMPLETER_TYPES
    LANG_VALIDATOR_TYPES, LANG_VALIDATOR_SUBTYPES, LANG_OUTLINER_TYPES, 
    LANG_PRIO, Definition, Suggestion, Documentation, ValidationError)

# services
import pida.services.filemanager.filehiddencheck as filehiddencheck

# utils
from .pyflakes.checker import Checker
from  import pyflakes
from .pyflakes import messages
# locale
from pida.core.locale import Locale
locale = Locale('python')
_ = locale.gettext

from .ropebrowser import ModuleParser

MAX_FIXES = 10
RE_MATCHES = (
    # traceback match
    (r'''File\s*"([^"]+)",\s*line\s*[0-9]+''',
    # internal
     re.compile(r'\s*File\s*\"(?P<file>[^"]+)\",\s*line\s*(?P<line>\d+).*'))
    ,
    #FIXME: how to handle localisation of this ???
)


class PythonEventsConfig(EventsConfig):

    def subscribe_all_foreign(self):
        self.subscribe_foreign('buffer', 'document-changed',
                    self.on_document_changed)
        self.subscribe_foreign('buffer', 'document-typchanged',
                    self.on_document_changed)

    def on_document_changed(self, document):
        self.svc.set_document(document)


class PythonFeaturesConfig(LanguageServiceFeaturesConfig):

    def subscribe_all_foreign(self):
        LanguageServiceFeaturesConfig.subscribe_all_foreign(self)
        self.subscribe_foreign('filemanager', 'file_hidden_check',
            self.python)
        for match in RE_MATCHES:
            self.subscribe_foreign('commander', 'match-callback',
            ('Python', match[0], match[1], self.svc.match_call))


    @filehiddencheck.fhc(filehiddencheck.SCOPE_PROJECT, 
        _("Hide Python Compiled Files"))
    def python(self, name, path, state):
        return os.path.splitext(name)[1] != '.pyc'


class PythonOptionsConfig(OptionsConfig):

    def create_options(self):
        self.create_option(
            'python_for_executing',
            _('Python Executable for executing'),
            str,
            'python',
            _('The Python executable when executing a module'),
        )


class PythonActionsConfig(ActionsConfig):

    def create_actions(self):
        self.create_action(
            'execute_python',
            TYPE_NORMAL,
            _('Execute Python Module'),
            _('Execute the current Python module in a shell'),
            gtk.STOCK_EXECUTE,
            self.on_python_execute,
        )

    def on_python_execute(self, action):
        self.svc.execute_current_document()


class PythonOutliner(Outliner):

    priority = LANG_PRIO.VERY_GOOD
    name = "rope"
    plugin = "python"
    description = _("A very deep and precises, but slow outliner")


    filter_type = (LANG_OUTLINER_TYPES.IMPORT,
                    LANG_OUTLINER_TYPES.BUILTIN,
                    LANG_OUTLINER_TYPES.METHOD,
                    LANG_OUTLINER_TYPES.FUNCTION,
                    LANG_OUTLINER_TYPES.PROPERTY,
                    LANG_OUTLINER_TYPES.ATTRIBUTE,
                    LANG_OUTLINER_TYPES.SUPERMETHOD,
                    )

    def get_outline(self):
        from rope.base.exceptions import RopeError
        try:
            mp = ModuleParser(self.document.filename,
                              project=self.document.project)
        except RopeError:
            return
        try:
            for node, parent in mp.get_nodes():
                yield node
        except Exception, e:
            import traceback
            traceback.print_exc()

    def sync(self):
        try:
            self.document.project['python']['ropeproject'].sync()
        except (KeyError, TypeError), e:
            pass

    def close(self):
        try:
            self.document.project['python']['ropeproject'].close()
        except (KeyError, TypeError), e:
            pass


class PythonDocumentator(Documentator):

    name = "rope"
    plugin = "python"
    description = _("A very good documentator")


    def get_documentation(self, buffer, offset):
        mp = ModuleParser(self.document.filename,
                          project=self.document.project)
        buffer = buffer + ('\n' * 20)
        
        from rope.contrib.codeassist import PyDocExtractor
        from rope.base.exceptions import RopeError
        from rope.contrib import fixsyntax
        try:
            fix = fixsyntax.FixSyntax(mp.project.pycore, buffer, None, maxfixes=MAX_FIXES)
            pymodule = fix.get_pymodule()
            pyname = fix.pyname_at(offset)
        except RopeError:
            return
        if pyname is None:
            return
        pyobject = pyname.get_object()
        rv = Documentation(
            short=PyDocExtractor().get_calltip(pyobject, False, False),
            long_=PyDocExtractor().get_doc(pyobject)
            )
        yield rv
        
class PythonLanguage(LanguageInfo):
    varchars = [chr(x) for x in xrange(97, 122)] + \
               [chr(x) for x in xrange(65, 90)] + \
               [chr(x) for x in xrange(48, 58)] + \
               ['_',]
    word = varchars

    # . in python
    attributerefs = ['.']

    completer_open = ['[', '(', ',', '.']
    completer_close = [']', ')', '}']



def _create_exception_validation(e):
    msg = e
    msg.name = e.__class__.__name__
    value = sys.exc_info()[1]
    (lineno, offset, line) = value[1][1:]
    if line.endswith("\n"):
        line = line[:-1]
    msg.lineno = lineno
    msg.message_args = (line,)
    msg.message = '<tt>%%s</tt>\n<tt>%s^</tt>' % (' ' * (offset - 2))
    msg.type_ = LANG_VALIDATOR_TYPES.ERROR
    if isinstance(e, SyntaxError):
        msg.subtype = LANG_VALIDATOR_SUBTYPES.SYNTAX
    else:
        msg.subtype = LANG_VALIDATOR_SUBTYPES.INDENTATION
    return [msg]

class PythonError(ValidationError):
    def get_markup(self):
        args = [('<b>%s</b>' % arg) for arg in self.message_args]
        message_string = self.message % tuple(args)
        if self.type_ == LANG_VALIDATOR_TYPES.ERROR:
            typec = self.lookup_color('pida-val-error')
        elif self.type_ == LANG_VALIDATOR_TYPES.INFO:
            typec = self.lookup_color('pida-val-info')
        elif self.type_ == LANG_VALIDATOR_TYPES.WARNING:
            typec = self.lookup_color('pida-val-warning')
        else:
            typec = self.lookup_color('pida-val-def')
        
        if typec:
            typec = typec.to_string()
        else:
            typec = "black"
        
        linecolor = self.lookup_color('pida-lineno')
        if linecolor:
            linecolor = linecolor.to_string()
        else:
            linecolor = "black"
        
        markup = ("""<tt><span color="%(linecolor)s">%(lineno)s</span> </tt>"""
    """<span foreground="%(typec)s" style="italic" weight="bold">%(type)s</span"""
    """>:<span style="italic">%(subtype)s</span>\n%(message)s""" % 
                      {'lineno':self.lineno, 
                      'type':_(LANG_VALIDATOR_TYPES.whatis(self.type_).capitalize()),
                      'subtype':_(LANG_VALIDATOR_SUBTYPES.whatis(
                                    self.subtype).capitalize()),
                      'message':message_string,
                      'linecolor': linecolor,
                      'typec': typec,
                      })
        return markup
    markup = property(get_markup)

class PythonValidator(Validator):

    priority = LANG_PRIO.GOOD
    name = "pyflakes"
    plugin = "python"
    description = _("A not very precise, non configurable validator, but fast")

    def get_validations(self):
        code_string = self.document.content
        filename = self.document.filename
        try:
            tree = compiler.parse(code_string)
        except (SyntaxError, IndentationError), e:
            messages = _create_exception_validation(e)
        else:
            w = Checker(tree, filename)
            messages = w.messages
        for m in messages:
            type_ = getattr(m, 'type_', LANG_VALIDATOR_TYPES.UNKNOWN)
            subtype = getattr(m, 'subtype', LANG_VALIDATOR_SUBTYPES.UNKNOWN)

            #FIXME add pyflakes 0.3 types
            #FIXME make mapping
            if isinstance(m, pyflakes.messages.UnusedImport):
                type_ = LANG_VALIDATOR_TYPES.INFO
                subtype = LANG_VALIDATOR_SUBTYPES.UNUSED
            elif isinstance(m, pyflakes.messages.RedefinedWhileUnused):
                type_ = LANG_VALIDATOR_TYPES.WARNING
                subtype = LANG_VALIDATOR_SUBTYPES.REDEFINED
            elif isinstance(m, pyflakes.messages.ImportStarUsed):
                type_ = LANG_VALIDATOR_TYPES.WARNING
                subtype = LANG_VALIDATOR_SUBTYPES.BADSTYLE
            elif isinstance(m, pyflakes.messages.UndefinedName):
                type_ = LANG_VALIDATOR_TYPES.ERROR
                subtype = LANG_VALIDATOR_SUBTYPES.UNDEFINED
            elif isinstance(m, pyflakes.messages.DuplicateArgument):
                type_ = LANG_VALIDATOR_TYPES.ERROR
                subtype = LANG_VALIDATOR_SUBTYPES.DUPLICATE

            ve = PythonError(
                message=m.message,
                message_args=m.message_args,
                lineno=m.lineno,
                type_=type_,
                subtype=subtype,
                filename=filename
                )
            yield ve


class PythonCompleter(Completer):

    priority = LANG_PRIO.VERY_GOOD
    name = "rope"
    plugin = "python"
    description = _("Creates very exact suggestions at reasonable speed")

    def get_completions(self, base, buffer, offset):

        from rope.contrib.codeassist import code_assist,sorted_proposals
        from rope.base.exceptions import RopeError

        try:
            mp = ModuleParser(self.document.filename, 
                              project=self.document.project)
            buffer = buffer + ('\n' * 20)
            co = code_assist(mp.project, buffer, offset, maxfixes=MAX_FIXES)
        except RopeError, IndentationError:
            return
        so = sorted_proposals(co)
        for c in so:
            if c.name.startswith(base):
                r = Suggestion(c.name)
                #'variable', 'class', 'function', 'imported' , 'paramter'
                if keyword.iskeyword(c.name):
                    r.type_ = LANG_COMPLETER_TYPES.KEYWORD
                elif c.type == 'variable':
                    r.type_ = LANG_COMPLETER_TYPES.VARIABLE
                elif c.type == 'class':
                    r.type_ = LANG_COMPLETER_TYPES.CLASS
                elif c.type == 'builtin':
                    r.type_ = LANG_COMPLETER_TYPES.BUILTIN
                elif c.type == 'function':
                    r.type_ = LANG_COMPLETER_TYPES.FUNCTION
                elif c.type == 'parameter':
                    r.type_ = LANG_COMPLETER_TYPES.PARAMETER
                elif c.type == None:
                    if c.kind == "parameter_keyword":
                        r.type_ = LANG_COMPLETER_TYPES.PARAMETER
                else:
                    r.type_ = LANG_COMPLETER_TYPES.UNKNOWN
                yield r

class PythonDefiner(Definer):

    name = "rope"
    plugin = "python"
    description = _("Shows a good definition of a function")

    def get_definition(self, buffer, offset):
        mp = ModuleParser(self.document.filename,
                          project=self.document.project)
        buffer = buffer + ('\n' * 20)

        from rope.contrib.findit import find_definition
        from rope.base.exceptions import RopeError

        try:
            dl = find_definition(mp.project, buffer, offset, maxfixes=MAX_FIXES)
        except RopeError:
            return

        if not dl:
            return

        if dl.resource is not None:
            file_name = dl.resource.path
        else:
            file_name = self.document.filename


        rv = Definition(file_name=file_name, offset=dl.offset,
                        line=dl.lineno, length=(dl.region[1]-dl.region[0]))

        yield rv

class PythonExternal(External):
    outliner = PythonOutliner
    validator = PythonValidator
    completer = PythonCompleter
    definer = PythonDefiner
    documentator = PythonDocumentator

class Python(LanguageService):

    language_name = 'Python'
    language_info = PythonLanguage
    outliner_factory = PythonOutliner
    validator_factory = PythonValidator
    completer_factory = PythonCompleter
    definer_factory = PythonDefiner
    documentator_factory = PythonDocumentator

    features_config = PythonFeaturesConfig
    actions_config = PythonActionsConfig
    options_config = PythonOptionsConfig
    events_config = PythonEventsConfig

    external = PythonExternal

    def pre_start(self):
        self.execute_action = self.get_action('execute_python')
        self.execute_action.set_sensitive(False)

#     def start(self):
#         for match in RE_MATCHES:
#             self.boss.get_service('commander').register_matcher(
#                 match[0], self.match_call)
#
#     def stop(self):
#         for match in RE_MATCHES:
#             self.boss.get_service('commander').unregister_matcher(
#                 match[0], self.match_call)

    def match_call(self, term, event, match, *args, **kwargs):
        for pattern in RE_MATCHES:
            test = pattern[1].match(match)
            if test:
                self.boss.get_service('buffer').open_file(
                    kwargs['usr'].get_absolute_path(test.groups()[0]),
                    line=int(test.groups()[1]))

    def execute_current_document(self):
        python_ex = self.opt('python_for_executing')
        doc = self.boss.cmd('buffer', 'get_current')
        if doc and doc.filename:
            self.boss.cmd('commander', 'execute',
                commandargs=[python_ex, doc.filename],
                cwd = doc.directory,
                )

    def is_current_python(self):
        doc = self.boss.cmd('buffer', 'get_current')
        if doc.doctype and (doc.doctype.internal == self.language_name):
            return True
        return False

    def set_document(self, document):
        self.execute_action.set_sensitive(self.is_current_python())



# Required Service attribute for service loading
Service = Python



# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.