Added module stub for copy_reg renaming in 3.0.

Renamed copy_reg to copyreg in the standard library, to avoid
spurious warnings and ease later merging to py3k branch. Public
documentation remains intact.
This commit is contained in:
Alexandre Vassalotti 2008-05-11 08:25:28 +00:00
parent f602c71b07
commit 9510e4a9f8
15 changed files with 302 additions and 294 deletions

View File

@ -49,7 +49,7 @@ __getstate__() and __setstate__(). See the documentation for module
""" """
import types import types
from copy_reg import dispatch_table from copyreg import dispatch_table
class Error(Exception): class Error(Exception):
pass pass

View File

@ -1,201 +1,8 @@
"""Helper to provide extensibility for pickle/cPickle. import sys
from warnings import warnpy3k
This is only useful to add pickle support for extension types defined in warnpy3k("the copy_reg module has been renamed "
C, not for instances of user-defined classes. "to 'copyreg' in Python 3.0", stacklevel=2)
"""
from types import ClassType as _ClassType import copyreg
sys.modules[__name__] = copyreg
__all__ = ["pickle", "constructor",
"add_extension", "remove_extension", "clear_extension_cache"]
dispatch_table = {}
def pickle(ob_type, pickle_function, constructor_ob=None):
if type(ob_type) is _ClassType:
raise TypeError("copy_reg is not intended for use with classes")
if not hasattr(pickle_function, '__call__'):
raise TypeError("reduction functions must be callable")
dispatch_table[ob_type] = pickle_function
# The constructor_ob function is a vestige of safe for unpickling.
# There is no reason for the caller to pass it anymore.
if constructor_ob is not None:
constructor(constructor_ob)
def constructor(object):
if not hasattr(object, '__call__'):
raise TypeError("constructors must be callable")
# Example: provide pickling support for complex numbers.
try:
complex
except NameError:
pass
else:
def pickle_complex(c):
return complex, (c.real, c.imag)
pickle(complex, pickle_complex, complex)
# Support for pickling new-style objects
def _reconstructor(cls, base, state):
if base is object:
obj = object.__new__(cls)
else:
obj = base.__new__(cls, state)
if base.__init__ != object.__init__:
base.__init__(obj, state)
return obj
_HEAPTYPE = 1<<9
# Python code for object.__reduce_ex__ for protocols 0 and 1
def _reduce_ex(self, proto):
assert proto < 2
for base in self.__class__.__mro__:
if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
break
else:
base = object # not really reachable
if base is object:
state = None
else:
if base is self.__class__:
raise TypeError, "can't pickle %s objects" % base.__name__
state = base(self)
args = (self.__class__, base, state)
try:
getstate = self.__getstate__
except AttributeError:
if getattr(self, "__slots__", None):
raise TypeError("a class that defines __slots__ without "
"defining __getstate__ cannot be pickled")
try:
dict = self.__dict__
except AttributeError:
dict = None
else:
dict = getstate()
if dict:
return _reconstructor, args, dict
else:
return _reconstructor, args
# Helper for __reduce_ex__ protocol 2
def __newobj__(cls, *args):
return cls.__new__(cls, *args)
def _slotnames(cls):
"""Return a list of slot names for a given class.
This needs to find slots defined by the class and its bases, so we
can't simply return the __slots__ attribute. We must walk down
the Method Resolution Order and concatenate the __slots__ of each
class found there. (This assumes classes don't modify their
__slots__ attribute to misrepresent their slots after the class is
defined.)
"""
# Get the value from a cache in the class if possible
names = cls.__dict__.get("__slotnames__")
if names is not None:
return names
# Not cached -- calculate the value
names = []
if not hasattr(cls, "__slots__"):
# This class has no slots
pass
else:
# Slots found -- gather slot names from all base classes
for c in cls.__mro__:
if "__slots__" in c.__dict__:
slots = c.__dict__['__slots__']
# if class has a single slot, it can be given as a string
if isinstance(slots, basestring):
slots = (slots,)
for name in slots:
# special descriptors
if name in ("__dict__", "__weakref__"):
continue
# mangled names
elif name.startswith('__') and not name.endswith('__'):
names.append('_%s%s' % (c.__name__, name))
else:
names.append(name)
# Cache the outcome in the class if at all possible
try:
cls.__slotnames__ = names
except:
pass # But don't die if we can't
return names
# A registry of extension codes. This is an ad-hoc compression
# mechanism. Whenever a global reference to <module>, <name> is about
# to be pickled, the (<module>, <name>) tuple is looked up here to see
# if it is a registered extension code for it. Extension codes are
# universal, so that the meaning of a pickle does not depend on
# context. (There are also some codes reserved for local use that
# don't have this restriction.) Codes are positive ints; 0 is
# reserved.
_extension_registry = {} # key -> code
_inverted_registry = {} # code -> key
_extension_cache = {} # code -> object
# Don't ever rebind those names: cPickle grabs a reference to them when
# it's initialized, and won't see a rebinding.
def add_extension(module, name, code):
"""Register an extension code."""
code = int(code)
if not 1 <= code <= 0x7fffffff:
raise ValueError, "code out of range"
key = (module, name)
if (_extension_registry.get(key) == code and
_inverted_registry.get(code) == key):
return # Redundant registrations are benign
if key in _extension_registry:
raise ValueError("key %s is already registered with code %s" %
(key, _extension_registry[key]))
if code in _inverted_registry:
raise ValueError("code %s is already in use for key %s" %
(code, _inverted_registry[code]))
_extension_registry[key] = code
_inverted_registry[code] = key
def remove_extension(module, name, code):
"""Unregister an extension code. For testing only."""
key = (module, name)
if (_extension_registry.get(key) != code or
_inverted_registry.get(code) != key):
raise ValueError("key %s is not registered with code %s" %
(key, code))
del _extension_registry[key]
del _inverted_registry[code]
if code in _extension_cache:
del _extension_cache[code]
def clear_extension_cache():
_extension_cache.clear()
# Standard extension code assignments
# Reserved ranges
# First Last Count Purpose
# 1 127 127 Reserved for Python standard library
# 128 191 64 Reserved for Zope
# 192 239 48 Reserved for 3rd parties
# 240 255 16 Reserved for private use (will never be assigned)
# 256 Inf Inf Reserved for future assignment
# Extension codes are assigned by the Python Software Foundation.

201
Lib/copyreg.py Normal file
View File

@ -0,0 +1,201 @@
"""Helper to provide extensibility for pickle/cPickle.
This is only useful to add pickle support for extension types defined in
C, not for instances of user-defined classes.
"""
from types import ClassType as _ClassType
__all__ = ["pickle", "constructor",
"add_extension", "remove_extension", "clear_extension_cache"]
dispatch_table = {}
def pickle(ob_type, pickle_function, constructor_ob=None):
if type(ob_type) is _ClassType:
raise TypeError("copy_reg is not intended for use with classes")
if not hasattr(pickle_function, '__call__'):
raise TypeError("reduction functions must be callable")
dispatch_table[ob_type] = pickle_function
# The constructor_ob function is a vestige of safe for unpickling.
# There is no reason for the caller to pass it anymore.
if constructor_ob is not None:
constructor(constructor_ob)
def constructor(object):
if not hasattr(object, '__call__'):
raise TypeError("constructors must be callable")
# Example: provide pickling support for complex numbers.
try:
complex
except NameError:
pass
else:
def pickle_complex(c):
return complex, (c.real, c.imag)
pickle(complex, pickle_complex, complex)
# Support for pickling new-style objects
def _reconstructor(cls, base, state):
if base is object:
obj = object.__new__(cls)
else:
obj = base.__new__(cls, state)
if base.__init__ != object.__init__:
base.__init__(obj, state)
return obj
_HEAPTYPE = 1<<9
# Python code for object.__reduce_ex__ for protocols 0 and 1
def _reduce_ex(self, proto):
assert proto < 2
for base in self.__class__.__mro__:
if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
break
else:
base = object # not really reachable
if base is object:
state = None
else:
if base is self.__class__:
raise TypeError, "can't pickle %s objects" % base.__name__
state = base(self)
args = (self.__class__, base, state)
try:
getstate = self.__getstate__
except AttributeError:
if getattr(self, "__slots__", None):
raise TypeError("a class that defines __slots__ without "
"defining __getstate__ cannot be pickled")
try:
dict = self.__dict__
except AttributeError:
dict = None
else:
dict = getstate()
if dict:
return _reconstructor, args, dict
else:
return _reconstructor, args
# Helper for __reduce_ex__ protocol 2
def __newobj__(cls, *args):
return cls.__new__(cls, *args)
def _slotnames(cls):
"""Return a list of slot names for a given class.
This needs to find slots defined by the class and its bases, so we
can't simply return the __slots__ attribute. We must walk down
the Method Resolution Order and concatenate the __slots__ of each
class found there. (This assumes classes don't modify their
__slots__ attribute to misrepresent their slots after the class is
defined.)
"""
# Get the value from a cache in the class if possible
names = cls.__dict__.get("__slotnames__")
if names is not None:
return names
# Not cached -- calculate the value
names = []
if not hasattr(cls, "__slots__"):
# This class has no slots
pass
else:
# Slots found -- gather slot names from all base classes
for c in cls.__mro__:
if "__slots__" in c.__dict__:
slots = c.__dict__['__slots__']
# if class has a single slot, it can be given as a string
if isinstance(slots, basestring):
slots = (slots,)
for name in slots:
# special descriptors
if name in ("__dict__", "__weakref__"):
continue
# mangled names
elif name.startswith('__') and not name.endswith('__'):
names.append('_%s%s' % (c.__name__, name))
else:
names.append(name)
# Cache the outcome in the class if at all possible
try:
cls.__slotnames__ = names
except:
pass # But don't die if we can't
return names
# A registry of extension codes. This is an ad-hoc compression
# mechanism. Whenever a global reference to <module>, <name> is about
# to be pickled, the (<module>, <name>) tuple is looked up here to see
# if it is a registered extension code for it. Extension codes are
# universal, so that the meaning of a pickle does not depend on
# context. (There are also some codes reserved for local use that
# don't have this restriction.) Codes are positive ints; 0 is
# reserved.
_extension_registry = {} # key -> code
_inverted_registry = {} # code -> key
_extension_cache = {} # code -> object
# Don't ever rebind those names: cPickle grabs a reference to them when
# it's initialized, and won't see a rebinding.
def add_extension(module, name, code):
"""Register an extension code."""
code = int(code)
if not 1 <= code <= 0x7fffffff:
raise ValueError, "code out of range"
key = (module, name)
if (_extension_registry.get(key) == code and
_inverted_registry.get(code) == key):
return # Redundant registrations are benign
if key in _extension_registry:
raise ValueError("key %s is already registered with code %s" %
(key, _extension_registry[key]))
if code in _inverted_registry:
raise ValueError("code %s is already in use for key %s" %
(code, _inverted_registry[code]))
_extension_registry[key] = code
_inverted_registry[code] = key
def remove_extension(module, name, code):
"""Unregister an extension code. For testing only."""
key = (module, name)
if (_extension_registry.get(key) != code or
_inverted_registry.get(code) != key):
raise ValueError("key %s is not registered with code %s" %
(key, code))
del _extension_registry[key]
del _inverted_registry[code]
if code in _extension_cache:
del _extension_cache[code]
def clear_extension_cache():
_extension_cache.clear()
# Standard extension code assignments
# Reserved ranges
# First Last Count Purpose
# 1 127 127 Reserved for Python standard library
# 128 191 64 Reserved for Zope
# 192 239 48 Reserved for 3rd parties
# 240 255 16 Reserved for private use (will never be assigned)
# 256 Inf Inf Reserved for future assignment
# Extension codes are assigned by the Python Software Foundation.

View File

@ -37,7 +37,7 @@ import cPickle as pickle
import threading import threading
import Queue import Queue
import traceback import traceback
import copy_reg import copyreg
import types import types
import marshal import marshal
@ -60,8 +60,8 @@ def pickle_code(co):
# assert isinstance(fn, type.FunctionType) # assert isinstance(fn, type.FunctionType)
# return repr(fn) # return repr(fn)
copy_reg.pickle(types.CodeType, pickle_code, unpickle_code) copyreg.pickle(types.CodeType, pickle_code, unpickle_code)
# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function) # copyreg.pickle(types.FunctionType, pickle_function, unpickle_function)
BUFSIZE = 8*1024 BUFSIZE = 8*1024
LOCALHOST = '127.0.0.1' LOCALHOST = '127.0.0.1'

View File

@ -729,7 +729,7 @@ if _exists("fork"):
return p.stdin, p.stdout return p.stdin, p.stdout
__all__.append("popen4") __all__.append("popen4")
import copy_reg as _copy_reg import copyreg as _copy_reg
def _make_stat_result(tup, dict): def _make_stat_result(tup, dict):
return stat_result(tup, dict) return stat_result(tup, dict)

View File

@ -27,8 +27,8 @@ Misc variables:
__version__ = "$Revision$" # Code version __version__ = "$Revision$" # Code version
from types import * from types import *
from copy_reg import dispatch_table from copyreg import dispatch_table
from copy_reg import _extension_registry, _inverted_registry, _extension_cache from copyreg import _extension_registry, _inverted_registry, _extension_cache
import marshal import marshal
import sys import sys
import struct import struct
@ -295,7 +295,7 @@ class Pickler:
self.save_global(obj) self.save_global(obj)
return return
# Check copy_reg.dispatch_table # Check copyreg.dispatch_table
reduce = dispatch_table.get(t) reduce = dispatch_table.get(t)
if reduce: if reduce:
rv = reduce(obj) rv = reduce(obj)

View File

@ -278,12 +278,12 @@ def _subx(pattern, template):
# register myself for pickling # register myself for pickling
import copy_reg import copyreg
def _pickle(p): def _pickle(p):
return _compile, (p.pattern, p.flags) return _compile, (p.pattern, p.flags)
copy_reg.pickle(_pattern_type, _pickle, _compile) copyreg.pickle(_pattern_type, _pickle, _compile)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# experimental stuff (see python-dev discussions for details) # experimental stuff (see python-dev discussions for details)

View File

@ -2,7 +2,7 @@ import unittest
import pickle import pickle
import cPickle import cPickle
import pickletools import pickletools
import copy_reg import copyreg
from test.test_support import TestFailed, have_unicode, TESTFN, \ from test.test_support import TestFailed, have_unicode, TESTFN, \
run_with_locale run_with_locale
@ -44,21 +44,21 @@ class ExtensionSaver:
# there is one). # there is one).
def __init__(self, code): def __init__(self, code):
self.code = code self.code = code
if code in copy_reg._inverted_registry: if code in copyreg._inverted_registry:
self.pair = copy_reg._inverted_registry[code] self.pair = copyreg._inverted_registry[code]
copy_reg.remove_extension(self.pair[0], self.pair[1], code) copyreg.remove_extension(self.pair[0], self.pair[1], code)
else: else:
self.pair = None self.pair = None
# Restore previous registration for code. # Restore previous registration for code.
def restore(self): def restore(self):
code = self.code code = self.code
curpair = copy_reg._inverted_registry.get(code) curpair = copyreg._inverted_registry.get(code)
if curpair is not None: if curpair is not None:
copy_reg.remove_extension(curpair[0], curpair[1], code) copyreg.remove_extension(curpair[0], curpair[1], code)
pair = self.pair pair = self.pair
if pair is not None: if pair is not None:
copy_reg.add_extension(pair[0], pair[1], code) copyreg.add_extension(pair[0], pair[1], code)
class C: class C:
def __cmp__(self, other): def __cmp__(self, other):
@ -690,14 +690,14 @@ class AbstractPickleTests(unittest.TestCase):
self.assertEqual(B(x), B(y), detail) self.assertEqual(B(x), B(y), detail)
self.assertEqual(x.__dict__, y.__dict__, detail) self.assertEqual(x.__dict__, y.__dict__, detail)
# Register a type with copy_reg, with extension code extcode. Pickle # Register a type with copyreg, with extension code extcode. Pickle
# an object of that type. Check that the resulting pickle uses opcode # an object of that type. Check that the resulting pickle uses opcode
# (EXT[124]) under proto 2, and not in proto 1. # (EXT[124]) under proto 2, and not in proto 1.
def produce_global_ext(self, extcode, opcode): def produce_global_ext(self, extcode, opcode):
e = ExtensionSaver(extcode) e = ExtensionSaver(extcode)
try: try:
copy_reg.add_extension(__name__, "MyList", extcode) copyreg.add_extension(__name__, "MyList", extcode)
x = MyList([1, 2, 3]) x = MyList([1, 2, 3])
x.foo = 42 x.foo = 42
x.bar = "hello" x.bar = "hello"

View File

@ -629,7 +629,7 @@ def cleanup_test_droppings(testname, verbose):
def dash_R(the_module, test, indirect_test, huntrleaks): def dash_R(the_module, test, indirect_test, huntrleaks):
# This code is hackish and inelegant, but it seems to do the job. # This code is hackish and inelegant, but it seems to do the job.
import copy_reg, _abcoll, io import copyreg, _abcoll, io
if not hasattr(sys, 'gettotalrefcount'): if not hasattr(sys, 'gettotalrefcount'):
raise Exception("Tracking reference leaks requires a debug build " raise Exception("Tracking reference leaks requires a debug build "
@ -637,7 +637,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
# Save current values for dash_R_cleanup() to restore. # Save current values for dash_R_cleanup() to restore.
fs = warnings.filters[:] fs = warnings.filters[:]
ps = copy_reg.dispatch_table.copy() ps = copyreg.dispatch_table.copy()
pic = sys.path_importer_cache.copy() pic = sys.path_importer_cache.copy()
abcs = {} abcs = {}
modules = _abcoll, io modules = _abcoll, io
@ -677,7 +677,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
refrep.close() refrep.close()
def dash_R_cleanup(fs, ps, pic, abcs): def dash_R_cleanup(fs, ps, pic, abcs):
import gc, copy_reg import gc, copyreg
import _strptime, linecache import _strptime, linecache
dircache = test_support.import_module('dircache', deprecated=True) dircache = test_support.import_module('dircache', deprecated=True)
import urlparse, urllib, urllib2, mimetypes, doctest import urlparse, urllib, urllib2, mimetypes, doctest
@ -691,8 +691,8 @@ def dash_R_cleanup(fs, ps, pic, abcs):
# Restore some original values. # Restore some original values.
warnings.filters[:] = fs warnings.filters[:] = fs
copy_reg.dispatch_table.clear() copyreg.dispatch_table.clear()
copy_reg.dispatch_table.update(ps) copyreg.dispatch_table.update(ps)
sys.path_importer_cache.clear() sys.path_importer_cache.clear()
sys.path_importer_cache.update(pic) sys.path_importer_cache.update(pic)

View File

@ -61,7 +61,7 @@ class AllTest(unittest.TestCase):
self.check_all("commands") self.check_all("commands")
self.check_all("compileall") self.check_all("compileall")
self.check_all("copy") self.check_all("copy")
self.check_all("copy_reg") self.check_all("copyreg")
self.check_all("csv") self.check_all("csv")
self.check_all("dbhash") self.check_all("dbhash")
self.check_all("decimal") self.check_all("decimal")

View File

@ -1,7 +1,7 @@
"""Unit tests for the copy module.""" """Unit tests for the copy module."""
import copy import copy
import copy_reg import copyreg
import unittest import unittest
from test import test_support from test import test_support
@ -42,7 +42,7 @@ class TestCopy(unittest.TestCase):
return (C, (obj.foo,)) return (C, (obj.foo,))
x = C(42) x = C(42)
self.assertRaises(TypeError, copy.copy, x) self.assertRaises(TypeError, copy.copy, x)
copy_reg.pickle(C, pickle_C, C) copyreg.pickle(C, pickle_C, C)
y = copy.copy(x) y = copy.copy(x)
def test_copy_reduce_ex(self): def test_copy_reduce_ex(self):
@ -215,7 +215,7 @@ class TestCopy(unittest.TestCase):
return (C, (obj.foo,)) return (C, (obj.foo,))
x = C(42) x = C(42)
self.assertRaises(TypeError, copy.deepcopy, x) self.assertRaises(TypeError, copy.deepcopy, x)
copy_reg.pickle(C, pickle_C, C) copyreg.pickle(C, pickle_C, C)
y = copy.deepcopy(x) y = copy.deepcopy(x)
def test_deepcopy_reduce_ex(self): def test_deepcopy_reduce_ex(self):

View File

@ -1,4 +1,4 @@
import copy_reg import copyreg
import unittest import unittest
from test import test_support from test import test_support
@ -27,15 +27,15 @@ class WithInherited(WithSingleString):
class CopyRegTestCase(unittest.TestCase): class CopyRegTestCase(unittest.TestCase):
def test_class(self): def test_class(self):
self.assertRaises(TypeError, copy_reg.pickle, self.assertRaises(TypeError, copyreg.pickle,
C, None, None) C, None, None)
def test_noncallable_reduce(self): def test_noncallable_reduce(self):
self.assertRaises(TypeError, copy_reg.pickle, self.assertRaises(TypeError, copyreg.pickle,
type(1), "not a callable") type(1), "not a callable")
def test_noncallable_constructor(self): def test_noncallable_constructor(self):
self.assertRaises(TypeError, copy_reg.pickle, self.assertRaises(TypeError, copyreg.pickle,
type(1), int, "not a callable") type(1), int, "not a callable")
def test_bool(self): def test_bool(self):
@ -47,42 +47,42 @@ class CopyRegTestCase(unittest.TestCase):
e = ExtensionSaver(code) e = ExtensionSaver(code)
try: try:
# Shouldn't be in registry now. # Shouldn't be in registry now.
self.assertRaises(ValueError, copy_reg.remove_extension, self.assertRaises(ValueError, copyreg.remove_extension,
mod, func, code) mod, func, code)
copy_reg.add_extension(mod, func, code) copyreg.add_extension(mod, func, code)
# Should be in the registry. # Should be in the registry.
self.assert_(copy_reg._extension_registry[mod, func] == code) self.assert_(copyreg._extension_registry[mod, func] == code)
self.assert_(copy_reg._inverted_registry[code] == (mod, func)) self.assert_(copyreg._inverted_registry[code] == (mod, func))
# Shouldn't be in the cache. # Shouldn't be in the cache.
self.assert_(code not in copy_reg._extension_cache) self.assert_(code not in copyreg._extension_cache)
# Redundant registration should be OK. # Redundant registration should be OK.
copy_reg.add_extension(mod, func, code) # shouldn't blow up copyreg.add_extension(mod, func, code) # shouldn't blow up
# Conflicting code. # Conflicting code.
self.assertRaises(ValueError, copy_reg.add_extension, self.assertRaises(ValueError, copyreg.add_extension,
mod, func, code + 1) mod, func, code + 1)
self.assertRaises(ValueError, copy_reg.remove_extension, self.assertRaises(ValueError, copyreg.remove_extension,
mod, func, code + 1) mod, func, code + 1)
# Conflicting module name. # Conflicting module name.
self.assertRaises(ValueError, copy_reg.add_extension, self.assertRaises(ValueError, copyreg.add_extension,
mod[1:], func, code ) mod[1:], func, code )
self.assertRaises(ValueError, copy_reg.remove_extension, self.assertRaises(ValueError, copyreg.remove_extension,
mod[1:], func, code ) mod[1:], func, code )
# Conflicting function name. # Conflicting function name.
self.assertRaises(ValueError, copy_reg.add_extension, self.assertRaises(ValueError, copyreg.add_extension,
mod, func[1:], code) mod, func[1:], code)
self.assertRaises(ValueError, copy_reg.remove_extension, self.assertRaises(ValueError, copyreg.remove_extension,
mod, func[1:], code) mod, func[1:], code)
# Can't remove one that isn't registered at all. # Can't remove one that isn't registered at all.
if code + 1 not in copy_reg._inverted_registry: if code + 1 not in copyreg._inverted_registry:
self.assertRaises(ValueError, copy_reg.remove_extension, self.assertRaises(ValueError, copyreg.remove_extension,
mod[1:], func[1:], code + 1) mod[1:], func[1:], code + 1)
finally: finally:
e.restore() e.restore()
# Shouldn't be there anymore. # Shouldn't be there anymore.
self.assert_((mod, func) not in copy_reg._extension_registry) self.assert_((mod, func) not in copyreg._extension_registry)
# The code *may* be in copy_reg._extension_registry, though, if # The code *may* be in copyreg._extension_registry, though, if
# we happened to pick on a registered code. So don't check for # we happened to pick on a registered code. So don't check for
# that. # that.
@ -90,25 +90,25 @@ class CopyRegTestCase(unittest.TestCase):
for code in 1, 0x7fffffff: for code in 1, 0x7fffffff:
e = ExtensionSaver(code) e = ExtensionSaver(code)
try: try:
copy_reg.add_extension(mod, func, code) copyreg.add_extension(mod, func, code)
copy_reg.remove_extension(mod, func, code) copyreg.remove_extension(mod, func, code)
finally: finally:
e.restore() e.restore()
# Ensure invalid codes blow up. # Ensure invalid codes blow up.
for code in -1, 0, 0x80000000L: for code in -1, 0, 0x80000000L:
self.assertRaises(ValueError, copy_reg.add_extension, self.assertRaises(ValueError, copyreg.add_extension,
mod, func, code) mod, func, code)
def test_slotnames(self): def test_slotnames(self):
self.assertEquals(copy_reg._slotnames(WithoutSlots), []) self.assertEquals(copyreg._slotnames(WithoutSlots), [])
self.assertEquals(copy_reg._slotnames(WithWeakref), []) self.assertEquals(copyreg._slotnames(WithWeakref), [])
expected = ['_WithPrivate__spam'] expected = ['_WithPrivate__spam']
self.assertEquals(copy_reg._slotnames(WithPrivate), expected) self.assertEquals(copyreg._slotnames(WithPrivate), expected)
self.assertEquals(copy_reg._slotnames(WithSingleString), ['spam']) self.assertEquals(copyreg._slotnames(WithSingleString), ['spam'])
expected = ['eggs', 'spam'] expected = ['eggs', 'spam']
expected.sort() expected.sort()
result = copy_reg._slotnames(WithInherited) result = copyreg._slotnames(WithInherited)
result.sort() result.sort()
self.assertEquals(result, expected) self.assertEquals(result, expected)

View File

@ -105,18 +105,18 @@ static PyObject *BadPickleGet;
/* As the name says, an empty tuple. */ /* As the name says, an empty tuple. */
static PyObject *empty_tuple; static PyObject *empty_tuple;
/* copy_reg.dispatch_table, {type_object: pickling_function} */ /* copyreg.dispatch_table, {type_object: pickling_function} */
static PyObject *dispatch_table; static PyObject *dispatch_table;
/* For EXT[124] opcodes. */ /* For EXT[124] opcodes. */
/* copy_reg._extension_registry, {(module_name, function_name): code} */ /* copyreg._extension_registry, {(module_name, function_name): code} */
static PyObject *extension_registry; static PyObject *extension_registry;
/* copy_reg._inverted_registry, {code: (module_name, function_name)} */ /* copyreg._inverted_registry, {code: (module_name, function_name)} */
static PyObject *inverted_registry; static PyObject *inverted_registry;
/* copy_reg._extension_cache, {code: object} */ /* copyreg._extension_cache, {code: object} */
static PyObject *extension_cache; static PyObject *extension_cache;
/* For looking up name pairs in copy_reg._extension_registry. */ /* For looking up name pairs in copyreg._extension_registry. */
static PyObject *two_tuple; static PyObject *two_tuple;
static PyObject *__class___str, *__getinitargs___str, *__dict___str, static PyObject *__class___str, *__getinitargs___str, *__dict___str,
@ -124,7 +124,7 @@ static PyObject *__class___str, *__getinitargs___str, *__dict___str,
*__reduce_ex___str, *__reduce_ex___str,
*write_str, *append_str, *write_str, *append_str,
*read_str, *readline_str, *__main___str, *read_str, *readline_str, *__main___str,
*copy_reg_str, *dispatch_table_str; *copyreg_str, *dispatch_table_str;
/************************************************************************* /*************************************************************************
Internal Data type for pickle data. */ Internal Data type for pickle data. */
@ -2477,7 +2477,7 @@ save(Picklerobject *self, PyObject *args, int pers_save)
} }
/* Get a reduction callable, and call it. This may come from /* Get a reduction callable, and call it. This may come from
* copy_reg.dispatch_table, the object's __reduce_ex__ method, * copyreg.dispatch_table, the object's __reduce_ex__ method,
* or the object's __reduce__ method. * or the object's __reduce__ method.
*/ */
__reduce__ = PyDict_GetItem(dispatch_table, (PyObject *)type); __reduce__ = PyDict_GetItem(dispatch_table, (PyObject *)type);
@ -2856,7 +2856,7 @@ newPicklerobject(PyObject *file, int proto)
if (PyEval_GetRestricted()) { if (PyEval_GetRestricted()) {
/* Restricted execution, get private tables */ /* Restricted execution, get private tables */
PyObject *m = PyImport_Import(copy_reg_str); PyObject *m = PyImport_Import(copyreg_str);
if (m == NULL) if (m == NULL)
goto err; goto err;
@ -5566,7 +5566,7 @@ static struct PyMethodDef cPickle_methods[] = {
static int static int
init_stuff(PyObject *module_dict) init_stuff(PyObject *module_dict)
{ {
PyObject *copy_reg, *t, *r; PyObject *copyreg, *t, *r;
#define INIT_STR(S) if (!( S ## _str=PyString_InternFromString(#S))) return -1; #define INIT_STR(S) if (!( S ## _str=PyString_InternFromString(#S))) return -1;
@ -5588,30 +5588,30 @@ init_stuff(PyObject *module_dict)
INIT_STR(append); INIT_STR(append);
INIT_STR(read); INIT_STR(read);
INIT_STR(readline); INIT_STR(readline);
INIT_STR(copy_reg); INIT_STR(copyreg);
INIT_STR(dispatch_table); INIT_STR(dispatch_table);
if (!( copy_reg = PyImport_ImportModule("copy_reg"))) if (!( copyreg = PyImport_ImportModule("copyreg")))
return -1; return -1;
/* This is special because we want to use a different /* This is special because we want to use a different
one in restricted mode. */ one in restricted mode. */
dispatch_table = PyObject_GetAttr(copy_reg, dispatch_table_str); dispatch_table = PyObject_GetAttr(copyreg, dispatch_table_str);
if (!dispatch_table) return -1; if (!dispatch_table) return -1;
extension_registry = PyObject_GetAttrString(copy_reg, extension_registry = PyObject_GetAttrString(copyreg,
"_extension_registry"); "_extension_registry");
if (!extension_registry) return -1; if (!extension_registry) return -1;
inverted_registry = PyObject_GetAttrString(copy_reg, inverted_registry = PyObject_GetAttrString(copyreg,
"_inverted_registry"); "_inverted_registry");
if (!inverted_registry) return -1; if (!inverted_registry) return -1;
extension_cache = PyObject_GetAttrString(copy_reg, extension_cache = PyObject_GetAttrString(copyreg,
"_extension_cache"); "_extension_cache");
if (!extension_cache) return -1; if (!extension_cache) return -1;
Py_DECREF(copy_reg); Py_DECREF(copyreg);
if (!(empty_tuple = PyTuple_New(0))) if (!(empty_tuple = PyTuple_New(0)))
return -1; return -1;

View File

@ -3284,7 +3284,7 @@ initparser(void)
* If this fails, the import of this module will fail because an * If this fails, the import of this module will fail because an
* exception will be raised here; should we clear the exception? * exception will be raised here; should we clear the exception?
*/ */
copyreg = PyImport_ImportModuleNoBlock("copy_reg"); copyreg = PyImport_ImportModuleNoBlock("copyreg");
if (copyreg != NULL) { if (copyreg != NULL) {
PyObject *func, *pickler; PyObject *func, *pickler;

View File

@ -3058,31 +3058,31 @@ static PyGetSetDef object_getsets[] = {
/* Stuff to implement __reduce_ex__ for pickle protocols >= 2. /* Stuff to implement __reduce_ex__ for pickle protocols >= 2.
We fall back to helpers in copy_reg for: We fall back to helpers in copyreg for:
- pickle protocols < 2 - pickle protocols < 2
- calculating the list of slot names (done only once per class) - calculating the list of slot names (done only once per class)
- the __newobj__ function (which is used as a token but never called) - the __newobj__ function (which is used as a token but never called)
*/ */
static PyObject * static PyObject *
import_copy_reg(void) import_copyreg(void)
{ {
static PyObject *copy_reg_str; static PyObject *copyreg_str;
if (!copy_reg_str) { if (!copyreg_str) {
copy_reg_str = PyString_InternFromString("copy_reg"); copyreg_str = PyString_InternFromString("copyreg");
if (copy_reg_str == NULL) if (copyreg_str == NULL)
return NULL; return NULL;
} }
return PyImport_Import(copy_reg_str); return PyImport_Import(copyreg_str);
} }
static PyObject * static PyObject *
slotnames(PyObject *cls) slotnames(PyObject *cls)
{ {
PyObject *clsdict; PyObject *clsdict;
PyObject *copy_reg; PyObject *copyreg;
PyObject *slotnames; PyObject *slotnames;
if (!PyType_Check(cls)) { if (!PyType_Check(cls)) {
@ -3097,12 +3097,12 @@ slotnames(PyObject *cls)
return slotnames; return slotnames;
} }
copy_reg = import_copy_reg(); copyreg = import_copyreg();
if (copy_reg == NULL) if (copyreg == NULL)
return NULL; return NULL;
slotnames = PyObject_CallMethod(copy_reg, "_slotnames", "O", cls); slotnames = PyObject_CallMethod(copyreg, "_slotnames", "O", cls);
Py_DECREF(copy_reg); Py_DECREF(copyreg);
if (slotnames != NULL && if (slotnames != NULL &&
slotnames != Py_None && slotnames != Py_None &&
!PyList_Check(slotnames)) !PyList_Check(slotnames))
@ -3123,7 +3123,7 @@ reduce_2(PyObject *obj)
PyObject *args = NULL, *args2 = NULL; PyObject *args = NULL, *args2 = NULL;
PyObject *getstate = NULL, *state = NULL, *names = NULL; PyObject *getstate = NULL, *state = NULL, *names = NULL;
PyObject *slots = NULL, *listitems = NULL, *dictitems = NULL; PyObject *slots = NULL, *listitems = NULL, *dictitems = NULL;
PyObject *copy_reg = NULL, *newobj = NULL, *res = NULL; PyObject *copyreg = NULL, *newobj = NULL, *res = NULL;
Py_ssize_t i, n; Py_ssize_t i, n;
cls = PyObject_GetAttrString(obj, "__class__"); cls = PyObject_GetAttrString(obj, "__class__");
@ -3218,10 +3218,10 @@ reduce_2(PyObject *obj)
goto end; goto end;
} }
copy_reg = import_copy_reg(); copyreg = import_copyreg();
if (copy_reg == NULL) if (copyreg == NULL)
goto end; goto end;
newobj = PyObject_GetAttrString(copy_reg, "__newobj__"); newobj = PyObject_GetAttrString(copyreg, "__newobj__");
if (newobj == NULL) if (newobj == NULL)
goto end; goto end;
@ -3248,7 +3248,7 @@ reduce_2(PyObject *obj)
Py_XDECREF(names); Py_XDECREF(names);
Py_XDECREF(listitems); Py_XDECREF(listitems);
Py_XDECREF(dictitems); Py_XDECREF(dictitems);
Py_XDECREF(copy_reg); Py_XDECREF(copyreg);
Py_XDECREF(newobj); Py_XDECREF(newobj);
return res; return res;
} }
@ -3271,17 +3271,17 @@ reduce_2(PyObject *obj)
static PyObject * static PyObject *
_common_reduce(PyObject *self, int proto) _common_reduce(PyObject *self, int proto)
{ {
PyObject *copy_reg, *res; PyObject *copyreg, *res;
if (proto >= 2) if (proto >= 2)
return reduce_2(self); return reduce_2(self);
copy_reg = import_copy_reg(); copyreg = import_copyreg();
if (!copy_reg) if (!copyreg)
return NULL; return NULL;
res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto); res = PyEval_CallMethod(copyreg, "_reduce_ex", "(Oi)", self, proto);
Py_DECREF(copy_reg); Py_DECREF(copyreg);
return res; return res;
} }