Programming ZopeLDAP Entry Objects Author -- "Jeffrey P Shell", mailto:jeffrey@digicool.com Date -- Dec 18, 2000 Revision -- For ZopeLDAP 1.1.0 1. Getting an Entry Object and its attributes Using an LDAP Filter object is the best way to get an Entry object. LDAP Filter objects act like methods\functions and return a sequence of entry objects (so they can be used with any sort of looping structure). For example, if you had an LDAP Filter titled 'lookupByEmail' with the parameter 'email' with the content:: mail=* Can be used in DTML like this:: Surname:
Common name:

Or in a Python Script like this:: entries = container.lookupByEmail(email='jef') for entry in entries: # do something here... 1.1. Notes about Attributes and Entry Objects By default, LDAP always returns its attributes as sequences (Python lists), even if there is only one value. ZopeLDAP Entry objects use a special class, *AttrWrap*, when returning attributes accessed through normal __getattr__ (the a.b syntax). AttrWrap behaves and acts like a normal Python list with the exception that when printed as a string (ie, with 'dtml-var' or Python 'str()' or '"%s"'), it printes the results as a comma seperated list. This makes DTML representations of Entry object significantly easier. When using the Entry method 'get()', the attribute is returned as a Python list as returned by PythonLDAP. But if you're wanting to do tests based on attributes, you have to *remember to qualify the attribute*, ie:: if entry.sn[0] == 'Shell': # Works if entry.sn == 'Shell': # Won't work And also remember that 'getattr' based access returns *AttrWrap* instances, which means the following:: if entry.get('sn') == ['Shell']: # Works if entry.sn == ['Shell']: # Won't work 2. Changing attribute values Changing attributes on Entry objects is protected by the permission **Manage Entry Information**. This permission can be set anywhere in Zope, and will work best when set in the folder containing the LDAP Filter used to access the Entry object. The methods exposed under this permission are: **set(key, value)** -- example: 'entry.set("sn", "Shell")', 'entry.set("mail", ["foo@bar.com", "foo@baz.net"])' **setattrs([kwdict, kw])** -- Takes either a mapping argument or keyword arguments. Or both. Example: 'entry.setattrs({"sn": "Bazzo"}, mail=["foo@bar.com, "foo@baz.net"])' **setAll([kwdict, kw])** -- Same as *setattrs*, except that the existing data is *replaced* by what's passed in here. **remove(attr)** -- Deletes the attribute, example: 'entry.remove("comments")' 3. Accessing subentries Attributes on Entry objects are available through the Python 'getattr' protocol, and subentries are available through the 'getitem' protocol via their Relative Distinguished Name (RDN). Meaning if you had an Organizational Unit entry for 'Housewares' and wanted to get the subentry '"Betty Ford"', it would appear like this (considering 'housewares' is the Entry object):: betty = housewares["cn=Betty Ford"] 3.1. Adding subentries Adding subentries to an Entry object is done through the 'addSubentry' method. Adding subentries is protected by the permission **Create New Entry Objects**. **addSubentry(rdn, [attrs,kw])** -- Add a new subentry identified by the rdn. The rdn **MUST** be a string in the form 'attr=value', such as 'ou=Housewares' or 'cn=Davy Jones'. The rest of the signature can be a combination of a dictionary of attributes passed in to 'attrs' or keyword arguments. If no 'objectClass' attribute is passed in, the default objectClass is 'top'. The newly created Entry object is returned, wrapped in the acquisition context of its parent. Some example uses are:: betty = housewares.addSubentry("cn=Betty Ford", { "objectClass": ["top", "person"], "sn": "Ford", }) clinic = betty.addSubentry("sn=Clinic", objectClass=["top","place"], description="A good place to go..." ) 3.2. Deleting subentries Deleting subentries from an Entry object is done through the 'deleteSubentry' method. Deleting subentries is protected by the permission **Delete Entry Objects**. **deleteSubentry(entry)** -- You can either delete a subentry by its 'rdn', or by passing in the subentry object itself. Deletion is recursive and will delete everything below the specified entry from the LDAP server as well as the Entry object itself. Some examples uses are:: betty.deleteSubentry("sn=Clinic") # Delete by rdn (local id) housewares.deleteSubentry(betty) # Delete by entry itself 4. Other Zope Interfaces supported Entry objects are a combination of classes: The basic Entry class (either GenericEntry or TransactionalEntry at present), and one called Entry, which implements some Zope level Interfaces (of the programming kind). These include:: - '__bobo_traverse__' -- To traverse to subentries along the URL. - The Tree Protocol -- Allows Entry objects to be used automatically with the 'dtml-tree' tag. - 'objectValues()' -- Returns all of the subentries in a list. - 'objectIds()' -- returns all of the RDN's of the subentries. - 'objectItems()' -- returns a list of tuples in the form of ('rdn', 'entry object').