Package: nti.externalization
nti.externalizationA flexible, schema-driven system for converting Python objects to and
from external formats such as JSON and YAML. This works well in a
zope.component environment such as Pyramid.Documentation is hosted athttps://ntiexternalization.readthedocs.io/Changes2.3.0 (2021-08-02)Add a new base class,StandardInternalObjectExternalizer. SeePR 120andissue 117.RenameIExternalMappingDecoratortoIExternalStandardDictionaryDecoratorto emphasize that it is
only used if you (directly or through a super class) callto_standard_external_dictionary. A compatibility alias remains.
SeePR 120andissue 118.Docs-deprecated aliases innti.externalization.interfacesnow also
emit deprecation warnings at runtime.Other documentation improvements. Sphinx can now run all the
doctests (on Python 3); many doctests are still run an Python 2.2.2.0 (2021-04-14)Add support for Python 3.9.Depend on BTrees 4.8 and above. This simplifies externalization
checks. Seeissue 111.2.1.0 (2020-08-03)Add support for “externalization policies.” These are instances ofExternalizationPolicythat can be used to tweak certain
low-level details of externalization without replacing
externalization objects wholesale. They are intended to have a very
low performance impact.The only supported detail that can be changed right now is whether
the standard created and last modified fields are externalized as
Unix timestamps (the default) or as ISO 8601 strings.Seehttps://github.com/NextThought/nti.externalization/issues/1092.0.0 (2020-07-02)ChangeILocatedExternalMapping: Previously it extended the
legacyzope.interface.common.mapping.IFullMapping. Now it
extends the modernzope.interface.common.collections.IMapping.
Note that this does not require mutability unlike the older
interface. (TheLocatedExternalDictclass provided by this
package is fully mutable and implementsIMutableMapping. It also
continues to implementIFullMapping, but use of that interface
is discouraged.)ChangeILocatedExternalSequence: Previously it extended the
legacyzope.interface.common.sequence.ISequence. Now it extends
the modernzope.interface.common.collections.ISequence.
Note that this does not require mutability unlike the older
interface. (TheLocatedExternalListclass provided by this
package is fully mutable and implementsIMutableSequence.)Fix the interface resolution order forLocatedExternalList.
Previously, with zope.interface 5, it began implementing bothIMutableSequence(the new interface fromzope.interface.common.collections) as well as the older
interfaceISequence(fromzope.interface.common.sequence);
the two have inconsistent resolution orders. Now, it only implementsIMutableSequenceand a subset of the legacy interfaces that do
not conflict. Seeissue 105.1.1.3 (2020-06-25)Correctly fireIObjectWillUpdateFromExternalEventevents before
updating an object.1.1.2 (2020-04-07)Adapt to a change in zope.container 4.4.0 that exposed unsafe
assumptions thatprovidedBy(obj)would return the exact same
object with the exact same state on a subsequent call. This was
always a bug in the case of concurrency (e.g., if a different thread
calleddirectlyProvideson the same object, or adjusted the__bases__of some interface in the IRO); the zope.container
changes made it possible without concurrency. Seehttps://github.com/zopefoundation/zope.container/issues/38andhttps://github.com/NextThought/nti.externalization/issues/104.1.1.1 (2020-03-27)Fix a faulty assertion error. Seeissue 102.1.1.0 (2020-03-27)Make instances offractions.Fractionexternalize as a string
such as"1/3". When received by a schema field that can parse
this format, such aszope.schema.Rational(or higher on the
numeric tower), this means fractions can be round-tripped.Support externalizingdecimal.Decimalobjects in the YAML
representation.1.0.0 (2020-03-19)Add compatibility with, and require, zope.interface 5.0.Document which tagged values are inherited and which are not.Stop inheriting_ext_is_marker_interface.1.0.0a14 (2019-11-13)Build with Cython 0.29.14 using ‘3str’ as the language level.Add support for Python 3.8.Update PyYAML to 5.1 and change the default output style slightly.Fix tests with Persistent 4.4.3 and above.Support zope.interface 4.7, which lets tagged values on interfaces
be inherited, when using<registerAutoPackageIO>on a module
that had multiple objects implementing a derived interface. Seeissue 97.1.0.0a13 (2018-09-20)SupportIFromBytesfields introduced by zope.schema 4.8.0. Seeissue 92.Makevalidate_field_value(and by extensionInterfaceObjectIO.update_from_external_object) callfromObjectdefined by any fields for non-byte and non-text data.
Previously, only if the field raised aWrongContainedTypeErrorwouldfromObjectbe called.1.0.0a12 (2018-09-11)Add support for zope.schema 4.7.0 and nti.schema 1.5.0. Drop support
for older versions, which includes dropping support fordm.zope.schema.Objectfields.1.0.0a11 (2018-08-29)The@WithReprdecorator takes into account the updated default
repr of Persistent objects with persistent 4.4 and doesn’t hide it.Subclasses ofExternalizableInstanceDictthat have non-str
(unicode on Python 2, bytes on Python 3) keys in their__dict__do not throwTypeErrorwhen externalizing. Instead, the non-str
values are converted to strs (using ASCII encoding) and the_p_changedattribute, if any, is set.1.0.0a10 (2018-08-21)Theregistryargument to most functions is deprecated and
ignored. Instead of making calls toregistry.queryAdapter, we
now invoke the interface directly. For example,IInternalObjectExternalizer(containedObject). This lets
individual objects have a say if they already provide the interface
without going through the legacy code paths (it also calls__conform__on the object if needed).1.0.0a9 (2018-08-20)Allow subclasses ofInterfaceObjectIOto have non-frozenset
values for_ext_primitive_out_ivars_. This issues a warning and
in the future will be a TypeError.1.0.0a8 (2018-08-16)Better support for internalizing anonymous value objects discovered
in aDictvalue. Now, they won’t raise aComponentLookupErrorwhenrequire_updateris True, and they
will be given aMimeTypebased on the schema (if they don’t have one).1.0.0a7 (2018-07-31)Avoid aTypeErrorfromvalidate_named_field_valuewhen
external objects have unicode keys.LocatedExternalDictobjects accept more constructor arguments
and allow arbitrary attributes.1.0.0a6 (2018-07-31)InterfaceObjectIOonly returns an anonymous factory forIDictfields when it wants objects for the value.StandardExternalFieldsandStandardInternalFieldsare
deprecated aliases innti.externalization.externalization.update_from_external_objectproperly handles the case whereINamedExternalizedObjectFactoryFinderandIInternalObjectUpdaterare registered with different levels of
specificity, and the finder also implementsIInternalObjectUpdater. Before, the finder would, perhaps
incorrectly, be used as the updater.1.0.0a5 (2018-07-30)Objects inheriting fromInterfaceObjectIOand registered with
the component registry (in ZCML) forIInternalObjectIOcan still
be found and used asINamedExternalizedObjectFactoryFinder, an
interface implemented byInterfaceObjectIOthroughIInternalObjectIOFinder. A warning will be issued to update the
registration (which generally means removing theprovidesline
in ZCML).ExternalizableInstanceDictno longer inherits fromAbstractDynamicIO, it just implements the same interface (with
the exception of many of the_extmethods). This class is deprecated.Formally document thenotify_modifiedmember ofnti.externalization.internalization.notifyModifiedis a
deprecated alias.1.0.0a4 (2018-07-30)MakeInterfaceObjectIO._ext_selfreadable from Python, even
though that is not documented (and may change again in the future).
Document the intended API,_ext_replacement(). Seeissue 73.MakeAbstractDynamicObjectIO._ext_getattrhandle a default
value, and add_ext_replacement_getattrfor when it will only
be called once. Seeissue 73.1.0.0a3 (2018-07-28)The@NoPickledecorator also works withPersistentsubclasses (and may or may not work with multiple-inheritance
subclasses ofPersistent, depending on the MRO,
but that’s always been the case for regular objects). APersistentsubclass being decorated with@NoPickledoesn’t
make much sense, so aRuntimeWarningis issued. A warning is
also issued if the class directly implements one of the pickle
protocol methods.Updating objects that usecreateFieldPropertiesor otherwise
haveFieldPropertyobjects in their type is at least 10% faster
thanks to avoiding double-validation due to a small monkey-patch onFieldProperty. Seeissue 67.Proxies around objects that implementtoExternalObjectare
allowed again; the proxied object’stoExternalObjectwill be called.The signature forupdateFromExternalObject()has been tightened.
It should be(self, external_object, context, **kwargs), where**kwargsis optional, as is context.**kwargscurrently
contains nothing useful. Uses ofdataserver=Nonein the
signature will generate a warning. This may be tightened further in
the future. Seeissue 30.__ext_ignore_updateFromExternalObject__is officially
deprecated and generates a warning.update_from_external_objectcaches certain information about the
types of the updater objects, making it 8-25% faster.update_from_external_objectmutates sequences contained in a
dict in-place instead of overwriting with a new list.update_from_external_objectmutates sequences at the top level
instead of returning a new list.Add support for finding factories for incoming data which do not
specify a MIME type or class field based on the key they are
assigned to. This aids in consuming data produced by foreign systems
or usingDictschema fields that require modelled
values. Seeissue 51andPR 68.Schemas that useInterfaceObjectIO(including through the ZCML
directiveregisterAutoPackageIO) can useDictfields more
easily on internalization (externalization has always worked): They
automatically internalize their values by treating theDictas
anonymous external data.Strings can automatically be adapted intoITimeDeltaobjects.1.0.0a2 (2018-07-05)The low levels of externalization no longer catch and hide
POSKeyError. This indicates a problem with the database. Seehttps://github.com/NextThought/nti.externalization/issues/60Remove support forobject_hookinupdate_from_external_object. Seehttps://github.com/NextThought/nti.externalization/issues/29.A number of deprecated aliases for moved functions have been
removed.On CPython, some of the modules are compiled as extension modules
using Cython for a 10-30% increase in speed. Set thePURE_PYTHONenvironment variable to disable this at runtime.The unused, undocumented methodstripSyntheticKeysFromExternalDictionarywas removed from
instances ofExternalizableDictionaryMixin. Use the import instead.Unused keyword arguments forto_standard_external_dictionaryandto_minimal_standard_external_dictionarynow produce a warning.
In the future, extra keyword arguments will be an error.notifyModifiedno longer accepts theeventFactoryargument.Thenotify_modifiedalias fornotifyModifiedhas been removed.Decorating external mappings and external objects handleddecorate_callbackdifferently. This argument is only used whendecorateis false. This argument is also confusing and should be
considered deprecated.choose_fieldno longer has the undocumented conversion behaviour for the
CREATOR external field name.1.0.0a1 (2017-09-29)First PyPI release.Add support for Python 3.Drop support for externalizing to plists. Seehttps://github.com/NextThought/nti.externalization/issues/21Reach 100% test coverage and ensure we remain there through CI.Introducenti.externalization.extension_pointsto hold hook
functions. Move the Pyramid integration there (and deprecate that).
Also move the NTIID support there (but the old name works too).
Seehttps://github.com/NextThought/nti.externalization/issues/27Deprecatenti.externalization.internalization.register_legacy_search_module.
Seehttps://github.com/NextThought/nti.externalization/issues/35Stopext:registerAutoPackageIOfrom registering the legacy
class-name based factories by default. If you need class-name based
factories, there are two options. The first is to explicitly
registerIClassObjectFactoryobjects in ZCML (we could add a
scanning directive to make that more convenient for large numbers of
classes), and the second is to setregister_legacy_search_moduleto a true value in the ZCML directive forext:registerAutoPackageIO. Note that we expect the behaviour of
this attribute to change in the near future.
Seehttps://github.com/NextThought/nti.externalization/issues/33Makeext:registerAutoPackageIOperform legacy class
registrations when the configuration context executes, not when the
directive runs. This means that conflicts in legacy class names will be
detected at configuration time. It also means that legacy class names can
be registered locally withz3c.baseregistry(previously they
were always registered in the global site manager).
Seehttps://github.com/NextThought/nti.externalization/issues/28Drop dependency onzope.preferenceandzope.annotation. They
were not used by this package, although ourconfigure.zcmldid
include them. If you usezope.preferenceorzope.annotation,
please include them in your own ZCML file.Drop hard dependency on Acquisition. It is still used if available
and is used in test mode.Add public implementations ofIMimeObjectFactoryandIClassObjectFactoryinnti.externalization.factory.Drop dependency onnti.zodband itsPersistentPropertyHolder. The datastructures innti.externalization.persistenceno longer extend that class; if
you have further subclasses that addnti.zodb.peristentproperty.PropertyHoldingPersistentproperties,
you’ll need to be sure to mixin this class now.
Seehttps://github.com/NextThought/nti.externalization/issues/43Add the<ext:classObjectFactory>directive for registeringClassbased factories. (Note: MIME factories are preferred.)Callers ofto_standard_external_dictionary(which includes
AutoPackageScopedInterfaceIO) will now automatically get aMimeTypevalue if one can be found. Previously only callers ofto_minimal_standard_external_dictionarywould.