[Subversion] / PEAK / src / peak / config / interfaces.py |
No default branch
Bookmark a link to HEAD:
(view)
(download)
(as text)
Properties and utilities are unified at last! Both properties and utilities are now handled by the __instance_provides__ and __class_provides__ attributes of component classes. This simplified the code and interfaces for both PropertyMap and for registering dynamic utility providers. Property names now have an additional syntax form: 'some.prop?' which is used as a default value that is checked after 'some.prop', 'some.*', and 'some.prop' (a second time). This is handled transparently for you by way of the 'setDefault()' method of 'IPropertyMap', so effectively it's an implementation detail. Documentation is still a little sketchy, but it should now be straightforward to get the naming system using properties and utilities in a harmonious way. ALSO: Fixed config.getLocal() to ensure it's working with a root component. binding.New() can now use an import string instead of a class/type/callable. The object referenced by the import string will be loaded and called as though the object itself had been used. GlobalConfig and LocalConfig now have 'setup()' methods that can be overridden to create default rule and provider registrations. This'll be handy for making LocalConfig register a default transaction service provider, for example.
Moved all PEAK API exceptions to 'peak.exceptions' module, because it was getting pretty darn inconvenient to keep importing them across subpackages. 'from peak.api import exceptions' or 'from peak import exceptions' can be used to access them. It's worth the trouble of referring to 'exceptions.SomeException', because it allows the names to be shorter (no need for Exception or Error in the name) and makes the exceptions globally available. Added 'binding.iterParents()', which walks from a component up through its root parent, into the local and global configuration objects, if available. It's now used in getProperty() and findUtilities(). Synchronized interface of 'binding.findUtility()' and 'config.getProperty()'. Now both take an optional 'default' argument which will be returned if the sought item is not found, or, if a default is not supplied and the item isn't found, an 'exceptions.NameNotFound' error is raised. (findUtility() used to return 'None' to mean not-found). Fixed a bug in 'binding.lookupComponent()' for looking up utilities (which also caused 'bindTo(ISomething)' to not work correctly). Added a 'config.Property' class, a subclass of 'str', which parses and validates property names, as well as handling wildcard iteration. It also implements enough of 'IInterface' to allow it to be used as a key in an EigenRegistry. There's a new interface 'config.IConfigKey', which is implemented by both Interface objects and Property objects, so everything that can be used as a configuration key now implements it. This is another step towards unification of configuration properties (keyed by name) and utilities (keyed by Interface). After a few more passes, I should be able to eliminate the rest of the parallel logic that exists to process both Utilities and Properties. Fixed a typo in 'storage.TransactionComponent' which would have caused it to raise an error upon joining a transaction.
Fixed some missing interface docs re: object scope of property maps.
Fixed a problem with wildcard handling. Added IRuleFactory to make it easier for IRules to be instantiated per property map. Created a 'LoadingRule' factory for rules that load configuration data on-demand, and a 'loadEnviron' rule to test it with. Added unit test for the 'loadEnviron' rule, and code in the default GlobalConfig to add an "environ.*" rule based on loadEnviron. Also changed the default PropertyMap implementation to allow setting property values for "None", which is to say an assumed global property scope under the owner of the map.
Added "dirt-simple" property test. Fixed typos, and a logic hole that would've allowed you to set a value in a PropertyMap even if a rule had already been accessed to compute it. Corrected some interface docs.
A third swing at the right resolution algorithm for properties. Now, values and defaults are specific, and only rules can have wildcards. A value is checked for first, then rules, and finally the default. A rule can thus load data more specific than itself, eliminating the need to redirect between say, a "peak.foo" property and a "config.peak.foo" property. Instead, one can have a "*" rule that loads in all the config files appropriate to that level of property map. As long as the config files only define values or defaults, the rule doesn't even need to look for the value that the property map asked for, it can just pass by returning the 'NOT_GIVEN' singleton.
Some minor corrections to interface docstrings.
Finished out the rest of the PropertyMap implementation. It turns out we need to distinguish between "rules" (which compute a property value for a specific target) and "defaults" (which compute a property value irrespective of the target object). Updated interfaces to reflect this. Reworked PropertyMap algorithms to properly handle delayed locking of eigenstate for missing rules/defaults that are loaded by a higher-level wildcard rule or default. Added scope management to the IPropertyMap interface and implementation; i.e. when you set a value you must specify the intended target object, so that IPropertyMaps which manage properties per-target can do so, and ones that don't support it can raise a fuss if they're asked to do it.
Added basic property-related APIs -- they should work fine except that they'll never find any IPropertyMap utilities to use! :) (IPropertyMap implementations are up next...) I also moved the config API implementation out of the 'api' module and into a separate 'api_impl' module to avoid crowding the 'api' module with details, plus I cleaned up the code a little and added a few docstrings.
Added IRule and IPropertyMap interfaces for new configuration API's.
cvs-admin@eby-sarna.com Powered by ViewCVS 1.0-dev |
ViewCVS and CVS Help |