Skip to content

Commit

Permalink
Merge pull request #70 from NextThought/auto-anon-dict-fields
Browse files Browse the repository at this point in the history
InterfaceObjectIO uses its newfound powers to make Dict fields internalize easier
  • Loading branch information
jamadden committed Jul 25, 2018
2 parents 7c0848b + 85103f8 commit 1044271
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 10 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
`PR 68
<https://github.com/NextThought/nti.externalization/pull/68>`_.

- Schemas that use ``InterfaceObjectIO`` (including through the ZCML
directive ``registerAutoPackageIO``) can use ``Dict`` fields more
easily on internalization (externalization has always worked): They
automatically internalize their values by treating the ``Dict`` as
anonymous external data.

1.0.0a2 (2018-07-05)
====================

Expand Down
2 changes: 2 additions & 0 deletions src/nti/externalization/_datastructures.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ cdef make_repr
cdef isSyntheticKey
cdef find_most_derived_interface
cdef NotGiven
cdef IDict_providedBy
cdef _anonymous_dict_factory

cdef class ExternalizableDictionaryMixin(object):
# This is a mixin used with other C base classes (E.g., persistent)
Expand Down
18 changes: 13 additions & 5 deletions src/nti/externalization/datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from zope import interface
from zope import schema
from zope.schema.interfaces import SchemaNotProvided
from zope.schema.interfaces import IDict

from nti.schema.interfaces import find_most_derived_interface

Expand All @@ -39,6 +40,7 @@
from .internalization import validate_named_field_value
from .internalization.factories import find_factory_for
from .representation import make_repr
from .factory import AnonymousObjectFactory

from ._base_interfaces import get_standard_external_fields
from ._base_interfaces import get_standard_internal_fields
Expand All @@ -48,6 +50,7 @@

StandardExternalFields = get_standard_external_fields()
StandardInternalFields = get_standard_internal_fields()
IDict_providedBy = IDict.providedBy

__all__ = [
'ExternalizableDictionaryMixin',
Expand Down Expand Up @@ -330,6 +333,8 @@ def _ext_accept_update_key(self, k, ext_self, ext_keys):

_primitives = six.string_types + (numbers.Number, bool)

_anonymous_dict_factory = AnonymousObjectFactory(lambda x: x)
_anonymous_dict_factory.__external_factory_wants_arg__ = True

class InterfaceObjectIO(AbstractDynamicObjectIO):
"""
Expand Down Expand Up @@ -510,11 +515,14 @@ def find_factory_for_named_value(self, key, value, registry):
# Anything else is a programming error.
if isinstance(factory, str):
factory = registry.getUtility(IAnonymousObjectFactory, factory)
# TODO: If there is no factory found, check to see if the
# schema field is a Dict with a complex value type, and if
# so, automatically update it in place? This currently
# requires the user use a ZCML directive for each such
# dict field.

if factory is None and IDict_providedBy(field) and isinstance(value, dict):
# If is no factory found, check to see if the
# schema field is a Dict with a complex value type, and if
# so, automatically update it in place. The alternative
# requires the user to use a ZCML directive for each such
# dict field.
factory = _anonymous_dict_factory
return factory

def updateFromExternalObject(self, parsed, *unused_args, **unused_kwargs):
Expand Down
5 changes: 0 additions & 5 deletions src/nti/externalization/tests/benchmarks/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,4 @@
modules=".objects"
/>

<ext:anonymousObjectFactoryInPlace
for=".interfaces.IUserContactProfile"
field="addresses"
/>

</configure>

0 comments on commit 1044271

Please sign in to comment.