[Python-checkins] bpo-40950: Port nis module to multiphase initialization (GH-20811)

Dong-hee Na webhook-mailer at python.org
Thu Jun 11 22:26:10 EDT 2020


https://github.com/python/cpython/commit/ddef3bdc7b254a7e1129a52c17d79cb7c73a88f5
commit: ddef3bdc7b254a7e1129a52c17d79cb7c73a88f5
branch: master
author: Dong-hee Na <donghee.na92 at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-06-12T11:26:00+09:00
summary:

bpo-40950: Port nis module to multiphase initialization (GH-20811)

files:
A Misc/NEWS.d/next/Core and Builtins/2020-06-12-00-12-28.bpo-40950.tzMy7m.rst
M Modules/nismodule.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-06-12-00-12-28.bpo-40950.tzMy7m.rst b/Misc/NEWS.d/next/Core and Builtins/2020-06-12-00-12-28.bpo-40950.tzMy7m.rst
new file mode 100644
index 0000000000000..925b5790f73f3
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-06-12-00-12-28.bpo-40950.tzMy7m.rst	
@@ -0,0 +1,2 @@
+Add a state to the :mod:`nis` module (:pep:`3121`) and apply
+the multiphase initialization. Patch by Dong-hee Na.
diff --git a/Modules/nismodule.c b/Modules/nismodule.c
index a24978e068670..6655451ebd2fb 100644
--- a/Modules/nismodule.c
+++ b/Modules/nismodule.c
@@ -44,12 +44,42 @@ PyDoc_STRVAR(maps__doc__,
 Returns an array of all available NIS maps within a domain. If domain\n\
 is not specified it defaults to the system default domain.\n");
 
-static PyObject *NisError;
+typedef struct {
+    PyObject *nis_error;
+} nis_state;
+
+static inline nis_state*
+get_nis_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (nis_state *)state;
+}
+
+static int
+nis_clear(PyObject *m)
+{
+    Py_CLEAR(get_nis_state(m)->nis_error);
+    return 0;
+}
+
+static int
+nis_traverse(PyObject *m, visitproc visit, void *arg)
+{
+    Py_VISIT(get_nis_state(m)->nis_error);
+    return 0;
+}
+
+static void
+nis_free(void *m)
+{
+    nis_clear((PyObject *) m);
+}
 
 static PyObject *
-nis_error (int err)
+nis_error(nis_state *state, int err)
 {
-    PyErr_SetString(NisError, yperr_string(err));
+    PyErr_SetString(state->nis_error, yperr_string(err));
     return NULL;
 }
 
@@ -70,7 +100,7 @@ static struct nis_map {
 };
 
 static char *
-nis_mapname (char *map, int *pfix)
+nis_mapname(char *map, int *pfix)
 {
     int i;
 
@@ -98,7 +128,7 @@ struct ypcallback_data {
 };
 
 static int
-nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
+nis_foreach(int instatus, char *inkey, int inkeylen, char *inval,
              int invallen, struct ypcallback_data *indata)
 {
     if (instatus == YP_TRUE) {
@@ -137,21 +167,22 @@ nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
 }
 
 static PyObject *
-nis_get_default_domain (PyObject *self, PyObject *Py_UNUSED(ignored))
+nis_get_default_domain(PyObject *module, PyObject *Py_UNUSED(ignored))
 {
     char *domain;
     int err;
     PyObject *res;
-
-    if ((err = yp_get_default_domain(&domain)) != 0)
-        return nis_error(err);
+    nis_state *state = get_nis_state(module);
+    if ((err = yp_get_default_domain(&domain)) != 0) {
+        return nis_error(state, err);
+    }
 
     res = PyUnicode_FromStringAndSize (domain, strlen(domain));
     return res;
 }
 
 static PyObject *
-nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
+nis_match(PyObject *module, PyObject *args, PyObject *kwdict)
 {
     char *match;
     char *domain = NULL;
@@ -165,18 +196,22 @@ nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwdict,
                                      "Us|s:match", kwlist,
-                                     &ukey, &map, &domain))
+                                     &ukey, &map, &domain)) {
         return NULL;
-    if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL)
+    }
+    if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL) {
         return NULL;
+    }
     /* check for embedded null bytes */
     if (PyBytes_AsStringAndSize(bkey, &key, &keylen) == -1) {
         Py_DECREF(bkey);
         return NULL;
     }
+
+    nis_state *state = get_nis_state(module);
     if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
         Py_DECREF(bkey);
-        return nis_error(err);
+        return nis_error(state, err);
     }
     map = nis_mapname (map, &fix);
     if (fix)
@@ -187,15 +222,16 @@ nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
     Py_DECREF(bkey);
     if (fix)
         len--;
-    if (err != 0)
-        return nis_error(err);
+    if (err != 0) {
+        return nis_error(state, err);
+    }
     res = PyUnicode_DecodeFSDefaultAndSize(match, len);
     free (match);
     return res;
 }
 
 static PyObject *
-nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
+nis_cat(PyObject *module, PyObject *args, PyObject *kwdict)
 {
     char *domain = NULL;
     char *map;
@@ -206,10 +242,13 @@ nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
     static char *kwlist[] = {"map", "domain", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s|s:cat",
-                                     kwlist, &map, &domain))
+                                     kwlist, &map, &domain)) {
         return NULL;
-    if (!domain && ((err = yp_get_default_domain(&domain)) != 0))
-        return nis_error(err);
+    }
+    nis_state *state = get_nis_state(module);
+    if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
+        return nis_error(state, err);
+    }
     dict = PyDict_New ();
     if (dict == NULL)
         return NULL;
@@ -222,7 +261,7 @@ nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
     PyEval_RestoreThread(data.state);
     if (err != 0) {
         Py_DECREF(dict);
-        return nis_error(err);
+        return nis_error(state, err);
     }
     return dict;
 }
@@ -352,7 +391,7 @@ nisproc_maplist_2(domainname *argp, CLIENT *clnt)
 
 static
 nismaplist *
-nis_maplist (char *dom)
+nis_maplist(nis_state *state, char *dom)
 {
     nisresp_maplist *list;
     CLIENT *cl;
@@ -364,12 +403,12 @@ nis_maplist (char *dom)
         mapi++;
     }
     if (!server) {
-        PyErr_SetString(NisError, "No NIS master found for any map");
+        PyErr_SetString(state->nis_error, "No NIS master found for any map");
         return NULL;
     }
     cl = clnt_create(server, YPPROG, YPVERS, "tcp");
     if (cl == NULL) {
-        PyErr_SetString(NisError, clnt_spcreateerror(server));
+        PyErr_SetString(state->nis_error, clnt_spcreateerror(server));
         goto finally;
     }
     list = nisproc_maplist_2 (&dom, cl);
@@ -388,7 +427,7 @@ nis_maplist (char *dom)
 }
 
 static PyObject *
-nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
+nis_maps (PyObject *module, PyObject *args, PyObject *kwdict)
 {
     char *domain = NULL;
     nismaplist *maps;
@@ -397,17 +436,22 @@ nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
     static char *kwlist[] = {"domain", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwdict,
-                                     "|s:maps", kwlist, &domain))
+                                     "|s:maps", kwlist, &domain)) {
         return NULL;
+    }
+
+    nis_state *state = get_nis_state(module);
     if (!domain && ((err = yp_get_default_domain (&domain)) != 0)) {
-        nis_error(err);
+        nis_error(state, err);
         return NULL;
     }
 
-    if ((maps = nis_maplist (domain)) == NULL)
+    if ((maps = nis_maplist(state, domain)) == NULL) {
         return NULL;
-    if ((list = PyList_New(0)) == NULL)
+    }
+    if ((list = PyList_New(0)) == NULL) {
         return NULL;
+    }
     for (; maps; maps = maps->next) {
         PyObject *str = PyUnicode_FromString(maps->map);
         if (!str || PyList_Append(list, str) < 0)
@@ -439,31 +483,45 @@ static PyMethodDef nis_methods[] = {
     {NULL,                      NULL}            /* Sentinel */
 };
 
+static int
+nis_exec(PyObject *module)
+{
+    nis_state* state = get_nis_state(module);
+    state->nis_error = PyErr_NewException("nis.error", NULL, NULL);
+    if (state->nis_error == NULL) {
+        return -1;
+    }
+
+    Py_INCREF(state->nis_error);
+    if (PyModule_AddObject(module, "error", state->nis_error) < 0) {
+        Py_DECREF(state->nis_error);
+        return -1;
+    }
+    return 0;
+}
+
+static PyModuleDef_Slot nis_slots[] = {
+    {Py_mod_exec, nis_exec},
+    {0, NULL}
+};
+
 PyDoc_STRVAR(nis__doc__,
 "This module contains functions for accessing NIS maps.\n");
 
 static struct PyModuleDef nismodule = {
     PyModuleDef_HEAD_INIT,
-    "nis",
-    nis__doc__,
-    -1,
-    nis_methods,
-    NULL,
-    NULL,
-    NULL,
-    NULL
+    .m_name = "nis",
+    .m_doc = nis__doc__,
+    .m_size = sizeof(nis_state),
+    .m_methods = nis_methods,
+    .m_traverse = nis_traverse,
+    .m_clear = nis_clear,
+    .m_free = nis_free,
+    .m_slots = nis_slots,
 };
 
 PyMODINIT_FUNC
 PyInit_nis(void)
 {
-    PyObject *m, *d;
-    m = PyModule_Create(&nismodule);
-    if (m == NULL)
-        return NULL;
-    d = PyModule_GetDict(m);
-    NisError = PyErr_NewException("nis.error", NULL, NULL);
-    if (NisError != NULL)
-        PyDict_SetItemString(d, "error", NisError);
-    return m;
+    return PyModuleDef_Init(&nismodule);
 }



More information about the Python-checkins mailing list