From 7a282739e27893ec710b0d92be0c1b4da59ba9ea Mon Sep 17 00:00:00 2001 From: David Bartley Date: Tue, 18 Dec 2007 01:24:58 -0500 Subject: [PATCH] Add tab completion for userid fields --- ceo/urwid/groups.py | 6 ++-- ceo/urwid/ldapfilter.py | 40 ----------------------- ceo/urwid/newmember.py | 7 ++-- ceo/urwid/positions.py | 3 +- ceo/urwid/renew.py | 3 +- ceo/urwid/shell.py | 3 +- ceo/urwid/widgets.py | 72 +++++++++++++++++++++++++++++++++++++---- 7 files changed, 78 insertions(+), 56 deletions(-) delete mode 100644 ceo/urwid/ldapfilter.py diff --git a/ceo/urwid/groups.py b/ceo/urwid/groups.py index 5110bb4..12278e7 100644 --- a/ceo/urwid/groups.py +++ b/ceo/urwid/groups.py @@ -53,7 +53,8 @@ class IntroPage(WizardPanel): class InfoPage(WizardPanel): def init_widgets(self): - self.group = WordEdit("Club or Group: ") + self.group = LdapWordEdit(csclub_uri, csclub_base, 'uid', + "Club or Group: ") self.widgets = [ urwid.Text( "Club or Group Information"), urwid.Divider(), @@ -75,7 +76,8 @@ class ChangeMember(WizardPanel): state['data'] = data WizardPanel.__init__(self, state) def init_widgets(self): - self.userid = WordEdit("Username: ") + self.userid = LdapWordEdit(csclub_uri, csclub_base, 'uid', + "Username: ") data = self.state['data'] self.widgets = [ diff --git a/ceo/urwid/ldapfilter.py b/ceo/urwid/ldapfilter.py deleted file mode 100644 index 406e3d1..0000000 --- a/ceo/urwid/ldapfilter.py +++ /dev/null @@ -1,40 +0,0 @@ -import ldap - -class LdapFilter: - def __init__(self, widget): - self.widget = widget - - def set_ldap_filter(self, ldap_uri, ldap_base, ldap_attr, ldap_map): - try: - self.ldap = ldap.initialize(ldap_uri) - self.ldap.simple_bind_s("", "") - except ldap.LDAPError: - return - self.base = ldap_base - self.attr = ldap_attr - self.map = ldap_map - - def keypress(self, size, key): - if self.ldap != None: - if key == 'enter' or key == 'down' or key == 'up': - attr = self.escape(self.attr) - search = self.escape(self.widget.get_edit_text(self)) - ldfilter = '(%s=%s)' % (attr, search) - try: - matches = self.ldap.search_s(self.base, - ldap.SCOPE_SUBTREE, ldfilter) - if len(matches) > 0: - (_, attrs) = matches[0] - for (k, v) in self.map.items(): - if attrs.has_key(k) and len(attrs[k]) > 0: - v.set_edit_text(attrs[k][0]) - except ldap.LDAPError: - pass - return self.widget.keypress(self, size, key) - - def escape(self, value): - value = str(value) - value = value.replace('\\', '\\5c').replace('*', '\\2a') - value = value.replace('(', '\\28').replace(')', '\\29') - value = value.replace('\x00', '\\00') - return value diff --git a/ceo/urwid/newmember.py b/ceo/urwid/newmember.py index 4281cc4..4fc3bc5 100644 --- a/ceo/urwid/newmember.py +++ b/ceo/urwid/newmember.py @@ -36,13 +36,10 @@ class ClubIntroPage(WizardPanel): class InfoPage(WizardPanel): def init_widgets(self): - self.userid = LdapFilterWordEdit("UWuserid: ") self.name = SingleEdit("Full name: ") self.program = SingleEdit("Program of Study: ") - self.userid.set_ldap_filter( - "ldap://uwldap.uwaterloo.ca/", "dc=uwaterloo,dc=ca", - "uid", {'cn':self.name, 'ou':self.program} - ) + self.userid = LdapFilterWordEdit(uwldap_uri, uwldap_base, 'uid', + {'cn':self.name, 'ou':self.program}, "UWuserid: ") self.widgets = [ urwid.Text( "Member Information - Please Check ID" ), urwid.Divider(), diff --git a/ceo/urwid/positions.py b/ceo/urwid/positions.py index cb4cb88..28f324a 100644 --- a/ceo/urwid/positions.py +++ b/ceo/urwid/positions.py @@ -36,7 +36,8 @@ class InfoPage(WizardPanel): positions = members.list_positions() self.position_widgets = {} for (position, text) in position_data: - widget = WordEdit("%s: " % text) + widget = LdapWordEdit(csclub_uri, csclub_base, 'uid', + "%s: " % text) if position in positions: widget.set_edit_text(','.join(positions[position].keys())) else: diff --git a/ceo/urwid/renew.py b/ceo/urwid/renew.py index f68ab9b..b9abb7c 100644 --- a/ceo/urwid/renew.py +++ b/ceo/urwid/renew.py @@ -16,7 +16,8 @@ class IntroPage(WizardPanel): class UserPage(WizardPanel): def init_widgets(self): - self.userid = WordEdit("Username: ") + self.userid = LdapWordEdit(csclub_uri, csclub_base, 'uid', + "Username: ") self.widgets = [ urwid.Text( "Member Information" ), diff --git a/ceo/urwid/shell.py b/ceo/urwid/shell.py index c4e7b16..d4be161 100644 --- a/ceo/urwid/shell.py +++ b/ceo/urwid/shell.py @@ -17,7 +17,8 @@ class IntroPage(WizardPanel): class YouPage(WizardPanel): def init_widgets(self): you = pwd.getpwuid(os.getuid()).pw_name - self.userid = WordEdit("Username: ", you) + self.userid = LdapWordEdit(csclub_uri, csclub_base, 'uid', + "Username: ", you) self.widgets = [ urwid.Text( "Member Information" ), diff --git a/ceo/urwid/widgets.py b/ceo/urwid/widgets.py index 4b1bd92..eb0e580 100644 --- a/ceo/urwid/widgets.py +++ b/ceo/urwid/widgets.py @@ -1,6 +1,11 @@ -import urwid -from ceo.urwid.ldapfilter import * +import urwid, ldap from ceo.urwid.window import raise_back, push_window +import ceo.ldapi as ldapi + +uwldap_uri = "ldap://uwldap.uwaterloo.ca/" +uwldap_base = "dc=uwaterloo,dc=ca" +csclub_uri = "ldap://ldap1.csclub.uwaterloo.ca/ ldap://ldap2.csclub.uwaterloo.ca" +csclub_base = "dc=csclub,dc=uwaterloo,dc=ca" def menu_items(items): return [ urwid.AttrWrap( ButtonText( cb, data, txt ), 'menu', 'selected') for (txt, cb, data) in items ] @@ -47,10 +52,65 @@ class WordEdit(SingleEdit): def valid_char(self, ch): return urwid.Edit.valid_char(self, ch) and ch != ' ' -class LdapFilterWordEdit(LdapFilter, WordEdit): - def __init__(self, *args): - LdapFilter.__init__(self, WordEdit) - WordEdit.__init__(self, *args) +class LdapWordEdit(WordEdit): + ldap = None + tabbing = False + def __init__(self, uri, base, attr, *args): + try: + self.ldap = ldap.initialize(uri) + self.ldap.simple_bind_s("", "") + except ldap.LDAPError: + return WordEdit.__init__(self, *args) + self.base = base + self.attr = ldapi.escape(attr) + return WordEdit.__init__(self, *args) + def keypress(self, size, key): + if key == 'tab' and self.ldap != None: + if self.tabbing: + self.index = (self.index + 1) % len(self.choices) + text = self.choices[self.index] + self.set_edit_text(text) + self.set_edit_pos(len(text)) + else: + try: + search = ldapi.escape(self.get_edit_text()) + matches = self.ldap.search_s(self.base, + ldap.SCOPE_SUBTREE, '(%s=%s*)' % (self.attr, search)) + self.choices = [] + for match in matches: + (_, attrs) = match + self.choices += attrs['uid'] + if len(self.choices) > 0: + self.index = 0 + self.tabbing = True + text = self.choices[self.index] + self.set_edit_text(text) + self.set_edit_pos(len(text)) + except ldap.LDAPError, e: + pass + else: + self.tabbing = False + return WordEdit.keypress(self, size, key) + +class LdapFilterWordEdit(LdapWordEdit): + def __init__(self, uri, base, attr, map, *args): + LdapWordEdit.__init__(self, uri, base, attr, *args) + self.map = map + def keypress(self, size, key): + if self.ldap != None: + if key == 'enter' or key == 'down' or key == 'up': + search = ldapi.escape(self.get_edit_text()) + try: + matches = self.ldap.search_s(self.base, + ldap.SCOPE_SUBTREE, '(%s=%s)' % (self.attr, search)) + if len(matches) > 0: + (_, attrs) = matches[0] + for (k, v) in self.map.items(): + if attrs.has_key(k) and len(attrs[k]) > 0: + v.set_edit_text(attrs[k][0]) + except ldap.LDAPError: + pass + return LdapWordEdit.keypress(self, size, key) class PassEdit(SingleEdit): def get_text(self):