From dffbf5f5421cbeb20237280c0bd70f989269f844 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 20 May 2008 07:49:57 +0000 Subject: Revert copy_reg -> copyreg rename. --- Doc/library/copy.rst | 2 +- Doc/library/copy_reg.rst | 45 ++++++++++ Doc/library/copyreg.rst | 48 ----------- Doc/library/modulefinder.rst | 2 +- Doc/library/persistence.rst | 2 +- Doc/library/pickle.rst | 4 +- Lib/copy.py | 2 +- Lib/copy_reg.py | 201 +++++++++++++++++++++++++++++++++++++++++++ Lib/copyreg.py | 201 ------------------------------------------- Lib/idlelib/rpc.py | 6 +- Lib/lib-old/copy_reg.py | 8 -- Lib/os.py | 2 +- Lib/pickle.py | 8 +- Lib/pickletools.py | 4 +- Lib/re.py | 4 +- Lib/test/pickletester.py | 18 ++-- Lib/test/regrtest.py | 10 +-- Lib/test/test___all__.py | 2 +- Lib/test/test_copy.py | 6 +- Lib/test/test_copy_reg.py | 121 ++++++++++++++++++++++++++ Lib/test/test_copyreg.py | 121 -------------------------- Lib/test/test_py3kwarn.py | 2 +- Misc/cheatsheet | 2 +- Modules/cPickle.c | 14 +-- Modules/parsermodule.c | 2 +- Objects/typeobject.c | 6 +- 26 files changed, 416 insertions(+), 427 deletions(-) create mode 100644 Doc/library/copy_reg.rst delete mode 100644 Doc/library/copyreg.rst create mode 100644 Lib/copy_reg.py delete mode 100644 Lib/copyreg.py delete mode 100644 Lib/lib-old/copy_reg.py create mode 100644 Lib/test/test_copy_reg.py delete mode 100644 Lib/test/test_copyreg.py diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index ce127a3..89b668d 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -63,7 +63,7 @@ of lists by assigning a slice of the entire list, for example, Classes can use the same interfaces to control copying that they use to control pickling. See the description of module :mod:`pickle` for information on these -methods. The :mod:`copy` module does not use the :mod:`copyreg` registration +methods. The :mod:`copy` module does not use the :mod:`copy_reg` registration module. .. index:: diff --git a/Doc/library/copy_reg.rst b/Doc/library/copy_reg.rst new file mode 100644 index 0000000..609ded0 --- /dev/null +++ b/Doc/library/copy_reg.rst @@ -0,0 +1,45 @@ +:mod:`copy_reg` --- Register :mod:`pickle` support functions +============================================================ + +.. module:: copy_reg + :synopsis: Register pickle support functions. + +.. note:: + The :mod:`copy_reg` module has been renamed to :mod:`copyreg` in Python 3.0. + The :term:`2to3` tool will automatically adapt imports when converting your + sources to 3.0. + +.. index:: + module: pickle + module: cPickle + module: copy + +The :mod:`copy_reg` module provides support for the :mod:`pickle` and +:mod:`cPickle` modules. The :mod:`copy` module is likely to use this in the +future as well. It provides configuration information about object constructors +which are not classes. Such constructors may be factory functions or class +instances. + + +.. function:: constructor(object) + + Declares *object* to be a valid constructor. If *object* is not callable (and + hence not valid as a constructor), raises :exc:`TypeError`. + + +.. function:: pickle(type, function[, constructor]) + + Declares that *function* should be used as a "reduction" function for objects of + type *type*; *type* must not be a "classic" class object. (Classic classes are + handled differently; see the documentation for the :mod:`pickle` module for + details.) *function* should return either a string or a tuple containing two or + three elements. + + The optional *constructor* parameter, if provided, is a callable object which + can be used to reconstruct the object when called with the tuple of arguments + returned by *function* at pickling time. :exc:`TypeError` will be raised if + *object* is a class or *constructor* is not callable. + + See the :mod:`pickle` module for more details on the interface expected of + *function* and *constructor*. + diff --git a/Doc/library/copyreg.rst b/Doc/library/copyreg.rst deleted file mode 100644 index 3a3f815..0000000 --- a/Doc/library/copyreg.rst +++ /dev/null @@ -1,48 +0,0 @@ -:mod:`copyreg` --- Register :mod:`pickle` support functions -=========================================================== - -.. module:: copy_reg - :synopsis: Old name for the copyreg module. - -.. module:: copyreg - :synopsis: Register pickle support functions. - -.. note:: - The :mod:`copy_reg` module has been renamed to :mod:`copyreg` in Python 3.0. - It is importable under both names in Python 2.6 and the rest of the 2.x - series. - -.. index:: - module: pickle - module: cPickle - module: copy - -The :mod:`copyreg` module provides support for the :mod:`pickle` and -:mod:`cPickle` modules. The :mod:`copy` module is likely to use this in the -future as well. It provides configuration information about object constructors -which are not classes. Such constructors may be factory functions or class -instances. - - -.. function:: constructor(object) - - Declares *object* to be a valid constructor. If *object* is not callable (and - hence not valid as a constructor), raises :exc:`TypeError`. - - -.. function:: pickle(type, function[, constructor]) - - Declares that *function* should be used as a "reduction" function for objects of - type *type*; *type* must not be a "classic" class object. (Classic classes are - handled differently; see the documentation for the :mod:`pickle` module for - details.) *function* should return either a string or a tuple containing two or - three elements. - - The optional *constructor* parameter, if provided, is a callable object which - can be used to reconstruct the object when called with the tuple of arguments - returned by *function* at pickling time. :exc:`TypeError` will be raised if - *object* is a class or *constructor* is not callable. - - See the :mod:`pickle` module for more details on the interface expected of - *function* and *constructor*. - diff --git a/Doc/library/modulefinder.rst b/Doc/library/modulefinder.rst index 402f5db..a086206 100644 --- a/Doc/library/modulefinder.rst +++ b/Doc/library/modulefinder.rst @@ -97,7 +97,7 @@ Sample output (may vary depending on the architecture):: Loaded modules: _types: - copyreg: _inverted_registry,_slotnames,__all__ + copy_reg: _inverted_registry,_slotnames,__all__ sre_compile: isstring,_sre,_optimize_unicode _sre: sre_constants: REPEAT_ONE,makedict,AT_END_LINE diff --git a/Doc/library/persistence.rst b/Doc/library/persistence.rst index 3708d17..78e40f6 100644 --- a/Doc/library/persistence.rst +++ b/Doc/library/persistence.rst @@ -19,7 +19,7 @@ The list of modules described in this chapter is: .. toctree:: pickle.rst - copyreg.rst + copy_reg.rst shelve.rst marshal.rst anydbm.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index eefa4d3..f197261 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -535,7 +535,7 @@ not :meth:`__reduce_ex__`, the :meth:`__reduce_ex__` implementation detects this and calls :meth:`__reduce__`. An alternative to implementing a :meth:`__reduce__` method on the object to be -pickled, is to register the callable with the :mod:`copyreg` module. This +pickled, is to register the callable with the :mod:`copy_reg` module. This module provides a way for programs to register "reduction functions" and constructors for user-defined types. Reduction functions have the same semantics and interface as the :meth:`__reduce__` method described above, except @@ -786,7 +786,7 @@ the same process or a new process. :: .. seealso:: - Module :mod:`copyreg` + Module :mod:`copy_reg` Pickle interface constructor registration for extension types. Module :mod:`shelve` diff --git a/Lib/copy.py b/Lib/copy.py index 26ab366..f3871e5 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -49,7 +49,7 @@ __getstate__() and __setstate__(). See the documentation for module """ import types -from copyreg import dispatch_table +from copy_reg import dispatch_table class Error(Exception): pass diff --git a/Lib/copy_reg.py b/Lib/copy_reg.py new file mode 100644 index 0000000..db17150 --- /dev/null +++ b/Lib/copy_reg.py @@ -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 , is about +# to be pickled, the (, ) 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. diff --git a/Lib/copyreg.py b/Lib/copyreg.py deleted file mode 100644 index bf8827e..0000000 --- a/Lib/copyreg.py +++ /dev/null @@ -1,201 +0,0 @@ -"""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("copyreg 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 , is about -# to be pickled, the (, ) 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. diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py index a8c6afb..e0bcf2c 100644 --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -37,7 +37,7 @@ import cPickle as pickle import threading import queue import traceback -import copyreg +import copy_reg import types import marshal @@ -60,8 +60,8 @@ def pickle_code(co): # assert isinstance(fn, type.FunctionType) # return repr(fn) -copyreg.pickle(types.CodeType, pickle_code, unpickle_code) -# copyreg.pickle(types.FunctionType, pickle_function, unpickle_function) +copy_reg.pickle(types.CodeType, pickle_code, unpickle_code) +# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function) BUFSIZE = 8*1024 LOCALHOST = '127.0.0.1' diff --git a/Lib/lib-old/copy_reg.py b/Lib/lib-old/copy_reg.py deleted file mode 100644 index 700698c..0000000 --- a/Lib/lib-old/copy_reg.py +++ /dev/null @@ -1,8 +0,0 @@ -import sys -from warnings import warnpy3k - -warnpy3k("the copy_reg module has been renamed " - "to 'copyreg' in Python 3.0", stacklevel=2) - -import copyreg -sys.modules[__name__] = copyreg diff --git a/Lib/os.py b/Lib/os.py index f938962..def448f 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -715,7 +715,7 @@ if _exists("fork"): return p.stdin, p.stdout __all__.append("popen4") -import copyreg as _copy_reg +import copy_reg as _copy_reg def _make_stat_result(tup, dict): return stat_result(tup, dict) diff --git a/Lib/pickle.py b/Lib/pickle.py index ddb2c81..02a1b1d 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -1,7 +1,7 @@ """Create portable serialized representations of Python objects. See module cPickle for a (much) faster implementation. -See module copyreg for a mechanism for registering custom picklers. +See module copy_reg for a mechanism for registering custom picklers. See module pickletools source for extensive comments. Classes: @@ -27,8 +27,8 @@ Misc variables: __version__ = "$Revision$" # Code version from types import * -from copyreg import dispatch_table -from copyreg import _extension_registry, _inverted_registry, _extension_cache +from copy_reg import dispatch_table +from copy_reg import _extension_registry, _inverted_registry, _extension_cache import marshal import sys import struct @@ -295,7 +295,7 @@ class Pickler: self.save_global(obj) return - # Check copyreg.dispatch_table + # Check copy_reg.dispatch_table reduce = dispatch_table.get(t) if reduce: rv = reduce(obj) diff --git a/Lib/pickletools.py b/Lib/pickletools.py index 623dd16..ae02a36 100644 --- a/Lib/pickletools.py +++ b/Lib/pickletools.py @@ -136,7 +136,7 @@ this and there isn't a use case that warrants the expense of such an analysis. To this end, all tests for __safe_for_unpickling__ or for -copyreg.safe_constructors are removed from the unpickling code. +copy_reg.safe_constructors are removed from the unpickling code. References to these variables in the descriptions below are to be seen as describing unpickling in Python 2.2 and before. """ @@ -1525,7 +1525,7 @@ opcodes = [ BUILD opcode to apply __setstate__ to that argument. If type(callable) is not ClassType, REDUCE complains unless the - callable has been registered with the copyreg module's + callable has been registered with the copy_reg module's safe_constructors dict, or the callable has a magic '__safe_for_unpickling__' attribute with a true value. I'm not sure why it does this, but I've sure seen this complaint often enough when diff --git a/Lib/re.py b/Lib/re.py index 3f4f02c..1d9c987 100644 --- a/Lib/re.py +++ b/Lib/re.py @@ -278,12 +278,12 @@ def _subx(pattern, template): # register myself for pickling -import copyreg +import copy_reg def _pickle(p): return _compile, (p.pattern, p.flags) -copyreg.pickle(_pattern_type, _pickle, _compile) +copy_reg.pickle(_pattern_type, _pickle, _compile) # -------------------------------------------------------------------- # experimental stuff (see python-dev discussions for details) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index ed3b626..e1bc078 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -2,7 +2,7 @@ import unittest import pickle import cPickle import pickletools -import copyreg +import copy_reg from test.test_support import TestFailed, have_unicode, TESTFN, \ run_with_locale @@ -44,21 +44,21 @@ class ExtensionSaver: # there is one). def __init__(self, code): self.code = code - if code in copyreg._inverted_registry: - self.pair = copyreg._inverted_registry[code] - copyreg.remove_extension(self.pair[0], self.pair[1], code) + if code in copy_reg._inverted_registry: + self.pair = copy_reg._inverted_registry[code] + copy_reg.remove_extension(self.pair[0], self.pair[1], code) else: self.pair = None # Restore previous registration for code. def restore(self): code = self.code - curpair = copyreg._inverted_registry.get(code) + curpair = copy_reg._inverted_registry.get(code) if curpair is not None: - copyreg.remove_extension(curpair[0], curpair[1], code) + copy_reg.remove_extension(curpair[0], curpair[1], code) pair = self.pair if pair is not None: - copyreg.add_extension(pair[0], pair[1], code) + copy_reg.add_extension(pair[0], pair[1], code) class C: def __cmp__(self, other): @@ -690,14 +690,14 @@ class AbstractPickleTests(unittest.TestCase): self.assertEqual(B(x), B(y), detail) self.assertEqual(x.__dict__, y.__dict__, detail) - # Register a type with copyreg, with extension code extcode. Pickle + # Register a type with copy_reg, with extension code extcode. Pickle # an object of that type. Check that the resulting pickle uses opcode # (EXT[124]) under proto 2, and not in proto 1. def produce_global_ext(self, extcode, opcode): e = ExtensionSaver(extcode) try: - copyreg.add_extension(__name__, "MyList", extcode) + copy_reg.add_extension(__name__, "MyList", extcode) x = MyList([1, 2, 3]) x.foo = 42 x.bar = "hello" diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 85df78e..7aa22ed 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -629,7 +629,7 @@ def cleanup_test_droppings(testname, verbose): def dash_R(the_module, test, indirect_test, huntrleaks): # This code is hackish and inelegant, but it seems to do the job. - import copyreg, _abcoll, io + import copy_reg, _abcoll, io if not hasattr(sys, 'gettotalrefcount'): 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. fs = warnings.filters[:] - ps = copyreg.dispatch_table.copy() + ps = copy_reg.dispatch_table.copy() pic = sys.path_importer_cache.copy() abcs = {} modules = _abcoll, io @@ -677,7 +677,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks): refrep.close() def dash_R_cleanup(fs, ps, pic, abcs): - import gc, copyreg + import gc, copy_reg import _strptime, linecache dircache = test_support.import_module('dircache', deprecated=True) import urlparse, urllib, urllib2, mimetypes, doctest @@ -691,8 +691,8 @@ def dash_R_cleanup(fs, ps, pic, abcs): # Restore some original values. warnings.filters[:] = fs - copyreg.dispatch_table.clear() - copyreg.dispatch_table.update(ps) + copy_reg.dispatch_table.clear() + copy_reg.dispatch_table.update(ps) sys.path_importer_cache.clear() sys.path_importer_cache.update(pic) diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py index 3b6d966..466d921 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -61,7 +61,7 @@ class AllTest(unittest.TestCase): self.check_all("commands") self.check_all("compileall") self.check_all("copy") - self.check_all("copyreg") + self.check_all("copy_reg") self.check_all("csv") self.check_all("dbhash") self.check_all("decimal") diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index 8645ba1..d2899bd 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -1,7 +1,7 @@ """Unit tests for the copy module.""" import copy -import copyreg +import copy_reg import unittest from test import test_support @@ -42,7 +42,7 @@ class TestCopy(unittest.TestCase): return (C, (obj.foo,)) x = C(42) self.assertRaises(TypeError, copy.copy, x) - copyreg.pickle(C, pickle_C, C) + copy_reg.pickle(C, pickle_C, C) y = copy.copy(x) def test_copy_reduce_ex(self): @@ -215,7 +215,7 @@ class TestCopy(unittest.TestCase): return (C, (obj.foo,)) x = C(42) self.assertRaises(TypeError, copy.deepcopy, x) - copyreg.pickle(C, pickle_C, C) + copy_reg.pickle(C, pickle_C, C) y = copy.deepcopy(x) def test_deepcopy_reduce_ex(self): diff --git a/Lib/test/test_copy_reg.py b/Lib/test/test_copy_reg.py new file mode 100644 index 0000000..c3d3964 --- /dev/null +++ b/Lib/test/test_copy_reg.py @@ -0,0 +1,121 @@ +import copy_reg +import unittest + +from test import test_support +from test.pickletester import ExtensionSaver + +class C: + pass + + +class WithoutSlots(object): + pass + +class WithWeakref(object): + __slots__ = ('__weakref__',) + +class WithPrivate(object): + __slots__ = ('__spam',) + +class WithSingleString(object): + __slots__ = 'spam' + +class WithInherited(WithSingleString): + __slots__ = ('eggs',) + + +class CopyRegTestCase(unittest.TestCase): + + def test_class(self): + self.assertRaises(TypeError, copy_reg.pickle, + C, None, None) + + def test_noncallable_reduce(self): + self.assertRaises(TypeError, copy_reg.pickle, + type(1), "not a callable") + + def test_noncallable_constructor(self): + self.assertRaises(TypeError, copy_reg.pickle, + type(1), int, "not a callable") + + def test_bool(self): + import copy + self.assertEquals(True, copy.copy(True)) + + def test_extension_registry(self): + mod, func, code = 'junk1 ', ' junk2', 0xabcd + e = ExtensionSaver(code) + try: + # Shouldn't be in registry now. + self.assertRaises(ValueError, copy_reg.remove_extension, + mod, func, code) + copy_reg.add_extension(mod, func, code) + # Should be in the registry. + self.assert_(copy_reg._extension_registry[mod, func] == code) + self.assert_(copy_reg._inverted_registry[code] == (mod, func)) + # Shouldn't be in the cache. + self.assert_(code not in copy_reg._extension_cache) + # Redundant registration should be OK. + copy_reg.add_extension(mod, func, code) # shouldn't blow up + # Conflicting code. + self.assertRaises(ValueError, copy_reg.add_extension, + mod, func, code + 1) + self.assertRaises(ValueError, copy_reg.remove_extension, + mod, func, code + 1) + # Conflicting module name. + self.assertRaises(ValueError, copy_reg.add_extension, + mod[1:], func, code ) + self.assertRaises(ValueError, copy_reg.remove_extension, + mod[1:], func, code ) + # Conflicting function name. + self.assertRaises(ValueError, copy_reg.add_extension, + mod, func[1:], code) + self.assertRaises(ValueError, copy_reg.remove_extension, + mod, func[1:], code) + # Can't remove one that isn't registered at all. + if code + 1 not in copy_reg._inverted_registry: + self.assertRaises(ValueError, copy_reg.remove_extension, + mod[1:], func[1:], code + 1) + + finally: + e.restore() + + # Shouldn't be there anymore. + self.assert_((mod, func) not in copy_reg._extension_registry) + # The code *may* be in copy_reg._extension_registry, though, if + # we happened to pick on a registered code. So don't check for + # that. + + # Check valid codes at the limits. + for code in 1, 0x7fffffff: + e = ExtensionSaver(code) + try: + copy_reg.add_extension(mod, func, code) + copy_reg.remove_extension(mod, func, code) + finally: + e.restore() + + # Ensure invalid codes blow up. + for code in -1, 0, 0x80000000L: + self.assertRaises(ValueError, copy_reg.add_extension, + mod, func, code) + + def test_slotnames(self): + self.assertEquals(copy_reg._slotnames(WithoutSlots), []) + self.assertEquals(copy_reg._slotnames(WithWeakref), []) + expected = ['_WithPrivate__spam'] + self.assertEquals(copy_reg._slotnames(WithPrivate), expected) + self.assertEquals(copy_reg._slotnames(WithSingleString), ['spam']) + expected = ['eggs', 'spam'] + expected.sort() + result = copy_reg._slotnames(WithInherited) + result.sort() + self.assertEquals(result, expected) + + +def test_main(): + test_support.run_unittest(CopyRegTestCase) + + +if __name__ == "__main__": + test_main() diff --git a/Lib/test/test_copyreg.py b/Lib/test/test_copyreg.py deleted file mode 100644 index 0b42128..0000000 --- a/Lib/test/test_copyreg.py +++ /dev/null @@ -1,121 +0,0 @@ -import copyreg -import unittest - -from test import test_support -from test.pickletester import ExtensionSaver - -class C: - pass - - -class WithoutSlots(object): - pass - -class WithWeakref(object): - __slots__ = ('__weakref__',) - -class WithPrivate(object): - __slots__ = ('__spam',) - -class WithSingleString(object): - __slots__ = 'spam' - -class WithInherited(WithSingleString): - __slots__ = ('eggs',) - - -class CopyRegTestCase(unittest.TestCase): - - def test_class(self): - self.assertRaises(TypeError, copyreg.pickle, - C, None, None) - - def test_noncallable_reduce(self): - self.assertRaises(TypeError, copyreg.pickle, - type(1), "not a callable") - - def test_noncallable_constructor(self): - self.assertRaises(TypeError, copyreg.pickle, - type(1), int, "not a callable") - - def test_bool(self): - import copy - self.assertEquals(True, copy.copy(True)) - - def test_extension_registry(self): - mod, func, code = 'junk1 ', ' junk2', 0xabcd - e = ExtensionSaver(code) - try: - # Shouldn't be in registry now. - self.assertRaises(ValueError, copyreg.remove_extension, - mod, func, code) - copyreg.add_extension(mod, func, code) - # Should be in the registry. - self.assert_(copyreg._extension_registry[mod, func] == code) - self.assert_(copyreg._inverted_registry[code] == (mod, func)) - # Shouldn't be in the cache. - self.assert_(code not in copyreg._extension_cache) - # Redundant registration should be OK. - copyreg.add_extension(mod, func, code) # shouldn't blow up - # Conflicting code. - self.assertRaises(ValueError, copyreg.add_extension, - mod, func, code + 1) - self.assertRaises(ValueError, copyreg.remove_extension, - mod, func, code + 1) - # Conflicting module name. - self.assertRaises(ValueError, copyreg.add_extension, - mod[1:], func, code ) - self.assertRaises(ValueError, copyreg.remove_extension, - mod[1:], func, code ) - # Conflicting function name. - self.assertRaises(ValueError, copyreg.add_extension, - mod, func[1:], code) - self.assertRaises(ValueError, copyreg.remove_extension, - mod, func[1:], code) - # Can't remove one that isn't registered at all. - if code + 1 not in copyreg._inverted_registry: - self.assertRaises(ValueError, copyreg.remove_extension, - mod[1:], func[1:], code + 1) - - finally: - e.restore() - - # Shouldn't be there anymore. - self.assert_((mod, func) not in copyreg._extension_registry) - # The code *may* be in copyreg._extension_registry, though, if - # we happened to pick on a registered code. So don't check for - # that. - - # Check valid codes at the limits. - for code in 1, 0x7fffffff: - e = ExtensionSaver(code) - try: - copyreg.add_extension(mod, func, code) - copyreg.remove_extension(mod, func, code) - finally: - e.restore() - - # Ensure invalid codes blow up. - for code in -1, 0, 0x80000000L: - self.assertRaises(ValueError, copyreg.add_extension, - mod, func, code) - - def test_slotnames(self): - self.assertEquals(copyreg._slotnames(WithoutSlots), []) - self.assertEquals(copyreg._slotnames(WithWeakref), []) - expected = ['_WithPrivate__spam'] - self.assertEquals(copyreg._slotnames(WithPrivate), expected) - self.assertEquals(copyreg._slotnames(WithSingleString), ['spam']) - expected = ['eggs', 'spam'] - expected.sort() - result = copyreg._slotnames(WithInherited) - result.sort() - self.assertEquals(result, expected) - - -def test_main(): - test_support.run_unittest(CopyRegTestCase) - - -if __name__ == "__main__": - test_main() diff --git a/Lib/test/test_py3kwarn.py b/Lib/test/test_py3kwarn.py index 0641f7d..ece38ec 100644 --- a/Lib/test/test_py3kwarn.py +++ b/Lib/test/test_py3kwarn.py @@ -215,7 +215,7 @@ class TestStdlibRemovals(unittest.TestCase): class TestStdlibRenames(unittest.TestCase): - renames = {'copy_reg': 'copyreg', 'Queue': 'queue', + renames = {'Queue': 'queue', 'SocketServer': 'socketserver', 'ConfigParser': 'configparser', 'repr': 'reprlib'} diff --git a/Misc/cheatsheet b/Misc/cheatsheet index 1ce1996..e699359 100644 --- a/Misc/cheatsheet +++ b/Misc/cheatsheet @@ -1864,7 +1864,7 @@ commands Tools for executing UNIX commands . compileall Force "compilation" of all .py files in a directory. configparser Configuration file parser (much like windows .ini files) copy Generic shallow and deep copying operations. -copyreg Helper to provide extensibility for pickle/cPickle. +copy_reg Helper to provide extensibility for pickle/cPickle. csv Read and write files with comma separated values. dbhash (g)dbm-compatible interface to bsdhash.hashopen. dircache Sorted list of files in a dir, using a cache. diff --git a/Modules/cPickle.c b/Modules/cPickle.c index 06726ee..f130087 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -105,18 +105,18 @@ static PyObject *BadPickleGet; /* As the name says, an empty tuple. */ static PyObject *empty_tuple; -/* copyreg.dispatch_table, {type_object: pickling_function} */ +/* copy_reg.dispatch_table, {type_object: pickling_function} */ static PyObject *dispatch_table; /* For EXT[124] opcodes. */ -/* copyreg._extension_registry, {(module_name, function_name): code} */ +/* copy_reg._extension_registry, {(module_name, function_name): code} */ static PyObject *extension_registry; -/* copyreg._inverted_registry, {code: (module_name, function_name)} */ +/* copy_reg._inverted_registry, {code: (module_name, function_name)} */ static PyObject *inverted_registry; -/* copyreg._extension_cache, {code: object} */ +/* copy_reg._extension_cache, {code: object} */ static PyObject *extension_cache; -/* For looking up name pairs in copyreg._extension_registry. */ +/* For looking up name pairs in copy_reg._extension_registry. */ static PyObject *two_tuple; static PyObject *__class___str, *__getinitargs___str, *__dict___str, @@ -2477,7 +2477,7 @@ save(Picklerobject *self, PyObject *args, int pers_save) } /* Get a reduction callable, and call it. This may come from - * copyreg.dispatch_table, the object's __reduce_ex__ method, + * copy_reg.dispatch_table, the object's __reduce_ex__ method, * or the object's __reduce__ method. */ __reduce__ = PyDict_GetItem(dispatch_table, (PyObject *)type); @@ -5591,7 +5591,7 @@ init_stuff(PyObject *module_dict) INIT_STR(copyreg); INIT_STR(dispatch_table); - if (!( copyreg = PyImport_ImportModule("copyreg"))) + if (!( copyreg = PyImport_ImportModule("copy_reg"))) return -1; /* This is special because we want to use a different diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index 02a1e48..6e52343 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -3284,7 +3284,7 @@ initparser(void) * If this fails, the import of this module will fail because an * exception will be raised here; should we clear the exception? */ - copyreg = PyImport_ImportModuleNoBlock("copyreg"); + copyreg = PyImport_ImportModuleNoBlock("copy_reg"); if (copyreg != NULL) { PyObject *func, *pickler; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1138291..c3aa090 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3058,7 +3058,7 @@ static PyGetSetDef object_getsets[] = { /* Stuff to implement __reduce_ex__ for pickle protocols >= 2. - We fall back to helpers in copyreg for: + We fall back to helpers in copy_reg for: - pickle protocols < 2 - calculating the list of slot names (done only once per class) - the __newobj__ function (which is used as a token but never called) @@ -3070,7 +3070,7 @@ import_copyreg(void) static PyObject *copyreg_str; if (!copyreg_str) { - copyreg_str = PyString_InternFromString("copyreg"); + copyreg_str = PyString_InternFromString("copy_reg"); if (copyreg_str == NULL) return NULL; } @@ -3108,7 +3108,7 @@ slotnames(PyObject *cls) !PyList_Check(slotnames)) { PyErr_SetString(PyExc_TypeError, - "copyreg._slotnames didn't return a list or None"); + "copy_reg._slotnames didn't return a list or None"); Py_DECREF(slotnames); slotnames = NULL; } -- cgit v0.12