Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace use of sweet_pickle in naming, and delete sweet_pickle subpackage #199

Merged
merged 18 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ that is commonly needed by many applications
listener of selected items in an application.
- **apptools.scripting**: A framework for automatic recording of Python
scripts.
- **apptools.sweet_pickle**: Handles class-level versioning, to support
loading of saved data that exist over several generations of internal class
structures.
- **apptools.undo**: Supports undoing and scripting application commands.

Prerequisites
Expand Down
14 changes: 4 additions & 10 deletions apptools/naming/object_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@
import logging
from traceback import print_exc
from os.path import splitext

# import cPickle
# import pickle
import pickle

# Enthought library imports.
import apptools.sweet_pickle as sweet_pickle
from apptools.persistence.versioned_unpickler import VersionedUnpickler
from traits.api import HasTraits, Str


Expand Down Expand Up @@ -57,9 +55,7 @@ def load(self, path):
f = open(path, "rb")
try:
try:
obj = sweet_pickle.load(f)
# obj = cPickle.load(f)
# obj = pickle.load(f)
obj = VersionedUnpickler(f).load()
except Exception as ex:
print_exc()
logger.exception(
Expand Down Expand Up @@ -89,9 +85,7 @@ def save(self, path, obj):
# Pickle the object.
f = open(actual_path, "wb")
try:
sweet_pickle.dump(obj, f, 1)
# cPickle.dump(obj, f, 1)
# pickle.dump(obj, f, 1)
pickle.dump(obj, f, 1)
kitchoi marked this conversation as resolved.
Show resolved Hide resolved
except Exception as ex:
logger.exception(
"Failed to pickle into file: %s, %s, object:%s"
Expand Down
52 changes: 52 additions & 0 deletions apptools/naming/tests/test_object_serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
import os
import shutil
import tempfile
import unittest

from traits.api import cached_property, HasTraits, Property, Str, Event

from apptools.naming.api import ObjectSerializer


class FooWithTraits(HasTraits):
"""Dummy HasTraits class for testing ObjectSerizalizer."""

full_name = Str()

last_name = Property(depends_on="full_name")

event = Event()

@cached_property
def _get_last_name(self):
return self.full_name.split(" ")[-1]

class TestObjectSerializer(unittest.TestCase):

def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, self.tmpdir)
self.tmp_file = os.path.join(self.tmpdir, "tmp.pickle")

def test_save_load_roundtrip(self):
# Test HasTraits objects can be serialized and deserialized as expected
obj = FooWithTraits(full_name="John Doe")

serializer = ObjectSerializer()
serializer.save(self.tmp_file, obj)

self.assertTrue(serializer.can_load(self.tmp_file))
deserialized = serializer.load(self.tmp_file)

self.assertIsInstance(deserialized, FooWithTraits)
self.assertEqual(deserialized.full_name, "John Doe")
self.assertEqual(deserialized.last_name, "Doe")
79 changes: 79 additions & 0 deletions apptools/persistence/tests/test_class_mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -----------------------------------------------------------------------------
#
# Copyright (c) 2006 by Enthought, Inc.
# All rights reserved.
#
# Author: Dave Peterson <dpeterson@enthought.com>
#
# -----------------------------------------------------------------------------

""" Tests the class mapping functionality of the enthought.pickle
framework.
"""

# Standard library imports.
import io
import pickle
import unittest

# Enthought library imports
from apptools.persistence.versioned_unpickler import VersionedUnpickler
from apptools.persistence.updater import Updater


##############################################################################
# Classes to use within the tests
##############################################################################


class Foo:
pass


class Bar:
pass


class Baz:
pass


##############################################################################
# class 'ClassMappingTestCase'
##############################################################################


class ClassMappingTestCase(unittest.TestCase):
"""Tests the class mapping functionality of the apptools.sweet_pickle
framework.
"""

##########################################################################
# 'TestCase' interface
##########################################################################

### public interface #####################################################

def test_unpickled_class_mapping(self):

class TestUpdater(Updater):
def __init__(self):
self.refactorings = {
(Foo.__module__, Foo.__name__): (Bar.__module__, Bar.__name__),
(Bar.__module__, Bar.__name__): (Baz.__module__, Baz.__name__),
}
self.setstates = {}

# Validate that unpickling the first class gives us an instance of
# the second class.
start = Foo()
test_file = io.BytesIO(pickle.dumps(start, 2))
end = VersionedUnpickler(test_file, updater=TestUpdater()).load()
self.assertIsInstance(end, Bar)

# Validate that unpickling the second class gives us an instance of
# the third class.
start = Bar()
test_file = io.BytesIO(pickle.dumps(start, 2))
end = VersionedUnpickler(test_file, updater=TestUpdater()).load()
self.assertIsInstance(end, Baz)
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@
# Prabhu Ramachandran <prabhu@aero.iitb.ac.in>
# -----------------------------------------------------------------------------

# Test cases.
from __future__ import print_function
""" This was previously a test for the now deleted apptools.sweet_pickle
sub package. It is included here to showcase how apptools.persistance can be
used to replace sweet_pickle functionality.
"""

import io
import random
import re
import pickle
import unittest

import apptools.sweet_pickle as sweet_pickle
from apptools.persistence.versioned_unpickler import VersionedUnpickler

########################################


# Usecase1: generic case
class A(object):
def __init__(self, b=None):
Expand Down Expand Up @@ -66,8 +71,6 @@ def __initialize__(self):

class GenericTestCase(unittest.TestCase):
def test_generic(self):
print("\nRunning generic test...")

a = A()
b = B()
a.x = random.randint(1, 100)
Expand All @@ -79,24 +82,19 @@ def test_generic(self):
s = pickle.dumps(a)
new_a = pickle.loads(s)
try:
print("\ta.x: %s" % new_a.x)
print("\ta.b_ref.y: %s" % new_a.b_ref.y)
except Exception as msg:
print("\t%s" % "Expected Error".center(75, "*"))
print("\t%s" % msg)
print("\t%s" % ("*" * 75))
new_a.x
new_a.b_ref.y
except Exception:
pass
aaronayres35 marked this conversation as resolved.
Show resolved Hide resolved

# This will work!
s = pickle.dumps(a)
new_a = sweet_pickle.loads(s)
new_a = VersionedUnpickler(io.BytesIO(s)).load()
assert new_a.x == new_a.b_ref.y == value

print("Generic test succesfull.\n\n")


########################################
# Usecase2: Toy Application
import re


class StringFinder(object):
Expand Down Expand Up @@ -154,14 +152,11 @@ def __init__(self):
self.finder = StringFinder(self.reader, "e")

def get(self):
print("\t%s" % self.finder.data)
print("\t%s" % self.reader.data)
pass
aaronayres35 marked this conversation as resolved.
Show resolved Hide resolved


class ToyAppTestCase(unittest.TestCase):
def test_toy_app(self):
print("\nRunning toy app test...")

a = Application()
a.finder.find()
a.get()
Expand All @@ -170,19 +165,9 @@ def test_toy_app(self):
# Won't work.
try:
b.get()
except Exception as msg:
print("\t%s" % "Expected Error".center(75, "*"))
print("\t%s" % msg)
print("\t%s" % ("*" * 75))
except Exception:
pass
aaronayres35 marked this conversation as resolved.
Show resolved Hide resolved

# Works fine.
c = sweet_pickle.loads(s)
c = VersionedUnpickler(io.BytesIO(s)).load()
c.get()

print("Toy app test succesfull.\n\n")


if __name__ == "__main__":
test_generic()
test_toy_app()
print("ALL TESTS SUCCESFULL\n")
3 changes: 2 additions & 1 deletion apptools/persistence/versioned_unpickler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Standard library imports
from pickle import BUILD, Unpickler, UnpicklingError
from pickle import _Unpickler as Unpickler
kitchoi marked this conversation as resolved.
Show resolved Hide resolved
from pickle import UnpicklingError, BUILD
import logging
from types import GeneratorType

Expand Down
8 changes: 0 additions & 8 deletions apptools/sweet_pickle/README.txt

This file was deleted.

1 change: 0 additions & 1 deletion apptools/sweet_pickle/tests/__init__.py

This file was deleted.

Loading