mirror of
https://github.com/python/cpython.git
synced 2025-10-01 12:52:18 +00:00
Merge
This commit is contained in:
commit
dcbe46bc5b
4 changed files with 54 additions and 15 deletions
|
@ -212,6 +212,8 @@ Standard names are defined for the following types:
|
||||||
keys = sorted(self.__dict__)
|
keys = sorted(self.__dict__)
|
||||||
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
|
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
|
||||||
return "{}({})".format(type(self).__name__, ", ".join(items))
|
return "{}({})".format(type(self).__name__, ", ".join(items))
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.__dict__ == other.__dict__
|
||||||
|
|
||||||
``SimpleNamespace`` may be useful as a replacement for ``class NS: pass``.
|
``SimpleNamespace`` may be useful as a replacement for ``class NS: pass``.
|
||||||
However, for a structured record type use :func:`~collections.namedtuple`
|
However, for a structured record type use :func:`~collections.namedtuple`
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
from test.support import run_unittest, run_with_locale
|
from test.support import run_unittest, run_with_locale
|
||||||
import collections
|
import collections
|
||||||
|
import pickle
|
||||||
import locale
|
import locale
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
@ -1077,9 +1078,19 @@ class SimpleNamespaceTests(unittest.TestCase):
|
||||||
ns2 = types.SimpleNamespace()
|
ns2 = types.SimpleNamespace()
|
||||||
ns2.x = "spam"
|
ns2.x = "spam"
|
||||||
ns2._y = 5
|
ns2._y = 5
|
||||||
|
name = "namespace"
|
||||||
|
|
||||||
self.assertEqual(repr(ns1), "namespace(w=3, x=1, y=2)")
|
self.assertEqual(repr(ns1), "{name}(w=3, x=1, y=2)".format(name=name))
|
||||||
self.assertEqual(repr(ns2), "namespace(_y=5, x='spam')")
|
self.assertEqual(repr(ns2), "{name}(_y=5, x='spam')".format(name=name))
|
||||||
|
|
||||||
|
def test_equal(self):
|
||||||
|
ns1 = types.SimpleNamespace(x=1)
|
||||||
|
ns2 = types.SimpleNamespace()
|
||||||
|
ns2.x = 1
|
||||||
|
|
||||||
|
self.assertEqual(types.SimpleNamespace(), types.SimpleNamespace())
|
||||||
|
self.assertEqual(ns1, ns2)
|
||||||
|
self.assertNotEqual(ns2, types.SimpleNamespace())
|
||||||
|
|
||||||
def test_nested(self):
|
def test_nested(self):
|
||||||
ns1 = types.SimpleNamespace(a=1, b=2)
|
ns1 = types.SimpleNamespace(a=1, b=2)
|
||||||
|
@ -1117,11 +1128,12 @@ class SimpleNamespaceTests(unittest.TestCase):
|
||||||
ns1.spam = ns1
|
ns1.spam = ns1
|
||||||
ns2.spam = ns3
|
ns2.spam = ns3
|
||||||
ns3.spam = ns2
|
ns3.spam = ns2
|
||||||
|
name = "namespace"
|
||||||
|
repr1 = "{name}(c='cookie', spam={name}(...))".format(name=name)
|
||||||
|
repr2 = "{name}(spam={name}(spam={name}(...), x=1))".format(name=name)
|
||||||
|
|
||||||
self.assertEqual(repr(ns1),
|
self.assertEqual(repr(ns1), repr1)
|
||||||
"namespace(c='cookie', spam=namespace(...))")
|
self.assertEqual(repr(ns2), repr2)
|
||||||
self.assertEqual(repr(ns2),
|
|
||||||
"namespace(spam=namespace(spam=namespace(...), x=1))")
|
|
||||||
|
|
||||||
def test_as_dict(self):
|
def test_as_dict(self):
|
||||||
ns = types.SimpleNamespace(spam='spamspamspam')
|
ns = types.SimpleNamespace(spam='spamspamspam')
|
||||||
|
@ -1144,6 +1156,14 @@ class SimpleNamespaceTests(unittest.TestCase):
|
||||||
self.assertIs(type(spam), Spam)
|
self.assertIs(type(spam), Spam)
|
||||||
self.assertEqual(vars(spam), {'ham': 8, 'eggs': 9})
|
self.assertEqual(vars(spam), {'ham': 8, 'eggs': 9})
|
||||||
|
|
||||||
|
def test_pickle(self):
|
||||||
|
ns = types.SimpleNamespace(breakfast="spam", lunch="spam")
|
||||||
|
|
||||||
|
ns_pickled = pickle.dumps(ns)
|
||||||
|
ns_roundtrip = pickle.loads(ns_pickled)
|
||||||
|
|
||||||
|
self.assertEqual(ns, ns_roundtrip)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
run_unittest(TypesTests, MappingProxyTests, ClassCreationTests,
|
run_unittest(TypesTests, MappingProxyTests, ClassCreationTests,
|
||||||
|
|
|
@ -252,6 +252,8 @@ Core and Builtins
|
||||||
- Issue #15111: __import__ should propagate ImportError when raised as a
|
- Issue #15111: __import__ should propagate ImportError when raised as a
|
||||||
side-effect of a module triggered from using fromlist.
|
side-effect of a module triggered from using fromlist.
|
||||||
|
|
||||||
|
- Issue #15022: Add pickle and comparison support to types.SimpleNamespace.
|
||||||
|
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -66,16 +66,20 @@ namespace_dealloc(_PyNamespaceObject *ns)
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
namespace_repr(_PyNamespaceObject *ns)
|
namespace_repr(PyObject *ns)
|
||||||
{
|
{
|
||||||
int i, loop_error = 0;
|
int i, loop_error = 0;
|
||||||
PyObject *pairs = NULL, *d = NULL, *keys = NULL, *keys_iter = NULL;
|
PyObject *pairs = NULL, *d = NULL, *keys = NULL, *keys_iter = NULL;
|
||||||
PyObject *key;
|
PyObject *key;
|
||||||
PyObject *separator, *pairsrepr, *repr = NULL;
|
PyObject *separator, *pairsrepr, *repr = NULL;
|
||||||
|
const char * name;
|
||||||
|
|
||||||
i = Py_ReprEnter((PyObject *)ns);
|
name = (Py_TYPE(ns) == &_PyNamespace_Type) ? "namespace"
|
||||||
|
: ns->ob_type->tp_name;
|
||||||
|
|
||||||
|
i = Py_ReprEnter(ns);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
return i > 0 ? PyUnicode_FromString("namespace(...)") : NULL;
|
return i > 0 ? PyUnicode_FromFormat("%s(...)", name) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pairs = PyList_New(0);
|
pairs = PyList_New(0);
|
||||||
|
@ -127,8 +131,7 @@ namespace_repr(_PyNamespaceObject *ns)
|
||||||
if (pairsrepr == NULL)
|
if (pairsrepr == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
repr = PyUnicode_FromFormat("%s(%S)",
|
repr = PyUnicode_FromFormat("%s(%S)", name, pairsrepr);
|
||||||
((PyObject *)ns)->ob_type->tp_name, pairsrepr);
|
|
||||||
Py_DECREF(pairsrepr);
|
Py_DECREF(pairsrepr);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -136,7 +139,7 @@ error:
|
||||||
Py_XDECREF(d);
|
Py_XDECREF(d);
|
||||||
Py_XDECREF(keys);
|
Py_XDECREF(keys);
|
||||||
Py_XDECREF(keys_iter);
|
Py_XDECREF(keys_iter);
|
||||||
Py_ReprLeave((PyObject *)ns);
|
Py_ReprLeave(ns);
|
||||||
|
|
||||||
return repr;
|
return repr;
|
||||||
}
|
}
|
||||||
|
@ -158,14 +161,26 @@ namespace_clear(_PyNamespaceObject *ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
namespace_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
|
{
|
||||||
|
if (PyObject_IsInstance(self, (PyObject *)&_PyNamespace_Type) &&
|
||||||
|
PyObject_IsInstance(other, (PyObject *)&_PyNamespace_Type))
|
||||||
|
return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict,
|
||||||
|
((_PyNamespaceObject *)other)->ns_dict, op);
|
||||||
|
Py_INCREF(Py_NotImplemented);
|
||||||
|
return Py_NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(namespace_doc,
|
PyDoc_STRVAR(namespace_doc,
|
||||||
"A simple attribute-based namespace.\n\
|
"A simple attribute-based namespace.\n\
|
||||||
\n\
|
\n\
|
||||||
namespace(**kwargs)");
|
SimpleNamespace(**kwargs)");
|
||||||
|
|
||||||
PyTypeObject _PyNamespace_Type = {
|
PyTypeObject _PyNamespace_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"namespace", /* tp_name */
|
"types.SimpleNamespace", /* tp_name */
|
||||||
sizeof(_PyNamespaceObject), /* tp_size */
|
sizeof(_PyNamespaceObject), /* tp_size */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
(destructor)namespace_dealloc, /* tp_dealloc */
|
(destructor)namespace_dealloc, /* tp_dealloc */
|
||||||
|
@ -188,7 +203,7 @@ PyTypeObject _PyNamespace_Type = {
|
||||||
namespace_doc, /* tp_doc */
|
namespace_doc, /* tp_doc */
|
||||||
(traverseproc)namespace_traverse, /* tp_traverse */
|
(traverseproc)namespace_traverse, /* tp_traverse */
|
||||||
(inquiry)namespace_clear, /* tp_clear */
|
(inquiry)namespace_clear, /* tp_clear */
|
||||||
0, /* tp_richcompare */
|
namespace_richcompare, /* tp_richcompare */
|
||||||
0, /* tp_weaklistoffset */
|
0, /* tp_weaklistoffset */
|
||||||
0, /* tp_iter */
|
0, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue