diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-06-13 13:58:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-13 13:58:51 +0200 |
commit | 63ab4ba07b492448844940c347787ba30735b7f2 (patch) | |
tree | e76e84e6bd8355398833353bf9afdf6f2a1b6da8 /Lib/pickle.py | |
parent | 6f75c873752a16a7ad8f35855b1e29f59d048e84 (diff) | |
download | cpython-git-63ab4ba07b492448844940c347787ba30735b7f2.tar.gz |
bpo-37210: Fix pure Python pickle when _pickle is unavailable (GH-14016)
Allow pure Python implementation of pickle to work
even when the C _pickle module is unavailable.
Fix test_pickle when _pickle is missing: declare PyPicklerHookTests
outside "if has_c_implementation:" block.
Diffstat (limited to 'Lib/pickle.py')
-rw-r--r-- | Lib/pickle.py | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py index a67ac7dd8b..71aa57d500 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -36,10 +36,16 @@ import io import codecs import _compat_pickle -from _pickle import PickleBuffer - __all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler", - "Unpickler", "dump", "dumps", "load", "loads", "PickleBuffer"] + "Unpickler", "dump", "dumps", "load", "loads"] + +try: + from _pickle import PickleBuffer + __all__.append("PickleBuffer") + _HAVE_PICKLE_BUFFER = True +except ImportError: + _HAVE_PICKLE_BUFFER = False + # Shortcut for use in isinstance testing bytes_types = (bytes, bytearray) @@ -812,31 +818,32 @@ class _Pickler: self.write(BYTEARRAY8 + pack("<Q", n) + obj) dispatch[bytearray] = save_bytearray - def save_picklebuffer(self, obj): - if self.proto < 5: - raise PicklingError("PickleBuffer can only pickled with " - "protocol >= 5") - with obj.raw() as m: - if not m.contiguous: - raise PicklingError("PickleBuffer can not be pickled when " - "pointing to a non-contiguous buffer") - in_band = True - if self._buffer_callback is not None: - in_band = bool(self._buffer_callback(obj)) - if in_band: - # Write data in-band - # XXX The C implementation avoids a copy here - if m.readonly: - self.save_bytes(m.tobytes()) + if _HAVE_PICKLE_BUFFER: + def save_picklebuffer(self, obj): + if self.proto < 5: + raise PicklingError("PickleBuffer can only pickled with " + "protocol >= 5") + with obj.raw() as m: + if not m.contiguous: + raise PicklingError("PickleBuffer can not be pickled when " + "pointing to a non-contiguous buffer") + in_band = True + if self._buffer_callback is not None: + in_band = bool(self._buffer_callback(obj)) + if in_band: + # Write data in-band + # XXX The C implementation avoids a copy here + if m.readonly: + self.save_bytes(m.tobytes()) + else: + self.save_bytearray(m.tobytes()) else: - self.save_bytearray(m.tobytes()) - else: - # Write data out-of-band - self.write(NEXT_BUFFER) - if m.readonly: - self.write(READONLY_BUFFER) + # Write data out-of-band + self.write(NEXT_BUFFER) + if m.readonly: + self.write(READONLY_BUFFER) - dispatch[PickleBuffer] = save_picklebuffer + dispatch[PickleBuffer] = save_picklebuffer def save_str(self, obj): if self.bin: |