Skip to content

Commit

Permalink
Drop support for plist. Fixes #21
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Sep 20, 2017
1 parent d0e632a commit 7889551
Show file tree
Hide file tree
Showing 8 changed files with 18 additions and 72 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@

- First PyPI release.
- Add support for Python 3.
- Drop support for externalizing to plists.
- Drop support for externalizing to plists. See
https://github.com/NextThought/nti.externalization/issues/21
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@
'https://docs.python.org/': None,
#'https://ntiwref.readthedocs.io/en/latest': None,
'https://persistent.readthedocs.io/en/latest': None,
'https://zopecomponent.readthedocs.io/en/latest': None,
'https://zodb.readthedocs.io/en/latest': None,
}

extlinks = {
Expand Down
1 change: 0 additions & 1 deletion src/nti/externalization/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@

<utility factory=".representation.JsonRepresenter" />
<utility factory=".representation.YamlRepresenter" />
<utility factory=".representation.PlistRepresenter" />

<!-- Offer to adapt strings to dates -->
<!-- TODO: This is a bit ad-hoc. Surely there's a more formal set
Expand Down
13 changes: 4 additions & 9 deletions src/nti/externalization/externalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,7 @@ def _to_external_object_state(obj, state, top_level=False, decorate=True,
result.append(ext_obj)
result = state.registry.getAdapter(result,
ILocatedExternalSequence)
# PList doesn't support None values, JSON does. The closest
# coersion I can think of is False.
elif obj is None:
if state.coerceNone:
result = False
else:
elif obj is not None:
# Otherwise, we probably won't be able to JSON-ify it.
# TODO: Should this live here, or at a higher level where the ultimate
# external target/use-case is known?
Expand Down Expand Up @@ -307,7 +302,6 @@ def _to_external_object_state(obj, state, top_level=False, decorate=True,


def toExternalObject(obj,
coerceNone=False,
name=_NotGiven,
registry=component,
catch_components=(),
Expand Down Expand Up @@ -677,8 +671,9 @@ def _clean(m):
"nti.externalization.persistence",
"NoPickle")

EXT_FORMAT_JSON = 'json' #: Constant requesting JSON format data
EXT_FORMAT_PLIST = 'plist' #: Constant requesting PList (XML) format data
#: Constant requesting JSON format data
EXT_FORMAT_JSON = 'json'


zope.deferredimport.deprecatedFrom(
"Import from .representation",
Expand Down
3 changes: 0 additions & 3 deletions src/nti/externalization/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,6 @@ class IExternalObjectIO(IExternalObjectRepresenter,
#: Constant requesting JSON format data
EXT_REPR_JSON = u'json'

#: Constant requesting PList (XML) format data
EXT_REPR_PLIST = u'plist'

#: Constant requesting YAML format data
EXT_REPR_YAML = u'yaml'

Expand Down
3 changes: 1 addition & 2 deletions src/nti/externalization/internalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,7 @@ def update_from_external_object(containedObject, externalObject,
``v`` is the newly-updated value, and ``x`` is the external object used to update ``v``.
:param callable pre_hook: If given, called with the before update_from_external_object is
called for every nested object. Signature ``f(k,x)`` where ``k`` is either the key name,
or None in the case of a sequence and ``x`` is the external object
or None in the case of a sequence and ``x`` is the external object
:return: `containedObject` after updates from `externalObject`
"""

Expand Down
53 changes: 6 additions & 47 deletions src/nti/externalization/representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@
"""
External representation support.
.. $Id$
"""

from __future__ import print_function, absolute_import, division
__docformat__ = "restructuredtext en"

import collections
import plistlib

import six
from six import iteritems

from zope import component
from zope import interface
Expand All @@ -22,7 +16,6 @@

from nti.externalization.interfaces import EXT_REPR_JSON
from nti.externalization.interfaces import EXT_REPR_YAML
from nti.externalization.interfaces import EXT_REPR_PLIST

from nti.externalization.interfaces import IExternalObjectIO
from nti.externalization.interfaces import IExternalObjectRepresenter
Expand All @@ -36,9 +29,11 @@
def to_external_representation(obj, ext_format=EXT_REPR_JSON,
name=_NotGiven, registry=component):
"""
Transforms (and returns) the `obj` into its external (string) representation.
Transforms (and returns) the `obj` into its external (string)
representation.
:param ext_format: One of :const:`EXT_FORMAT_JSON` or :const:`EXT_FORMAT_PLIST`.
:param ext_format: One of :const:`nti.externalization.interfaces.EXT_REPR_JSON` or
:const:`nti.externalization.interfaces.EXT_REPR_YAML`.
"""
# It would seem nice to be able to do this in one step during
# the externalization process itself, but we would wind up traversing
Expand All @@ -57,39 +52,6 @@ def to_json_representation(obj):
return to_external_representation(obj, EXT_REPR_JSON)


# Plist



# The API changed in Python 3.4
_plist_dump = getattr(plistlib, 'dump', None) or plistlib.writePlist
_plist_dumps = getattr(plistlib, 'dumps', None) or plistlib.writePlistToString


@interface.named(EXT_REPR_PLIST)
@interface.implementer(IExternalObjectRepresenter)
class PlistRepresenter(object):

def stripNoneFromExternal(self, obj):
"""
Given an already externalized object, strips ``None`` values.
"""
if isinstance(obj, (list, tuple)):
obj = [self.stripNoneFromExternal(x) for x in obj if x is not None]
elif isinstance(obj, collections.Mapping):
obj = {k: self.stripNoneFromExternal(v)
for k, v in iteritems(obj)
if v is not None and k is not None}
return obj

def dump(self, obj, fp=None):
ext = self.stripNoneFromExternal(obj)
if fp is not None:
_plist_dump(ext, fp)
else:
return _plist_dumps(ext)


# JSON


Expand Down Expand Up @@ -143,7 +105,7 @@ def load(self, stream):
# Depending on whether the simplejson C speedups are active, we can still
# get back a non-unicode string if the object was a naked string. (If the python
# version is used, it returns unicode; the C version returns str.)
if isinstance(value, six.binary_type):
if isinstance(value, bytes):
# we know it's simple ascii or it would have produced unicode
value = to_unicode(value)
return value
Expand Down Expand Up @@ -199,10 +161,7 @@ def load(self, stream):
from ZODB.POSException import ConnectionStateError


def make_repr(default=None):
if default is None:
def default(self):
return "%s().__dict__.update( %s )" % (self.__class__.__name__, self.__dict__)
def make_repr(default=lambda self: "%s().__dict__.update( %s )" % (self.__class__.__name__, self.__dict__)):

def __repr__(self):
try:
Expand Down
12 changes: 3 additions & 9 deletions src/nti/externalization/tests/test_externalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

import sys
import json
import plistlib

import unittest

try:
Expand All @@ -43,8 +43,6 @@
from nti.externalization.datastructures import ExternalizableInstanceDict
from nti.externalization.datastructures import ExternalizableDictionaryMixin

from nti.externalization.externalization import EXT_FORMAT_JSON
from nti.externalization.externalization import EXT_FORMAT_PLIST

from nti.externalization.externalization import _manager
from nti.externalization.externalization import _DevmodeNonExternalizableObjectReplacer
Expand All @@ -57,6 +55,7 @@
from nti.externalization.externalization import to_standard_external_dictionary

from nti.externalization.interfaces import EXT_REPR_YAML
from nti.externalization.interfaces import EXT_REPR_JSON
from nti.externalization.interfaces import LocatedExternalList
from nti.externalization.interfaces import LocatedExternalDict

Expand Down Expand Up @@ -136,13 +135,8 @@ def test_hookable(self):
def test_to_external_representation_none_handling(self):
d = {'a': 1, 'None': None}
# JSON keeps None
assert_that(json.loads(to_external_representation(d, EXT_FORMAT_JSON)),
assert_that(json.loads(to_external_representation(d, EXT_REPR_JSON)),
is_(d))
# PList strips it
# The api changed in Python 3.4
read_plist = getattr(plistlib, 'loads', getattr(plistlib, 'readPlistFromString', None))
assert_that(read_plist(to_external_representation(d, EXT_FORMAT_PLIST)),
is_({'a': 1}))

def test_to_external_representation_yaml(self):
l = LocatedExternalList()
Expand Down

0 comments on commit 7889551

Please sign in to comment.