Object factory using the Python import mechanism

Today something related to Python programing … These snippets were rescued from a forgotten repository into my old Inspiron 6000.

Speaking clearly, this post is about one app (purpose of it is not relevant) which internal handlers class can be setting in configuration time. This idea is cool when you want minimize hookups in your app. For example, this solution is a easy way when, in a hypothetical future, a third developer want to extend your app with a new handler. In this scenario, this developer only should build the handler as a external module and load it in the python classpath.

First step, I build my Factory class. These objects class create DataSources objects:

class DataSourceFactory (object):

def create (self,handlerClassname, object_uid=None, key_value=None, \
handler_options={}):

...
modulename, classname = handlerClassname.rsplit('.',1)
module = __import__(modulename, {}, {}, classname)
handler_class = getattr (module,classname)
ds_handler = handler_class()
for k,v in handler_options.items():
setattr(ds_handler, k, eval(v))

ds = DataSource(ds_handler)
ds.key_value = key_value
ds.object_uid = object_uid

return ds

You note, two things in the previous code:

  • The create function received a string with the classname of the handler
  • I use getattr and __import__ ( object reflexion ) for instantiate the hadler objects received as parameter

The classname, in my app, is setting in the app configuration file. This file is a standard Python config file:

[origin]
datasource_handler='syncldap.datasources.LdapDataSourceHandler'
key_value='sid'
object_uid='sid'
...

This confs are loaded into de app using the RawConfigParser:

def create_Synchronizer(self,config_filename):
  # RawConfigParser not interpolate attribute values
  cfg = self.ConfigParser.RawConfigParser()
  cfg.readfp(file(config_filename))

# DataSourceFactory
data_source_factory = self.datasources.DataSourceFactory()
# Load class name of origin handler
origin_data_source_handler_classname = \
eval (cfg.get('origin','datasource_handler'))
# For example: 'syncldap.datasources.LdapDataSourceHandler'

# Load origin options
origin_handler_options = dict (cfg.items('opt:origin_handler'))
origin_key_value = eval \
  (cfg.get('origin','key_value'))

origin_object_uid = eval \
  (cfg.get('origin','object_uid'))

# Creating origin source
origin_source = \
  data_source_factory.create(origin_data_source_handler_classname, \
  origin_object_uid, origin_key_value, origin_handler_options)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s