You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by fo...@apache.org on 2018/11/07 15:10:07 UTC
[avro] branch master updated: AVRO-2234 Use MappingProxyType,
not ImmutableDict (#337)
This is an automated email from the ASF dual-hosted git repository.
fokko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/master by this push:
new 9e60e59 AVRO-2234 Use MappingProxyType, not ImmutableDict (#337)
9e60e59 is described below
commit 9e60e59c53e006629a341822a39a22fa35f8270c
Author: Michael A. Smith <mi...@smith-li.com>
AuthorDate: Wed Nov 7 10:10:01 2018 -0500
AVRO-2234 Use MappingProxyType, not ImmutableDict (#337)
Per the Rejection Notice of PEP-416, use MappingProxyType instead of
creating our own implementation of ImmutableDict.
---
lang/py3/avro/protocol.py | 14 ++++-------
lang/py3/avro/schema.py | 59 ++++++++++-------------------------------------
2 files changed, 17 insertions(+), 56 deletions(-)
diff --git a/lang/py3/avro/protocol.py b/lang/py3/avro/protocol.py
index 629d2fd..2568fb4 100644
--- a/lang/py3/avro/protocol.py
+++ b/lang/py3/avro/protocol.py
@@ -21,6 +21,7 @@
Protocol implementation.
"""
+from types import MappingProxyType
import hashlib
import json
@@ -28,8 +29,6 @@ import logging
from avro import schema
-ImmutableDict = schema.ImmutableDict
-
# ------------------------------------------------------------------------------
# Constants
@@ -146,8 +145,7 @@ class Protocol(object):
self._types = tuple(types)
# Map: type full name -> type schema
- self._type_map = (
- ImmutableDict((type.fullname, type) for type in self._types))
+ self._type_map = MappingProxyType({type.fullname: type for type in self._types})
# This assertion cannot fail unless we don't track named schemas properly:
assert (len(self._types) == len(self._type_map)), (
'Type list %r does not match type map: %r'
@@ -158,8 +156,7 @@ class Protocol(object):
# Map: message name -> Message
# Note that message names are simple names unique within the protocol.
- self._message_map = ImmutableDict(
- items=((message.name, message) for message in self._messages))
+ self._message_map = MappingProxyType({message.name: message for message in self._messages})
if len(self._messages) != len(self._message_map):
raise ProtocolParseException(
'Invalid protocol %s with duplicate message name: %r'
@@ -227,7 +224,7 @@ class Protocol(object):
return to_dump
def __str__(self):
- return json.dumps(self.to_json())
+ return json.dumps(self.to_json(), cls=schema.MappingProxyEncoder)
def __eq__(self, that):
to_cmp = json.loads(str(self))
@@ -319,7 +316,7 @@ class Message(object):
return self._props
def __str__(self):
- return json.dumps(self.to_json())
+ return json.dumps(self.to_json(), cls=schema.MappingProxyEncoder)
def to_json(self, names=None):
if names is None:
@@ -399,4 +396,3 @@ def Parse(json_string):
% (json_string, exn))
return ProtocolFromJSONData(json_data)
-
diff --git a/lang/py3/avro/schema.py b/lang/py3/avro/schema.py
index 7ed3b54..0ebd41f 100644
--- a/lang/py3/avro/schema.py
+++ b/lang/py3/avro/schema.py
@@ -38,6 +38,7 @@ A schema may be one of:
- Null.
"""
+from types import MappingProxyType
import abc
import collections
@@ -45,7 +46,7 @@ import json
import logging
import re
-logger = logging.getLogger(__name__)
+logger = logging.getLogger(__name__)
# ------------------------------------------------------------------------------
# Constants
@@ -149,49 +150,13 @@ class SchemaParseException(AvroException):
"""Error while parsing a JSON schema descriptor."""
pass
-
# ------------------------------------------------------------------------------
-
-
-class ImmutableDict(dict):
- """Dictionary guaranteed immutable.
-
- All mutations raise an exception.
- Behaves exactly as a dict otherwise.
- """
-
- def __init__(self, items=None, **kwargs):
- if items is not None:
- super(ImmutableDict, self).__init__(items)
- assert (len(kwargs) == 0)
- else:
- super(ImmutableDict, self).__init__(**kwargs)
-
- def __setitem__(self, key, value):
- raise Exception(
- 'Attempting to map key %r to value %r in ImmutableDict %r'
- % (key, value, self))
-
- def __delitem__(self, key):
- raise Exception(
- 'Attempting to remove mapping for key %r in ImmutableDict %r'
- % (key, self))
-
- def clear(self):
- raise Exception('Attempting to clear ImmutableDict %r' % self)
-
- def update(self, items=None, **kwargs):
- raise Exception(
- 'Attempting to update ImmutableDict %r with items=%r, kwargs=%r'
- % (self, args, kwargs))
-
- def pop(self, key, default=None):
- raise Exception(
- 'Attempting to pop key %r from ImmutableDict %r' % (key, self))
-
- def popitem(self):
- raise Exception('Attempting to pop item from ImmutableDict %r' % self)
-
+# Utilities
+class MappingProxyEncoder(json.JSONEncoder):
+ def default(self, obj):
+ if isinstance(obj, MappingProxyType):
+ return obj.copy()
+ return json.JSONEncoder.default(self, obj)
# ------------------------------------------------------------------------------
@@ -255,7 +220,7 @@ class Schema(object, metaclass=abc.ABCMeta):
Returns:
A read-only dictionary of properties associated to this schema.
"""
- return ImmutableDict(self._props)
+ return MappingProxyType(self._props)
@property
def other_props(self):
@@ -264,7 +229,7 @@ class Schema(object, metaclass=abc.ABCMeta):
def __str__(self):
"""Returns: the JSON representation of this schema."""
- return json.dumps(self.to_json())
+ return json.dumps(self.to_json(), cls=MappingProxyEncoder)
@abc.abstractmethod
def to_json(self, names):
@@ -620,7 +585,7 @@ class Field(object):
return FilterKeysOut(items=self._props, keys=FIELD_RESERVED_PROPS)
def __str__(self):
- return json.dumps(self.to_json())
+ return json.dumps(self.to_json(), cls=MappingProxyEncoder)
def to_json(self, names=None):
if names is None:
@@ -1003,7 +968,7 @@ class RecordSchema(NamedSchema):
raise SchemaParseException(
'Duplicate field name %r in list %r.' % (field.name, field_desc_list))
field_map[field.name] = field
- return ImmutableDict(field_map)
+ return MappingProxyType(field_map)
def __init__(
self,