Fred Drake | 78a6a36 | 2000-10-11 22:16:45 +0000 | [diff] [blame] | 1 | """Helper to provide extensibility for pickle/cPickle. |
| 2 | |
| 3 | This is only useful to add pickle support for extension types defined in |
| 4 | C, not for instances of user-defined classes. |
| 5 | """ |
| 6 | |
| 7 | from types import ClassType as _ClassType |
Guido van Rossum | 72be306 | 1997-05-20 18:03:22 +0000 | [diff] [blame] | 8 | |
Skip Montanaro | e99d5ea | 2001-01-20 19:54:20 +0000 | [diff] [blame] | 9 | __all__ = ["pickle","constructor"] |
| 10 | |
Guido van Rossum | 4706562 | 1997-04-09 17:44:11 +0000 | [diff] [blame] | 11 | dispatch_table = {} |
| 12 | safe_constructors = {} |
| 13 | |
Fred Drake | 78a6a36 | 2000-10-11 22:16:45 +0000 | [diff] [blame] | 14 | def pickle(ob_type, pickle_function, constructor_ob=None): |
| 15 | if type(ob_type) is _ClassType: |
| 16 | raise TypeError("copy_reg is not intended for use with classes") |
| 17 | |
| 18 | if not callable(pickle_function): |
| 19 | raise TypeError("reduction functions must be callable") |
Guido van Rossum | 4706562 | 1997-04-09 17:44:11 +0000 | [diff] [blame] | 20 | dispatch_table[ob_type] = pickle_function |
| 21 | |
Guido van Rossum | 72be306 | 1997-05-20 18:03:22 +0000 | [diff] [blame] | 22 | if constructor_ob is not None: |
Guido van Rossum | 4706562 | 1997-04-09 17:44:11 +0000 | [diff] [blame] | 23 | constructor(constructor_ob) |
| 24 | |
| 25 | def constructor(object): |
Fred Drake | 78a6a36 | 2000-10-11 22:16:45 +0000 | [diff] [blame] | 26 | if not callable(object): |
| 27 | raise TypeError("constructors must be callable") |
Guido van Rossum | 4706562 | 1997-04-09 17:44:11 +0000 | [diff] [blame] | 28 | safe_constructors[object] = 1 |
| 29 | |
Guido van Rossum | 72be306 | 1997-05-20 18:03:22 +0000 | [diff] [blame] | 30 | # Example: provide pickling support for complex numbers. |
Guido van Rossum | 4706562 | 1997-04-09 17:44:11 +0000 | [diff] [blame] | 31 | |
Guido van Rossum | 72be306 | 1997-05-20 18:03:22 +0000 | [diff] [blame] | 32 | def pickle_complex(c): |
| 33 | return complex, (c.real, c.imag) |
| 34 | |
| 35 | pickle(type(1j), pickle_complex, complex) |
Guido van Rossum | 3926a63 | 2001-09-25 16:25:58 +0000 | [diff] [blame] | 36 | |
| 37 | # Support for picking new-style objects |
| 38 | |
Guido van Rossum | 3926a63 | 2001-09-25 16:25:58 +0000 | [diff] [blame] | 39 | def _reconstructor(cls, base, state): |
Guido van Rossum | 698acf9 | 2001-09-25 19:46:05 +0000 | [diff] [blame] | 40 | obj = base.__new__(cls, state) |
| 41 | base.__init__(obj, state) |
Guido van Rossum | 3926a63 | 2001-09-25 16:25:58 +0000 | [diff] [blame] | 42 | return obj |
| 43 | _reconstructor.__safe_for_unpickling__ = 1 |
| 44 | |
| 45 | _HEAPTYPE = 1<<9 |
| 46 | |
| 47 | def _reduce(self): |
| 48 | for base in self.__class__.__mro__: |
Guido van Rossum | 00fb0c9 | 2001-11-24 21:04:31 +0000 | [diff] [blame] | 49 | if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE: |
Guido van Rossum | 3926a63 | 2001-09-25 16:25:58 +0000 | [diff] [blame] | 50 | break |
| 51 | else: |
| 52 | base = object # not really reachable |
| 53 | if base is object: |
| 54 | state = None |
| 55 | else: |
Guido van Rossum | 2a6f5b3 | 2001-12-27 16:27:28 +0000 | [diff] [blame] | 56 | if base is self.__class__: |
| 57 | raise TypeError, "can't pickle %s objects" % base.__name__ |
Guido van Rossum | 3926a63 | 2001-09-25 16:25:58 +0000 | [diff] [blame] | 58 | state = base(self) |
Guido van Rossum | 6cef6d5 | 2001-09-28 18:13:29 +0000 | [diff] [blame] | 59 | args = (self.__class__, base, state) |
| 60 | try: |
Guido van Rossum | 00fb0c9 | 2001-11-24 21:04:31 +0000 | [diff] [blame] | 61 | getstate = self.__getstate__ |
Guido van Rossum | 6cef6d5 | 2001-09-28 18:13:29 +0000 | [diff] [blame] | 62 | except AttributeError: |
Guido van Rossum | 00fb0c9 | 2001-11-24 21:04:31 +0000 | [diff] [blame] | 63 | try: |
| 64 | dict = self.__dict__ |
| 65 | except AttributeError: |
| 66 | dict = None |
| 67 | else: |
| 68 | dict = getstate() |
Guido van Rossum | 6cef6d5 | 2001-09-28 18:13:29 +0000 | [diff] [blame] | 69 | if dict: |
| 70 | return _reconstructor, args, dict |
| 71 | else: |
| 72 | return _reconstructor, args |