=========================== at convenience directives =========================== fieldevents provides a couple of directives for handling non-invasive setup of fieldevent behavior. wicked:decorate-at-field -- Monecorates fieldevent wicked:atschema-fields-implement at field decorator directive ============================ Nothing too fancy here, we just want to monkey patch our render and store methods inplace of a field's:: >>> from cStringIO import StringIO >>> out = StringIO() >>> class DummyATField(object): ... def get(self, instance, **kw): ... value = self.value ... return value ... def set(self, instance, value, **kw): ... self.value = value so we'll register a storage subscriber so we can log the value when it's stored >>> @adapter(DummyATField, wicked.fieldevent.IFieldStorageEvent) ... @implementer(IFieldValueSetter) ... def log_store(field, event): ... print >> out, "%s" %(event.value) >>> provideSubscriptionAdapter(log_store) decorate_at_field does the work here: it can be run to register with a context or just immediately do registrations(zcml=False). It will add our class to the classes to be cleaned up later:: >>> decorate_at_field(fieldclass=DummyATField, zcml=False) >>> from meta import _fieldclass_monkies >>> DummyATField in _fieldclass_monkies True It also swaps the existing get and set methods for 'render' and 'store':: >>> DummyATField.__original_get >>> DummyATField.__original_set >>> DummyATField.get >>> DummyATField.set Now when we instantiate a field instance, calling get and set should do exactly as before, since the old getter and setter have been registered as part of adapters:: >>> instance = object() >>> field = DummyATField() >>> field.set(instance, 'HOWDY', foo='bar') >>> print out.getvalue() HOWDY... >>> print field.get(instance, foo='bar') HOWDY atschema-fields-implement directive =================================== We'll create some mock objects to simulate a schema in module space. >>> class IMarker(Interface): ... """a marker interface""" >>> atschema = dict(text=DummyATField(), ... description=DummyATField(), ... other=DummyATField()) "schemafields_provide" will apply (via alsoProvides) the interface to all the fields specified by in the said schema. Field names must be correct, or errors will raise. Here we mark "text" and "other":: >>> from wicked.fieldevent import meta >>> meta.schemafields_provide(IMarker, atschema, ['text', 'other']) >>> IMarker.providedBy(atschema['text']) True >>> IMarker.providedBy(atschema['other']) True but descriptions is not marked:: >>> IMarker.providedBy(atschema['description']) False if run with the cleanUp flag, "schemafields_provide" will remove the interfaces rather than apply them. The cleanup function "cleanup_schemafields_provide" utilizes this and the global var "_schemafields_marked" to cleanup the fields:: see the currently marked fields:: >>> meta._schemafields_marked [(, {...}, ['text', 'other'])] running it again should not add more fields to clean up:: >>> meta.schemafields_provide(IMarker, atschema, ['text', 'other']) >>> meta._schemafields_marked [(, {...}, ['text', 'other'])] >>> len(meta._schemafields_marked) 1 do cleanup:: >>> cleanup_schemafields_provide() >>> meta._schemafields_marked [] check to make sure fields are clean:: >>> IMarker.providedBy(atschema['text']) False >>> IMarker.providedBy(atschema['other']) False >>> IMarker.providedBy(atschema['description']) False finally, "schemafields_implement" provides the zope.configuration compatible wrapper. The only other wrinkle is that the implemented interface is provided(if zcml=True) :: >>> class AT(object): ... schema = atschema >>> meta.schemafields_implement(_context=None, atclass=AT(), implements=IMarker, fields=['text', 'other'], zcml=False) the interfaces are now set as before:: >>> IMarker.providedBy(atschema['text']) True >>> IMarker.providedBy(atschema['other']) True >>> IMarker.providedBy(atschema['description']) False The clean call by the test does the unregistering for this...