[py-svn] r10344 - in py/branch/py-collect: . test test/testing

hpk at codespeak.net hpk at codespeak.net
Tue Apr 5 19:37:16 CEST 2005


Author: hpk
Date: Tue Apr  5 19:37:16 2005
New Revision: 10344

Modified:
   py/branch/py-collect/__init__.py
   py/branch/py-collect/test/config.py
   py/branch/py-collect/test/defaultconfig.py
   py/branch/py-collect/test/testing/test_config.py
Log:
(somewhat questionable) refactoring of the
cmdline parsing code.  

The underlying problem is messy: we want an easy "no-api"
extensibility of the py.test session, especially adding
command line options.  But if a project provides custom
command line options then it wants to access its values
(usually from the conftest file itself), of course.  But
conftest.py modules are really loaded at global level (cached
at sys.modules level) so nesting testing sessions becomes
difficult due to the global-importedness of conftest.py files.
(Nesting testing sessions is neccessary for testing py.test,
btw :-) 

OTOH, we can't just execfile() the conftest.py files because
we want to allow users to have e.g. "import
myproject.conftest" work as expected.  The latter is crucial
if you want to share test configuration options across various
directories in your project. 

Or am i missing something? 

Anyway, this commit works ok enough by introducing a new API
"py.test.addoptions()" which you usually execute at conftest.py
import time and it will add the given options _and_ return an
option object (providing any custom cmdline option values)
which you can then peruse from functions and custom test
classes.    



Modified: py/branch/py-collect/__init__.py
==============================================================================
--- py/branch/py-collect/__init__.py	(original)
+++ py/branch/py-collect/__init__.py	Tue Apr  5 19:37:16 2005
@@ -1,6 +1,7 @@
 from initpkg import initpkg
 initpkg(__name__, exportdefs = {
     'test.skip'              : ('./test/item.py', 'skip'),
+    'test.addoptions'        : ('./test/config.py', 'addoptions'),
     'test.skip_on_error'     : ('./test/item.py', 'skip_on_error'),
     'test.raises'            : ('./test/raises.py', 'raises'),
     'test.fail'              : ('./test/item.py', 'fail'),

Modified: py/branch/py-collect/test/config.py
==============================================================================
--- py/branch/py-collect/test/config.py	(original)
+++ py/branch/py-collect/test/config.py	Tue Apr  5 19:37:16 2005
@@ -67,8 +67,12 @@
     configpaths = findconfigpaths(anchorpaths) 
     parser = makeparser(configpaths) 
     cmdlineoption, remaining = parser.parse_args(args) 
-    fixoptions(cmdlineoption)
-    return cmdlineoption, remaining 
+    uservalues = parser._pytestvalues 
+    for name, value in vars(cmdlineoption).items(): 
+        assert not hasattr(uservalues, name) 
+        setattr(uservalues, name, value) 
+    fixoptions(uservalues) 
+    return uservalues, remaining 
       
 #
 # helpers
@@ -112,18 +116,42 @@
         option.executable = exe
 
 def makeparser(configpaths):
-    # first a small fight with optparse to merge the
-    # conftest.py file options correctly
+    global _lastoptions, _option
+    # trigger loading config options
+    for p in configpaths: 
+        p.resolve() 
+    defaultconfig.join('adddefaultoptions').resolve()() 
     parser = optparse.OptionParser()
-    for config in configpaths:
-        meth = config.join('options')
-        if meth.check():
-            groupname, groupoptions = meth.resolve()
-            optgroup = optparse.OptionGroup(parser, groupname)
-            optgroup.add_options(groupoptions)
-            parser.add_option_group(optgroup)
+    for groupname, groupoptions in _lastoptions: 
+        optgroup = optparse.OptionGroup(parser, groupname)
+        optgroup.add_options(groupoptions)
+        parser.add_option_group(optgroup)
+    # each time we make a parser which incorporates 
+    # all the cmdline options that users may have provided 
+    # we want to start over 
+    parser._pytestvalues = _option 
+    _lastoptions = []
+    _option = optparse.Values() 
     return parser 
 
+# XXX _lastoptions holds all options that are added from conftest
+# py.test.addoptions() invocations.  This "global state"
+# manipulation is not completely nice but how else could we allow 
+# test projects to add cmdline options and provide them access to 
+# the resulting values?  (apart from exposing driver initialisation 
+# some more which i really don't want to do) 
+
+_lastoptions = []
+_option = optparse.Values()
+
+def addoptions(groupname, *specs): 
+    """ add a named group of options to the current testing session. 
+        This function gets invoked during testing session initialization. 
+    """ 
+    global _lastoptions 
+    _lastoptions.append((groupname, specs))
+    return _option 
+
 def findconfigpaths(anchors):
     """ return test configuration paths. """ 
     configpaths = []
@@ -133,12 +161,10 @@
             x = p.join(configbasename)
             if x.check(file=1):
                 extpy = py.path.extpy(x)
-                extpy.resolve() # trigger loading it
                 if extpy not in d:
                     configpaths.append(extpy)
                     d[extpy] = True
     configpaths.sort(lambda x,y: cmp(len(str(x)), len(str(y))))
-    configpaths.append(defaultconfig)
     return configpaths 
 
 def getcollectors(filenames):

Modified: py/branch/py-collect/test/defaultconfig.py
==============================================================================
--- py/branch/py-collect/test/defaultconfig.py	(original)
+++ py/branch/py-collect/test/defaultconfig.py	Tue Apr  5 19:37:16 2005
@@ -12,7 +12,8 @@
 
 additionalinfo = None
 
-options = ('py.test standard options', [
+def adddefaultoptions(): 
+    py.test.addoptions('py.test standard options',
         Option('-v', '--verbose',
                action="count", dest="verbose", default=0,
                help="increase verbosity"),
@@ -43,4 +44,4 @@
         Option('', '--collectonly',
                action="store_true", dest="collectonly", default=False,
                help="only collect tests, don't execute them. "),
-])
+    )

Modified: py/branch/py-collect/test/testing/test_config.py
==============================================================================
--- py/branch/py-collect/test/testing/test_config.py	(original)
+++ py/branch/py-collect/test/testing/test_config.py	Tue Apr  5 19:37:16 2005
@@ -28,6 +28,23 @@
     assert d1 == d2
     assert d1.check(dir=1) 
 
+def test_config_options(): 
+    o = py.test.ensuretemp('configoptions') 
+    o.ensure("conftest.py").write(py.code.Source(""" 
+        import py
+        Option = py.test.Option
+        option = py.test.addoptions("testing group", 
+            Option('-g', '--glong', action="store", default=42,
+                   type="int", dest="gdest", help="g value."), 
+            )
+        """))
+    old = o.chdir() 
+    try: 
+        driver, paths = py.test.config.init(['-g', '17'])
+        assert driver.option.gdest == 17 
+    finally: 
+        old.chdir() 
+    
 #def test_config_order():
 #    from py.__impl__.test import config
 #    o = py.test.ensuretemp('configorder') 



More information about the pytest-commit mailing list