[kupfer: 5/20] plugins: adjust to Kupfer's standarts
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [kupfer: 5/20] plugins: adjust to Kupfer's standarts
- Date: Wed, 7 Oct 2009 11:33:14 +0000 (UTC)
commit a1cd9c404a3d0c3816cb903265d2a7df578d7eab
Author: KarolBedkowski <karol bedkowsk+gh gmail com>
Date: Sun Oct 4 22:21:18 2009 +0200
plugins: adjust to Kupfer's standarts
For clawsmail, putty, tscclient, zim:
- using FilesystemWatchMixin (except zim)
- use launch_commandline instead of spawn_async
- use output_error instead of print
- use more specific exception
- checking whether the file and dirs exists before open or lsdir
- correct names, strings, imports, etc
- reformat code
kupfer/plugin/clawsmail.py | 108 +++++++++++++++++++++-----------------
kupfer/plugin/putty.py | 47 +++++++++--------
kupfer/plugin/tsclient.py | 48 ++++++++++-------
kupfer/plugin/zim.py | 124 ++++++++++++++++++++++++++++++--------------
4 files changed, 199 insertions(+), 128 deletions(-)
---
diff --git a/kupfer/plugin/clawsmail.py b/kupfer/plugin/clawsmail.py
index 804224d..89cd12d 100644
--- a/kupfer/plugin/clawsmail.py
+++ b/kupfer/plugin/clawsmail.py
@@ -4,18 +4,30 @@ import re
import urllib
from xml.dom import minidom
-from kupfer.objects import Leaf, Action, Source, TextLeaf, UrlLeaf, RunnableLeaf
-from kupfer.utils import spawn_async
+from kupfer.objects import Leaf, Action, Source, TextLeaf, UrlLeaf, RunnableLeaf, FilesystemWatchMixin
+from kupfer import utils
-__kupfer_name__ = _("ClawsMail contacts actions")
+__kupfer_name__ = _("Claws Mail")
__kupfer_sources__ = ("ClawsContactsSource", )
-__description__ = _("Contacts from ClawsMail")
-__version__ = "0.1"
+__kupfer_actions__ = ("NewMailAction", )
+__description__ = _("Claws Mail Contacts and Actions")
+__version__ = "0.2"
__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
+def _get_email_from_url(url):
+ ''' convert http://foo bar pl -> foo bar pl '''
+ sep = url.find('://')
+ return url[sep+3:] if sep > -1 else url
-class ClawsContactLeaf(Leaf):
+_CHECK_EMAIL_RE = re.compile(r"^[a-z0-9\ _%-+]+\ [a-z0-9 _%-]+\ [a-z]{2,6}$")
+
+def _check_email(email):
+ ''' simple email check '''
+ return len(email) > 7 and _CHECK_EMAIL_RE.match(email.lower()) is not None
+
+
+class ClawsContact(Leaf):
''' Leaf represent single contact from Claws address book '''
def get_actions(self):
yield NewMailAction()
@@ -27,28 +39,28 @@ class ClawsContactLeaf(Leaf):
return "stock_person"
-class ComposeMailAction(RunnableLeaf):
+class ComposeMail(RunnableLeaf):
''' Create new mail without recipient '''
def __init__(self):
- RunnableLeaf.__init__(self, name=_("Compose new mail"))
+ RunnableLeaf.__init__(self, name=_("Compose New Mail"))
def run(self):
- spawn_async(('claws-mail', '--compose'))
+ utils.launch_commandline('claws-mail --compose')
def get_description(self):
- return _("Compose new mail with ClawsMail")
+ return _("Compose New Mail with Claws Mail")
def get_icon_name(self):
return "stock_mail-compose"
-class ReceiveMailAction(RunnableLeaf):
+class ReceiveMail(RunnableLeaf):
''' Receive all new mail from all accounts '''
def __init__(self):
- RunnableLeaf.__init__(self, name=_("Receive all mails"))
+ RunnableLeaf.__init__(self, name=_("Receive All Mails"))
def run(self):
- spawn_async(('claws-mail', '--receive-all'))
+ utils.launch_commandline('claws-mail --receive-all')
def get_description(self):
return _("Receive new mail from all accounts by ClawsMail")
@@ -58,61 +70,61 @@ class ReceiveMailAction(RunnableLeaf):
class NewMailAction(Action):
- ''' Createn new mail to selected leaf (ClawsContactLeaf or TextLeaf)'''
+ ''' Createn new mail to selected leaf (ClawsContact or TextLeaf)'''
def __init__(self):
- Action.__init__(self, _('Write new mail'))
+ Action.__init__(self, _('Compose New Mail to'))
def activate(self, leaf):
email = leaf.object
if isinstance(leaf, UrlLeaf):
- email = NewMailAction._get_email_from_url(email)
+ email = _get_email_from_url(email)
- spawn_async(("claws-mail", "--compose", str(email)))
+ utils.launch_commandline("claws-mail --compose '%s'" % email)
def get_icon_name(self):
return 'stock_mail-compose'
def item_types(self):
- yield ClawsContactLeaf
+ yield ClawsContact
# we can enter email
yield TextLeaf
yield UrlLeaf
def valid_for_item(self, item):
- if isinstance(item, ClawsContactLeaf):
+ if isinstance(item, ClawsContact):
return True
- if isinstance(item, TextLeaf):
- return ClawsContactLeaf._check_email(self.object)
+ elif isinstance(item, TextLeaf):
+ return _check_email(item.object)
elif isinstance(item, UrlLeaf):
- url = NewMailAction._get_email_from_url(item.object)
- return ClawsContactLeaf._check_email(url)
+ url = _get_email_from_url(item.object)
+ return _check_email(url)
return False
- @staticmethod
- def _get_email_from_url(url):
- sep = url.find('://')
- return url[sep+3:] if sep > -1 else url
-
- @staticmethod
- def _check_email(email):
- return len(email) > 7 and re.match(r"^[a-z0-9\ _%-+]+\ [a-z0-9 _%-]+\ [a-z]{2,6}$", email.lower()) is not None
-
-
-class ClawsContactsSource(Source):
- def __init__(self, name=_("Claws contacts")):
+class ClawsContactsSource(Source, FilesystemWatchMixin):
+ def __init__(self, name=_("Claws Mail Address Book")):
Source.__init__(self, name)
self._claws_addrbook_dir = os.path.expanduser('~/.claws-mail/addrbook')
- self._claws_addrbook_index = os.path.join(self._claws_addrbook_dir, "addrbook--index.xml")
+ self._claws_addrbook_index = os.path.join(self._claws_addrbook_dir, \
+ "addrbook--index.xml")
+ self.unpickle_finish()
- def is_dynamic(self):
- return False
+ def unpickle_finish(self):
+ if not os.path.isdir(self._claws_addrbook_dir):
+ return
+
+ self.monitor_token = self.monitor_directories(self._claws_addrbook_dir)
+
+ def monitor_include_file(self, gfile):
+ # monitor only addrbook-*.xml files
+ return gfile and gfile.get_basename().endswith('.xml') and \
+ gfile.get_basename().startswith("addrbook-")
def get_items(self):
- if os.path.exists(self._claws_addrbook_index):
+ if os.path.isfile(self._claws_addrbook_index):
for addrbook_file in self._load_address_books():
addrbook_filepath = os.path.join(self._claws_addrbook_dir, addrbook_file)
if not os.path.exists(addrbook_filepath):
@@ -126,22 +138,22 @@ class ClawsContactsSource(Source):
addresses = person.getElementsByTagName('address')
for address in addresses:
email = address.getAttribute('email')
- yield ClawsContactLeaf(email, cn)
+ yield ClawsContact(email, cn)
- except Exception, err:
- print err
+ except StandardError, err:
+ self.output_error(err)
- yield ComposeMailAction()
- yield ReceiveMailAction()
+ yield ComposeMail()
+ yield ReceiveMail()
def get_description(self):
- return _("Session saved in Putty")
+ return _("Contacts from Claw Mail Address Book")
def get_icon_name(self):
return "claws-mail"
def provides(self):
- yield ClawsContactLeaf
+ yield ClawsContact
yield RunnableLeaf
def _load_address_books(self):
@@ -151,8 +163,8 @@ class ClawsContactsSource(Source):
for book in dtree.getElementsByTagName('book'):
yield book.getAttribute('file')
- except Exception, err:
- print err
+ except StandardError, err:
+ self.output_error(err)
diff --git a/kupfer/plugin/putty.py b/kupfer/plugin/putty.py
index c30a2f8..d29cbdf 100644
--- a/kupfer/plugin/putty.py
+++ b/kupfer/plugin/putty.py
@@ -4,18 +4,17 @@ from __future__ import with_statement
import os
import urllib
-from kupfer.objects import Leaf, Action, Source
-from kupfer.utils import spawn_async
+from kupfer.objects import Leaf, Action, Source, TextSource, FilesystemWatchMixin
+from kupfer import utils
-__kupfer_name__ = _("PuTTY sessions")
+__kupfer_name__ = _("PuTTY Sessions")
__kupfer_sources__ = ("PuttySessionSource", )
-__description__ = _("Session saved in PuTTY")
-__version__ = "0.1"
+__description__ = _("Quick access to PuTTY Sessions")
+__version__ = "0.2"
__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
-
-class PuttySessionLeaf(Leaf):
+class PuttySession(Leaf):
""" Leaf represent session saved in PuTTy"""
def __init__(self, name, description):
@@ -32,31 +31,32 @@ class PuttySessionLeaf(Leaf):
return "computer"
-
class PuttyOpenSession(Action):
''' opens putty session '''
def __init__(self):
- super(PuttyOpenSession, self).__init__(_('Open PuTTy session'))
+ Action.__init__(self, _('Start PuTTY Session'))
def activate(self, leaf):
- cli = ("putty", "-load", leaf.object)
- spawn_async(cli)
+ utils.launch_commandline("putty -load '%s'" % leaf.object)
def get_icon_name(self):
return 'putty'
-
-class PuttySessionSource(Source):
+class PuttySessionSource(Source, FilesystemWatchMixin):
''' indexes session saved in putty '''
- def __init__(self, name=_("PuTTy Session")):
+ def __init__(self, name=_("PuTTY Sessions")):
super(PuttySessionSource, self).__init__(name)
self._putty_sessions_dir = os.path.expanduser('~/.putty/sessions')
+ self.unpickle_finish()
- def is_dynamic(self):
- return True
+ def unpickle_finish(self):
+ self.monitor_token = self.monitor_directories(self._putty_sessions_dir)
def get_items(self):
+ if not os.path.isdir(self._putty_sessions_dir):
+ return
+
for filename in os.listdir(self._putty_sessions_dir):
if filename == 'Default%20Settings':
continue
@@ -65,7 +65,7 @@ class PuttySessionSource(Source):
if os.path.isfile(obj_path):
name = urllib.unquote(filename)
description = self._load_host_from_session_file(obj_path)
- yield PuttySessionLeaf(name, description)
+ yield PuttySession(name, description)
def get_description(self):
return _("Session saved in Putty")
@@ -74,7 +74,7 @@ class PuttySessionSource(Source):
return "putty"
def provides(self):
- yield PuttySessionLeaf
+ yield PuttySession
def _load_host_from_session_file(self, filepath):
user = None
@@ -84,15 +84,18 @@ class PuttySessionSource(Source):
for line in session_file:
if line.startswith('HostName='):
host = line.split('=', 2)[1].strip()
+
elif line.startswith('UserName='):
user = line.split('=', 2)[1].strip()
- except Exception, err:
- print err
+
+ except IOError, err:
+ self.output_error(err)
else:
- return user + '@' + host if user else host
+ if host:
+ return unicode(user + '@' + host if user else host)
- return 'PuTTY session'
+ return u'PuTTY Session'
diff --git a/kupfer/plugin/tsclient.py b/kupfer/plugin/tsclient.py
index ded1e7a..c6f05d4 100644
--- a/kupfer/plugin/tsclient.py
+++ b/kupfer/plugin/tsclient.py
@@ -3,18 +3,18 @@ from __future__ import with_statement
import os
-from kupfer.objects import Leaf, Action, Source
-from kupfer.utils import spawn_async
+from kupfer.objects import Leaf, Action, Source, FilesystemWatchMixin
+from kupfer import utils
__kupfer_name__ = _("Terminal Server Client")
__kupfer_sources__ = ("TsclientSessionSource", )
-__description__ = _("Session saved in Terminam Server Client")
-__version__ = "0.1"
+__description__ = _("Session saved in Terminal Server Client")
+__version__ = "0.2"
__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
-class TsclientSessionLeaf(Leaf):
+class TsclientSession(Leaf):
""" Leaf represent session saved in Tsclient"""
def __init__(self, obj_path, name, description):
@@ -31,31 +31,38 @@ class TsclientSessionLeaf(Leaf):
return "computer"
-
class TsclientOpenSession(Action):
''' opens tsclient session '''
def __init__(self):
- Action.__init__(self, _('Open Terminal Server Client session'))
+ Action.__init__(self, _('Start Terminal Server Session'))
def activate(self, leaf):
- cli = ("tsclient", "-x", leaf.object)
- spawn_async(cli)
+ utils.launch_commandline("tsclient -x '%s'" % leaf.object)
def get_icon_name(self):
return 'tsclient'
-
-class TsclientSessionSource(Source):
+class TsclientSessionSource(Source, FilesystemWatchMixin):
''' indexes session saved in tsclient '''
def __init__(self, name=_("TSClient sessions")):
Source.__init__(self, name)
self._sessions_dir = os.path.expanduser('~/.tsclient')
+ self.unpickle_finish()
+
+ def unpickle_finish(self):
+ if not os.path.isdir(self._sessions_dir):
+ return
+
+ self.monitor_token = self.monitor_directories(self._sessions_dir)
- def is_dynamic(self):
- return False
+ def monitor_include_file(self, gfile):
+ return gfile and gfile.get_basename().endswith('.rdp')
def get_items(self):
+ if not os.path.isdir(self._sessions_dir):
+ return
+
for filename in os.listdir(self._sessions_dir):
if not filename.endswith('.rdp'):
continue
@@ -64,7 +71,7 @@ class TsclientSessionSource(Source):
if os.path.isfile(obj_path):
name = filename[:-4]
description = self._load_descr_from_session_file(obj_path)
- yield TsclientSessionLeaf(obj_path, name, description)
+ yield TsclientSession(obj_path, name, description)
def get_description(self):
return _("Session saved in Terminal Server Client")
@@ -73,7 +80,7 @@ class TsclientSessionSource(Source):
return "tsclient"
def provides(self):
- yield TsclientSessionLeaf
+ yield TsclientSession
def _load_descr_from_session_file(self, filepath):
user = None
@@ -83,15 +90,18 @@ class TsclientSessionSource(Source):
for line in session_file:
if line.startswith('full address:s:'):
host = line.split(':s:', 2)[1].strip()
+
elif line.startswith('username:s:'):
user = line.split(':s:', 2)[1].strip()
- except Exception, err:
- print err
+
+ except IOError, err:
+ self.output_error(err)
else:
- return user + '@' + host if user else host
+ if host:
+ return unicode(user + '@' + host if user else host)
- return 'TSClient; session'
+ return u'Terminal Server Client Session'
diff --git a/kupfer/plugin/zim.py b/kupfer/plugin/zim.py
index 87c1667..b334329 100644
--- a/kupfer/plugin/zim.py
+++ b/kupfer/plugin/zim.py
@@ -3,78 +3,122 @@ from __future__ import with_statement
import os
-from kupfer.objects import Leaf, Action, Source, TextLeaf
-from kupfer.utils import spawn_async
+from kupfer.objects import Leaf, Action, Source, TextLeaf, FilesystemWatchMixin, TextSource
+from kupfer import utils
-__kupfer_name__ = _("Zim pages")
+__kupfer_name__ = _("Zim")
__kupfer_sources__ = ("ZimPagesSource", )
-__kupfer_actions__ = ("OpenZimPageAction", )
-__description__ = _("Zim pages")
-__version__ = "0.1"
+__kupfer_actions__ = ("CreateZimPage", )
+__description__ = _("Access to Pages stored in Zim - A Desktop Wiki and Outliner")
+__version__ = "0.2"
__author__ = "Karol BÄ?dkowski <karol bedkowski gmail com>"
+'''
+TODO:
+ use FilesystemWatchMixin (?)
+'''
-class ZimPageLeaf(Leaf):
+
+def _start_zim(notebook, page):
+ ''' Start zim and open given notebook and page. '''
+ cli = "zim '%s' '%s'" % (notebook, page.replace("'", "_"))
+ utils.launch_commandline(cli)
+
+
+class ZimPage(Leaf):
""" Represent single Zim page """
def __init__(self, notebook, page):
full_name = notebook + " " + page
- super(ZimPageLeaf, self).__init__(full_name, page)
+ Leaf.__init__(self, full_name, page)
self.page = page
self.notebook = notebook
def get_actions(self):
- yield OpenZimPageAction()
+ yield OpenZimPage()
+ yield CreateZimSubPage()
def get_description(self):
- return _('Zim page from notebook "%s"') % self.notebook
+ return _('Zim Page from Notebook "%s"') % self.notebook
def get_icon_name(self):
return "text-x-generic"
+class CreateZimPage(Action):
+ ''' create new page '''
+ rank_adjust = 5
-class OpenZimPageAction(Action):
- """ Open Zim page (or create it) """
def __init__(self):
- super(OpenZimPageAction, self).__init__(_('Open Zim page'))
+ Action.__init__(self, _('Create Zim Page as SubPage of'))
- def activate(self, leaf):
- if isinstance(leaf, ZimPageLeaf):
- # leaf are zim pages
- cli = ("zim", leaf.notebook, leaf.page)
+ def activate(self, leaf, iobj):
+ _start_zim(iobj.notebook, iobj.page + ":" + leaf.object.strip(':'))
+
+ def get_icon_name(self):
+ return 'document-new'
+
+ def item_types(self):
+ yield TextLeaf
+
+ def requires_object(self):
+ return True
+
+ def object_types(self):
+ yield ZimPage
- else:
- # leaf is enetere text (textleaf)
- page = leaf.object
- if page.find(' :') > -1:
- notebook, page = page.split(' ', 2)
- cli = ('zim', notebook, str(page))
+ def object_source(self, for_item=None):
+ return ZimPagesSource()
- else:
- cli = ('zim', '_default_', str(page))
- spawn_async(cli)
+class OpenZimPage(Action):
+ """ Open Zim page """
+ rank_adjust = 10
+
+ def __init__(self):
+ Action.__init__(self, _('Open Zim Page'))
+
+ def activate(self, leaf):
+ _start_zim(leaf.notebook, leaf.page)
def get_icon_name(self):
return 'document-open'
def item_types(self):
- yield ZimPageLeaf
- yield TextLeaf
+ yield ZimPage
+
+
+class CreateZimSubPage(Action):
+ """ Open Zim page """
+ def __init__(self):
+ Action.__init__(self, _('Create Zim SubPage'))
+
+ def activate(self, leaf, iobj):
+ _start_zim(leaf.notebook, leaf.page + ":" + iobj.object.strip(':'))
+
+ def get_icon_name(self):
+ return 'document-new'
+
+ def item_types(self):
+ yield ZimPage
+ def requires_object(self):
+ return True
+
+ def object_types(self):
+ yield TextLeaf
+
+ def object_source(self, for_item=None):
+ return TextSource()
class ZimPagesSource(Source):
''' Index pages in all Zim notebooks '''
- def __init__(self, name=_("Zim pages")):
- super(ZimPagesSource, self).__init__(name)
+ def __init__(self, name=_("Zim Pages")):
+ Source.__init__(self, name)
# path to file with list notebooks
self._zim_notebooks_file = os.path.expanduser('~/.config/zim/notebooks.list')
- def is_dynamic(self):
- return False
-
def get_items(self):
for notebook_name, notebook_path in self._get_notebooks():
notebook_path_len = len(notebook_path)
@@ -83,17 +127,18 @@ class ZimPagesSource(Source):
for filename in files:
if filename.endswith('.txt'):
file_path = os.path.join(root, filename)
- page_name = file_path[notebook_path_len:-4].replace(os.path.sep, ':')
- yield ZimPageLeaf(notebook_name, page_name)
+ page_name = file_path[notebook_path_len:-4]
+ page_name = page_name.replace(os.path.sep, ':').replace('_', ' ')
+ yield ZimPage(notebook_name, page_name)
def get_description(self):
- return _("Pages stored in Zim notebooks")
+ return _("Pages stored in Zim Notebooks")
def get_icon_name(self):
return "zim"
def provides(self):
- yield ZimPageLeaf
+ yield ZimPage
def _get_notebooks(self):
''' get (notebook name, notebook path) from zim config '''
@@ -104,6 +149,7 @@ class ZimPagesSource(Source):
notebook_name, notebook_path = line.strip().split('\t', 2)
notebook_path = os.path.expanduser(notebook_path)
yield (notebook_name, notebook_path)
- except Exception, err:
- print err
+
+ except IOError, err:
+ self.output_error(err)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]