From f7fa63dd55e638d300a8d4a148dcedb402fdb750 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Sun, 11 May 2008 08:55:36 +0000 Subject: Rename copy_reg module to copyreg. Updated documentation. Merged revisions 63042 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r63042 | alexandre.vassalotti | 2008-05-11 04:25:28 -0400 (Sun, 11 May 2008) | 5 lines 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. ........ --- Doc/library/copy.rst | 2 +- Doc/library/copy_reg.rst | 40 ----- Doc/library/copyreg.rst | 40 +++++ Doc/library/modulefinder.rst | 2 +- Doc/library/persistence.rst | 2 +- Doc/library/pickle.rst | 4 +- Lib/copy.py | 2 +- Lib/copy_reg.py | 196 ------------------------ Lib/copyreg.py | 196 ++++++++++++++++++++++++ Lib/idlelib/rpc.py | 6 +- Lib/os.py | 6 +- Lib/pickle.py | 8 +- Lib/pickletools.py | 96 ++++++------ Lib/re.py | 4 +- Lib/test/pickletester.py | 354 +++++++++++++++++++++---------------------- 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 +++++++++++++++ Misc/NEWS | 2 + Modules/parsermodule.c | 2 +- Objects/typeobject.c | 46 +++--- 23 files changed, 635 insertions(+), 633 deletions(-) delete mode 100644 Doc/library/copy_reg.rst create mode 100644 Doc/library/copyreg.rst delete mode 100644 Lib/copy_reg.py create mode 100644 Lib/copyreg.py delete mode 100644 Lib/test/test_copy_reg.py create mode 100644 Lib/test/test_copyreg.py diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 485cfc5..554801f 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -60,7 +60,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:`copy_reg` registration +methods. The :mod:`copy` module does not use the :mod:`copyreg` registration module. .. index:: diff --git a/Doc/library/copy_reg.rst b/Doc/library/copy_reg.rst deleted file mode 100644 index 2e85be7..0000000 --- a/Doc/library/copy_reg.rst +++ /dev/null @@ -1,40 +0,0 @@ - -:mod:`copy_reg` --- Register :mod:`pickle` support functions -============================================================ - -.. module:: copy_reg - :synopsis: Register pickle support functions. - - -.. 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*. *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 new file mode 100644 index 0000000..dd97ade --- /dev/null +++ b/Doc/library/copyreg.rst @@ -0,0 +1,40 @@ + +:mod:`copyreg` --- Register :mod:`pickle` support functions +============================================================ + +.. module:: copyreg + :synopsis: Register pickle support functions. + + +.. 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*. *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 7a289f4..13ea11d 100644 --- a/Doc/library/modulefinder.rst +++ b/Doc/library/modulefinder.rst @@ -95,7 +95,7 @@ Sample output (may vary depending on the architecture):: Loaded modules: _types: - copy_reg: _inverted_registry,_slotnames,__all__ + copyreg: _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 78e40f6..3708d17 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 - copy_reg.rst + copyreg.rst shelve.rst marshal.rst anydbm.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index ff3d918..c3b9c8f 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -524,7 +524,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:`copy_reg` module. This +pickled, is to register the callable with the :mod:`copyreg` 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 @@ -775,7 +775,7 @@ the same process or a new process. :: .. seealso:: - Module :mod:`copy_reg` + Module :mod:`copyreg` Pickle interface constructor registration for extension types. Module :mod:`shelve` diff --git a/Lib/copy.py b/Lib/copy.py index ec108b7..899ee4d 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -49,7 +49,7 @@ __getstate__() and __setstate__(). See the documentation for module """ import types -from copy_reg import dispatch_table +from copyreg import dispatch_table class Error(Exception): pass diff --git a/Lib/copy_reg.py b/Lib/copy_reg.py deleted file mode 100644 index 81a1e7f..0000000 --- a/Lib/copy_reg.py +++ /dev/null @@ -1,196 +0,0 @@ -"""Helper to provide extensibility for pickle. - -This is only useful to add pickle support for extension types defined in -C, not for instances of user-defined classes. -""" - -__all__ = ["pickle", "constructor", - "add_extension", "remove_extension", "clear_extension_cache"] - -dispatch_table = {} - -def pickle(ob_type, pickle_function, constructor_ob=None): - 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, str): - 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: pickling 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 new file mode 100644 index 0000000..81a1e7f --- /dev/null +++ b/Lib/copyreg.py @@ -0,0 +1,196 @@ +"""Helper to provide extensibility for pickle. + +This is only useful to add pickle support for extension types defined in +C, not for instances of user-defined classes. +""" + +__all__ = ["pickle", "constructor", + "add_extension", "remove_extension", "clear_extension_cache"] + +dispatch_table = {} + +def pickle(ob_type, pickle_function, constructor_ob=None): + 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, str): + 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: pickling 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 eb262f4..109797c 100644 --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -37,7 +37,7 @@ import pickle import threading import Queue import traceback -import copy_reg +import copyreg import types import marshal @@ -60,8 +60,8 @@ def pickle_code(co): # assert isinstance(fn, type.FunctionType) # return repr(fn) -copy_reg.pickle(types.CodeType, pickle_code, unpickle_code) -# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function) +copyreg.pickle(types.CodeType, pickle_code, unpickle_code) +# copyreg.pickle(types.FunctionType, pickle_function, unpickle_function) BUFSIZE = 8*1024 LOCALHOST = '127.0.0.1' diff --git a/Lib/os.py b/Lib/os.py index a489524..b6e1570 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -588,7 +588,7 @@ otherwise return -SIG, where SIG is the signal that killed it. """ __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",]) -import copy_reg as _copy_reg +import copyreg as _copyreg def _make_stat_result(tup, dict): return stat_result(tup, dict) @@ -598,7 +598,7 @@ def _pickle_stat_result(sr): return (_make_stat_result, args) try: - _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result) + _copyreg.pickle(stat_result, _pickle_stat_result, _make_stat_result) except NameError: # stat_result may not exist pass @@ -610,7 +610,7 @@ def _pickle_statvfs_result(sr): return (_make_statvfs_result, args) try: - _copy_reg.pickle(statvfs_result, _pickle_statvfs_result, + _copyreg.pickle(statvfs_result, _pickle_statvfs_result, _make_statvfs_result) except NameError: # statvfs_result may not exist pass diff --git a/Lib/pickle.py b/Lib/pickle.py index a9d4355..bf5c951 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -1,6 +1,6 @@ """Create portable serialized representations of Python objects. -See module copy_reg for a mechanism for registering custom picklers. +See module copyreg for a mechanism for registering custom picklers. See module pickletools source for extensive comments. Classes: @@ -26,8 +26,8 @@ Misc variables: __version__ = "$Revision$" # Code version from types import FunctionType, BuiltinFunctionType -from copy_reg import dispatch_table -from copy_reg import _extension_registry, _inverted_registry, _extension_cache +from copyreg import dispatch_table +from copyreg import _extension_registry, _inverted_registry, _extension_cache import marshal import sys import struct @@ -299,7 +299,7 @@ class Pickler: self.save_global(obj) return - # Check copy_reg.dispatch_table + # Check copyreg.dispatch_table reduce = dispatch_table.get(t) if reduce: rv = reduce(obj) diff --git a/Lib/pickletools.py b/Lib/pickletools.py index 37dad9b..7bc9c67 100644 --- a/Lib/pickletools.py +++ b/Lib/pickletools.py @@ -142,7 +142,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 -copy_reg.safe_constructors are removed from the unpickling code. +copyreg.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. """ @@ -1559,7 +1559,7 @@ opcodes = [ BUILD opcode to apply __setstate__ to that argument. If not isinstance(callable, type), REDUCE complains unless the - callable has been registered with the copy_reg module's + callable has been registered with the copyreg 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 @@ -2137,58 +2137,58 @@ highest protocol among opcodes = 0 0: ( MARK 1: l LIST (MARK at 0) 2: p PUT 0 - 5: c GLOBAL 'copy_reg _reconstructor' - 30: p PUT 1 - 33: ( MARK - 34: c GLOBAL 'pickletools _Example' - 56: p PUT 2 - 59: c GLOBAL 'builtins object' - 76: p PUT 3 - 79: N NONE - 80: t TUPLE (MARK at 33) - 81: p PUT 4 - 84: R REDUCE - 85: p PUT 5 - 88: ( MARK - 89: d DICT (MARK at 88) - 90: p PUT 6 - 93: V UNICODE 'value' - 100: p PUT 7 - 103: L LONG 42 - 107: s SETITEM - 108: b BUILD - 109: a APPEND - 110: g GET 5 - 113: a APPEND - 114: . STOP + 5: c GLOBAL 'copyreg _reconstructor' + 29: p PUT 1 + 32: ( MARK + 33: c GLOBAL 'pickletools _Example' + 55: p PUT 2 + 58: c GLOBAL 'builtins object' + 75: p PUT 3 + 78: N NONE + 79: t TUPLE (MARK at 32) + 80: p PUT 4 + 83: R REDUCE + 84: p PUT 5 + 87: ( MARK + 88: d DICT (MARK at 87) + 89: p PUT 6 + 92: V UNICODE 'value' + 99: p PUT 7 + 102: L LONG 42 + 106: s SETITEM + 107: b BUILD + 108: a APPEND + 109: g GET 5 + 112: a APPEND + 113: . STOP highest protocol among opcodes = 0 >>> dis(pickle.dumps(x, 1)) 0: ] EMPTY_LIST 1: q BINPUT 0 3: ( MARK - 4: c GLOBAL 'copy_reg _reconstructor' - 29: q BINPUT 1 - 31: ( MARK - 32: c GLOBAL 'pickletools _Example' - 54: q BINPUT 2 - 56: c GLOBAL 'builtins object' - 73: q BINPUT 3 - 75: N NONE - 76: t TUPLE (MARK at 31) - 77: q BINPUT 4 - 79: R REDUCE - 80: q BINPUT 5 - 82: } EMPTY_DICT - 83: q BINPUT 6 - 85: X BINUNICODE 'value' - 95: q BINPUT 7 - 97: K BININT1 42 - 99: s SETITEM - 100: b BUILD - 101: h BINGET 5 - 103: e APPENDS (MARK at 3) - 104: . STOP + 4: c GLOBAL 'copyreg _reconstructor' + 28: q BINPUT 1 + 30: ( MARK + 31: c GLOBAL 'pickletools _Example' + 53: q BINPUT 2 + 55: c GLOBAL 'builtins object' + 72: q BINPUT 3 + 74: N NONE + 75: t TUPLE (MARK at 30) + 76: q BINPUT 4 + 78: R REDUCE + 79: q BINPUT 5 + 81: } EMPTY_DICT + 82: q BINPUT 6 + 84: X BINUNICODE 'value' + 94: q BINPUT 7 + 96: K BININT1 42 + 98: s SETITEM + 99: b BUILD + 100: h BINGET 5 + 102: e APPENDS (MARK at 3) + 103: . STOP highest protocol among opcodes = 1 Try "the canonical" recursive-object test. diff --git a/Lib/re.py b/Lib/re.py index 32737b7..951f239 100644 --- a/Lib/re.py +++ b/Lib/re.py @@ -272,12 +272,12 @@ def _subx(pattern, template): # register myself for pickling -import copy_reg +import copyreg def _pickle(p): 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) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 0230f3c..666b9c2 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1,7 +1,7 @@ import unittest import pickle import pickletools -import copy_reg +import copyreg from test.test_support import TestFailed, TESTFN, run_with_locale @@ -43,21 +43,21 @@ class ExtensionSaver: # there is one). def __init__(self, code): self.code = 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) + if code in copyreg._inverted_registry: + self.pair = copyreg._inverted_registry[code] + copyreg.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 = copy_reg._inverted_registry.get(code) + curpair = copyreg._inverted_registry.get(code) 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 if pair is not None: - copy_reg.add_extension(pair[0], pair[1], code) + copyreg.add_extension(pair[0], pair[1], code) class C: def __eq__(self, other): @@ -98,7 +98,7 @@ DATA0 = ( b'L-65535\naL-65536\naL2' b'147483647\naL-2147483' b'647\naL-2147483648\na(' - b'Vabc\np4\ng4\nccopy_reg' + b'Vabc\np4\ng4\nccopyreg' b'\n_reconstructor\np5\n(' b'c__main__\nC\np6\ncbu' b'iltins\nobject\np7\nNt' @@ -119,74 +119,74 @@ DATA0_DIS = """\ 13: F FLOAT 2.0 18: a APPEND 19: c GLOBAL 'builtins complex' - 40: p PUT 1 - 43: ( MARK - 44: F FLOAT 3.0 - 49: F FLOAT 0.0 - 54: t TUPLE (MARK at 43) - 55: p PUT 2 - 58: R REDUCE - 59: p PUT 3 - 62: a APPEND - 63: L LONG 1 - 66: a APPEND - 67: L LONG -1 - 71: a APPEND - 72: L LONG 255 - 77: a APPEND - 78: L LONG -255 - 84: a APPEND - 85: L LONG -256 - 91: a APPEND - 92: L LONG 65535 - 99: a APPEND - 100: L LONG -65535 - 108: a APPEND - 109: L LONG -65536 - 117: a APPEND - 118: L LONG 2147483647 - 130: a APPEND - 131: L LONG -2147483647 - 144: a APPEND - 145: L LONG -2147483648 - 158: a APPEND - 159: ( MARK - 160: V UNICODE 'abc' - 165: p PUT 4 - 168: g GET 4 - 171: c GLOBAL 'copy_reg _reconstructor' - 196: p PUT 5 - 199: ( MARK - 200: c GLOBAL '__main__ C' - 212: p PUT 6 - 215: c GLOBAL 'builtins object' - 235: p PUT 7 - 238: N NONE - 239: t TUPLE (MARK at 199) - 240: p PUT 8 - 243: R REDUCE - 244: p PUT 9 - 247: ( MARK - 248: d DICT (MARK at 247) - 249: p PUT 10 - 253: V UNICODE 'foo' - 258: p PUT 11 - 262: L LONG 1 - 265: s SETITEM - 266: V UNICODE 'bar' - 271: p PUT 12 - 275: L LONG 2 - 278: s SETITEM - 279: b BUILD - 280: g GET 9 - 283: t TUPLE (MARK at 159) - 284: p PUT 13 - 288: a APPEND - 289: g GET 13 - 293: a APPEND - 294: L LONG 5 - 297: a APPEND - 298: . STOP + 37: p PUT 1 + 40: ( MARK + 41: F FLOAT 3.0 + 46: F FLOAT 0.0 + 51: t TUPLE (MARK at 40) + 52: p PUT 2 + 55: R REDUCE + 56: p PUT 3 + 59: a APPEND + 60: L LONG 1 + 63: a APPEND + 64: L LONG -1 + 68: a APPEND + 69: L LONG 255 + 74: a APPEND + 75: L LONG -255 + 81: a APPEND + 82: L LONG -256 + 88: a APPEND + 89: L LONG 65535 + 96: a APPEND + 97: L LONG -65535 + 105: a APPEND + 106: L LONG -65536 + 114: a APPEND + 115: L LONG 2147483647 + 127: a APPEND + 128: L LONG -2147483647 + 141: a APPEND + 142: L LONG -2147483648 + 155: a APPEND + 156: ( MARK + 157: V UNICODE 'abc' + 162: p PUT 4 + 165: g GET 4 + 168: c GLOBAL 'copyreg _reconstructor' + 192: p PUT 5 + 195: ( MARK + 196: c GLOBAL '__main__ C' + 208: p PUT 6 + 211: c GLOBAL 'builtins object' + 228: p PUT 7 + 231: N NONE + 232: t TUPLE (MARK at 195) + 233: p PUT 8 + 236: R REDUCE + 237: p PUT 9 + 240: ( MARK + 241: d DICT (MARK at 240) + 242: p PUT 10 + 246: V UNICODE 'foo' + 251: p PUT 11 + 255: L LONG 1 + 258: s SETITEM + 259: V UNICODE 'bar' + 264: p PUT 12 + 268: L LONG 2 + 271: s SETITEM + 272: b BUILD + 273: g GET 9 + 276: t TUPLE (MARK at 156) + 277: p PUT 13 + 281: a APPEND + 282: g GET 13 + 286: a APPEND + 287: L LONG 5 + 290: a APPEND + 291: . STOP highest protocol among opcodes = 0 """ @@ -197,7 +197,7 @@ DATA1 = ( b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ' b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff' b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab' - b'cq\x04h\x04ccopy_reg\n_reco' + b'cq\x04h\x04ccopyreg\n_reco' b'nstructor\nq\x05(c__main' b'__\nC\nq\x06cbuiltins\n' b'object\nq\x07Ntq\x08Rq\t}q\n(' @@ -214,59 +214,59 @@ DATA1_DIS = """\ 6: K BININT1 1 8: G BINFLOAT 2.0 17: c GLOBAL 'builtins complex' - 38: q BINPUT 1 - 40: ( MARK - 41: G BINFLOAT 3.0 - 50: G BINFLOAT 0.0 - 59: t TUPLE (MARK at 40) - 60: q BINPUT 2 - 62: R REDUCE - 63: q BINPUT 3 - 65: K BININT1 1 - 67: J BININT -1 - 72: K BININT1 255 - 74: J BININT -255 - 79: J BININT -256 - 84: M BININT2 65535 - 87: J BININT -65535 - 92: J BININT -65536 - 97: J BININT 2147483647 - 102: J BININT -2147483647 - 107: J BININT -2147483648 - 112: ( MARK - 113: X BINUNICODE 'abc' - 121: q BINPUT 4 - 123: h BINGET 4 - 125: c GLOBAL 'copy_reg _reconstructor' - 150: q BINPUT 5 - 152: ( MARK - 153: c GLOBAL '__main__ C' - 165: q BINPUT 6 - 167: c GLOBAL 'builtins object' - 187: q BINPUT 7 - 189: N NONE - 190: t TUPLE (MARK at 152) - 191: q BINPUT 8 - 193: R REDUCE - 194: q BINPUT 9 - 196: } EMPTY_DICT - 197: q BINPUT 10 - 199: ( MARK - 200: X BINUNICODE 'foo' - 208: q BINPUT 11 - 210: K BININT1 1 - 212: X BINUNICODE 'bar' - 220: q BINPUT 12 - 222: K BININT1 2 - 224: u SETITEMS (MARK at 199) - 225: b BUILD - 226: h BINGET 9 - 228: t TUPLE (MARK at 112) - 229: q BINPUT 13 - 231: h BINGET 13 - 233: K BININT1 5 - 235: e APPENDS (MARK at 3) - 236: . STOP + 35: q BINPUT 1 + 37: ( MARK + 38: G BINFLOAT 3.0 + 47: G BINFLOAT 0.0 + 56: t TUPLE (MARK at 37) + 57: q BINPUT 2 + 59: R REDUCE + 60: q BINPUT 3 + 62: K BININT1 1 + 64: J BININT -1 + 69: K BININT1 255 + 71: J BININT -255 + 76: J BININT -256 + 81: M BININT2 65535 + 84: J BININT -65535 + 89: J BININT -65536 + 94: J BININT 2147483647 + 99: J BININT -2147483647 + 104: J BININT -2147483648 + 109: ( MARK + 110: X BINUNICODE 'abc' + 118: q BINPUT 4 + 120: h BINGET 4 + 122: c GLOBAL 'copyreg _reconstructor' + 146: q BINPUT 5 + 148: ( MARK + 149: c GLOBAL '__main__ C' + 161: q BINPUT 6 + 163: c GLOBAL 'builtins object' + 180: q BINPUT 7 + 182: N NONE + 183: t TUPLE (MARK at 148) + 184: q BINPUT 8 + 186: R REDUCE + 187: q BINPUT 9 + 189: } EMPTY_DICT + 190: q BINPUT 10 + 192: ( MARK + 193: X BINUNICODE 'foo' + 201: q BINPUT 11 + 203: K BININT1 1 + 205: X BINUNICODE 'bar' + 213: q BINPUT 12 + 215: K BININT1 2 + 217: u SETITEMS (MARK at 192) + 218: b BUILD + 219: h BINGET 9 + 221: t TUPLE (MARK at 109) + 222: q BINPUT 13 + 224: h BINGET 13 + 226: K BININT1 5 + 228: e APPENDS (MARK at 3) + 229: . STOP highest protocol among opcodes = 1 """ @@ -293,51 +293,51 @@ DATA2_DIS = """\ 8: K BININT1 1 10: G BINFLOAT 2.0 19: c GLOBAL 'builtins complex' - 40: q BINPUT 1 - 42: G BINFLOAT 3.0 - 51: G BINFLOAT 0.0 - 60: \x86 TUPLE2 - 61: q BINPUT 2 - 63: R REDUCE - 64: q BINPUT 3 - 66: K BININT1 1 - 68: J BININT -1 - 73: K BININT1 255 - 75: J BININT -255 - 80: J BININT -256 - 85: M BININT2 65535 - 88: J BININT -65535 - 93: J BININT -65536 - 98: J BININT 2147483647 - 103: J BININT -2147483647 - 108: J BININT -2147483648 - 113: ( MARK - 114: X BINUNICODE 'abc' - 122: q BINPUT 4 - 124: h BINGET 4 - 126: c GLOBAL '__main__ C' - 138: q BINPUT 5 - 140: ) EMPTY_TUPLE - 141: \x81 NEWOBJ - 142: q BINPUT 6 - 144: } EMPTY_DICT - 145: q BINPUT 7 - 147: ( MARK - 148: X BINUNICODE 'foo' - 156: q BINPUT 8 - 158: K BININT1 1 - 160: X BINUNICODE 'bar' - 168: q BINPUT 9 - 170: K BININT1 2 - 172: u SETITEMS (MARK at 147) - 173: b BUILD - 174: h BINGET 6 - 176: t TUPLE (MARK at 113) - 177: q BINPUT 10 - 179: h BINGET 10 - 181: K BININT1 5 - 183: e APPENDS (MARK at 5) - 184: . STOP + 37: q BINPUT 1 + 39: G BINFLOAT 3.0 + 48: G BINFLOAT 0.0 + 57: \x86 TUPLE2 + 58: q BINPUT 2 + 60: R REDUCE + 61: q BINPUT 3 + 63: K BININT1 1 + 65: J BININT -1 + 70: K BININT1 255 + 72: J BININT -255 + 77: J BININT -256 + 82: M BININT2 65535 + 85: J BININT -65535 + 90: J BININT -65536 + 95: J BININT 2147483647 + 100: J BININT -2147483647 + 105: J BININT -2147483648 + 110: ( MARK + 111: X BINUNICODE 'abc' + 119: q BINPUT 4 + 121: h BINGET 4 + 123: c GLOBAL '__main__ C' + 135: q BINPUT 5 + 137: ) EMPTY_TUPLE + 138: \x81 NEWOBJ + 139: q BINPUT 6 + 141: } EMPTY_DICT + 142: q BINPUT 7 + 144: ( MARK + 145: X BINUNICODE 'foo' + 153: q BINPUT 8 + 155: K BININT1 1 + 157: X BINUNICODE 'bar' + 165: q BINPUT 9 + 167: K BININT1 2 + 169: u SETITEMS (MARK at 144) + 170: b BUILD + 171: h BINGET 6 + 173: t TUPLE (MARK at 110) + 174: q BINPUT 10 + 176: h BINGET 10 + 178: K BININT1 5 + 180: e APPENDS (MARK at 5) + 181: . STOP highest protocol among opcodes = 2 """ @@ -707,14 +707,14 @@ class AbstractPickleTests(unittest.TestCase): self.assertEqual(B(x), B(y), 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 # (EXT[124]) under proto 2, and not in proto 1. def produce_global_ext(self, extcode, opcode): e = ExtensionSaver(extcode) try: - copy_reg.add_extension(__name__, "MyList", extcode) + copyreg.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 bbc81bc..f87b8a8 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -676,7 +676,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 copy_reg, _abcoll + import copyreg, _abcoll if not hasattr(sys, 'gettotalrefcount'): raise Exception("Tracking reference leaks requires a debug build " @@ -684,7 +684,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks): # Save current values for dash_R_cleanup() to restore. fs = warnings.filters[:] - ps = copy_reg.dispatch_table.copy() + ps = copyreg.dispatch_table.copy() pic = sys.path_importer_cache.copy() abcs = {} for abc in [getattr(_abcoll, a) for a in _abcoll.__all__]: @@ -724,7 +724,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks): refrep.close() def dash_R_cleanup(fs, ps, pic, abcs): - import gc, copy_reg + import gc, copyreg import _strptime, linecache import urlparse, urllib, urllib2, mimetypes, doctest import struct, filecmp, _abcoll @@ -738,8 +738,8 @@ def dash_R_cleanup(fs, ps, pic, abcs): # Restore some original values. warnings.filters[:] = fs - copy_reg.dispatch_table.clear() - copy_reg.dispatch_table.update(ps) + copyreg.dispatch_table.clear() + copyreg.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 52b51db..3ba23de 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -53,7 +53,7 @@ class AllTest(unittest.TestCase): self.check_all("commands") self.check_all("compileall") self.check_all("copy") - self.check_all("copy_reg") + self.check_all("copyreg") 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 8b50e47..182b8c3 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 copy_reg +import copyreg 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) - copy_reg.pickle(C, pickle_C, C) + copyreg.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) - copy_reg.pickle(C, pickle_C, C) + copyreg.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 deleted file mode 100644 index 34ca4ec..0000000 --- a/Lib/test/test_copy_reg.py +++ /dev/null @@ -1,121 +0,0 @@ -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, 0x80000000: - 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 new file mode 100644 index 0000000..82f6c94 --- /dev/null +++ b/Lib/test/test_copyreg.py @@ -0,0 +1,121 @@ +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, 0x80000000: + 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/Misc/NEWS b/Misc/NEWS index 4ad6137..cdf0054 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,8 @@ Extension Modules Library ------- +- The copy_reg module has been renamed to copyreg. + - The mhlib module has been removed. - The ihooks module has been removed. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index 497d4e6..ecd4b83 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -3091,7 +3091,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("copy_reg"); + copyreg = PyImport_ImportModuleNoBlock("copyreg"); if (copyreg != NULL) { PyObject *func, *pickler; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2d12a8b..8880cab 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2941,31 +2941,31 @@ static PyGetSetDef object_getsets[] = { /* 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 - calculating the list of slot names (done only once per class) - the __newobj__ function (which is used as a token but never called) */ static PyObject * -import_copy_reg(void) +import_copyreg(void) { - static PyObject *copy_reg_str; + static PyObject *copyreg_str; - if (!copy_reg_str) { - copy_reg_str = PyUnicode_InternFromString("copy_reg"); - if (copy_reg_str == NULL) + if (!copyreg_str) { + copyreg_str = PyUnicode_InternFromString("copyreg"); + if (copyreg_str == NULL) return NULL; } - return PyImport_Import(copy_reg_str); + return PyImport_Import(copyreg_str); } static PyObject * slotnames(PyObject *cls) { PyObject *clsdict; - PyObject *copy_reg; + PyObject *copyreg; PyObject *slotnames; if (!PyType_Check(cls)) { @@ -2980,18 +2980,18 @@ slotnames(PyObject *cls) return slotnames; } - copy_reg = import_copy_reg(); - if (copy_reg == NULL) + copyreg = import_copyreg(); + if (copyreg == NULL) return NULL; - slotnames = PyObject_CallMethod(copy_reg, "_slotnames", "O", cls); - Py_DECREF(copy_reg); + slotnames = PyObject_CallMethod(copyreg, "_slotnames", "O", cls); + Py_DECREF(copyreg); if (slotnames != NULL && slotnames != Py_None && !PyList_Check(slotnames)) { PyErr_SetString(PyExc_TypeError, - "copy_reg._slotnames didn't return a list or None"); + "copyreg._slotnames didn't return a list or None"); Py_DECREF(slotnames); slotnames = NULL; } @@ -3006,7 +3006,7 @@ reduce_2(PyObject *obj) PyObject *args = NULL, *args2 = NULL; PyObject *getstate = NULL, *state = NULL, *names = 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; cls = PyObject_GetAttrString(obj, "__class__"); @@ -3105,10 +3105,10 @@ reduce_2(PyObject *obj) goto end; } - copy_reg = import_copy_reg(); - if (copy_reg == NULL) + copyreg = import_copyreg(); + if (copyreg == NULL) goto end; - newobj = PyObject_GetAttrString(copy_reg, "__newobj__"); + newobj = PyObject_GetAttrString(copyreg, "__newobj__"); if (newobj == NULL) goto end; @@ -3135,7 +3135,7 @@ reduce_2(PyObject *obj) Py_XDECREF(names); Py_XDECREF(listitems); Py_XDECREF(dictitems); - Py_XDECREF(copy_reg); + Py_XDECREF(copyreg); Py_XDECREF(newobj); return res; } @@ -3158,17 +3158,17 @@ reduce_2(PyObject *obj) static PyObject * _common_reduce(PyObject *self, int proto) { - PyObject *copy_reg, *res; + PyObject *copyreg, *res; if (proto >= 2) return reduce_2(self); - copy_reg = import_copy_reg(); - if (!copy_reg) + copyreg = import_copyreg(); + if (!copyreg) return NULL; - res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto); - Py_DECREF(copy_reg); + res = PyEval_CallMethod(copyreg, "_reduce_ex", "(Oi)", self, proto); + Py_DECREF(copyreg); return res; } -- cgit v0.12