diff options
author | Rob Crittenden <rcritten@redhat.com> | 2009-02-05 15:03:08 -0500 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2009-02-09 14:35:15 -0500 |
commit | 262ff2d731b1bfc4acd91153088b8fcde7ae92b8 (patch) | |
tree | baf8894d4b357b610113b87d4bfee84de24f08bd /ipapython/entity.py | |
parent | 58ae191a5afbf29d78afd3969f8d106415897958 (diff) | |
download | freeipa-262ff2d731b1bfc4acd91153088b8fcde7ae92b8.tar.gz freeipa-262ff2d731b1bfc4acd91153088b8fcde7ae92b8.tar.xz freeipa-262ff2d731b1bfc4acd91153088b8fcde7ae92b8.zip |
Rename ipa-python directory to ipapython so it is a real python library
We used to install it as ipa, now installing it as ipapython. The rpm
is still ipa-python.
Diffstat (limited to 'ipapython/entity.py')
-rw-r--r-- | ipapython/entity.py | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/ipapython/entity.py b/ipapython/entity.py new file mode 100644 index 000000000..580cbd00b --- /dev/null +++ b/ipapython/entity.py @@ -0,0 +1,202 @@ +# Copyright (C) 2007 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import ldap +import ldif +import re +import cStringIO +import copy + +import ipapython.ipautil + +def utf8_encode_value(value): + if isinstance(value,unicode): + return value.encode('utf-8') + return value + +def utf8_encode_values(values): + if isinstance(values,list) or isinstance(values,tuple): + return map(utf8_encode_value, values) + else: + return utf8_encode_value(values) + +def copy_CIDict(x): + """Do a deep copy of a CIDict""" + y = {} + for key, value in x.iteritems(): + y[copy.deepcopy(key)] = copy.deepcopy(value) + return y + +class Entity: + """This class represents an IPA user. An LDAP entry consists of a DN + and a list of attributes. Each attribute consists of a name and a list of + values. For the time being I will maintain this. + + In python-ldap, entries are returned as a list of 2-tuples. + Instance variables: + dn - string - the string DN of the entry + data - CIDict - case insensitive dict of the attributes and values + orig_data - CIDict - case insentiive dict of the original attributes and values""" + + def __init__(self,entrydata=None): + """data is the raw data returned from the python-ldap result method, + which is a search result entry or a reference or None. + If creating a new empty entry, data is the string DN.""" + if entrydata: + if isinstance(entrydata,tuple): + self.dn = entrydata[0] + self.data = ipapython.ipautil.CIDict(entrydata[1]) + elif isinstance(entrydata,str) or isinstance(entrydata,unicode): + self.dn = entrydata + self.data = ipapython.ipautil.CIDict() + elif isinstance(entrydata,dict): + self.dn = entrydata['dn'] + del entrydata['dn'] + self.data = ipapython.ipautil.CIDict(entrydata) + else: + self.dn = '' + self.data = ipapython.ipautil.CIDict() + + self.orig_data = ipapython.ipautil.CIDict(copy_CIDict(self.data)) + + def __nonzero__(self): + """This allows us to do tests like if entry: returns false if there is no data, + true otherwise""" + return self.data != None and len(self.data) > 0 + + def hasAttr(self,name): + """Return True if this entry has an attribute named name, False otherwise""" + return self.data and self.data.has_key(name) + + def __setattr__(self,name,value): + """One should use setValue() or setValues() to set values except for + dn and data which are special.""" + if name != 'dn' and name != 'data' and name != 'orig_data': + raise KeyError, 'use setValue() or setValues()' + else: + self.__dict__[name] = value + + def __getattr__(self,name): + """If name is the name of an LDAP attribute, return the first value for that + attribute - equivalent to getValue - this allows the use of + entry.cn + instead of + entry.getValue('cn') + This also allows us to return None if an attribute is not found rather than + throwing an exception""" + return self.getValue(name) + + def getValues(self,name): + """Get the list (array) of values for the attribute named name""" + return self.data.get(name) + + def getValue(self,name,default=None): + """Get the first value for the attribute named name""" + value = self.data.get(name,default) + if isinstance(value,list) or isinstance(value,tuple): + return value[0] + else: + return value + + def setValue(self,name,*value): + """Value passed in may be a single value, several values, or a single sequence. + For example: + ent.setValue('name', 'value') + ent.setValue('name', 'value1', 'value2', ..., 'valueN') + ent.setValue('name', ['value1', 'value2', ..., 'valueN']) + ent.setValue('name', ('value1', 'value2', ..., 'valueN')) + Since *value is a tuple, we may have to extract a list or tuple from that + tuple as in the last two examples above""" + if (len(value) < 1): + return + if (len(value) == 1): + self.data[name] = utf8_encode_values(value[0]) + else: + self.data[name] = utf8_encode_values(value) + + setValues = setValue + + def setValueNotEmpty(self,name,*value): + """Similar to setValue() but will not set an empty field. This + is an attempt to avoid adding empty attributes.""" + if (len(value) >= 1) and value[0] and len(value[0]) > 0: + if isinstance(value[0], list): + if len(value[0][0]) > 0: + self.setValue(name, *value) + return + else: + self.setValue(name, *value) + return + + # At this point we have an empty incoming value. See if they are + # trying to erase the current value. If so we'll delete it so + # it gets marked as removed in the modlist. + v = self.getValues(name) + if v: + self.delValue(name) + + return + + def delValue(self,name): + """Remove the attribute named name.""" + if self.data.get(name,None): + del self.data[name] + + def toTupleList(self): + """Convert the attrs and values to a list of 2-tuples. The first element + of the tuple is the attribute name. The second element is either a + single value or a list of values.""" + return self.data.items() + + def toDict(self): + """Convert the attrs and values to a dict. The dict is keyed on the + attribute name. The value is either single value or a list of values.""" + result = ipapython.ipautil.CIDict(self.data) + result['dn'] = self.dn + return result + + def attrList(self): + """Return a list of all attributes in the entry""" + return self.data.keys() + + def origDataDict(self): + """Returns a dict of the original values of the user. Used for updates.""" + result = ipapython.ipautil.CIDict(self.orig_data) + result['dn'] = self.dn + return result + +# def __str__(self): +# """Convert the Entry to its LDIF representation""" +# return self.__repr__() +# +# # the ldif class base64 encodes some attrs which I would rather see in raw form - to +# # encode specific attrs as base64, add them to the list below +# ldif.safe_string_re = re.compile('^$') +# base64_attrs = ['nsstate', 'krbprincipalkey', 'krbExtraData'] +# +# def __repr__(self): +# """Convert the Entry to its LDIF representation""" +# sio = cStringIO.StringIO() +# # what's all this then? the unparse method will currently only accept +# # a list or a dict, not a class derived from them. self.data is a +# # cidict, so unparse barfs on it. I've filed a bug against python-ldap, +# # but in the meantime, we have to convert to a plain old dict for printing +# # I also don't want to see wrapping, so set the line width really high (1000) +# newdata = {} +# newdata.update(self.data) +# ldif.LDIFWriter(sio,User.base64_attrs,1000).unparse(self.dn,newdata) +# return sio.getvalue() |