Configuration Files in Python

Another day, another language; such is the life of a consultant. This time it was Python and I was parameterizing tests for a client so I could log into their system without having to change anything other an an external file. Their CI server will have its own file, as will each of the team members writing / maintaining the Selenium scripts.

So building on what was covered in One, and only one config file and If you really must write your Selenium framework in Java, here is how I am currently suggesting how people incorporate configuration files into their scripts and frameworks.

First, you need to tell your framework (which in this case I mean ‘your own custom runner’) where exactly to find your config file.

import getopt
 
# this is a custom module / class you can see below
import config
 
try:
    opts, args = getopt.getopt(sys.argv[1:], "hc:", ["config="])
except:
    print("crap")
    sys.exit(2)
 
config_file = ""
for o, a in opts:
    if o == "-h":
        print("Usage:")
        print("sh.[bat|sh] script_pattern")
        print("    script_pattern can be either a script name (mco_rpt_wo_0001.py) or path part (mco_rpt)")
    if o in ("-c", "--config"):
        config_file = a
 
if config_file == "":
    logger.info("using config/flyingmonkey.cfg as config")
    config_file = "flyingmonkey.cfg"
 
# two ways to specify the config; either as a filename in the config dir or by path
cf = config.config()
if os.path.exists(os.path.abspath(config_file)):
    cf.configure(config_file)    
elif os.path.exists(os.path.join(os.path.dirname(__file__), "..",  "config", config_file)):
    cf.configure(os.path.join(os.path.dirname(__file__), "..",  "config", config_file))
else:
    print "config file (%s) does not exist" % config_file
    sys.exit(1)

Basically, what is happening here is that the runner can take as an optional parameter -c or –config which both take the name of a config file. And if the parameter isn’t provided then a default of flyingmonkey.cfg is used.

In my original way of doing this almost three years ago, I had it read the config from an XML file, but that doesn’t appear to be the Pythonic way of doing things. In the standard modules that Python comes with is the ConfigParser module which is a lot nicer — and since it is there by default is implicitly blessed as the way to do this sort of thing. Here is my new class for parsing this file.

import ConfigParser
 
class config(object):
    # singleton
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(config, cls).__new__(cls, *args, **kwargs)
        return cls._instance
 
    def configure(self, config_file):
        # parse config
        self.config = ConfigParser.RawConfigParser()
        self.config.readfp(open(config_file))

A lot nicer.

And here is how it is used in a script.

import unittest,  logging
from selenium import selenium
import config, rabbit
 
class createAlert(unittest.TestCase):
    def setUp(self):
        self.log = logging.getLogger("monkey.createAlert")
        self.cf = config.config().config
        self.verificationErrors = []
        self.selenium = selenium("localhost", 4444, self.cf.get("General", "browser"), self.cf.get("General", "server"))
        self.selenium.start()
        rabbit.login(self.selenium, self.cf.get("Login", "username"), self.cf.get("Login", "password"))

As for the actual file that it reads from, for those who used to have to hack around in DOS and Windows 3.x, it is quite similar to the .ini format that everything used to be.

[General]
server: http://flying.monkey.com
environment: test
browser: *chrome
 
[Login]
username: adam@element34.ca
password: monkey

The observant reader will see that the way to reference a particular parameter is by “Section” and then “Key”.

I’m pretty happy with how easy, and nice, it is to do this now.

Post a Comment

Your email is never published nor shared. Required fields are marked *