[Python-checkins] bpo-1635741: Port _sha1, _sha512, _md5 to multiphase init (GH-21818)

Mohamed Koubaa webhook-mailer at python.org
Sun Sep 6 06:10:22 EDT 2020


https://github.com/python/cpython/commit/63f102fe079ecb5cb7b921a1cf8bce4077a9d7e2
commit: 63f102fe079ecb5cb7b921a1cf8bce4077a9d7e2
branch: master
author: Mohamed Koubaa <koubaa.m at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-09-06T12:09:51+02:00
summary:

bpo-1635741: Port _sha1, _sha512, _md5 to multiphase init (GH-21818)

Port the _sha1, _sha512, and _md5 extension modules
to multi-phase initialization API (PEP 489).

files:
A Misc/NEWS.d/next/Core and Builtins/2020-08-10-16-11-32.bpo-1635741.O0d3ym.rst
M Modules/clinic/md5module.c.h
M Modules/clinic/sha1module.c.h
M Modules/clinic/sha512module.c.h
M Modules/md5module.c
M Modules/sha1module.c
M Modules/sha512module.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-10-16-11-32.bpo-1635741.O0d3ym.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-10-16-11-32.bpo-1635741.O0d3ym.rst
new file mode 100644
index 0000000000000..12af3d01ed8ef
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-10-16-11-32.bpo-1635741.O0d3ym.rst	
@@ -0,0 +1,2 @@
+Port the :mod:`_sha1`, :mod:`_sha512`, and :mod:`_md5` extension modules
+to multi-phase initialization API (:pep:`489`).
diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h
index c109f9efec6b6..4762f2800d4b8 100644
--- a/Modules/clinic/md5module.c.h
+++ b/Modules/clinic/md5module.c.h
@@ -9,15 +9,26 @@ PyDoc_STRVAR(MD5Type_copy__doc__,
 "Return a copy of the hash object.");
 
 #define MD5TYPE_COPY_METHODDEF    \
-    {"copy", (PyCFunction)MD5Type_copy, METH_NOARGS, MD5Type_copy__doc__},
+    {"copy", (PyCFunction)(void(*)(void))MD5Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, MD5Type_copy__doc__},
 
 static PyObject *
-MD5Type_copy_impl(MD5object *self);
+MD5Type_copy_impl(MD5object *self, PyTypeObject *cls);
 
 static PyObject *
-MD5Type_copy(MD5object *self, PyObject *Py_UNUSED(ignored))
+MD5Type_copy(MD5object *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
-    return MD5Type_copy_impl(self);
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = { NULL};
+    static _PyArg_Parser _parser = {":copy", _keywords, 0};
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
+        )) {
+        goto exit;
+    }
+    return_value = MD5Type_copy_impl(self, cls);
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(MD5Type_digest__doc__,
@@ -115,4 +126,4 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=dbe3abc60086f3ef input=a9049054013a1b77]*/
+/*[clinic end generated code: output=53ff7f22dbaaea36 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h
index fc37b1ab880ff..3a3ab58c1233c 100644
--- a/Modules/clinic/sha1module.c.h
+++ b/Modules/clinic/sha1module.c.h
@@ -9,15 +9,26 @@ PyDoc_STRVAR(SHA1Type_copy__doc__,
 "Return a copy of the hash object.");
 
 #define SHA1TYPE_COPY_METHODDEF    \
-    {"copy", (PyCFunction)SHA1Type_copy, METH_NOARGS, SHA1Type_copy__doc__},
+    {"copy", (PyCFunction)(void(*)(void))SHA1Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, SHA1Type_copy__doc__},
 
 static PyObject *
-SHA1Type_copy_impl(SHA1object *self);
+SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls);
 
 static PyObject *
-SHA1Type_copy(SHA1object *self, PyObject *Py_UNUSED(ignored))
+SHA1Type_copy(SHA1object *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
-    return SHA1Type_copy_impl(self);
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = { NULL};
+    static _PyArg_Parser _parser = {":copy", _keywords, 0};
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
+        )) {
+        goto exit;
+    }
+    return_value = SHA1Type_copy_impl(self, cls);
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(SHA1Type_digest__doc__,
@@ -115,4 +126,4 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=3ddd637ae17e14b3 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=abf1ab2545cea5a2 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha512module.c.h b/Modules/clinic/sha512module.c.h
index b8185b62bb669..f1192d74f9a1a 100644
--- a/Modules/clinic/sha512module.c.h
+++ b/Modules/clinic/sha512module.c.h
@@ -9,15 +9,26 @@ PyDoc_STRVAR(SHA512Type_copy__doc__,
 "Return a copy of the hash object.");
 
 #define SHA512TYPE_COPY_METHODDEF    \
-    {"copy", (PyCFunction)SHA512Type_copy, METH_NOARGS, SHA512Type_copy__doc__},
+    {"copy", (PyCFunction)(void(*)(void))SHA512Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, SHA512Type_copy__doc__},
 
 static PyObject *
-SHA512Type_copy_impl(SHAobject *self);
+SHA512Type_copy_impl(SHAobject *self, PyTypeObject *cls);
 
 static PyObject *
-SHA512Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored))
+SHA512Type_copy(SHAobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
-    return SHA512Type_copy_impl(self);
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = { NULL};
+    static _PyArg_Parser _parser = {":copy", _keywords, 0};
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
+        )) {
+        goto exit;
+    }
+    return_value = SHA512Type_copy_impl(self, cls);
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(SHA512Type_digest__doc__,
@@ -166,4 +177,4 @@ _sha512_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=bbfa72d8703c82b5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=9ff9f11937fabf35 input=a9049054013a1b77]*/
diff --git a/Modules/md5module.c b/Modules/md5module.c
index e4d9db40f22df..5cd4e94510132 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -318,22 +318,32 @@ md5_done(struct md5_state *md5, unsigned char *out)
  * ------------------------------------------------------------------------
  */
 
-static PyTypeObject MD5type;
+typedef struct {
+    PyTypeObject* md5_type;
+} MD5State;
 
+static inline MD5State*
+md5_get_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (MD5State *)state;
+}
 
 static MD5object *
-newMD5object(void)
+newMD5object(MD5State * st)
 {
-    return (MD5object *)PyObject_New(MD5object, &MD5type);
+    return (MD5object *)PyObject_New(MD5object, st->md5_type);
 }
 
-
 /* Internal methods for a hash object */
 
 static void
 MD5_dealloc(PyObject *ptr)
 {
+    PyTypeObject *tp = Py_TYPE(ptr);
     PyObject_Del(ptr);
+    Py_DECREF(tp);
 }
 
 
@@ -342,16 +352,19 @@ MD5_dealloc(PyObject *ptr)
 /*[clinic input]
 MD5Type.copy
 
+    cls: defining_class
+
 Return a copy of the hash object.
 [clinic start generated code]*/
 
 static PyObject *
-MD5Type_copy_impl(MD5object *self)
-/*[clinic end generated code: output=596eb36852f02071 input=2c09e6d2493f3079]*/
+MD5Type_copy_impl(MD5object *self, PyTypeObject *cls)
+/*[clinic end generated code: output=bf055e08244bf5ee input=d89087dcfb2a8620]*/
 {
-    MD5object *newobj;
+    MD5State *st = PyType_GetModuleState(cls);
 
-    if ((newobj = newMD5object())==NULL)
+    MD5object *newobj;
+    if ((newobj = newMD5object(st))==NULL)
         return NULL;
 
     newobj->hash_state = self->hash_state;
@@ -445,7 +458,6 @@ md5_get_digest_size(PyObject *self, void *closure)
     return PyLong_FromLong(MD5_DIGESTSIZE);
 }
 
-
 static PyGetSetDef MD5_getseters[] = {
     {"block_size",
      (getter)MD5_get_block_size, NULL,
@@ -462,40 +474,19 @@ static PyGetSetDef MD5_getseters[] = {
     {NULL}  /* Sentinel */
 };
 
-static PyTypeObject MD5type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_md5.md5",         /*tp_name*/
-    sizeof(MD5object),  /*tp_basicsize*/
-    0,                  /*tp_itemsize*/
-    /* methods */
-    MD5_dealloc,        /*tp_dealloc*/
-    0,                  /*tp_vectorcall_offset*/
-    0,                  /*tp_getattr*/
-    0,                  /*tp_setattr*/
-    0,                  /*tp_as_async*/
-    0,                  /*tp_repr*/
-    0,                  /*tp_as_number*/
-    0,                  /*tp_as_sequence*/
-    0,                  /*tp_as_mapping*/
-    0,                  /*tp_hash*/
-    0,                  /*tp_call*/
-    0,                  /*tp_str*/
-    0,                  /*tp_getattro*/
-    0,                  /*tp_setattro*/
-    0,                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT, /*tp_flags*/
-    0,                  /*tp_doc*/
-    0,                  /*tp_traverse*/
-    0,                  /*tp_clear*/
-    0,                  /*tp_richcompare*/
-    0,                  /*tp_weaklistoffset*/
-    0,                  /*tp_iter*/
-    0,                  /*tp_iternext*/
-    MD5_methods,        /* tp_methods */
-    NULL,               /* tp_members */
-    MD5_getseters,      /* tp_getset */
+static PyType_Slot md5_type_slots[] = {
+    {Py_tp_dealloc, MD5_dealloc},
+    {Py_tp_methods, MD5_methods},
+    {Py_tp_getset, MD5_getseters},
+    {0,0}
 };
 
+static PyType_Spec md5_type_spec = {
+    .name = "_md5.md5",
+    .basicsize =  sizeof(MD5object),
+    .flags = Py_TPFLAGS_DEFAULT,
+    .slots = md5_type_slots
+};
 
 /* The single module-level function: new() */
 
@@ -519,7 +510,8 @@ _md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity)
     if (string)
         GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
 
-    if ((new = newMD5object()) == NULL) {
+    MD5State *st = md5_get_state(module);
+    if ((new = newMD5object(st)) == NULL) {
         if (string)
             PyBuffer_Release(&buf);
         return NULL;
@@ -549,37 +541,69 @@ static struct PyMethodDef MD5_functions[] = {
     {NULL,      NULL}            /* Sentinel */
 };
 
+static int
+_md5_traverse(PyObject *module, visitproc visit, void *arg)
+{
+    MD5State *state = md5_get_state(module);
+    Py_VISIT(state->md5_type);
+    return 0;
+}
+
+static int
+_md5_clear(PyObject *module)
+{
+    MD5State *state = md5_get_state(module);
+    Py_CLEAR(state->md5_type);
+    return 0;
+}
+
+static void
+_md5_free(void *module)
+{
+    _md5_clear((PyObject *)module);
+}
 
 /* Initialize this module. */
+static int
+md5_exec(PyObject *m)
+{
+    MD5State *st = md5_get_state(m);
+
+    st->md5_type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        m, &md5_type_spec, NULL);
+
+    if (st->md5_type == NULL) {
+        return -1;
+    }
+
+    Py_INCREF((PyObject *)st->md5_type);
+    if (PyModule_AddObject(m, "MD5Type", (PyObject *)st->md5_type) < 0) {
+         Py_DECREF(st->md5_type);
+        return -1;
+    }
+
+    return 0;
+}
+
+static PyModuleDef_Slot _md5_slots[] = {
+    {Py_mod_exec, md5_exec},
+    {0, NULL}
+};
+
 
 static struct PyModuleDef _md5module = {
         PyModuleDef_HEAD_INIT,
-        "_md5",
-        NULL,
-        -1,
-        MD5_functions,
-        NULL,
-        NULL,
-        NULL,
-        NULL
+        .m_name = "_md5",
+        .m_size = sizeof(MD5State),
+        .m_methods = MD5_functions,
+        .m_slots = _md5_slots,
+        .m_traverse = _md5_traverse,
+        .m_clear = _md5_clear,
+        .m_free = _md5_free,
 };
 
 PyMODINIT_FUNC
 PyInit__md5(void)
 {
-    PyObject *m;
-
-    Py_SET_TYPE(&MD5type, &PyType_Type);
-    if (PyType_Ready(&MD5type) < 0) {
-        return NULL;
-    }
-
-    m = PyModule_Create(&_md5module);
-    if (m == NULL) {
-        return NULL;
-    }
-
-    Py_INCREF((PyObject *)&MD5type);
-    PyModule_AddObject(m, "MD5Type", (PyObject *)&MD5type);
-    return m;
+    return PyModuleDef_Init(&_md5module);
 }
diff --git a/Modules/sha1module.c b/Modules/sha1module.c
index b0656d83b3ae8..c22437de256b6 100644
--- a/Modules/sha1module.c
+++ b/Modules/sha1module.c
@@ -295,13 +295,22 @@ sha1_done(struct sha1_state *sha1, unsigned char *out)
  * ------------------------------------------------------------------------
  */
 
-static PyTypeObject SHA1type;
+typedef struct {
+    PyTypeObject* sha1_type;
+} SHA1State;
 
+static inline SHA1State*
+sha1_get_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (SHA1State *)state;
+}
 
 static SHA1object *
-newSHA1object(void)
+newSHA1object(SHA1State *st)
 {
-    return (SHA1object *)PyObject_New(SHA1object, &SHA1type);
+    return (SHA1object *)PyObject_New(SHA1object, st->sha1_type);
 }
 
 
@@ -310,7 +319,9 @@ newSHA1object(void)
 static void
 SHA1_dealloc(PyObject *ptr)
 {
+    PyTypeObject *tp = Py_TYPE(ptr);
     PyObject_Del(ptr);
+    Py_DECREF(tp);
 }
 
 
@@ -319,16 +330,19 @@ SHA1_dealloc(PyObject *ptr)
 /*[clinic input]
 SHA1Type.copy
 
+    cls: defining_class
+
 Return a copy of the hash object.
 [clinic start generated code]*/
 
 static PyObject *
-SHA1Type_copy_impl(SHA1object *self)
-/*[clinic end generated code: output=b4e001264620f02a input=b7eae10df6f89b36]*/
+SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls)
+/*[clinic end generated code: output=b32d4461ce8bc7a7 input=6c22e66fcc34c58e]*/
 {
-    SHA1object *newobj;
+    SHA1State *st = PyType_GetModuleState(cls);
 
-    if ((newobj = newSHA1object()) == NULL)
+    SHA1object *newobj;
+    if ((newobj = newSHA1object(st)) == NULL)
         return NULL;
 
     newobj->hash_state = self->hash_state;
@@ -422,7 +436,6 @@ sha1_get_digest_size(PyObject *self, void *closure)
     return PyLong_FromLong(SHA1_DIGESTSIZE);
 }
 
-
 static PyGetSetDef SHA1_getseters[] = {
     {"block_size",
      (getter)SHA1_get_block_size, NULL,
@@ -439,40 +452,19 @@ static PyGetSetDef SHA1_getseters[] = {
     {NULL}  /* Sentinel */
 };
 
-static PyTypeObject SHA1type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_sha1.sha1",               /*tp_name*/
-    sizeof(SHA1object), /*tp_basicsize*/
-    0,                  /*tp_itemsize*/
-    /* methods */
-    SHA1_dealloc,       /*tp_dealloc*/
-    0,                  /*tp_vectorcall_offset*/
-    0,                  /*tp_getattr*/
-    0,                  /*tp_setattr*/
-    0,                  /*tp_as_async*/
-    0,                  /*tp_repr*/
-    0,                  /*tp_as_number*/
-    0,                  /*tp_as_sequence*/
-    0,                  /*tp_as_mapping*/
-    0,                  /*tp_hash*/
-    0,                  /*tp_call*/
-    0,                  /*tp_str*/
-    0,                  /*tp_getattro*/
-    0,                  /*tp_setattro*/
-    0,                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT, /*tp_flags*/
-    0,                  /*tp_doc*/
-    0,                  /*tp_traverse*/
-    0,                  /*tp_clear*/
-    0,                  /*tp_richcompare*/
-    0,                  /*tp_weaklistoffset*/
-    0,                  /*tp_iter*/
-    0,                  /*tp_iternext*/
-    SHA1_methods,       /* tp_methods */
-    NULL,               /* tp_members */
-    SHA1_getseters,      /* tp_getset */
+static PyType_Slot sha1_type_slots[] = {
+    {Py_tp_dealloc, SHA1_dealloc},
+    {Py_tp_methods, SHA1_methods},
+    {Py_tp_getset, SHA1_getseters},
+    {0,0}
 };
 
+static PyType_Spec sha1_type_spec = {
+    .name = "_sha1.sha1",
+    .basicsize =  sizeof(SHA1object),
+    .flags = Py_TPFLAGS_DEFAULT,
+    .slots = sha1_type_slots
+};
 
 /* The single module-level function: new() */
 
@@ -496,7 +488,8 @@ _sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity)
     if (string)
         GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
 
-    if ((new = newSHA1object()) == NULL) {
+    SHA1State *st = sha1_get_state(module);
+    if ((new = newSHA1object(st)) == NULL) {
         if (string)
             PyBuffer_Release(&buf);
         return NULL;
@@ -526,37 +519,72 @@ static struct PyMethodDef SHA1_functions[] = {
     {NULL,      NULL}            /* Sentinel */
 };
 
+static int
+_sha1_traverse(PyObject *module, visitproc visit, void *arg)
+{
+    SHA1State *state = sha1_get_state(module);
+    Py_VISIT(state->sha1_type);
+    return 0;
+}
+
+static int
+_sha1_clear(PyObject *module)
+{
+    SHA1State *state = sha1_get_state(module);
+    Py_CLEAR(state->sha1_type);
+    return 0;
+}
+
+static void
+_sha1_free(void *module)
+{
+    _sha1_clear((PyObject *)module);
+}
+
+static int
+_sha1_exec(PyObject *module)
+{
+    SHA1State* st = sha1_get_state(module);
+
+    st->sha1_type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        module, &sha1_type_spec, NULL);
+
+    if (st->sha1_type == NULL) {
+        return -1;
+    }
+
+    Py_INCREF(st->sha1_type);
+    if (PyModule_AddObject(module, 
+                           "SHA1Type",
+                           (PyObject *)st->sha1_type) < 0) {
+        Py_DECREF(st->sha1_type);
+        return -1;
+    }
+
+    return 0;
+}
+
 
 /* Initialize this module. */
 
+static PyModuleDef_Slot _sha1_slots[] = {
+    {Py_mod_exec, _sha1_exec},
+    {0, NULL}
+};
+
 static struct PyModuleDef _sha1module = {
         PyModuleDef_HEAD_INIT,
-        "_sha1",
-        NULL,
-        -1,
-        SHA1_functions,
-        NULL,
-        NULL,
-        NULL,
-        NULL
+        .m_name = "_sha1",
+        .m_size = sizeof(SHA1State),
+        .m_methods = SHA1_functions,
+        .m_slots = _sha1_slots,
+        .m_traverse = _sha1_traverse,
+        .m_clear = _sha1_clear,
+        .m_free = _sha1_free
 };
 
 PyMODINIT_FUNC
 PyInit__sha1(void)
 {
-    PyObject *m;
-
-    Py_SET_TYPE(&SHA1type, &PyType_Type);
-    if (PyType_Ready(&SHA1type) < 0) {
-        return NULL;
-    }
-
-    m = PyModule_Create(&_sha1module);
-    if (m == NULL) {
-        return NULL;
-    }
-
-    Py_INCREF((PyObject *)&SHA1type);
-    PyModule_AddObject(m, "SHA1Type", (PyObject *)&SHA1type);
-    return m;
+    return PyModuleDef_Init(&_sha1module);
 }
diff --git a/Modules/sha512module.c b/Modules/sha512module.c
index aa2aeedcc6c64..725098def4d06 100644
--- a/Modules/sha512module.c
+++ b/Modules/sha512module.c
@@ -422,20 +422,29 @@ sha512_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
  * ------------------------------------------------------------------------
  */
 
-static PyTypeObject SHA384type;
-static PyTypeObject SHA512type;
+typedef struct {
+    PyTypeObject* sha384_type;
+    PyTypeObject* sha512_type;
+} SHA512State;
 
+static inline SHA512State*
+sha512_get_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (SHA512State *)state;
+}
 
 static SHAobject *
-newSHA384object(void)
+newSHA384object(SHA512State *st)
 {
-    return (SHAobject *)PyObject_New(SHAobject, &SHA384type);
+    return (SHAobject *)PyObject_New(SHAobject, st->sha384_type);
 }
 
 static SHAobject *
-newSHA512object(void)
+newSHA512object(SHA512State *st)
 {
-    return (SHAobject *)PyObject_New(SHAobject, &SHA512type);
+    return (SHAobject *)PyObject_New(SHAobject, st->sha512_type);
 }
 
 /* Internal methods for a hash object */
@@ -443,7 +452,9 @@ newSHA512object(void)
 static void
 SHA512_dealloc(PyObject *ptr)
 {
+    PyTypeObject *tp = Py_TYPE(ptr);
     PyObject_Del(ptr);
+    Py_DECREF(tp);
 }
 
 
@@ -452,21 +463,27 @@ SHA512_dealloc(PyObject *ptr)
 /*[clinic input]
 SHA512Type.copy
 
+    cls: defining_class
+
 Return a copy of the hash object.
 [clinic start generated code]*/
 
 static PyObject *
-SHA512Type_copy_impl(SHAobject *self)
-/*[clinic end generated code: output=adea896ed3164821 input=9f5f31e6c457776a]*/
+SHA512Type_copy_impl(SHAobject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=85ea5b47837a08e6 input=f673a18f66527c90]*/
 {
     SHAobject *newobj;
+    SHA512State *st = PyType_GetModuleState(cls);
 
-    if (Py_IS_TYPE((PyObject*)self, &SHA512type)) {
-        if ( (newobj = newSHA512object())==NULL)
+    if (Py_IS_TYPE((PyObject*)self, st->sha512_type)) {
+        if ( (newobj = newSHA512object(st))==NULL) {
             return NULL;
-    } else {
-        if ( (newobj = newSHA384object())==NULL)
+        }
+    }
+    else {
+        if ( (newobj = newSHA384object(st))==NULL) {
             return NULL;
+        }
     }
 
     SHAcopy(self, newobj);
@@ -574,74 +591,37 @@ static PyMemberDef SHA_members[] = {
     {NULL}  /* Sentinel */
 };
 
-static PyTypeObject SHA384type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_sha512.sha384",   /*tp_name*/
-    sizeof(SHAobject),  /*tp_basicsize*/
-    0,                  /*tp_itemsize*/
-    /* methods */
-    SHA512_dealloc,     /*tp_dealloc*/
-    0,                  /*tp_vectorcall_offset*/
-    0,                  /*tp_getattr*/
-    0,                  /*tp_setattr*/
-    0,                  /*tp_as_async*/
-    0,                  /*tp_repr*/
-    0,                  /*tp_as_number*/
-    0,                  /*tp_as_sequence*/
-    0,                  /*tp_as_mapping*/
-    0,                  /*tp_hash*/
-    0,                  /*tp_call*/
-    0,                  /*tp_str*/
-    0,                  /*tp_getattro*/
-    0,                  /*tp_setattro*/
-    0,                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT, /*tp_flags*/
-    0,                  /*tp_doc*/
-    0,                  /*tp_traverse*/
-    0,                  /*tp_clear*/
-    0,                  /*tp_richcompare*/
-    0,                  /*tp_weaklistoffset*/
-    0,                  /*tp_iter*/
-    0,                  /*tp_iternext*/
-    SHA_methods,        /* tp_methods */
-    SHA_members,        /* tp_members */
-    SHA_getseters,      /* tp_getset */
+static PyType_Slot sha512_sha384_type_slots[] = {
+    {Py_tp_dealloc, SHA512_dealloc},
+    {Py_tp_methods, SHA_methods},
+    {Py_tp_members, SHA_members},
+    {Py_tp_getset, SHA_getseters},
+    {0,0}
+};
+
+static PyType_Spec sha512_sha384_type_spec = {
+    .name = "_sha512.sha384",
+    .basicsize =  sizeof(SHAobject),
+    .flags = Py_TPFLAGS_DEFAULT,
+    .slots = sha512_sha384_type_slots
 };
 
-static PyTypeObject SHA512type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_sha512.sha512",   /*tp_name*/
-    sizeof(SHAobject),  /*tp_basicsize*/
-    0,                  /*tp_itemsize*/
-    /* methods */
-    SHA512_dealloc,     /*tp_dealloc*/
-    0,                  /*tp_vectorcall_offset*/
-    0,                  /*tp_getattr*/
-    0,                  /*tp_setattr*/
-    0,                  /*tp_as_async*/
-    0,                  /*tp_repr*/
-    0,                  /*tp_as_number*/
-    0,                  /*tp_as_sequence*/
-    0,                  /*tp_as_mapping*/
-    0,                  /*tp_hash*/
-    0,                  /*tp_call*/
-    0,                  /*tp_str*/
-    0,                  /*tp_getattro*/
-    0,                  /*tp_setattro*/
-    0,                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT, /*tp_flags*/
-    0,                  /*tp_doc*/
-    0,                  /*tp_traverse*/
-    0,                  /*tp_clear*/
-    0,                  /*tp_richcompare*/
-    0,                  /*tp_weaklistoffset*/
-    0,                  /*tp_iter*/
-    0,                  /*tp_iternext*/
-    SHA_methods,        /* tp_methods */
-    SHA_members,        /* tp_members */
-    SHA_getseters,      /* tp_getset */
+static PyType_Slot sha512_sha512_type_slots[] = {
+    {Py_tp_dealloc, SHA512_dealloc},
+    {Py_tp_methods, SHA_methods},
+    {Py_tp_members, SHA_members},
+    {Py_tp_getset, SHA_getseters},
+    {0,0}
 };
 
+// Using PyType_GetModuleState() on this type is safe since
+// it cannot be subclassed: it does not have the Py_TPFLAGS_BASETYPE flag.
+static PyType_Spec sha512_sha512_type_spec = {
+    .name = "_sha512.sha512",
+    .basicsize =  sizeof(SHAobject),
+    .flags = Py_TPFLAGS_DEFAULT,
+    .slots = sha512_sha512_type_slots
+};
 
 /* The single module-level function: new() */
 
@@ -662,10 +642,12 @@ _sha512_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity)
     SHAobject *new;
     Py_buffer buf;
 
+    SHA512State *st = sha512_get_state(module);
+
     if (string)
         GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
 
-    if ((new = newSHA512object()) == NULL) {
+    if ((new = newSHA512object(st)) == NULL) {
         if (string)
             PyBuffer_Release(&buf);
         return NULL;
@@ -704,10 +686,12 @@ _sha512_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity)
     SHAobject *new;
     Py_buffer buf;
 
+    SHA512State *st = sha512_get_state(module);
+
     if (string)
         GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
 
-    if ((new = newSHA384object()) == NULL) {
+    if ((new = newSHA384object(st)) == NULL) {
         if (string)
             PyBuffer_Release(&buf);
         return NULL;
@@ -738,43 +722,80 @@ static struct PyMethodDef SHA_functions[] = {
     {NULL,      NULL}            /* Sentinel */
 };
 
+static int
+_sha512_traverse(PyObject *module, visitproc visit, void *arg)
+{
+    SHA512State *state = sha512_get_state(module);
+    Py_VISIT(state->sha384_type);
+    Py_VISIT(state->sha512_type);
+    return 0;
+}
 
-/* Initialize this module. */
+static int
+_sha512_clear(PyObject *module)
+{
+    SHA512State *state = sha512_get_state(module);
+    Py_CLEAR(state->sha384_type);
+    Py_CLEAR(state->sha512_type);
+    return 0;
+}
 
-static struct PyModuleDef _sha512module = {
-        PyModuleDef_HEAD_INIT,
-        "_sha512",
-        NULL,
-        -1,
-        SHA_functions,
-        NULL,
-        NULL,
-        NULL,
-        NULL
-};
+static void
+_sha512_free(void *module)
+{
+    _sha512_clear((PyObject *)module);
+}
 
-PyMODINIT_FUNC
-PyInit__sha512(void)
+
+/* Initialize this module. */
+static int
+_sha512_exec(PyObject *m)
 {
-    PyObject *m;
+    SHA512State* st = sha512_get_state(m);
 
-    Py_SET_TYPE(&SHA384type, &PyType_Type);
-    if (PyType_Ready(&SHA384type) < 0) {
-        return NULL;
+    st->sha384_type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        m, &sha512_sha384_type_spec, NULL);
+
+    st->sha512_type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        m, &sha512_sha512_type_spec, NULL);
+
+    if (st->sha384_type == NULL || st->sha512_type == NULL) {
+        return -1;
     }
-    Py_SET_TYPE(&SHA512type, &PyType_Type);
-    if (PyType_Ready(&SHA512type) < 0) {
-        return NULL;
+
+    Py_INCREF(st->sha384_type);
+    if (PyModule_AddObject(m, "SHA384Type", (PyObject *)st->sha384_type) < 0) {
+        Py_DECREF(st->sha384_type);
+        return -1;
     }
 
-    m = PyModule_Create(&_sha512module);
-    if (m == NULL) {
-        return NULL;
+    Py_INCREF(st->sha512_type);
+    if (PyModule_AddObject(m, "SHA384Type", (PyObject *)st->sha512_type) < 0) {
+        Py_DECREF(st->sha512_type);
+        return -1;
     }
 
-    Py_INCREF((PyObject *)&SHA384type);
-    PyModule_AddObject(m, "SHA384Type", (PyObject *)&SHA384type);
-    Py_INCREF((PyObject *)&SHA512type);
-    PyModule_AddObject(m, "SHA512Type", (PyObject *)&SHA512type);
-    return m;
+    return 0;
+}
+
+static PyModuleDef_Slot _sha512_slots[] = {
+    {Py_mod_exec, _sha512_exec},
+    {0, NULL}
+};
+
+static struct PyModuleDef _sha512module = {
+        PyModuleDef_HEAD_INIT,
+        .m_name = "_sha512",
+        .m_size = sizeof(SHA512State),
+        .m_methods = SHA_functions,
+        .m_slots = _sha512_slots,
+        .m_traverse = _sha512_traverse,
+        .m_clear = _sha512_clear,
+        .m_free = _sha512_free
+};
+
+PyMODINIT_FUNC
+PyInit__sha512(void)
+{
+    return PyModuleDef_Init(&_sha512module);
 }



More information about the Python-checkins mailing list