Datastructures

Datastructures to help externalization.

class ExternalizableDictionaryMixin[source]

Bases: object

Implements a toExternalDictionary method as a base for subclasses.

_ext_replacement()[source]

Return the object that we are externalizing.

This class returns self, but subclasses will typically override this.

toExternalDictionary(mergeFrom=None, *unused_args, **kwargs)[source]

Produce the standard external dictionary for this object.

Uses _ext_replacement.

class StandardInternalObjectExternalizer(context)[source]

Bases: nti.externalization.datastructures.ExternalizableDictionaryMixin

An adapter that can be used to implement IInternalObjectExternalizer.

The result of externalizing is the standard external dictionary for this adapter’s context argument.

This can be registered as-is, or subclassed to add additional items in the external dictionary. In that case, always begin by calling this implemention first and updating the result.

New in version 2.3.0.

The constructor sets __external_can_create__ to False (because creating from just an externalizer makes no sense) and __external_class_name__ to None (if you override this value, it will replace the Class value in the returned dictionary; it must be a native str).

_ext_replacement()[source]

Returns this adapter’s context argument.

class AbstractDynamicObjectIO[source]

Bases: nti.externalization.datastructures.ExternalizableDictionaryMixin

Base class for objects that externalize based on dynamic information.

Abstractions are in place to allow subclasses to map external and internal names independently (this type never uses getattr/setattr/hasattr, except for some standard fields).

See InterfaceObjectIO for a complete implementation.

_ext_accept_external_id(ext_self, parsed)[source]

If the object we’re updating does not have an id set, but there is an ID in the external object, should we be able to use it?

Returns:boolean
_ext_accept_update_key(k, ext_self, ext_keys)[source]

Returns whether or not this key should be accepted for setting on the object, or silently ignored.

Parameters:ext_keys – As an optimization, the value of _ext_all_possible_keys() is passed. Keys are only accepted if they are in this list.
_ext_all_possible_keys()[source]

This method must return a frozenset of native strings.

_ext_getattr(object, name[, default]) → value[source]

Return the attribute of the ext_self object with the internal name name. If the attribute does not exist, should raise (typically AttributeError), unless default is given, in which case it returns that.

Changed in version 1.0a4: Add the default argument.

_ext_keys()[source]

Return only the names of attributes that should be externalized. These values will be used as keys in the external dictionary.

See _ext_all_possible_keys(). This implementation then filters out private attributes (those beginning with an underscore), and those listed in _excluded_in_ivars_.

This method must return a set of native strings.

_ext_primitive_keys()[source]

Return a container of string keys whose values are known to be primitive. This is an optimization for writing.

This method must return a frozenset.

_ext_replacement()[source]

Return the object that we are externalizing.

This class returns self, but subclasses will typically override this.

_ext_replacement_getattr(name, default=<default value>)[source]

Like _ext_getattr, but automatically fills in _ext_replacement for the ext_self argument.

New in version 1.0a4.

find_factory_for_named_value(key, value)[source]

Uses find_factory_for to locate a factory.

This does not take into account the current object (context) or the key. It only handles finding factories based on the class or MIME type found within value.

toExternalDictionary(mergeFrom=None, *unused_args, **kwargs)[source]

Produce the standard external dictionary for this object.

Uses _ext_replacement.

class ExternalizableInstanceDict[source]

Bases: object

Externalizes to a dictionary containing the members of __dict__ that do not start with an underscore.

Meant to be used as a super class; also can be used as an external object superclass.

Consider carefully before using this class. Generally, an interface and InterfaceObjectIO are better.

Changed in version 1.0a5: No longer extends AbstractDynamicObjectIO, just delegates to it. Most of the _ext_` prefixed methods can no longer be overridden.

_ext_replacement()[source]

See ExternalizableDictionaryMixin._ext_replacement.

toExternalDictionary(mergeFrom=None, *unused_args, **kwargs)[source]

See ExternalizableDictionaryMixin.toExternalDictionary

toExternalObject(mergeFrom=None, *args, **kwargs)[source]

See toExternalObject. Calls toExternalDictionary.

updateFromExternalObject(parsed, *unused_args, **unused_kwargs)[source]

See updateFromExternalObject

class InterfaceObjectIO(context, iface_upper_bound=None, validate_after_update=True)[source]

Bases: nti.externalization.datastructures.AbstractDynamicObjectIO

Externalizes the context to a dictionary based on getting the attributes of an object defined by an interface. If any attribute has a true value for the tagged value _ext_excluded_out, it will not be considered for reading or writing.

This is an implementation of IInternalObjectIOFinder, meaning it can both internalize (update existing objects) and externalize (producing dictionaries), and that it gets to choose the factories used for sub-objects when internalizing.

This class is meant to be used as an adapter, so it accepts the object to externalize in the constructor, as well as the interface to use to guide the process. The object is externalized using the most-derived version of the interface given to the constructor that it implements.

If the interface (or an ancestor) has a tagged value __external_class_name__, it can either be the value to use for the Class key, or a callable __external_class_name__(interface, object ) -> name.

(TODO: In the future extend this to multiple, non-overlapping interfaces, and better interface detection (see ModuleScopedInterfaceObjectIO for a limited version of this.)

This class overrides _ext_replacement to return the context.

Parameters:
  • iface_upper_bound – The upper bound on the schema to use to externalize ext_self; we will use the most derived sub-interface of this interface that the object implements. Subclasses can either override this constructor to pass this parameter (while taking one argument themselves, to be usable as an adapter), or they can define the class attribute _ext_iface_upper_bound
  • validate_after_update (bool) – If True (the default) then the entire schema will be validated after an object has been updated with update_from_external_object(), not just the keys that were assigned.
_ext_accept_external_id(ext_self, parsed)[source]

If the interface we’re working from has a tagged value of __external_accept_id__ on the id field, then this will return that value; otherwise, returns false.

_ext_all_possible_keys()[source]

This method must return a frozenset of native strings.

_ext_getattr(object, name[, default]) → value[source]

Return the attribute of the ext_self object with the internal name name. If the attribute does not exist, should raise (typically AttributeError), unless default is given, in which case it returns that.

Changed in version 1.0a4: Add the default argument.

_ext_replacement()[source]

Return the object that we are externalizing.

This class returns self, but subclasses will typically override this.

find_factory_for_named_value(key, value)[source]

If AbstractDynamicObjectIO.find_factory_for_named_value cannot find a factory based on examining value, then we use the context objects’s schema to find a factory.

If the schema contains an attribute named key, it will be queried for the tagged value __external_factory__. If present, this tagged value should be the name of a factory object implementing IAnonymousObjectFactory registered in registry (typically registered in the global site).

The ZCML directive IAnonymousObjectFactoryDirective sets up both the registration and the tagged value.

This is useful for internalizing data from external sources that does not provide a class or MIME field within the data.

The most obvious limitation of this is that if the value is part of a sequence, it must be a homogeneous sequence. The factory is called with no arguments, so the only way to deal with heterogeneous sequences is to subclass this object and override this method to examine the value itself.

A second limitation is that the external data key must match the internal schema field name. Again, the only way to remove this limitation is to subclass this object.

If no registered factory is found, and the schema field is a zope.schema.Dict with a value type of zope.schema.Object, then we return a factory which will update the object in place.

Changed in version 1.0a6: Only return an anonymous factory for IDict fields when it wants objects for the value.

schema

The schema we will use to guide the process

class ModuleScopedInterfaceObjectIO(context, iface_upper_bound=None, validate_after_update=True)[source]

Bases: nti.externalization.datastructures.InterfaceObjectIO

Only considers the interfaces provided within a given module (usually declared as a class attribute) when searching for the schema to use to externalize an object; the most derived version of interfaces within that module will be used. Subclasses must declare the class attribute _ext_search_module to be a module (something with the __name__) attribute to locate interfaces in.

Suitable for use when all the externalizable fields of interest are declared by an interface within a module, and an object does not implement two unrelated interfaces from the same module.

Note

If the object does implement unrelated interfaces, but one (set) of them is a marker interface (featuring no schema fields or attributes), then it can be tagged with _ext_is_marker_interface and it will be excluded when determining the most derived interfaces. This can correct some cases that would otherwise raise a TypeError. This tag is not inherited.

Parameters:
  • iface_upper_bound – The upper bound on the schema to use to externalize ext_self; we will use the most derived sub-interface of this interface that the object implements. Subclasses can either override this constructor to pass this parameter (while taking one argument themselves, to be usable as an adapter), or they can define the class attribute _ext_iface_upper_bound
  • validate_after_update (bool) – If True (the default) then the entire schema will be validated after an object has been updated with update_from_external_object(), not just the keys that were assigned.