[Subversion] / PEAK / CHANGES.txt |
No default branch
Bookmark a link to HEAD:
(view)
(download)
The 'logging.logger:' URL scheme has been simplified to 'logger:'. Please convert your scripts and configuration files, as the longer form will go away in the alpha 4 development cycle. Also, fix 'peak help logs' breaking due to a missing 'mdl_typeCode' on 'naming.CompositeName'.
Added 'commands.lookupCommand()' to look up a command shortcut or URL, ala the 'peak' script or 'commands.Bootstrap' class. Also added various 'commands.ErrorSubcommand' subclasses to make it easier to issue errors from subcommands.
Added 'peak.core' as a minimal subset of 'peak.api'. 'peak.core' offers only "core" API packages and primitives, not the full set of available framework APIs. 'peak.api' will continue to expand as frameworks are added, but 'peak.core' will stay as small as practical. ('peak.exceptions' may in fact end up being removed from 'peak.core', or at least renamed.) Also, added 'peak.util.symbol' module, to contain 'NOT_GIVEN', 'NOT_FOUND', and the 'Symbol' class used to create them.
Renamed 'fd:' URL to 'fd.socket:', simplified its syntax to 'fd.socket:fileno/family/kind/protocol', and changed its attribute names to match the syntax. (The rename is because we may want 'fd.file:' later as well.)
Promote peak.running.supervisor to peak.tools.supervisor.
Give peak.running.tools a promotion... it's now just peak.tools
Formatting fixes.
Configuration system cleanups and new features: - Replaced the "[Provide Utilities]" section of .ini files with "[Component Factories]". The new section type is easier to use, much more versatile, and does all registration and imports lazily. See the 'peak.ini' file for docs. "[Provide Utilities]" and 'config.ProvideInstance()' are now DEPRECATED, so please convert ASAP. - 'binding.Make()' now accepts configuration keys, using them to look up a factory object that's then invoked to create the attribute. This makes it a lot easier to define a component with its own transaction service, 'IBasicReactor', or other normally "global" component. It also makes it easier to globally specify a factory class for some interface. Factories are looked up under the 'config.FactoryFor(key)' configuration key. (See below.) - Added 'config.FactoryFor(key)', a 'config.IConfigKey' implementation that provides a configuration namespace for factories. When you use 'binding.Make(ISomething)', it's roughly equivalent to:: binding.Make( lambda self,d,a: binding.lookupComponent( self, config.FactoryFor(ISomething), adaptTo = binding.IRecipe )(self,d,a) ) That is, the 'config.FactoryFor(ISomething)' is looked up and invoked. - Added 'config.CreateViaFactory(key)', a 'config.IRule' implementation that creates an implementation of 'key', by looking up 'config.FactoryFor(key)'and invoking it. - Added 'config.ruleForExpr(name,expr)', that returns a 'config.IRule' that computes the Python expression in the string 'expr'. This is the mechanism used by configuration files to create rules, factored out into an API call so that configuration extensions can use it, too.
The 'referencedType' of a 'model.StructuralFeature' can now be any 'binding.IComponentKey', not just a type or a string. Types are also now implicitly component keys, which means you can use 'binding.Obtain(SomeType)' to look up 'SomeType'. (Right now, this is no different than using 'SomeType' without the 'binding.Obtain()', but in future releases this will use a "class replacement service" to allow easy replacement of model and other collaborator classes, while implementing AOP-like features.)
Added 'naming.Indirect(key)', a 'binding.IComponentKey' that can be used to do an indirect lookup via another 'IComponentKey' (such as a name). Using 'naming.Indirect()', you can replace code like this:: socket = binding.Obtain( lambda self: self.lookupComponent(self.socketURL), adaptTo = [IListeningSocket] ) with code like this:: socket = binding.Obtain( naming.Indirect('socketURL'), adaptTo = [IListeningSocket] )
Remove process supervisor from TODO, add it to CHANGES and README. Also, added a link from its ZConfig schema to the original design proposal, since it'll no longer be linked from the TODO.
Standardized these characteristics of name and address syntax: * '//' at the beginning of URL bodies is *mandatory* when the URL begins with an "authority" as described by RFC 2396. When the URL is not required to contain an authority (e.g. 'peak.storage.SQL.GenericSQL_URL'), the '//' is *optional*, and the canonical form of the URL will not include it. * Standardized names for RFC 2396 fields: 'user', 'passwd', 'host', and 'port'. In addition, added test cases for all name/address schemes, or documented why no tests are needed (or possible, in the case of icb). Also, refactor 'fd:' URL scheme to use 'model.Enumeration' types so that the URLs have a canonical form (at least within a given platform), and can be properly formatted as well as parsed. Finally, added more docs to 'fdURL' class.
Prototype fix: 'peak.running.commands.CGICommand' could become confused on certain BSD variants (such as Mac OS/X), and assume it was running under FastCGI, even if it wasn't. (Because the operating systems in question use socket pairs to implement pipes.)
Added 'peak.metamodels.ASDL', a metamodel for the Zephyr Abstract Syntax Description Language. ASDL is a convenient way to describe a domain model for an abstract syntax tree (AST), and the models generated with the new ASDL tool can be combined with concrete syntax to create a complete parsing solution for "mini languages", possibly including the Python language itself. (Future versions of the Python and Jython compilers are likely to use AST models based on ASDL, and in the current Python CVS sandbox there's already an ASDL model of Python's AST available.)
Enhanced 'fmtparse' and 'peak.model' to allow using types as syntax rules for parsing, including abstract types. An abstract type's syntax is the union (using 'fmtparse.Alternatives') of the syntaxes of its subclasses (as specified by 'mdl_subclassNames').
First draft of new 'SupervisorProcess' pre-forking process manager. Added 'IProcessTemplate' and a draft implementation thereof, along with a revised version of 'IProcessProxy' and a draft implementation of that. Also added 'IMainLoop.setExitCode()' and 'IMainLoop.childForked()' methods, to allow reactor-driven components to control the mainloop's exit code.
DEPRECATED 'peak.util.signal_stack'. Instead, bind to a 'running.ISignalManager' and use its 'addHandler()/removeHandler()' methods. This has the same effect as 'pushSignals()' and 'popSignals()', except that you do not have to remove handlers in the same order as you add them, and *all* active handlers are invoked for a given signal that they handle. Added 'IBasicReactor.crash()', which forces an immediate reactor loop exit, ignoring pending scheduled calls. This required changing some tests, because the precise moment of reactor termination is now different in some scheduling scenarios. Some changes were also made to task scheduling for CGI programs to account for this.
Added 'peak.running.commands.runMain()', a convenience function for starting an application's "main" command, that also makes it easy for forked child processes to exit and replace the parent process' "main". The 'peak' script has now been shortened to:: from peak.running import commands commands.runMain( commands.Bootstrap ) so it's now much easier to create alternative startup scripts, if you need to, or to add an 'if __name__=="__main__"' clause to a module.
Added 'peak.util.mockdb', a "mock object" implementation of a DBAPI 2.0 driver module. 'mockdb' connections can be told to 'expect()' queries and 'provide()' data to their callers, and will raise AssertionErrors when they are used in a way that doesn't conform to your supplied expectations. This is intended to be used for unit testing components that depend on a database connection: you can verify that they send the right SQL, and you can provide them with dummy data to use. There is also a 'mockdb:' URL and peak.storage driver, so you can easily use a mock DB connection in place of a real one within a PEAK application, for testing purposes. Note, however, that 'peak.util.mockdb' is a DBAPI 2.0 driver in itself, and thus can also be used to test DBAPI usage outside of PEAK.
Update PEAK's CHANGES for the 2.3 test suite bugfixes.
SQL connection objects now provide an 'appConfig' attribute that is a driver-specific 'config.Namespace()'. This allows you to easily set up configuration properties that are driver-specific. For example, you could use properties to configure driver-specific SQL snippets, then access them via the connection's 'appConfig' namespace. The namespaces are of the form 'DRIVER.appConfig', where 'DRIVER' is the name of the DBAPI module for that connection type (e.g. 'pgdb', 'cx_Oracle', etc.).
Merged 'Fallback' and 'PropertySet' to create 'config.Namespace'. Removed 'Fallback' and deprecated 'PropertySet'.
Added 'config.Fallback()' convenience class for redirecting property lookups from one namespace to another. See 'peak.ini' for usage examples.
SQL connection objects now get their type converters from a distinct property namespace for each DBAPI driver. For example a driver using the 'cx_Oracle' module will get its type converters from the 'cx_Oracle.sql_types' property namespace, instead of 'peak.sql_types'. For backward compatibility, these driver-specific namespaces are set up to fall back to 'peak.sql_types' for their defaults. Type converter construction has also been improved, to eliminate conversion overhead completely when no conversions are required for a specific query. Also, SQL connections now offer a method that will create a row conversion function for a given result description and optional postprocessing function. This new method should now be used in place of direct access to the 'typeMap' attribute of connection objects.
Misc. doc fixes.
First phase of the binding API simplification, including detailed docs for 'Descriptor' and 'Attribute'. (Second phase will be mass search-and-replace of the API's usage in PEAK, third will be additional tests and docs.) Added 'binding.Require', 'binding.Obtain', 'binding.Make', and 'binding.Delegate'. *ALL* other binding types are now DEPRECATED, and will go away before 0.5 beta is released. Please see CHANGES.txt for a detailed mapping of how to translate from the old to new API, and let me know if anything's missing. Note that the new 'Make' and 'Obtain' bindings also support sequences of recipes and keys, and in those cases will produce a sequence of the results from those recipes or keys. Also, 'Make' will accept no-argument and one-argument callables, where 'Once' always required three-argument functions. This should make it a lot easier to write short binding functions. Also, note that the 'activateUponAssembly' keyword is now 'uponAssembly', and 'isVolatile' is now 'noCache'. (The old names will work as keyword arguments until the alpha 4 development cycle begins.) The 'binding.IActiveDescriptor' interface also changed as a result of this. Last, but not least, a 'binding.IRecipe' interface was added, to support the new 'binding.Make' type.
Added a 'lockName' attribute to 'runnning.AdaptiveTask', and a 'LockURL' setting to its ZConfig schema. This allows a lockfile URL to be specified for adaptive tasks that need exclusive access to some resource while running.
Update misc. notes re: deprecated binding APIs.
A list or tuple of 'IComponentKey' instances is now treated as a single component key, that returns a tuple of the values returned by each constituent component key. This means that 'binding.bindTo()' and 'lookupComponent()' can now accept a list or tuple of component keys. This makes 'bindSequence()' obsolete, so 'bindSequence()' is now DEPRECATED. 'binding.bindSequence(key1,key2,...)' can now be replaced with 'binding.bindTo([key1,key,...])', and will produce the same results.
'naming.IBasicContext.lookup()' and 'naming.lookup()' now accept a 'default' argument, similar to that used by 'lookupComponent()' and most other lookup-like APIs in PEAK. This change was made so that component lookups don't need to rely on catching 'exceptions.NameNotFound' errors to tell them when to use the default value. This could hide 'NameNotFound' errors that were actually from a broken component somewhere in the lookup process. (In general, it's probably a bad idea to have an exception that's used for both control flow and real errors!) Also, removed most trapping of 'NameNotFound' errors throughout PEAK, except for those in N2, which I'll leave for Ty. :) Last, but not least, cleaned up documentation of related interfaces/methods.
Added new 'version' tool that automatically edits files to update version information in them. Just execute the 'version' file in the main PEAK source directory. (Use '--help' for help.) You can use this tool with your own projects by creating 'version' and 'version.dat' files in your project directory, similar to the ones used by PEAK. The 'version' file is a ZConfig file that describes your project's version numbering scheme(s), formats, and the files that need to be edited, while the 'version.dat' file contains the current version number values. Source for the tool, including the configuration file schema, is in the 'peak.running.tools.version' package. (Error handling and documentation, alas, are still minimal.) Also, bumped PEAK version stamps to 0.5a3, using the new tool. (Yay!)
Added new 'Alias' command in 'peak.running.commands'. An 'Alias' instance can be used as a 'peak.running.shortcut' property that expands to another command with arbitrary arguments inserted before the original command's arguments. Thus, one might alias 'mycommand' to 'runIni somefile --option', similar to command aliases in many shells.
Fix errors in a participant's 'abortTransaction()' from causing the overall abort operation to break.
Fix not closing SQL cursors when transaction aborted.
Misc. peak.binding cleanups and DEPRECATIONS, as follows: - The following 'binding' forms are now deprecated, and will go away before 0.5 beta is released: 'bindToProperty(x,y)' -- use 'bindTo(PropertyName(x),default=y)' 'bindToParent()' -- use 'bindTo("..")' 'bindToSelf()' -- use 'bindTo(".")' 'bindToUtilities()' -- no replacement; let me know if you're using this. - 'naming.IName' is now derived from 'binding.IComponentKey', so names and addresses must now support the 'findComponent()' method. All PEAK name and address types provide support for this. - The 'lookup()' method of 'binding.IComponentKey' is now called 'findComponent()', to better distinguish it from 'lookup()' in 'naming.IBasicContext', which does something very different. - 'binding.bindTo()' and 'binding.bindSequence()' now pre-adapt their arguments to 'IComponentKey', to speed lookups at runtime, and to ensure that errors due to an unusable parameter type occur at class creation time instead of waiting until lookup time.
Fix problem found by Yaroslav Samchuk: The logging system would raise an error if a log message with no arguments contained a '%' sign.
There's a new 'peak.storage.files' module, with handy classes like 'EditableFile'. 'EditableFile' is a class that lets you edit the contents of a file "in place", with atomic replacement of the original at transaction commit. If the transaction is aborted, the original file is left unchanged. Also, added 'delete()' method to standard 'openable.FileFactory' objects, and changed 'FileFactory.getObjectInstance()' so that new instances created from references use their retrieval context as a parent component.
Move signal management to UntwistedReactor, for better compatibility with Twisted's signal handling. Add 'installSignalHandlers' argument to 'run()' method, for the same reason.
'peak.running.scheduler.UntwistedReactor' now supports a configuration property ('peak.running.reactor.checkInterval') to determine how long it should run 'select()' calls for, when there are no scheduled tasks. Also, fixed reactor needlessly sleeping for the defined check interval, when there are neither scheduled tasks nor I/O handlers. This is important for Windows, where signals (e.g. ^C, BREAK) aren't processed during 'sleep()'. (Of course, this'll also burn CPU in a tight loop, but hey, it's Windows, and you won't have anything important running there, right?)
'peak.running.scheduler.MainLoop' now supports using a "signal manager" component (via the 'peak.running.signalManager' property) to process signals while a 'run()' loop is in progress. Signal managers can also be added or removed at any time via the new 'peak.util.signal_stack' module. Also, fixed scheduler tests using an app object without a config root.
'peak.running.commands.AbstractCommand' now offers a '_run()' method that can be overridden in subclasses, instead of 'run()'. If you override the new '_run()' method instead, you get the advantage of automatic handling for invocation errors and 'SystemExit' exceptions, provided for you by the 'run()' method.
Forgot to include CHANGES.txt in the checkin.
Update CHANGES.txt to describe 'PropertyName.fromString()' constructor.
It's now possible to extend .ini file parsing with custom section types, and PEAK defines its own built-in section types using this extension mechanism. Custom section types must include at least one space, (e.g. '[My Section]') or they will be treated as a plain property name. See the 'peak.config.iniFile.sectionParsers' section in 'peak.ini' for more details, along with the 'config.ISettingParser' and 'config.IIniParser' interfaces.
When creating a 'PropertyName()', it's now possible to force conversion of invalid characters to '_', by supplying 'force=True'. This doesn't address syntactic issues (like having a non-terminating '*'), or character sets (non-ASCII characters are still rejected). But it's convenient for things like filenames or text that might contain spaces. Used this new ability to fix the SQL typeMap problem when spaces appear in SQL type names.
It's now possible to declare an attribute as offering a wildcard property; such lookups now follow the same rules as other wildcard property lookups. The 'config.IConfigKey' interface has been changed to cleanly support implied keys at both registration and lookup time, so you can implement your own key types that work the way interfaces or property names do for configuration lookups. I also moved the 'EigenRegistry' class from 'peak.util.EigenData' to 'peak.config.registries', as it hasn't really been useful outside PEAK for a while now.
Added "smart properties" support, w/tests. You can now use 'naming.LinkRef' and 'naming.Reference' in .ini files and have them work, even without using peak.naming to look up the properties. Also, it should be possible to create useful caching rule objects, such as we will need for peak.web templates. Also, fixed a typo in peak.naming.arithmetic that caused certain name subtractions to fail.
Fixed 'peak.util.imports.whenImported()' function, so you can now register functions to be called when another module is imported. This should be useful for declaring adapters for external types, e.g. adapting Zope interfaces to IConfigKey, without causing the external type to be imported unless it's actually used.
Got rid of the 'adaptTo' requirement for retrieving objects from naming contexts. Note that if you have defined any URL schemes that do not also define a naming context class, you will need to revise them. Specifically, you need to add a 'defaultFactory' attribute referencing the name of the class of object that the URL should retrieve, and you need to have that class declare that it (not its instances) provide 'naming.IObjectFactory', and add a 'getObjectInstance()' classmethod to do the dirty work. If your URL scheme references a subclass of ManagedConnection, you don't need to do the object factory stuff, however, as it's already done for you in the ManagedConnection base. All you need is the 'defaultFactory' attribute. Also, if you defined any adapter declarations for your URLs to the target class, you should get rid of them.
Property definition rules in an .ini file can now refer to 'rulePrefix' and 'ruleSuffix' variables. 'rulePrefix' is a '.'-terminated string, representing the name the rule was defined with. For example, if the rule was defined for '"foo.bar.*"', then 'rulePrefix' will be '"foo.bar."'. The 'ruleSuffix' will be the portion of the 'propertyName' that follows 'rulePrefix'. So, if looking up property '"foo.bar.baz"', then the '"foo.bar.*"' rule will execute with a 'ruleSuffix' of '"baz"'. This should make it easier to work with hierarchical property namespaces.
Brought CHANGES.txt up-to-date.
Forgot to check this in with the PEAK_CONFIG change.
Added preliminary DM implementations for "Bulletins" app, and 'adduser' and 'showusers' commands. Also, changed 'storage.EntityDM' to supply a default implementation of the '_defaultState()' method.
Added Python/Zope 'datetime' package.
'peak.web' is born; just interface sketches and a draft of 'BaseInteraction' for now. CGI support has been moved from 'peak.running.zpublish' into 'peak.running.commands' (for "raw" CGI/FastCGI) and 'peak.web' (for the PEAK high-level publishing framework). You can use 'peak CGI someName' to adapt 'someName' to a 'running.IRerunnableCGI' and run it as a CGI/FastCGI. This will form the basis for creating the web version of an app later; you'll do something like:: class MyAppAsCGI(web.CGIPublisher): app = binding.New(MyAppClass) And then use 'peak CGI import:somepkg.MyAppAsCGI' to run it. Or, if your app wants to exec a config file, you might define your CGIPublisher subclass as an adapter from MyAppClass to IRerunnableCGI, rather than invoking it directly.
Added attribute name -> permission mappings for both declaration and checking. Added complex scenario-driven tests based on a data-driven permissions model.
Doc fixes: name -> attrName.
There is now an interface for "Active Descriptors": 'binding.IActiveDescriptor'. 'peak.binding' now uses this interface to identify active descriptors, so you can now create your own. (Previously, 'peak.binding' used 'isinstance()' to detect active descriptors.)
The naming system base classes no longer use 'attrs' as an input parameter or return value. If you've subclassed anything from 'peak.naming.contexts', note that your '_get()' methods should now just return the lookup value, rather than a 'state,attrs' tuple. For most naming contexts, this just means you should change 'return foo, None' statements to just 'return foo'.
'peak.naming' no longer automatically converts all addresses to the addressed objects. You must specifically request the interface you want by adapting the retrieved object to that interface. This can be done by supplying an 'adaptTo=ISomething' keyword argument to the attribute binding definition or your 'lookupComponent()' call. The naming system no longer has 'objectFactories' and 'stateFactories'; these have been replaced with adaptation. Writable naming contexts must have a 'serializationProtocol' attribute specifying what interface an object should be adapted to before attempting to store it in that context. The naming system no longer processes the 'creationName' keyword argument; this is now considered the sole responsibility of 'peak.binding'. The 'IComponent.lookupComponent()' method still accepts the keyword argument, and attribute bindings still handle the creation name transparently. It is just not available via naming system APIs, and naming contexts no longer have to deal with it. Also, removed 'naming.ParsedURL'; it was deprecated as of 0.5 alpha 2. (Note: 'smtp:' URLs are currently broken, in that we don't have an interface to adapt them to for retrieval, and I didn't want to create an SMTP naming context, since what we want to do with SMTP is still up in the air.)
All 'peak.binding' APIs now only accept positional parameters for items unique to that API. Items common to multiple APIs (such as 'offerAs', 'doc', 'attrName', etc.) should now be supplied as keyword arguments. Bindings also now automatically "suggest" the containing object as a parent component for the contained object, whenever a value is assigned to them or computed. If a non-None 'adaptTo' is set on the binding, the value assigned or computed will be adapted to the specified protocol before the parent component is suggested. 'binding.New()' no longer relies on the 'IComponentFactory' interface, but instead uses the new adapt/suggest mechanisms. Previously, parent components were only "suggested" when a binding was set via component constructor keyword arguments. Now, this is done at any time bindings are set, but *not* for non-binding keyword arguments. In other words, ordinary attributes of a component do not receive "suggested parent" notices, even when set via constructor keyword arguments. If you want an attribute to do this, you must define the attribute with the binding API; e.g. via 'requireBinding()' or 'binding.Constant()'.
The 'provides' keyword argument to various 'peak.binding' APIs has been renamed to 'offerAs', and it must be a sequence of configuration keys. (Previously, it accepted either a single key or a tuple of keys.) The signature of 'binding.Constant()' was changed as well; the first positional argument is now the constant value, and 'offerAs' is now a keyword argument. (Previously, 'provides' was the first positional argument of 'binding.Constant()'.) The 'registerProvider()' method of 'config.IConfigurable()' also now accepts only a single configuration key, as does 'EigenRegistry.register()'.
Fix HTML formatting of CHANGES file
Misc. doc cleanups/enhancements. Added info on 'invoke' command.
Finished URLChecker and FileCleaner demo daemons; updated CHANGES and TODO.
Fill in some items I missed documenting while I was focused on PyProtocols.
Misc. edits preparing for 0.5a2
Added a ZConfig schema for 'running.commands.EventDriven' applications, a ZConfig component definition for adaptive tasks, and a running shortcut called 'EventDriven'. It should now be possible to do this:: #!/usr/bin/env peak EventDriven at the top of a ZConfig file formatted according to the new schema, and have it run. Unfortunately, so far the only type of task that can be included is 'running.daemons.AdaptiveTask', which doesn't actually *do* anything. So, right now doing this is equivalent to creating an over- engineered 'sleep' command. ;) Also, fixed a problem in ZConfig 'schema.dtd'; I used 'PCDATA' where I should've used 'CDATA', and I fixed various problems with the 'fromZConfig()' component constructor. It's kind of annoying that ZConfig defaults unspecified items to 'None', even if you said they weren't required and had no default. :( I'll see if I can do something about this later; for now I just delete 'None' values from the data.
Added ZConfig URL support. ZConfig schemas and files can be loaded from any PEAK-supported stream URL, including 'pkgfile:'. Interfile references aren't tested yet, nor are there any unit tests. Those will be added once we have some meaningful schemas and configurations to test with. There is a 'zconfig.schema' URL scheme that loads a command interpreter, and a 'peak ZConfig' option as well. See 'CHANGES.txt' for details on the new features. Also, fixed up some issues with the 'fromZConfig()' component constructor. All we need now are some useful base schemas for daemons, and the last piece for 0.5a2 (besides PyProtocols) will be in place.
Standardized file-based URL syntaxes (e.g logfiles and lockfiles) to follow RFC 1738/2396, and Python 'urllib'. This shouldn't affect much besides the canonical forms of the URLs. Added 'pkgfile:some.pkg/filepath' URL syntax for ease of referring to files near modules. (A convenience intended mainly for referencing ZConfig schemas.)
Added the UML 1.4 metamodel, and thus the ability to load UML 1.4 models encoded in XMI 1.1. Added support in the mof2py code generator for "unprefixing" enumerated values, so that UML and other metamodels' enumerations work correctly when loading from XMI. Fixed source distributions missing essential setup files. Rescheduled UML 1.5 and CWM support to version 0.6. Hardly any tools use UML 1.5 yet, and we can't do anything useful with CWM until we have XMI writing, and some type of UI for editing models.
Finished switchover to using protocols.advise() API to declare interfaces.
Began the move of 'peak.interface' to a separate 'protocols' package for ease of distribution independently of PEAK. Also, removed caching of success/failed adapter lookups, because there was no way for them to be cleared when declarations were made for base classes of a class whose lookup was cached. (To do caching, I'll have to add a separate cache.) In the next pass, I'll add the new declaration API that Ty and I designed, and then change PEAK to use it, factoring out the interim API, and changing the few remaining introspections in PEAK to work via adapation. Then, it's off to documentation, unit tests, and packaging for the 'protocols' package.
Made interfaces thread-safe for registration. Added more interfaces to explain the interface of the interface package. :) Refined adapter comparison algorithm to better understand the "distance" between protocols. Removed classic-class adapter, since protocols now do reasonable caching for classic MRO's and subtypes.
And so we bid a fond farewell to introspection as well. 'isImplementedBy' is now a thing of the past. Refactored anything that used it, to now use adapt(), which has now opened up a lot of extension possibilities in places that were previously not extensible without modifying PEAK core code. See below. Also, the interface module has been refactored to support 'classProvides()' in a clean and kludge-free fashion, along with support for faster adaptation of old and new-style classes (by caching lookups, and by safely adding '__conform__' methods to classic classes), and the ability for classes to manage their own "implements" information. The core interface code is now quite elegant in the way it uses its own adaptation system as the basis for implementing adaptation. :) 'binding.Acquire()' now accepts a 'default' value argument, and 'binding.New()' no longer accepts the 'bindToOwner' flag. There is a new 'binding.IComponentKey' interface that is used to implement 'IComponent.lookupComponent()'. Now you can implement this interface, or create an adapter for it, in order to make an object usable as an argument to 'binding.lookupComponent()' - and therefore usable as a key for 'binding.bindTo()' or 'binding.bindToSequence()'. Not that it's necessarily very useful to do so; you're probably better off simply creating a naming scheme. But it might be useful for lookups done in the context of classes, since naming schemes aren't usable there. (It was actually added in order to factor out all the type testing that 'lookupComponent' used to do, so it doesn't matter if it's useful for much else.) PEAK has been refactored to avoid the use of 'isImplementedBy()' and similar introspection, in favor of 'adapt()'. As a result, some 'peak.naming' interfaces have changed. This should not affect you if you are only subclassing PEAK-provided naming components and not implementing these interfaces "from scratch". However, the various 'isAddress', 'isAddressClass', 'isResolver', and 'isName' APIs have also been removed, as they were based on 'isImplementedBy()'. The ability to use 'isImplementedBy()' with interfaces declared by PEAK is REMOVED. You can still use 'isImplementedBy()' with Zope interfaces, of course, but we recommend you switch to 'adapt()', which will work with both PEAK and Zope interfaces.
Added transitive adaptation: declaring an adapter "AB" from A to B, and "BC" from B to C, automatically implies adaptation from A to C via BC(AB()). Used it to simplify the mechanism for adapting an IExecutable to an ICmdLineAppFactory. Refactored some of the interface package's initial kludges to cleaner mechanisms based on adaptation. Learned some interesting things along the way... Classic classes don't have __mro__, which made adapt() break on them. The technique I was using in the hopes of suppressing unwanted TypeErrors suppressed wanted ones, and meanwhile there weren't any unwanted ones in PEAK. Finally, Python 2.2 doesn't support 'super()' access to properties, and metamethods are properties, so you have to use my new 'supermeta' to work around this when you need to call a super() metamethod. This is supposed to be fixed in Python 2.3, but not backported 2.2 because Guido considers it a "feature". Ah well.
Farewell, 'zope.interface'. You served us well.
__implements__ is dead, long live implements()! We are also no longer using 'zope.interface', but instead using a complete, interoperable replacement for it. Also, tweaked a few things so that using pydoc or 'help()' on PEAK component classes and interfaces now works halfway decently, as opposed to producing tracebacks (or dumping core!). 'zope.interface' will soon be removed from the PEAK distribution altogether. See CHANGES.txt for details of why this replacement was created.
DEPRECATED use of '__implements__' and '__class_implements__' to declare support for interfaces. Use 'implements()', 'classProvides()', 'directlyProvides()', 'moduleProvides()', etc. to do this now; they are now available automatically from 'peak.api'. Please note that alpha 2 will *not* support the use of __implements__ attributes at all! Start using the APIs for this *now*, even if you're using alpha 1 (which at least supports the 'implements()' and 'classProvides()' functions).
'EigenRegistry' and 'PropertyMap' no longer attempt to figure out whether implied (i.e. inherited) interfaces are more or less general with respect to a previous registration. This was behavior that emulated Zope adapter registries, but what we really wanted was more akin to a Zope "type" registry. The only parts of the test suite that used the old behavior were the tests specifically written to ensure that behavior! Also, changed the implementation of '__class_provides__' so that the registry becomes immutable as soon as it is computed by the class.
Fixed 'naming.lookup()' and related APIs not setting the parent component of created objects without an explicitly supplied 'creationParent' keyword argument. This used to "sort of work" when we had implicit configuration parents, but was broken when we went "all explicit" for 0.5 alpha 1. Also, fixed SPI-level calls that didn't go through "paramegeddon": 'getObjectInstance()', 'getStateToBind()', and 'getURLContext()' weren't following the "parent/context goes first" signature convention.
'binding.bindTo()' now accepts a 'default=' argument, whose value will be used in case of a 'NameNotFound' error.
Removed regular expression support from URL.Base; it was only there for ease of migration while I was switching all of PEAK's URL classes over to the new parsing framework. Since use of regular expressions for URL syntax is now deprecated (so that URLs can be formattable as well as parseable), there's no reason to keep this in URL.Base. Added the ability for other name types (composite and compound) to be used as structural feature types (e.g. for URL fields), and for compound name types to generate a corresponding composite name type. Changed LDAP urls to use this ability, which means the LDAP 'basedn' field is now always a composite name.
Misc. doc edits
Refactoring to support "canonical formatting" of URLs. This required creating a sizeable parsing/formatting framework. :( On the brigher side, the framework is highly powerful and expressive. Potentially it could be pulled out as a 'peak.model' parsing framework, to be reused for other parse/format applications on model elements that have a single canonical string syntax. It would probably need to be reviewed for Unicode compatibility, however. Anyway, now printing a parsed URL object should give you back a canonical form of that URL; equivalent URLs (apart from case-sensitivity issues) should produce identical canonical forms. Passing keyword arguments to a URL constructor should also allow you to selectively override the URL body content, making it easy to produce new versions of a URL with an altered field.
Repoint 'ParsedURL' -> 'URL.Base'; this will let existing 'ParsedURL' subclasses continue to work for a while, until 'ParsedURL' is removed in alpha 3.
Began work on replacing 'naming.ParsedURL' with a structure type using 'peak.model'. See 'CHANGES.txt' for a summary of how your ParsedURL subclasses must be changed. There is a further refactoring coming, however, to support simpler parsing mechanisms for complex URL syntaxes, and to support URLs generating a "canonical form" body part. This will be important for robust comparison of URLs, path manipulation, etc.
Added 'binding.whenAssembled(...)' as syntax sugar for 'binding.Once(...,activateUponAssembly=True)'.
Implemented log system refactoring; also added tests for misc. URL schemes. See CHANGES.txt and my mailing list post for details.
Finally got rid of 'x.__class__.foo(x,...)' hacks! Now, if a metaclass needs to have a method that one of its instances might also have as an instance method, you can wrap it with 'binding.metamethod(foo)'. This is nice and clean because it doesn't force every caller of the 'foo' method to try and guess whether it's working with a class or an instance. Even nicer, this solution requires no special work by the person writing these methods, unless the method is going into a metaclass, and even then they need only wrap it with 'metamethod'. Last, but not least, this cleans up some of our __class__ usage so that we'll be able to work correctly with 'zope.security'. As far as I know, the 'x.__class__.foo(x,..)' trick wouldn't have worked consistently when 'x' was a proxied object, whereas a normal call to 'foo' would properly pass through the proxy barrier as long as the caller had permission to access 'foo'. (Note: at the moment 'foo' translates to the 'getParentComponent', '_getConfigData', 'getComponentName', and 'notifyUponAssembly' methods.)
Updated change log.
Made 'NOT_GIVEN' and 'NOT_FOUND' recognizable by humans (they 'repr' and 'str' to their names) and by Python (they can be pickled, and when restored they come back as the same object).
Fixed a formatting error for the online API reference (now up-to-date at http://www.telecommunity.com/PEAK/doc/). Of course, it's only as complete as the docstrings to date. :(
Changing docs from TransWarp->PEAK, referenced new site at http://www.telecommunity.com/PEAK/, prepping docs for 0.5a1 release.
Added 'TWX' package for extensions; added 'TWX.Diagrams.GraphViz' diagramming utility module. Very hacky and first-draft, with no unit tests, but I've manually verified most of the functionality so far.
Added support for pickling instances of nested classes; this required changing all uses of '__name__' which needed an unqualified class name. Notably, one should use 'feature.attrName' instead of 'feature.__name__' in verb definitions.
SEF.DynamicBinding is now SEF.AutoCreated, and all AutoCreatable classes like SEF.App and SEF.Service must now have an '__init__' method that accepts their SEF parent component. This lets such objects have access to the SEF hierarchy during initialization. (Note that this means any '__init__' methods of such classes must be revised to take this into consideration. See TW.Database.DataModel.Database for an example of such a revision.) Also, I dropped the unused SEF.StaticBinding class.
'setupModule()' and 'adviseModule()' will now issue warnings for most questionable code structures and variable redefinitions that might not work the way you'd expect or intend under module inheritance.
Added tests and documentation for 'adviseModule()' API
Added a 'test' command to 'setup.py' that installs and then tests all of TransWarp. (It saves me time running the unit tests while I'm writing new code.)
Added warnings for detectable module-level modifications of mutables in modules which are used for inheritances or advice. Added an API function, 'configure(object, attr1=val, attr2=val,...)' to safely set attributes of mutables that might have been defined in a derived module. Also, misc. updates to TODO.
Removed 'Meta.ClassInit' and '__class_init__' support. Use metaclass '__init__' methods instead; see 'TW.Database.DataModel.RecordTypeMC' for one example of the conversion.
Improved key integrity checks in DataModel: Record objects now disallow modification of key fields unless the old value is None, and cache collisions between records with supposedly unique keys will result in an AssertionError. Also, made the requirement of an LDAPConnection object more visible in Database.LDAPModel, and made misc. CHANGES/TODO updates.
Added 'SET' method (ala WarpCORE's set_X procedures) to TW.Utils.MiniTable.
Added more docs to TW.Utils.Code, and removed 'iterFromEnd()' method from code objects. Added experimental 'nextSplit' index to codeIndex objects that does top-level block analysis to allow splitting a code object into smaller routines.
Fixed the "reference to rebound class within another class" problem with module inheritance, as reported by (who else?) Ulrich Eck. :)
New-style features have landed! Lots o'docs and examples. CHANGES and TODO have been updated accordingly. Enjoy.
Fixed misc. bugs in DataModel, LDAPModel, Connections, and TW.Caching found by Ulrich Eck. Thanks Ulrich! Also, added a fix to ensure that non-existent records are invalidated by RecordType.getItem().
* Added basic Specialist implementation to 'TW.SEF.Basic', and reverted naming from 'TypeService' and 'ITypeService' to 'Specialist' and 'ISpecialist'. Updated 'TW.SEF.Interfaces' to reflect "self"-less convention for documenting methods. * Dropped obsolete 'TW.Database.Records' module.
Many changes in preparation for 0.2 final, including: * Added 'SEF.bindToParent()' and 'SEF.bindToNames()' specifiers to allow more flexible component parameter bindings. * Fixed the base class "rebind by name" bugs in module inheritance, and updated the documentation to more clearly reflect what it is that metaclass generation and module inheritance does and does not do. Added test cases to prevent regression of the rebind-by-name problem. * The 'setup.py' script features a new command, 'happy', which can be used to generate the API reference docs, and this command runs as part of the 'sdist' command to build source distributions. * The API reference docs in the source distribution has been moved from the 'doc' directory to 'docs/html/reference'. * Added 'CHANGES.txt' file.
cvs-admin@eby-sarna.com Powered by ViewCVS 1.0-dev |
ViewCVS and CVS Help |