# HG changeset patch
# User Armin Rigo <arigo@tunes.org>
# Date 1590673856 -7200
#      Thu May 28 15:50:56 2020 +0200
# Node ID 54810acbf34db2d9944970aa42c15182ab0d51f5
# Parent  c9c297839ab3493d8de2121f093db32c475b4e4b
Systematically expose all types on the _cffi_backend module
under their correct name.  This name starts with '__' if it
is supposed to be non-portable and not guaranteed.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3354,7 +3354,7 @@
 
 static PyTypeObject CData_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__CDataBase",
+    "_cffi_backend._CDataBase",
     sizeof(CDataObject),
     0,
     (destructor)cdata_dealloc,                  /* tp_dealloc */
@@ -3417,7 +3417,7 @@
     0,  /* inherited */                         /* tp_setattro */
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
-    "This is an internal subtype of __CDataBase for performance only on "
+    "This is an internal subtype of _CDataBase for performance only on "
     "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
     0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
@@ -3461,7 +3461,7 @@
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES  /* tp_flags */
                        | Py_TPFLAGS_HAVE_GC,
-    "This is an internal subtype of __CDataBase for performance only on "
+    "This is an internal subtype of _CDataBase for performance only on "
     "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
     (traverseproc)cdataowninggc_traverse,       /* tp_traverse */
     (inquiry)cdataowninggc_clear,               /* tp_clear */
@@ -3505,7 +3505,7 @@
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES  /* tp_flags */
                        | Py_TPFLAGS_HAVE_GC,
-    "This is an internal subtype of __CDataBase for performance only on "
+    "This is an internal subtype of _CDataBase for performance only on "
     "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
     (traverseproc)cdatafrombuf_traverse,        /* tp_traverse */
     (inquiry)cdatafrombuf_clear,                /* tp_clear */
@@ -3552,7 +3552,7 @@
                        | Py_TPFLAGS_HAVE_FINALIZE
 #endif
                        | Py_TPFLAGS_HAVE_GC,
-    "This is an internal subtype of __CDataBase for performance only on "
+    "This is an internal subtype of _CDataBase for performance only on "
     "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
     (traverseproc)cdatagcp_traverse,            /* tp_traverse */
     0,                                          /* tp_clear */
@@ -4369,7 +4369,7 @@
 
 static PyTypeObject dl_type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__Library",          /* tp_name */
+    "_cffi_backend.CLibrary",           /* tp_name */
     sizeof(DynLibObject),               /* tp_basicsize */
     0,                                  /* tp_itemsize */
     /* methods */
@@ -7794,6 +7794,22 @@
     PyObject *m, *v;
     int i;
     static char init_done = 0;
+    static PyTypeObject *all_types[] = {
+        &dl_type,
+        &CTypeDescr_Type,
+        &CField_Type,
+        &CData_Type,
+        &CDataOwning_Type,
+        &CDataOwningGC_Type,
+        &CDataFromBuf_Type,
+        &CDataGCP_Type,
+        &CDataIter_Type,
+        &MiniBuffer_Type,
+        &FFI_Type,
+        &Lib_Type,
+        &GlobSupport_Type,
+        NULL
+    };
 
     v = PySys_GetObject("version");
     if (v == NULL || !PyText_Check(v) ||
@@ -7819,26 +7835,22 @@
             INITERROR;
     }
 
-    if (PyType_Ready(&dl_type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CTypeDescr_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CField_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CData_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CDataOwning_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CDataOwningGC_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CDataFromBuf_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CDataGCP_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&CDataIter_Type) < 0)
-        INITERROR;
-    if (PyType_Ready(&MiniBuffer_Type) < 0)
-        INITERROR;
+    /* readify all types and add them to the module */
+    for (i = 0; all_types[i] != NULL; i++) {
+        PyTypeObject *tp = all_types[i];
+        PyObject *tpo = (PyObject *)tp;
+        if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) {
+            PyErr_Format(PyExc_ImportError,
+                         "'%s' is an ill-formed type name", tp->tp_name);
+            INITERROR;
+        }
+        if (PyType_Ready(tp) < 0)
+            INITERROR;
+
+        Py_INCREF(tpo);
+        if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0)
+            INITERROR;
+    }
 
     if (!init_done) {
         v = PyText_FromString("_cffi_backend");
@@ -7884,18 +7896,6 @@
             INITERROR;
     }
 
-    Py_INCREF(&MiniBuffer_Type);
-    if (PyModule_AddObject(m, "buffer", (PyObject *)&MiniBuffer_Type) < 0)
-        INITERROR;
-
-    Py_INCREF(&CTypeDescr_Type);
-    if (PyModule_AddObject(m, "CType", (PyObject *)&CTypeDescr_Type) < 0)
-        INITERROR;
-
-    Py_INCREF(&CField_Type);
-    if (PyModule_AddObject(m, "CField", (PyObject *)&CField_Type) < 0)
-        INITERROR;
-
     init_cffi_tls();
     if (PyErr_Occurred())
         INITERROR;
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
--- a/c/cffi1_module.c
+++ b/c/cffi1_module.c
@@ -26,11 +26,6 @@
     int i, res;
     static char init_done = 0;
 
-    if (PyType_Ready(&FFI_Type) < 0)
-        return -1;
-    if (PyType_Ready(&Lib_Type) < 0)
-        return -1;
-
     if (!init_done) {
         if (init_global_types_dict(FFI_Type.tp_dict) < 0)
             return -1;
@@ -62,16 +57,6 @@
         }
         init_done = 1;
     }
-
-    x = (PyObject *)&FFI_Type;
-    Py_INCREF(x);
-    if (PyModule_AddObject(m, "FFI", x) < 0)
-        return -1;
-    x = (PyObject *)&Lib_Type;
-    Py_INCREF(x);
-    if (PyModule_AddObject(m, "Lib", x) < 0)
-        return -1;
-
     return 0;
 }
 
diff --git a/c/cglob.c b/c/cglob.c
--- a/c/cglob.c
+++ b/c/cglob.c
@@ -20,7 +20,7 @@
 
 static PyTypeObject GlobSupport_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "FFIGlobSupport",
+    "_cffi_backend.__FFIGlobSupport",
     sizeof(GlobSupportObject),
     0,
     (destructor)glob_support_dealloc,           /* tp_dealloc */
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
--- a/c/ffi_obj.c
+++ b/c/ffi_obj.c
@@ -1137,7 +1137,7 @@
 
 static PyTypeObject FFI_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "CompiledFFI",
+    "_cffi_backend.FFI",
     sizeof(FFIObject),
     0,
     (destructor)ffi_dealloc,                    /* tp_dealloc */
diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -589,7 +589,7 @@
 
 static PyTypeObject Lib_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "CompiledLib",
+    "_cffi_backend.Lib",
     sizeof(LibObject),
     0,
     (destructor)lib_dealloc,                    /* tp_dealloc */
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -109,7 +109,7 @@
     p = new_primitive_type("signed char")
     x = cast(p, -65 + 17*256)
     assert repr(x) == "<cdata 'signed char' -65>"
-    assert repr(type(x)) == "<%s '_cffi_backend.__CDataBase'>" % type_or_class
+    assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class
     assert int(x) == -65
     x = cast(p, -66 + (1<<199)*256)
     assert repr(x) == "<cdata 'signed char' -66>"
@@ -4454,9 +4454,40 @@
     complete_struct_or_union(BStruct, [('a1', BArray, -1)])
     assert sizeof(BStruct) == sys.maxsize
 
-def test_type_names():
-    assert (CType.__module__, CType.__name__) == ('_cffi_backend', 'CType')
-    assert (CField.__module__, CField.__name__) == ('_cffi_backend', 'CField')
-    CData, CType1 = _get_types()
-    assert CType1 is CType
-    assert (CData.__module__, CData.__name__) == ('_cffi_backend','__CDataBase')
+def test_get_types():
+    import _cffi_backend
+    CData, CType = _get_types()
+    assert CData is _cffi_backend._CDataBase
+    assert CType is _cffi_backend.CType
+
+def test_type_available_with_correct_names():
+    import _cffi_backend
+    check_names = [
+        'CType',
+        'CField',
+        'CLibrary',
+        '_CDataBase',
+        'FFI',
+        'Lib',
+        'buffer',
+    ]
+    if '__pypy__' in sys.builtin_module_names:
+        check_names += [
+            '__CData_iterator',
+            '__FFIGlobSupport',
+            '__FFIAllocator',
+            '__FFIFunctionWrapper',
+        ]
+    else:
+        check_names += [
+            '__CDataOwn',
+            '__CDataOwnGC',
+            '__CDataFromBuf',
+            '__CDataGCP',
+            '__CData_iterator',
+            '__FFIGlobSupport',
+        ]
+    for name in check_names:
+        tp = getattr(_cffi_backend, name)
+        assert isinstance(tp, type)
+        assert (tp.__module__, tp.__name__) == ('_cffi_backend', name)