#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''Connecting PyGTK object events to class methods automatically.
Helps you not to repeat yourself (DRY) with PyGTK. Example:
from pygtkconnect import *
class MyClass:
(...)
@gtk_event
def my_button_clicked(self, widget, data=None):
(...)
def __init__(self):
(...)
gtk_insert(self, 'my_button', gtk.Button('click me'))
# also does self.my_button = ...
(...)
gtk_connect_events(self)
# calls self.my_button.connect('clicked', self.my_button_clicked)
# and similar for all decorated methods in one line of code :)
If you call gtk_connect_events(self, False), you can even skip the
@gtk_event decorators, but then you have to be careful with method names!
'''
__author__ = 'Pavel Krc'
__email__ = 'pk-alt@seznam.cz'
__date__ ='2011-02-17'
__all__ = ['gtk_event', 'gtk_insert', 'gtk_connect_events', 'PygtkconnectException']
import re
class PygtkconnectException(Exception):
pass
def gtk_event(method):
'''A decorator that makes a method connectible to an event
The method name must be exactly [_[_]]membername_eventname.
'''
method._pygtkconnect_method_is_event = True
return method
def gtk_insert(user_object, member_name, gtk_object, insert_as_member=True):
'''Enables PyGTK event binding for a PyGTK object
You must make sure that the member names are not ambiguous, i.e. if you
remove leading underscores from member names, then a member name with added
underscore at the end isn't a prefix of some other member name. "member"
and "member1" are OK, "__member" and "member_two" are not.
If insert_as_member is True, the gtk object is also inserted as a member to
user_object (using member_name).
'''
if not hasattr(user_object, '__pygtkconnect_members'):
user_object.__pygtkconnect_members = {member_name: gtk_object}
else:
user_object.__pygtkconnect_members[member_name] = gtk_object
if insert_as_member:
setattr(user_object, member_name, gtk_object)
def gtk_connect_events(user_object, require_decorators=True):
'''Connects decorated event methods as event handlers to selected members
If require_decorators is False, the methods used as events are determined
purely by name prefix (be careful!).
'''
members = user_object.__pygtkconnect_members
if require_decorators:
funcs = [name for name, obj
in user_object.__class__.__dict__.iteritems()
if hasattr(obj, '_pygtkconnect_method_is_event')]
else:
funcs = [name for name, obj
in user_object.__class__.__dict__.iteritems()
if callable(obj)]
# create a regex with member names for separating member name and event
names_reg = re.compile('^(_{0,2})(%s)_(.*)$' %
'|'.join(members.iterkeys()))
# connect it all
for funcname in funcs:
m = names_reg.match(funcname)
if not m:
if require_decorators:
raise PygtkconnectException('Invalid method name or no matched '
'member object!')
else:
continue
leading_uscores, member_name, event_name = m.groups()
members[member_name].connect(event_name, getattr(user_object, funcname))
Diff to Previous Revision
--- revision 1 2011-02-17 22:31:13
+++ revision 2 2011-02-19 17:50:42
@@ -19,11 +19,10 @@
(...)
gtk_connect_events(self)
# calls self.my_button.connect('clicked', self.my_button_clicked)
- # and similar for all decorated functions in one line of code :)
+ # and similar for all decorated methods in one line of code :)
If you call gtk_connect_events(self, False), you can even skip the
-@gtk_event decorators, but then you have to be careful with member function
-names!
+@gtk_event decorators, but then you have to be careful with method names!
'''
__author__ = 'Pavel Krc'
@@ -38,7 +37,7 @@
pass
def gtk_event(method):
- '''A decorator that makes a method connectable to an event
+ '''A decorator that makes a method connectible to an event
The method name must be exactly [_[_]]membername_eventname.
'''
@@ -48,11 +47,14 @@
def gtk_insert(user_object, member_name, gtk_object, insert_as_member=True):
'''Enables PyGTK event binding for a PyGTK object
- Behavior is unspecified if member_name is a prefix of some other member
- name. If insert_as_member is True, the gtk object is also inserted as a
- member to user_object (using member_name).
+ You must make sure that the member names are not ambiguous, i.e. if you
+ remove leading underscores from member names, then a member name with added
+ underscore at the end isn't a prefix of some other member name. "member"
+ and "member1" are OK, "__member" and "member_two" are not.
+
+ If insert_as_member is True, the gtk object is also inserted as a member to
+ user_object (using member_name).
'''
-
if not hasattr(user_object, '__pygtkconnect_members'):
user_object.__pygtkconnect_members = {member_name: gtk_object}
else:
@@ -64,10 +66,9 @@
def gtk_connect_events(user_object, require_decorators=True):
'''Connects decorated event methods as event handlers to selected members
- If require_decorators is False, the member functions used as events are
- determined purely by name prefix (be careful!).
+ If require_decorators is False, the methods used as events are determined
+ purely by name prefix (be careful!).
'''
-
members = user_object.__pygtkconnect_members
if require_decorators:
funcs = [name for name, obj