[wingide-users] 3.1.2 and PyLint
Gustavo Tabares
gustavotabares at gmail.com
Thu Jul 24 14:41:43 MDT 2008
Hello,
This did not fix my particular problem. I tried it on OSX and Windows.
Gustavo
On Thu, Jul 24, 2008 at 3:43 PM, Wingware Support <support at wingware.com>
wrote:
> Gustavo Tabares wrote:
>
>> Hi all,
>>
>> I recently upgraded to Wing 3.1.2 and I'm having problems with the PyLint
>> integration. In my PyLint Panel configuration file I have this:
>>
>> args = --rcfile='mycfg.cfg'
>>
>> It doesn't appear to be reading my configuration file after upgrading from
>> 3.1.1. <http://3.1.1.> I'm seeing some warnings that I usually do not see
>> (specifically about line length).
>>
>
> I'm attaching the latest version that I've been working with; there have
> been changes in how argument parsing works that have caused problems. I'd
> like to get feedback on this before releasing it generally. To use it, find
> the scripts subdirectory of your Wing installation, rename the current
> pylintpanel.py to pylintpanel.py.orig, copy in the new pylintpanel.py, and
> then start or restart Wing.
>
> Thanks,
>
> John
>
> """
> PyLint Panel for Wing IDE 3.x
>
> Copyright (c) 2006-2007 Markus Meyer <meyer at mesw.de>
>
> 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.
>
>
> ----------------------------------------------------------------------------
> Change Log
>
> ----------------------------------------------------------------------------
>
> Version 1.0 (2006-10-12)
>
> * First release
>
> Version 1.1 (2007-03-19)
>
> * Fix compatibility issues with newer PyLint versions
> * Fix error message when PyLint returns no errors
>
> Version 1.2 (2008-06-05) Modifications by Wingware:
>
> * Pass configured environment to the pylint sub-process
> (includes also PYTHONPATH if it's set in project)
> * Use presence of a settings file to enable/disable for easier upgrades
> * Removed obsolete example args
> * Renamed "preferences" to "configure" in context menu to avoid confusion
> * Renamed command execute_pylint to pylint_execute and pylint_preferences
> to pylint_configure
> * Changed execution of pylint to be asyncronous
>
> """
>
> import os
> import wingapi
> import time
>
> PYLINTPANEL_VERSION = "1.1"
>
> import re
> _AI = wingapi.CArgInfo
>
> # Scripts can be internationalized with gettext. Strings to be translated
> # are sent to _() as in the code below.
> import gettext
> _ = gettext.translation('scripts_pylintpanel', fallback = 1).ugettext
>
> # This special attribute is used so that the script manager can translate
> # also docstrings for the commands found here
> _i18n_module = 'scripts_pylintpanel'
>
> ######################################################################
> # Utilities
>
> gMessageCategories = [
> ("errors", _("Errors"), _("Errors that must be fixed")),
> ("warnings", _("Warnings"), _("Warnings that could indicate problems")),
> ("information", _("Info"), _("General informative messages"))
> ]
>
> gTheView = None # Will be set later
>
> ######################################################################
> # Configuration file support
>
> class PylintConfig:
> def __init__(self):
> pass
>
> def get(self, name, default=""):
> """
> Get configuration option from configuration file
> """
> try:
> lines = file(self._get_config_file_name(), "rt").readlines()
> except IOError:
> return default
> for line in lines:
> words = line.split("=", 1)
> if len(words) == 2:
> key = words[0].strip()
> value = words[1].strip()
> if key == name:
> return value
> return default
>
> def edit(self):
> """
> Edit and possibly create configuration file. Currently, this will just
> open the configuration file inside WingIDE.
> """
> try:
> # Check if config file can be opened
> cfgfile = file(self._get_config_file_name(), "rt")
> except IOError:
> # The config file does not yet exist, create it
> cfgfile = file(self._get_config_file_name(), "wt")
> cfgfile.writelines([
> '#\n',
> '# PyLint Panel Configuration\n',
> '#\n',
> '\n',
> '# Full path to PyLint executable\n',
> 'command = \n',
> '#command = /usr/bin/pylint\n',
> '#command = C:\Python24\Scripts\pylint.bat\n',
> '\n',
> '# Additional args to give to PyLint (may be blank)\n',
> 'args = \n',
> '\n',
> '# Timeout for execution of pylint command\n',
> 'timeout = 30\n',
> '\n',
> '# Save current file before running PyLint on it (1=yes, 0=no)\n',
> 'autosave = 1\n'
> ])
> cfgfile.close()
>
> wingapi.gApplication.OpenEditor(self._get_config_file_name())
>
> def _get_config_file_name(self):
> """
> Get full name and path of config file
> """
> dir = wingapi.gApplication.GetUserSettingsDir()
> return os.path.join(dir, "pylintpanel.cfg")
>
> gTheConfig = PylintConfig()
>
> kResultParseExpr = re.compile("([^:]+):[ ]*([0-9]+):(.*)")
>
>
> ######################################################################
> # Commands
>
> def pylint_configure():
> """Show the pylint configuration file so it can be edited"""
> gTheConfig.edit()
>
> def pylint_execute():
> """Execute pyline for the current editor"""
>
> if gTheView is None:
> # Panel is not visible
> return
>
> view = gTheView
> app = wingapi.gApplication
>
> pylint_command = gTheConfig.get("command", None)
> pylint_args = gTheConfig.get("args", "")
> pylint_timeout = gTheConfig.get("timeout", "10000")
> pylint_autosave = gTheConfig.get("autosave", "1")
>
> if pylint_command is None:
> app.ShowMessageDialog(_('Error'), _('PyLint panel configuration file not
> found. ' +
> 'Choose "Configure" from the context menu to edit
> ' +
> 'the configuration file. You will need to install
> pylint '
> 'separately.'))
> return
>
> try:
> timeout = int(pylint_timeout)
> autosave = int(pylint_autosave) != 0
> except ValueError:
> app.ShowMessageDialog(_("Error"), _("Invalid values specified in
> configuration file"))
> return
>
> filename = app.GetActiveEditor().GetDocument().GetFilename()
> view._lastFilename = filename
>
> # Save active document before executing PyLint
> if autosave:
> app.ExecuteCommand("save")
>
> # Completion routine that updates the tree when pylint is finished running
> def _update_tree(result):
> resultLines = result.split('\n')
> tree_contents = [ [], [], [] ]
>
> for line in resultLines:
> matchobj = kResultParseExpr.match(line)
> if matchobj is not None:
> msg_type = matchobj.group(1)
> msg_line = matchobj.group(2).strip()
> msg_descr = matchobj.group(3).strip()
> if msg_type[0] == 'F' or msg_type[0] == 'E':
> msg_index = 0
> elif msg_type[0] == 'W':
> msg_index = 1
> else:
> msg_index = 2
>
> tree_contents[msg_index].append(
> ((msg_line, msg_type + ": " + msg_descr),))
>
> view.set_tree_contents(tree_contents)
>
> # Show pending execution message in tree column title
> view._ShowStatusMessage(_("Updating for %s") % filename)
>
> def arg_split(args, sep):
> cur_part = ''
> retval = []
> in_quote = None
> for c in args:
> if not in_quote:
> if c in '\'"':
> in_quote = c
> cur_part += c
> elif c == sep:
> if cur_part:
> retval.append(cur_part)
> cur_part = ''
> else:
> cur_part += c
> elif in_quote == c:
> in_quote = None
> cur_part += c
> else:
> cur_part += c
> if cur_part:
> retval.append(cur_part)
> return retval
>
> # Execute PyLint asyncronously
> cmd = pylint_command
> args = [cmd, filename.encode(config.kFileSystemEncoding), '--reports=n',
> '--include-ids=yes']
> args.extend(arg_split(pylint_args, ' '))
> args = tuple(args)
> env = app.GetProject().GetEnvironment(filename, set_pypath=True)
> start_time = time.time()
> handler = app.AsyncExecuteCommandLineE(cmd, os.path.split(filename)[0],
> env, *args)
> last_dot = [int(start_time)]
> dots = []
>
> def poll():
> if handler.Iterate():
> view._ShowStatusMessage('')
> stdout, stderr, err, status = handler.Terminate()
> if err:
> app.ShowMessageDialog(_("PyLint Failed"), _("Error executing PyLint:
> Command failed with error=%i; stderr:\n%s") % (err, stderr))
> else:
> _update_tree(stdout)
> return False
> elif time.time() > start_time + timeout:
> view._ShowStatusMessage('')
> stdout, stderr, err, status = handler.Terminate()
> app.ShowMessageDialog(_("PyLint Timed Out"), _("PyLint timed out:
> Command did not complete within timeout of %i seconds. Right click on the
> PyLint tool to configure this value. Output from PyLint:\n\n%s") %
> (timeout, stderr + stdout))
> return False
> else:
> if int(time.time()) > last_dot[0]:
> dots.append('.')
> if len(dots) > 3:
> while dots:
> dots.pop()
> view._ShowStatusMessage(_("Updating for %s%s") % (filename,
> ''.join(dots)))
> last_dot[0] = int(time.time())
> return True
>
> wingapi.gApplication.InstallTimeout(100, poll)
>
>
> def _IsAvailable_pylint_execute():
> app = wingapi.gApplication
> ed = app.GetActiveEditor()
> if not ed:
> return False
> doc = ed.GetDocument()
> if not doc:
> return False
> filename = doc.GetFilename()
> if not filename:
> return False
> mimetype = doc.GetMimeType()
> return mimetype == 'text/x-python'
>
> def pylint_show_docs():
> """Show the Wing IDE documentation section for the PyLint integration"""
> wingapi.gApplication.ExecuteCommand('show-document',
> section='edit/pylint')
>
>
> ######################################################################
> # XXX This is advanced scripting that accesses Wing IDE internals, which
> # XXX are subject to change from version to version without notice.
>
> from guiutils import wgtk
> from guiutils import dockview
> from guiutils import wingview
> from guiutils import winmgr
>
> from command import commandmgr
> import guimgr.menus
>
> # Note that panel IDs must be globally unique so all user-provided panels
> # MUST add a random uniquifier after '#'. The panel can still be referred
> # to by the portion of the name before '#' and Wing will warn when there
> # are multiple panel definitions with the same base name (in which case
> # Wing-defined panels win over user-defined panels and otherwise the
> # last user-defined panel type wins when referred to w/o the uniquifier).
> _kPanelID = 'pylintpanel#02EFWRQK9X24'
>
> class _CPylintPanelDefn(dockview.CPanelDefn):
> """Panel definition for the project manager"""
>
> def __init__(self, singletons):
> self.fSingletons = singletons
> dockview.CPanelDefn.__init__(self, self.fSingletons.fPanelMgr,
> _kPanelID, 'tall', 0)
> winmgr.CWindowConfig(self.fSingletons.fWinMgr, 'panel:%s' % _kPanelID,
> size=(350, 1000))
>
> def _CreateView(self):
> return _CPylintView(self.fSingletons)
>
> def _GetLabel(self, panel_instance):
> """Get display label to use for the given panel instance"""
>
> return _('PyLint')
>
> def _GetTitle(self, panel_instance):
> """Get full title for the given panel instance"""
>
> return _('PyLint Panel')
>
> class _CPylintViewCommands(commandmgr.CClassCommandMap):
> def __init__(self, singletons, view):
> commandmgr.CClassCommandMap.__init__(self, domain='user',
> package='pylintpanel',
> i18n_module=_i18n_module)
> assert isinstance(view, _CPylintView)
>
> self.fSingletons = singletons
> self.__fView = view
>
> class _CPylintView(wingview.CViewController):
> """A single template manager view"""
>
> def __init__(self, singletons):
> """ Constructor """
> global gTheView
>
> # Init inherited
> wingview.CViewController.__init__(self, ())
>
> # External managers
> self.fSingletons = singletons
>
> self.__fCmdMap = _CPylintViewCommands(self.fSingletons, self)
>
> self.fTrees = {}
> self.fLabels = {}
>
> self.__CreateGui()
>
> # Remember that this is the default view now
> gTheView = self
>
> def _destroy_impl(self):
> for tree, sview in self.fTrees.values():
> sview.destroy()
>
> def set_tree_contents(self, tree_contents):
> idx = 0
> for catkey, labeltext, tooltip in gMessageCategories:
> label = gTheView.fLabels[catkey]
> label.set_text('%s (%i)' % (labeltext, len(tree_contents[idx])))
> tree, sview = gTheView.fTrees[catkey]
> tree.set_contents(tree_contents[idx])
> idx += 1
>
> ##########################################################################
> # Inherited calls from wingview.CViewController
> ##########################################################################
>
> def GetDisplayTitle(self):
> """ Returns the title of this view suitable for display. """
>
> return _("PyLint Panel")
>
> def GetCommandMap(self):
> """ Get the command map object for this view. """
>
> return self.__fCmdMap
>
> def BecomeActive(self):
> pass
>
> ##########################################################################
> # Popup menu and actions
> ##########################################################################
>
> def __CreateGui(self):
> notebook = wgtk.Notebook()
>
> for catkey, label, tooltip in gMessageCategories:
> tree = wgtk.SimpleTree([wgtk.gobject.TYPE_STRING] * 2,
> [wgtk.CellRendererText(),
> wgtk.CellRendererText()],
> [_("Line"), _("Message")])
> tree.unset_flags(wgtk.CAN_FOCUS)
> tree.set_property('headers-visible', True)
>
> tree.connect('button-press-event', self.__CB_ButtonPress)
> sel = tree.get_selection()
> sel.connect('changed', self.__CB_SelectionChanged)
> tree.show()
>
> sview = wgtk.ScrolledWindow()
> sview.set_policy(wgtk.POLICY_AUTOMATIC, wgtk.POLICY_AUTOMATIC)
> sview.add(tree)
> sview.show()
>
> # Event box is needed to make tooltips work in this context (don't
> ask)
> tab_event_box = wgtk.TooltipBox()
> tab_label = wgtk.Label(label)
> tab_event_box.add(tab_label)
> tab_event_box.show_all()
> wgtk.set_tooltip(tab_event_box, tooltip)
>
> notebook.append_page(sview, tab_event_box)
> self.__fNotebook = notebook
>
> self.fTrees[catkey] = (tree, sview)
> self.fLabels[catkey] = tab_label
>
> notebook.set_current_page(0)
> self._SetGtkWidget(notebook)
>
> def __CreatePopup(self):
> """Construct popup menu for this object."""
>
> update_label = _("Update")
> app = wingapi.gApplication
> ed = app.GetActiveEditor()
> if ed:
> filename = ed.GetDocument().GetFilename()
> update_label = _("Update for %s") % os.path.basename(filename)
>
> kPopupDefn = [
> ( update_label, 'pylint-execute' ),
> ( _("Configure..."), 'pylint-configure' ),
> None,
> ( _("Show PyLint Tool Documentation"), 'pylint-show-docs' ),
> ]
>
> # Create menu
> defnlist = guimgr.menus.GetMenuDefnList(kPopupDefn,
> self.fSingletons.fGuiMgr,
> self.__fCmdMap, is_popup=1,
> static=1)
> menu = guimgr.menus.CMenu(_("PyLint"), self.fSingletons.fGuiMgr,
> defnlist, can_tearoff=0, is_popup=1)
> return menu
>
> def __CB_SelectionChanged(self, sel):
> pos = self.__fNotebook.get_current_page()
> catkey, label, tdir = gMessageCategories[pos]
> tree, sview = self.fTrees[catkey]
> rows = tree.GetSelectedContent()
>
> def __CB_ButtonPress(self, tree, event):
> app = wingapi.gApplication
>
> # Always select the row that the pointer is over
> event_path_info = tree.get_path_at_pos(int(event.x), int(event.y))
> if event_path_info is not None:
> event_path = event_path_info[0]
> selected_paths = tree.GetSelectedPaths()
> if event_path not in selected_paths:
> sel = tree.get_selection()
> sel.unselect_all()
> sel.select_path(event_path)
>
> # Popup menu on right mouse button
> if event.button == 3:
> self.__PopupMenu(event, (event.x_root, event.y_root))
> return 1
>
> selected = tree.GetSelectedContent()
> if selected is not None and len(selected) != 0:
> line = int(selected[0][0])
> if event.button == 1 and event.type == wgtk.gdk.BUTTON_PRESS:
> doc = app.OpenEditor(self._lastFilename)
> doc.ScrollToLine(lineno=line-1, pos='center', select=1)
>
> def __PopupMenu(self, event, pos):
> """Callback to display the popup menu"""
>
> menu = self.__CreatePopup()
> menu.Popup(event, pos=pos)
>
> def _ShowStatusMessage(self, msg):
> for tree, sview in self.fTrees.values():
> column = tree.get_column(1)
> if msg:
> column.set_title(_("Message: %s") % msg)
> else:
> column.set_title(_("Message"))
>
> # Register this panel type: Note that this needs to be at the
> # very end of the module so that all the classes defined here
> # are already available
> import config
> if _kPanelID not in config.kUserPanels:
> config.kUserPanels.append(_kPanelID)
> _CPylintPanelDefn(wingapi.gApplication.fSingletons)
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: /pipermail/wingide-users/attachments/20080724/8b452f9d/attachment-0001.html
More information about the wingide-users
mailing list