Friday, August 3, 2012

[ Level 3 ] Python config factory with __subclasses__.

It's a sample code for use __subclasses__ to validate the type. I write a config factory utility
#!/bin/env python
import os, sys
if './' not in sys.path: sys.path.append('./') 
if './lib' not in sys.path: sys.path.append('./lib')
if '../lib' not in sys.path: sys.path.append('../lib')
if os.getcwd()+'/lib' not in sys.path: sys.path.append(os.getcwd()+'/lib')

import yaml, json
from libproperty import *
from StringIO import StringIO
from abc import *

## Property Abstract Class
## Subclass naming rule: xxxProperty. (e.g. JavaProperty, YamlProperty)
class CommonProperty(object):
    __metaclass__ = ABCMeta
    def __init__(self, FILE=None):
        self._prop_file_output = self._prop_file = FILE
        self._prop = None
        pass

    @staticmethod
    def isValidType(type):
        return '%sProperty' % type in [ c.__name__ for c in CommonProperty.__subclasses__() ]

    @abstractmethod
    def save(self, FILE=None):
        if not FILE == None:
            self._prop_file_output = FILE
        pass

    @abstractmethod
    def load(self, FILE):
        self._prop_file = FILE
        pass

    def getInstance(self):
        return self._prop

    def setInstance(self, _prop):
        self._prop = _prop

    def getProperty(self):
        return self
    
## Java Property Implementation    
class JavaProperty(CommonProperty):
    def __init__(self, FILE):
        super(JavaProperty, self).__init__(FILE)
        self._prop = Properties()
        
    def save(self, FILE=None):
        super(JavaProperty, self).save(FILE)
        self._prop.store(open(self._prop_file_output, 'w'))
        pass
    
    def load(self, FILE):
        super(JavaProperty, self).load(FILE)
        self._prop.load(open(FILE, 'r'))
        pass

## Yaml Property Implementation
class YamlProperty(CommonProperty):
    def __init__(self, FILE):
        super(YamlProperty, self).__init__(FILE)      
        self._prop = yaml.load('{}')

    def save(self, FILE=None):
        super(YamlProperty, self).save(FILE)
        fd = open(self._prop_file_output, 'w')
        fd.write(yaml.dump(self._prop))
        fd.close()
        pass
    
    def load(self, FILE):
        super(YamlProperty, self).load(FILE)
        self._prop = yaml.load(open(FILE, 'r'))
        pass

## Json Property Implementation
class JsonProperty(CommonProperty):
    def __init__(self, FILE):
        super(JsonProperty, self).__init__(FILE)
        self._prop = json.load(StringIO('{}'))

    def save(self, FILE=None):
        super(JsonProperty, self).save(FILE)
        json.dump(self._prop, open(self._prop_file_output, 'w'))
        pass
    
    def load(self, FILE):
        super(JsonProperty, self).load(FILE)
        self._prop = json.load(open(FILE, 'r'))
        pass

class TypeNotFoundException(Exception):
    pass

## Property Factory
class PropertyFactory(object):
    @staticmethod 
    def getProperty(type, filename):
        p = None
        if CommonProperty.isValidType(type):
            exec "p = " + type + "Property('%s')" % (filename)
            p.load(filename)
            return p.getProperty()
        else:
            raise(TypeNotFoundException)

def test1():
    f = '/tmp/t.properties'
    p = PropertyFactory.getProperty('Java', f).getInstance()
    print p['hello']
    f = '/tmp/t.yaml'
    p = PropertyFactory.getProperty('Yaml', f).getInstance()
    print p['hello']
    f = '/tmp/t.json'
    p = PropertyFactory.getProperty('Json', f).getInstance()
    print p['hello']
    f = '/etc/hosts'
    p = PropertyFactory.getProperty('Xml', f).getInstance()
    print p['hello']

def test2():
    f = '/tmp/t.properties'
    PropertyFactory.getProperty('Java', f).save('/tmp/t2.property')
    #PropertyFactory.getProperty('Java', f).save()
    f = '/tmp/t.yaml'
    PropertyFactory.getProperty('Yaml', f).save('/tmp/t2.yaml')
    #PropertyFactory.getProperty('Yaml', f).save()
    f = '/tmp/t.json'
    PropertyFactory.getProperty('Json', f).save('/tmp/t2.json')
    #PropertyFactory.getProperty('Json', f).save()
    f = '/etc/hosts'
    PropertyFactory.getProperty('Xml', f).save('/tmp/t2.xml')

def test3():
    f = '/tmp/t.properties'
    p = PropertyFactory.getProperty('Java', f)
    i = p.getInstance()
    i['hello'] = 'world'
    p.save('/tmp/t1.cnf')
    p.setInstance(i)
    p.save('/tmp/t2.cnf')
       
## main for testing ##
if __name__ == "__main__":
    test1()
    test2()
    test3()
    pass


Wish this helps.

regards,
Stanley Huang