Commits

Brodie Rao  committed d39185c

Added support for specifying default options in .cramrc

  • Participants
  • Parent commits c775599

Comments (0)

Files changed (3)

 ``--interactive``, you'll be prompted to merge the actual output back
 into the test. This makes it easy to quickly prototype new tests.
 
+You can specify a default set of options by creating a ``.cramrc``
+file. For example::
+
+    [cram]
+    verbose = True
+    indent = 4
+
+Is the same as invoking Cram with ``--verbose`` and ``--indent=4``.
+
+To change what configuration file Cram loads, you can set the
+``CRAMRC`` environment variable. You can also specify command line
+options in the ``CRAM`` environment variable.
+
 Note that the following environment variables are reset before tests
 are run:
 
 
 import difflib
 import itertools
+import optparse
 import os
 import re
 import subprocess
 import time
 import tempfile
 
+try:
+    import configparser
+except ImportError:
+    import ConfigParser as configparser
+
 __all__ = ['main', 'test']
 
 def findtests(paths):
             return path
     return None
 
+def expandpath(path):
+    """Expands ~ and environment variables in path"""
+    return os.path.expanduser(os.path.expandvars(path))
+
+class OptionParser(optparse.OptionParser):
+    """Like optparse.OptionParser, but supports setting values through
+    CRAM= and .cramrc."""
+
+    def __init__(self, *args, **kwargs):
+        self.config_opts = {}
+        optparse.OptionParser.__init__(self, *args, **kwargs)
+
+    def add_option(self, *args, **kwargs):
+        option = optparse.OptionParser.add_option(self, *args, **kwargs)
+        if option.dest and option.dest != 'version':
+            key = option.dest.replace('_', '-')
+            if option.action == 'store_true':
+                type_ = 'bool'
+            else:
+                type_ = option.type
+            self.config_opts[key] = type_
+        return option
+
+    def parse_args(self, args=None, values=None):
+        config = configparser.RawConfigParser()
+        config.read(expandpath(os.environ.get('CRAMRC', '.cramrc')))
+        defaults = {}
+        for key, type_ in self.config_opts.items():
+            try:
+                if type_ == 'bool':
+                    value = config.getboolean('cram', key)
+                elif type_ == 'int':
+                    value = config.getint('cram', key)
+                elif type_ == 'float':
+                    value = config.getfloat('cram', key)
+                else:
+                    value = config.get('cram', key)
+            except (configparser.NoSectionError, configparser.NoOptionError):
+                pass
+            else:
+                defaults[key] = value
+        self.set_defaults(**defaults)
+
+        eargs = os.environ.get('CRAM', '').strip()
+        if eargs:
+            import shlex
+            args = args or []
+            args += shlex.split(eargs)
+
+        return optparse.OptionParser.parse_args(self, args, values)
+
 def main(args):
     """Main entry point.
 
     args should not contain the script name.
     """
-    from optparse import OptionParser
-
-    eargs = os.environ.get('CRAM', '').strip()
-    if eargs:
-        import shlex
-        args += shlex.split(eargs)
-
     p = OptionParser(usage='cram [OPTIONS] TESTS...')
     p.add_option('-V', '--version', action='store_true',
                  help='show version information and exit')

File tests/cram.t

   no such file: non-existent
   [2]
 
+Options in .cramrc:
+
+  $ cat > .cramrc <<EOF
+  > [cram]
+  > yes = True
+  > no = 1
+  > indent = 4
+  > EOF
+  $ cram
+  options -y and -n are mutually exclusive
+  [2]
+  $ mv .cramrc config
+  $ CRAMRC=config cram
+  options -y and -n are mutually exclusive
+  [2]
+  $ rm config
+
 Options in an environment variable:
 
   $ CRAM='-y -n' cram