Skip to content

Commit

Permalink
Write factories doc.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Jul 25, 2018
1 parent 58e670f commit 97a7be0
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 3 deletions.
7 changes: 7 additions & 0 deletions docs/externalization.rst
Expand Up @@ -129,3 +129,10 @@ from the object schema), and it is always before
this, but it's best to stick to ``IExternalObjectDecorator``.

.. _subscription adapters: http://muthukadan.net/docs/zca.html#subscription-adapter

Dublin Core Metadata
--------------------

Decorators for :mod:`zope.dublincore` metadata are installed for all
objects by default. See :mod:`nti.externalization.dublincore` for more
information.
51 changes: 51 additions & 0 deletions docs/internalization.rst
Expand Up @@ -2,7 +2,58 @@
Internalization
=================

We can create or update an existing object using external data with
the functions :func:`~nti.externalization.new_from_external_object` or
:func:`~nti.externalization.update_from_external_object`, respectively.

In a web framework like Pyramid where an application object is located
by route matching or `traversal`_, ``update_from_external_object``
makes the most sense.

.. _traversal: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/traversal.html

.. _factories:

Factories
=========

While updating objects, internalization will, by default, create a new
instance for every mapping that contains a ``MimeType`` or ``Class``
key using `Zope Component factories`_. Factories are named utilities,
that implement ``IFactory`` (essentially, a callable of no arguments)
This package uses extensions of that interface, namely
`~nti.externalization.interfaces.IMimeObjectFactory`,
`~nti.externalization.interfaces.IClassObjectFactory` and
`~nti.externalization.interfaces.IAnonymousObjectFactory` (whose
default implementations are found in
:mod:`nti.externalization.factory`).

The factory matching ``MimeType`` is preferred, but we can fall back
to one matching ``Class`` if needed.

Factories are usually registered automatically by
`ext:registerAutoPackageIO
<nti.externalization.zcml.IAutoPackageExternalizationDirective>` at the
same time it creates the ``InterfaceObjectIO`` adapters.

You can manually register factories from particular modules using
`ext:registerMimeFactories
<nti.externalization.zcml.IRegisterInternalizationMimeFactoriesDirective>`.

Lets look at the factories registered for our address:

>>> from zope import component
>>> from nti.externalization.interfaces import IMimeObjectFactory
>>> import nti.externalization.tests.benchmarks
>>> _ = xmlconfig.file('configure.zcml', nti.externalization.tests.benchmarks)
>>> factory = component.getUtility(IMimeObjectFactory, 'application/vnd.nextthought.benchmarks.address')
>>> factory
<MimeObjectFactory for <class 'nti.externalization.tests.benchmarks.objects.Address'>>
>>> factory()
<nti.externalization.tests.benchmarks.objects.Address ...>

.. _Zope Component factories: http://muthukadan.net/docs/zca.html#factory

Mime Types are found in the class attribute ``mimeType``;
``ext:registerAutoPackageIO`` will add computed ``mimeType`` values to
factory objects if needed.
3 changes: 2 additions & 1 deletion src/nti/externalization/externalization/dictionary.py
Expand Up @@ -95,7 +95,8 @@ def to_standard_external_dictionary(
* The `.StandardExternalFields.LAST_MODIFIED`.
* The `.StandardExternalFields.CREATED_TIME`.
* The `.StandardExternalFields.CONTAINER_ID`.
* The `.StandardExternalFields.CLASS` and `.StandardExternalFields.MIMETYPE`.
* The `.StandardExternalFields.CLASS` and `.StandardExternalFields.MIMETYPE`
(from the ``mimeType`` attribute of the object).
If the object has any
:class:`~nti.externalization.interfaces.IExternalMappingDecorator`
Expand Down
6 changes: 4 additions & 2 deletions src/nti/externalization/internalization/updater.py
Expand Up @@ -185,6 +185,8 @@ def update_from_external_object(containedObject, externalObject,
notify=True,
pre_hook=None):
"""
update_from_external_object(containedObject, externalObject, context=None, require_updater=False, notify=True)
Central method for updating objects from external values.
:param containedObject: The object to update.
Expand All @@ -195,9 +197,9 @@ def update_from_external_object(containedObject, externalObject,
:param require_updater: If True (not the default) an exception
will be raised if no implementation of
:class:`~nti.externalization.interfaces.IInternalObjectUpdater`
can be found for the `containedObject.`
can be found for the *containedObject.*
:keyword bool notify: If ``True`` (the default), then if the updater
for the `containedObject` either has no preference (returns
for the *containedObject* either has no preference (returns
None) or indicates that the object has changed, then an
:class:`~nti.externalization.interfaces.IObjectModifiedFromExternalEvent`
will be fired. This may be a recursive process so a top-level
Expand Down
2 changes: 2 additions & 0 deletions src/nti/externalization/representation.py
Expand Up @@ -38,6 +38,8 @@
def to_external_representation(obj, ext_format=EXT_REPR_JSON,
name=_NotGiven, registry=component):
"""
to_external_representation(obj, ext_format='json', name=NotGiven) -> str
Transforms (and returns) the *obj* into its external (string)
representation.
Expand Down
1 change: 1 addition & 0 deletions src/nti/externalization/tests/test_docs.py
Expand Up @@ -41,6 +41,7 @@ def test_suite():
files_to_test = (
'basics.rst',
'externalization.rst',
'internalization.rst',
)
paths = [os.path.join(docs, f) for f in files_to_test]
kwargs = {'tearDown': lambda _: cleanup.cleanUp}
Expand Down

0 comments on commit 97a7be0

Please sign in to comment.