[TransWarp] first experiences with Transwarp

Ulrich Eck ueck at net-labs.de
Mon Mar 18 13:48:42 EST 2002


Hi there,

after looking into TransWarp 0.2 preview, i find it very interesting.

i have played around with modules-inheritance which works pretty well and
tried the Database-Layer.

There were a few things that i needed to change to get the Database-part 
with
LDAP running (running at the moments means: Querying a record of a simple 
type):

I included my example and will comment the changes here:

Files:
 |- MyConnections.py	Modifications of TW.Database.Connections
 |- MyLDAPModel.py	Modifications of TW.Database.LDAPModel
 |- MyDataLayer.py	My Datalayer with Database and Type definitions
 |- test.py			how to use it ...

1. Changes to Connections
  - Error with QueryResult:
    """May be broken - needs testing since removal of 
ExtensionClass.Base""""

MyConnections.py-----------------------------------------------------------
--------------
from TW.API import *
from TW.Database import Connections

__bases__ = Connections,

class QueryResult:

	## File "/usr/lib/python2.2/site-packages/TW/Database/Connections.py",
	##   line 145, in __repr__
	##   self.realize(); return repr(self.data)
	##	TypeError: unbound method o__realize__() must be called with LDAPResult 
instance
	##   as first argument (got nothing instead)

	def realize(self): pass

class LDAPConnection:

	## add some debugging
	def __call__(self, baseDN=None, scope=None, filter=None, attrs=None,
             dn_only=0, timeout=-1, resultMaker=None):
		print baseDN,scope,filter,attrs
		ret = 
__proceed__(self,baseDN,scope,filter,attrs,dn_only,timeout,resultMaker)
		print ret
		return ret


setupModule()
~MyConnections.py----------------------------------------------------------
--------------

2. Changes to the LDAPModel
MyLDAPModel.py-------------------------------------------------------------
--------------
from TW.API import *
from TW.Database import LDAPModel,DataModel

__bases__ = LDAPModel,

def normalizeDN(dn):
    from ldap import explode_dn
    dn = explode_dn(dn.lower())

    ## fixed typo replaced 'key' with 'dn'
    return ','.join(
        ['='.join([x.strip() for x in y.split('=',1)]) for y in dn]
    )


class RecordType:

    def _loadDataFor(self, record, typeName=None):

        """Define in subclasses to read data into record"""

        objectClasses = record.objectClasses

        # If data already is loaded and it doesn't have the right classes
        if objectClasses and (self.requiredObjectClassSet - objectClasses):
            record.updateTypeMap(self,0)
            return

        # Else load the data
        conn = self.getService('LDAPConnection')

        if record.dn:
            results = conn(record.dn, 0,
                self.searchFilter, self.loadAttrs)
        else:
            results = conn(self.baseDN, self.searchScope,
                record.makeFilter(self.searchFilter), self.loadAttrs)
				
	## wrong error-msg if no result
        assert results is not None, ("No LDAP entry found for %s" % record)

        assert len(results)<2, ("More than one LDAP entry found for %s" % 
record)

        if results:
            record.loadDefaults([(k.lower(),v) for (k,v) in 
results[0].items()])
            record.updateTypeMap(self,1)
        else:
            record.updateTypeMap(self,0)



class RecordManager:

	## there is an error in the WeakCache Module:
	##  File "/usr/lib/python2.2/site-packages/TW/Database/DataModel.py",
	##  line 587, in _getFromCache
	##  record = get(key)
	##  File "/usr/lib/python2.2/weakref.py", line 68, in get
	##  wr = self.data[key]
	##  AttributeError: 'WeakCache' object has no attribute 'data'
	
	from TW.Caching import NoCache as recordCache	

    def _getKeysFor(self, mapping):

        keys = []
        g = mapping.get

        for key in self.allKeys:

            values = []

            for k in key:
                v = g(k)
                if v is None:
                    break

		    ## fixed typo replaced: values.append(key)
                values.append(v)
            else:
                keys.append( (key,tuple(values)) )

        return keys

		
setupModule()
~MyLDAPModel.py------------------------------------------------------------
--------------

3. MyDataLayer:
MyDataLayer.py-------------------------------------------------------------
--------------
from TW.API import *

import MyLDAPModel
import MyConnections

class MyDatabase(MyLDAPModel.Database):

	class Accounts(MyLDAPModel.RecordManager):
	
		rootTypeName = 'PosixAccount'

		class PosixAccount(MyLDAPModel.RecordType):
			baseDN = 'ou=people,dc=net-labs,dc=local'
			searchFilter = 'objectclass=account'
			allKeys = (('uid',),)
			loadAttrs = ['cn','uid','uidNumber','gidNumber','homeDirectory' ]

	class LDAPConnection(MyConnections.LDAPConnection):
		URL = 'ldap://intranet.net-labs.local'


setupModule()
~MyDataLayer.py------------------------------------------------------------
--------------

and now the final test.py:
test.py--------------------------------------------------------------------
--------------
import MyDataLayer
db = MyDataLayer.MyDatabase()
i = db.Accounts.getItem({'uid':'jack'})
if i.exists():
	print "Record exists."
	print i.items()
~test.py-------------------------------------------------------------------
--------------

this is the output of the python-shell:
---------------------------------------------------------------------------
--------------
jack at intranet twtest > python
Python 2.2 (#1, Feb 13 2002, 13:40:02)
[GCC 2.95.3 20010315 (release)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MyDataLayer
>>> db = MyDataLayer.MyDatabase()
>>> i = db.Accounts.getItem({'uid':'jack'})
>>> if i.exists():
...     print "Record exists."
...     print i.items()
...
ou=people,dc=net-labs,dc=local 2 (&(objectclass=account)(uid=jack))
	['cn', 'uid', 'uidNumber', 'gidNumber', 'homeDirectory']
[('cn=jack, ou=people, dc=net-labs, dc=local',
	{'gidNumber': ['100'], 'homeDirectory': ['/home/jack'],
	 'uidNumber': ['500'], 'cn': ['jack'], 'uid': ['jack']})]

Record exists.
[('dn', 'cn=jack, ou=people, dc=net-labs, dc=local'),
	('gidnumber', ['100']), ('uid', 'jack'),
	('homedirectory', ['/home/jack']),
	('uidnumber', ['500']), ('cn', ['jack'])]
>>>


I have a few questions on this:
  - Did I use the Database-package as you think that it is the right way ?
  - How would this application look like if it would make use of the SEF 
Model ?

I also build a small logger based on TW.API to learn AOP Basics, which i can
provide as example as well.

I hope this helps others to find into TransWarp as well
.. as long as what i've done is right ..

Ulrich Eck
---------------------------------------------------------------------------
net-labs Systemhaus GmbH
Ebersberger Str. 46
85570 Markt Schwaben
fon:   +49-8121-4747-11
fax:   +49-8121-4747-77
email: ueck at net-labs.de
http://www.net-labs.de




More information about the PEAK mailing list