Issue #1069 open

CherryPy dies if a config file value is a dictionary

guest
created an issue

CherryPy allows — nay, requires — that config file values be Python expressions. But if I try to provide a small dictionary that my application needs: {{{ [/] selections = {'noller': 'bacon'} }}} then instead of parsing the dictionary, CherryPy returns: {{{

Traceback (most recent call last): File "/home/brandon/rover/cory/venv/bin/cherryd", line 108, in <module> options.pidfile, options.imports, options.cgi) File "/home/brandon/rover/cory/venv/bin/cherryd", line 19, in start cherrypy.config.update(c) File "/home/brandon/rover/cory/venv/lib/python2.7/site-packages/cherrypy/_cpconfig.py", line 156, in update reprconf.Config.update(self, config) File "/home/brandon/rover/cory/venv/lib/python2.7/site-packages/cherrypy/lib/reprconf.py", line 143, in update config = Parser().dict_from_file(config) File "/home/brandon/rover/cory/venv/lib/python2.7/site-packages/cherrypy/lib/reprconf.py", line 214, in dict_from_file return self.as_dict() File "/home/brandon/rover/cory/venv/lib/python2.7/site-packages/cherrypy/lib/reprconf.py", line 205, in as_dict raise ValueError(msg, x.class.name, x.args) ValueError: ('Config error in section: \'global\', option: \'selections\', value: "{\'noller\': \'bacon\'}". Config values must be valid Python.', 'AssertionError', ()) }}} It seems that the "assert" statement at transformer.py:1214 in the Python 2.7 standard library thinks that a dictionary node should start with a "dictorsetmaker" but instead is seeing what it thinks is a "classdef" node. Is this an error in the deprecated "compiler" Standard Library package (I ran into one of those recently), or an error in how CherryPy is calling it?

And, while all this is on the table: why does CherryPy bother with the parser module and then trying to evaluate the (now deprecated) output, instead of just running "eval()" on configuration file entries?

Thanks for any help in getting this working!

Comments (4)

  1. Robert Brewer

    And, while all this is on the table: why does CherryPy bother with the parser module and then trying to evaluate the (now deprecated) output, instead of just running "eval()" on configuration file entries?

    Excellent question. If there are no objections, I'd be happy to switch to using eval(), except for one feature. The current implementation is smart enough to try to import expressions from named modules without requiring a separate import statement. That would have to be re-implemented somehow in an eval approach.

  2. guest reporter

    Could you just wrap the eval statement in a try-except clause that catches errors caused by undefined names, and then re-attempt the expression with the name defined? (Because, of course, the name error might come from inside of some function that the expression is calling, and not have to do with the expression's namespace at all.)

  3. Anonymous

    We tried to reproduce the problem (in test_config.py) and could not reproduce it.

    Here is what we tried...

     def test_configConfigValueDictionnaryWorks( self ):
            from textwrap import dedent
            conf = dedent("""
            [/]
            selections = {'noller': 'bacon'}
            """)
            fp = StringIO(conf)
    
            cherrypy.config.update(fp)
            self.assertEqual(cherrypy.config["/"]["selections"], {'noller': 'bacon'} )
    

    in the class VariableSubstitutionTests

  4. Log in to comment