| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -829,6 +829,9 @@ they can have object code that is not dependent on Python compilation flags. | |||
| 829 | 829 | PyAPI_FUNC(void) Py_IncRef(PyObject *); | |
| 830 | 830 | PyAPI_FUNC(void) Py_DecRef(PyObject *); | |
| 831 | 831 | ||
| 832 | + PyAPI_DATA(PyTypeObject) PyNone_Type; | ||
| 833 | + PyAPI_DATA(PyTypeObject) PyNotImplemented_Type; | ||
| 834 | + | ||
| 832 | 835 | /* | |
| 833 | 836 | _Py_NoneStruct is an object of undefined type which can be used in contexts | |
| 834 | 837 | where NULL (nil) is not suitable (since NULL often means 'error'). | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -954,8 +954,17 @@ def save_global(self, obj, name=None): | |||
| 954 | 954 | ||
| 955 | 955 | self.memoize(obj) | |
| 956 | 956 | ||
| 957 | + def save_type(self, obj): | ||
| 958 | + if obj is type(None): | ||
| 959 | + return self.save_reduce(type, (None,), obj=obj) | ||
| 960 | + elif obj is type(NotImplemented): | ||
| 961 | + return self.save_reduce(type, (NotImplemented,), obj=obj) | ||
| 962 | + elif obj is type(...): | ||
| 963 | + return self.save_reduce(type, (...,), obj=obj) | ||
| 964 | + return self.save_global(obj) | ||
| 965 | + | ||
| 957 | 966 | dispatch[FunctionType] = save_global | |
| 958 | - dispatch[type] = save_global | ||
| 967 | + dispatch[type] = save_type | ||
| 959 | 968 | ||
| 960 | 969 | ||
| 961 | 970 | # Unpickling machinery | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -804,6 +804,15 @@ def test_notimplemented(self): | |||
| 804 | 804 | u = self.loads(s) | |
| 805 | 805 | self.assertIs(NotImplemented, u) | |
| 806 | 806 | ||
| 807 | + def test_singleton_types(self): | ||
| 808 | + # Issue #6477: Test that types of built-in singletons can be pickled. | ||
| 809 | + singletons = [None, ..., NotImplemented] | ||
| 810 | + for singleton in singletons: | ||
| 811 | + for proto in protocols: | ||
| 812 | + s = self.dumps(type(singleton), proto) | ||
| 813 | + u = self.loads(s) | ||
| 814 | + self.assertIs(type(singleton), u) | ||
| 815 | + | ||
| 807 | 816 | # Tests for protocol 2 | |
| 808 | 817 | ||
| 809 | 818 | def test_proto(self): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,6 +33,9 @@ Library | |||
| 33 | 33 | - Fixed _pickle.Unpickler to not fail when loading empty strings as | |
| 34 | 34 | persistent IDs. | |
| 35 | 35 | ||
| 36 | + - Issue #6477: Added support for pickling the types of built-in singletons | ||
| 37 | + (i.e., Ellipsis, NotImplemented, None). | ||
| 38 | + | ||
| 36 | 39 | - ssl.create_default_context() sets OP_NO_COMPRESSION to prevent CRIME. | |
| 37 | 40 | ||
| 38 | 41 | - Issue #19802: Add socket.SO_PRIORITY. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3287,6 +3287,36 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name) | |||
| 3287 | 3287 | return status; | |
| 3288 | 3288 | } | |
| 3289 | 3289 | ||
| 3290 | + static int | ||
| 3291 | + save_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton) | ||
| 3292 | + { | ||
| 3293 | + PyObject *reduce_value; | ||
| 3294 | + int status; | ||
| 3295 | + | ||
| 3296 | + reduce_value = Py_BuildValue("O(O)", &PyType_Type, singleton); | ||
| 3297 | + if (reduce_value == NULL) { | ||
| 3298 | + return -1; | ||
| 3299 | + } | ||
| 3300 | + status = save_reduce(self, reduce_value, obj); | ||
| 3301 | + Py_DECREF(reduce_value); | ||
| 3302 | + return status; | ||
| 3303 | + } | ||
| 3304 | + | ||
| 3305 | + static int | ||
| 3306 | + save_type(PicklerObject *self, PyObject *obj) | ||
| 3307 | + { | ||
| 3308 | + if (obj == (PyObject *)&PyNone_Type) { | ||
| 3309 | + return save_singleton_type(self, obj, Py_None); | ||
| 3310 | + } | ||
| 3311 | + else if (obj == (PyObject *)&PyEllipsis_Type) { | ||
| 3312 | + return save_singleton_type(self, obj, Py_Ellipsis); | ||
| 3313 | + } | ||
| 3314 | + else if (obj == (PyObject *)&PyNotImplemented_Type) { | ||
| 3315 | + return save_singleton_type(self, obj, Py_NotImplemented); | ||
| 3316 | + } | ||
| 3317 | + return save_global(self, obj, NULL); | ||
| 3318 | + } | ||
| 3319 | + | ||
| 3290 | 3320 | static int | |
| 3291 | 3321 | save_pers(PicklerObject *self, PyObject *obj, PyObject *func) | |
| 3292 | 3322 | { | |
@@ -3696,7 +3726,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save) | |||
| 3696 | 3726 | goto done; | |
| 3697 | 3727 | } | |
| 3698 | 3728 | else if (type == &PyType_Type) { | |
| 3699 | - status = save_global(self, obj, NULL); | ||
| 3729 | + status = save_type(self, obj); | ||
| 3700 | 3730 | goto done; | |
| 3701 | 3731 | } | |
| 3702 | 3732 | else if (type == &PyFunction_Type) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1409,7 +1409,7 @@ static PyNumberMethods none_as_number = { | |||
| 1409 | 1409 | 0, /* nb_index */ | |
| 1410 | 1410 | }; | |
| 1411 | 1411 | ||
| 1412 | - static PyTypeObject PyNone_Type = { | ||
| 1412 | + PyTypeObject PyNone_Type = { | ||
| 1413 | 1413 | PyVarObject_HEAD_INIT(&PyType_Type, 0) | |
| 1414 | 1414 | "NoneType", | |
| 1415 | 1415 | 0, | |
@@ -1494,7 +1494,7 @@ notimplemented_dealloc(PyObject* ignore) | |||
| 1494 | 1494 | Py_FatalError("deallocating NotImplemented"); | |
| 1495 | 1495 | } | |
| 1496 | 1496 | ||
| 1497 | - static PyTypeObject PyNotImplemented_Type = { | ||
| 1497 | + PyTypeObject PyNotImplemented_Type = { | ||
| 1498 | 1498 | PyVarObject_HEAD_INIT(&PyType_Type, 0) | |
| 1499 | 1499 | "NotImplementedType", | |
| 1500 | 1500 | 0, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments