#!/usr/bin/env python3 # Copyright 2014 Brett Slatkin, Pearson Education Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Preamble to mimick book environment import logging from pprint import pprint from sys import stdout as STDOUT # Example 1 import json class Serializable(object): def __init__(self, *args): self.args = args def serialize(self): return json.dumps({'args': self.args}) # Example 2 class Point2D(Serializable): def __init__(self, x, y): super().__init__(x, y) self.x = x self.y = y def __repr__(self): return 'Point2D(%d, %d)' % (self.x, self.y) point = Point2D(5, 3) print('Object: ', point) print('Serialized:', point.serialize()) # Example 3 class Deserializable(Serializable): @classmethod def deserialize(cls, json_data): params = json.loads(json_data) return cls(*params['args']) # Example 4 class BetterPoint2D(Deserializable): def __init__(self, x, y): super().__init__(x, y) self.x = x self.y = y def __repr__(self): return 'BetterPoint2D(%d, %d)' % (self.x, self.y) point = BetterPoint2D(5, 3) print('Before: ', point) data = point.serialize() print('Serialized:', data) after = BetterPoint2D.deserialize(data) print('After: ', after) # Example 5 class BetterSerializable(object): def __init__(self, *args): self.args = args def serialize(self): return json.dumps({ 'class': self.__class__.__name__, 'args': self.args, }) def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, ', '.join(str(x) for x in self.args)) # Example 6 registry = {} def register_class(target_class): registry[target_class.__name__] = target_class def deserialize(data): params = json.loads(data) name = params['class'] target_class = registry[name] return target_class(*params['args']) # Example 7 class EvenBetterPoint2D(BetterSerializable): def __init__(self, x, y): super().__init__(x, y) self.x = x self.y = y register_class(EvenBetterPoint2D) # Example 8 point = EvenBetterPoint2D(5, 3) print('Before: ', point) data = point.serialize() print('Serialized:', data) after = deserialize(data) print('After: ', after) # Example 9 class Point3D(BetterSerializable): def __init__(self, x, y, z): super().__init__(x, y, z) self.x = x self.y = y self.z = z # Forgot to call register_class! Whoops! # Example 10 try: point = Point3D(5, 9, -4) data = point.serialize() deserialize(data) except: logging.exception('Expected') else: assert False # Example 11 class Meta(type): def __new__(meta, name, bases, class_dict): cls = type.__new__(meta, name, bases, class_dict) register_class(cls) return cls class RegisteredSerializable(BetterSerializable, metaclass=Meta): pass # Example 12 class Vector3D(RegisteredSerializable): def __init__(self, x, y, z): super().__init__(x, y, z) self.x, self.y, self.z = x, y, z v3 = Vector3D(10, -7, 3) print('Before: ', v3) data = v3.serialize() print('Serialized:', data) print('After: ', deserialize(data))