Repository: imankulov/pickle-compat (language: python)

Issue:
PY2: TypeError: unbound method load_newobj() must be called with CompatUnpickler instance as first argument (got Unpickler instance instead)
Ubuntu 20.04, Python2.7
```
version: python2.7-pickle
         pickle-compat==2.1.0
```
```python2
import pickle
import pickle_compat
pickle_compat.unpatch()
s = ".........\x81......"
#   If there is this format('\x81') in the data, an error will be generated.   NEWOBJ = '\x81'
>>> pickle.loads(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/pickle.py", line 1388, in loads
    return Unpickler(file).load()
  File "/usr/lib/python2.7/pickle.py", line 864, in load
    dispatch[key](self)
TypeError: unbound method load_newobj() must be called with CompatUnpickler instance as first argument (got Unpickler instance instead)
```


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 11ea0c9..ea2fc0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 All notable changes to this project will be documented in this file.
 
+## UNRELEASED
+
+- Fix TypeError() on loading objects after `pickle_compat.unpatch()`
+
 ## [2.1.0] - 2020-12-28
 
 Add compatibility with Python 3.7 and 3.9
diff --git a/pickle_compat/compat.py b/pickle_compat/compat.py
index b13539d..b18cd8e 100644
--- a/pickle_compat/compat.py
+++ b/pickle_compat/compat.py
@@ -57,9 +57,10 @@ def load_newobj(self):
 
     # We also need to explicitly register our own handler in the dispatcher, because
     # otherwise a method of the superclass will be called
-    CompatUnpickler.dispatch[  # type: ignore
-        pickle.NEWOBJ
-    ] = CompatUnpickler.load_newobj
+    CompatUnpickler.dispatch = VanillaUnpickler.dispatch.copy()  # type: ignore
+    CompatUnpickler.dispatch[
+        pickle.NEWOBJ  # type: ignore
+    ] = CompatUnpickler.load_newobj  # type: ignore
 
     # Forward-compatible load and loads, nothing is needed to be patched
     compat_load = pickle.load  # type: ignore


Test patch:
diff --git a/tests/test_pickle_compat.py b/tests/test_pickle_compat.py
index 93ce589..6b0bd7d 100644
--- a/tests/test_pickle_compat.py
+++ b/tests/test_pickle_compat.py
@@ -82,3 +82,14 @@ def test_namedtuple(get_fixture):
 
 def test_dict_subclass(get_fixture):
     assert pickle.loads(get_fixture("dict_subclass")) == {u"foo": 1}
+
+
+class Foo(object):
+    pass
+
+
+def test_loads_after_unpatch():
+    serialized = pickle.dumps(Foo())
+    unpatch()
+    foo = pickle.loads(serialized)
+    assert isinstance(foo, Foo)