Jim Gallacher wrote .. > > I have a better option (pun intended). :-) > > > > We do not need a new directive. Instead use existing "PythonOption" > > directive. > > That could work. > > > In the handler code for the directive, it can look at the > > value of the "cmd_parms->path" and determine if it is being used outside > > of all VirtualHost, Directory, Location, File directives, ie., at global > > scope "path" will be NULL. > > The disadvantage is that every request which triggers the > directive_PythonOption call would require a number of string > comparisons. Granted this is done in C, but there is a penalty to be paid.
No. No string comparisons at all. Check that cmd->path == NULL only. > > If it is, then stick it in a table object associated > > with the server level config for mod_python. This would then be accessible > > as: "req.server.get_options()". > > Do you see us adding a new apr_table_t field to the py_config structure > (define in mod_python.h)? Or would these server options go in either the > directives or options table? Hmmm, this is interesting. It seems that the code may have intended to implement the exact feature I was talking about but it wasn't completed. The code has: static const char *directive_PythonOption(cmd_parms *cmd, void * mconfig, const char *key, const char *val) { py_config *conf; conf = (py_config *) mconfig; if(val!=NULL) { apr_table_set(conf->options, key, val); conf = ap_get_module_config(cmd->server->module_config, &python_module); apr_table_set(conf->options, key, val); } else { /** We don't remove the value, but set it to an empty string. There is no possibility of colliding with an actual value, since an entry string precisely means 'remove the value' */ apr_table_set(conf->options, key, ""); conf = ap_get_module_config(cmd->server->module_config, &python_module); apr_table_set(conf->options, key, ""); } return NULL; } It was already setting the options table object in the server config object, but was doing it no matter where in config. Thus no different to request object. If instead it is written as: static const char *directive_PythonOption(cmd_parms *cmd, void * mconfig, const char *key, const char *val) { py_config *conf; conf = (py_config *) mconfig; if(val!=NULL) { apr_table_set(conf->options, key, val); if (cmd->path == NULL) { conf = ap_get_module_config(cmd->server->module_config, &python_module); apr_table_set(conf->options, key, val); } } else { /** We don't remove the value, but set it to an empty string. There is no possibility of colliding with an actual value, since an entry string precisely means 'remove the value' */ apr_table_set(conf->options, key, ""); if (cmd->path == NULL) { conf = ap_get_module_config(cmd->server->module_config, &python_module); apr_table_set(conf->options, key, ""); } } return NULL; } Then it then correctly separates the global from the non global. The merging code already merges the two back together to construct the actual request object. Code will actually run quicker than before, as have avoided inserting values into two tables when not global config. The only thing then missing is in serverobject.c, which needs: /** ** server.get_options(server self) ** * Returns the options set through PythonOption directives. * unlike req.get_options, this one returns the per-server config */ static PyObject * server_get_options(serverobject *self) { py_config *conf = (py_config *) ap_get_module_config(self->server->module_config, &python_module); return MpTable_FromTable(conf->options); } static PyMethodDef server_methods[] = { {"get_config", (PyCFunction) server_get_config, METH_NOARGS}, {"get_options", (PyCFunction) server_get_options, METH_NOARGS}, {"register_cleanup", (PyCFunction) server_register_cleanup, METH_VARARGS}, { NULL, NULL } /* sentinel */ }; If I then have at global config scope: PythonOption global 1 PythonOption override 1 and in a .htaccess file: PythonOption local 1 PythonOption override 2 The end result is: req.get_options()={'local': '1', 'override': '2', 'global': '1'} req.server.get_options()={'override': '1', 'global': '1'} > How does req.server.get_options() differ from req.server.get_config(), > which already exists? I still see what is in get_config() as special, ie., the values for actual directives. Just don't think it is good to mix them. > And lest we forget the original intent of this > discussion, we want this so we can pass runtime configuration > information during mod_python initialization. Maybe it really is more > logical to have a new directive rather than overloading the behaviour of > PythonOption. Well, with only slight changes as above, seems it can be done with what we have. Graham