[TransWarp] Requirements/use cases for configuration properties and files

Phillip J. Eby pje at telecommunity.com
Fri Oct 4 14:56:01 EDT 2002

Comments and questions welcome...  This is more or less the plan for 
expanding the current peak.config package to support actual configuration 
properties and config files.

Configuration Properties:

* Get a property for an object (e.g. config.getProperty(obj, 
'dotted.property.name') )

* Bind an attribute to a property (e.g. foo = 

* Acquire properties contextually, where a property set on some component 
implies that setting exists for child components unless overridden closer 
to the child.  (Implies the need for localizable property maps)

* Define lazy "rules" to specify the default value of a property, which 
will be passed the target object and property name in order to compute a 
value if no value is otherwise defined.  Rules should be able to return a 
special value (e.g. NOT_FOUND) to indicate that the search for a property 
should continue.

* Set or override global, application-specific properties at startup 
(implies a global property map; API = 
config.setGlobalProperty('property.name', value) )

* Set or override global, package-specific rules for default properties at 
startup (implies a global rules map; API = 
config.setGlobalRule('property.name', ruleObj)

* Set application-specific rules for default properties on a LocalConfig 
object (implies local rule maps; API = config.setRuleFor(obj, 
'property.name', ruleObj))

* Set task-specific properties on a LocalConfig object (presumably using a 
local property map; config.setPropertyFor(obj, 'property.name', value) )

Configuration Files:

* Load application-specific configuration files at end of "global" startup

* Load task/object-specific configuration files upon first use

* "Include" a configuration file from another, to provide defaults (e.g 
site-wide vs. app-specific)

* Syntax checking: an error should occur for redefinition of a property 
within the same configuration file

* Different types of configuration files, supplying either properties or 
rules for deriving properties (e.g "style sheets")

* At least one file format should include support for Python expressions

======= Design notes ========

The above seems to imply we need some type of PropertyMap utility which 
supports having both rules and values.  When asked for a property, a 
PropertyMap searches its values and rules, then falls through to any 
subordinate (e.g. more global) PropertyMaps if a result can't be 
found.  Both the GlobalConfig and LocalConfig objects should supply 
PropertyMaps by default; other objects could be supplied them on an 
individualized basis.

Configuration files and other data sources could be parsed to set either 
values or rules, according to their format.

Custom IPropertyMap implementations could use more exotic means of 
computation, such as path-based or stylesheet-like rules.  The basic 
property map might even allow wildcard rules, e.g. "environ.*" might be 
mapped to a rule that looks for an environment value.  This would allow 
delayed computation of certain configuration namespaces.  E.g. a 
configuration file might be mapped to a particular property namespace.

Ensuring immutability might be tricky, however.  Presumably, rules will 
have to guarantee that they will always produce the same value for a given 
property name/object pair.  The map can guarantee that the same rule will 
always be used for a given property, however.  Once a wildcard rule is 
found, it can be copied to the cell for the target property, and locked 
after the rule has been executed.

Locking after running the rule would allow the rule to "bootstrap" a more 
specific rule after first performing a computation.  For example, lazy 
loading of configuration files could be done with wildcard loaders that 
in-load all of their rules to the same (or more specific) configuration 
map, then doing a recursive getProperty() lookup for the same property, 
causing the newly loaded (more-specific) rule to be fired.  Thus, the 
default rule for property "*" could load the global configuration files as 
soon as a property was needed for which no default existed.

Downside to that concept: most properties will have global default rules, 
which means there isn't a good automatic "triggering point" to load 
them.  A fix is straightforward, but possibly tedious: make the default 
rules check for one or more, *differently-named* properties (which will 
trigger the configuration file loads) before falling back to an actual 
default value.  This might be as simple as prefixing the property 
namespace.  For example, if one has a property, 
"peak.naming.urlpackageprefixes", then the *configuration* of that property 
might actually be in "config.peak.naming.urlpackageprefixes".  The package 
that uses the variable would create a rule for the unprefixed property 
name, that checks for the prefixed property name before falling back to a 
default value.  A "config.*" property rule which loaded the global 
configuration files would then do the trick.

Note that this same namespace could work for both the local and global 
configs: even if a system property lookup falls through to the global map, 
the default rule begins the lookup again at the local level, so the local's 
"config.*" rule kicks in, loading the local configuration files and giving 
them a chance to supply the value before falling back to the global level's 
config files.

If configuration files can specify a rule that points to another 
configuration file or a portion thereof as a "wildcard" rule, then it's 
also possible to implement configuration "inheritance" or "includes", 
causing undefined items in a namespace to be "inherited" from the other 
configuration file.  This could be as simple as allowing the same sort of 
"fallback to another namespace" rule as is needed for system->config 

Also, "rewrite rules" like these could be supplied "close" to a component, 
where say, a "wxpython.bgcolor" property might be mapped to come from 
"myapp.widgetstyles.foo.background".  Thus allowing a transformation from 
properties needed by a framework, to properties defined by an application.

More information about the PEAK mailing list