Trying to make a dict behave like a clean class/method structure

Viewed 604

I'm trying to make a dictionary (read from an yaml data), behave like a class. Therefore if I call for class.key I would retrieve his value. The code is listed below:

import errno
import sys
import yaml

backup_conf="""
loglevel: INFO
username: root
password: globalsecret
destdir: /dsk/bckdir/
avoidprojects: 

matchregex: /bkp/

depots:
    server1:
        password: asecret

    server2:
        username: root

    server3:

    server4:
        destdir: /disk2/bkp/

projects:
    proj1:
        matchregex: 
            - /backups/
            - /bkp/
"""

class Struct:
    def __init__(self, **entries): 
        self.__dict__.update(entries)

class Config:

    def __init__(self, filename="backup.cfg", data=None):
        self.cfg = {}
        if data is None:
            try:
                fd = open(filename,'r')
                try:
                    yamlcfg = yaml.safe_load(fd)
                except yaml.YAMLError as e:
                    sys.exit(e.errno)
                finally:
                    fd.close()
            except ( IOError, OSError ) as e:
                sys.exit(e.errno)
        else:
            try:
                yamlcfg = yaml.safe_load(data)
            except yaml.YAMLError as e:
                sys.exit(e.errno)

        self.cfg = Struct(**yamlcfg)

    def __getattribute__(self, name):
        try:
            return object.__getattribute__(self, name)
        except AttributeError:
            return self.cfg.__getattribute__(name)


    def get_depot_param(self,depot,param):
        try:
            self.depot_param = self.cfg.depots[depot][param]
        except ( TypeError, KeyError) as e:
            try:
                self.depot_param = getattr(self.cfg, param)
            except KeyError as e:
                    sys.exit(e.errno)

        return self.depot_param

    def get_project_param(self,project,param):
        try:
            self.project_param = self.cfg.projects[project][param]
        except ( TypeError, KeyError) as e:
            try:
                self.project_param = getattr(self.cfg, param)
            except KeyError as e:
                sys.exit(e.errno)

        return self.project_param

    def get_project_matches(self,project):
        try:
            self.reglist = self.cfg.projects[project]['matchregex']
        except KeyError as e:
            try:
                self.reglist = self.cfg.matchregex
            except KeyError as e:
                    print "Error in configuration file: {0}: No default regex defined. Please add a matchregex entry on conf file".format(e)
                    sys.exit(e.errno)

        if isinstance(self.reglist, str):
            self.reglist = self.reglist.split()

        return self.reglist

    def get_depots(self):
        return self.cfg.depots.keys()                                                        

if __name__ == '__main__':
    # Read config file to cfg
    config = Config(data=backup_conf)

The code runs fine and I'm able to fetch data like: config.cfg.loglevel that returns INFO as expected. But I wish to know how can I call as config.loglevel removing that cfg that cleary cames from my self.cfg instance variable. (Of course any tips to enhance the code is welcome).

3 Answers
Related