From dc3be188b42a90404d0655c250e6697f5a55b862 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 21 Feb 2021 14:26:27 +0100
Subject: Delete intermediate Python modules for some API features.

---
 plugins/pychrysalide/common/fnv1a.c    |  91 ++++++--------------------
 plugins/pychrysalide/common/fnv1a.h    |   7 +-
 plugins/pychrysalide/common/leb128.c   |   4 +-
 plugins/pychrysalide/common/module.c   |   4 +-
 plugins/pychrysalide/common/pathname.c | 114 ++++++++++-----------------------
 plugins/pychrysalide/common/pathname.h |   7 +-
 tests/common/fnv1a.py                  |  13 +---
 tests/common/pathname.py               |  30 +++------
 8 files changed, 73 insertions(+), 197 deletions(-)

diff --git a/plugins/pychrysalide/common/fnv1a.c b/plugins/pychrysalide/common/fnv1a.c
index 510b531..4103c86 100644
--- a/plugins/pychrysalide/common/fnv1a.c
+++ b/plugins/pychrysalide/common/fnv1a.c
@@ -36,16 +36,8 @@
 
 
 
-#define FNV1A_DOC                                           \
-    "Python version for Chrysalide of the Fowler-Noll-Vo"   \
-    " hash function.\n"                                     \
-    "\n"                                                    \
-    "There is no constructor for this class: its methods"   \
-    " are static methods only."
-
-
 /* Détermine l'empreinte FNV1a d'une chaîne de caractères. */
-static PyObject *py_fnv1a_hash(PyObject *, PyObject *);
+static PyObject *py_fnv1a(PyObject *, PyObject *);
 
 
 
@@ -62,18 +54,21 @@ static PyObject *py_fnv1a_hash(PyObject *, PyObject *);
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_fnv1a_hash(PyObject *self, PyObject *args)
+static PyObject *py_fnv1a(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
     const char *str;                        /* Chaîne à traiter.           */
     int ret;                                /* Bilan de lecture des args.  */
     fnv64_t value;                          /* Empreinte calculée          */
 
-#define FNV1A_HASH_METHOD PYTHON_METHOD_DEF                 \
-(                                                           \
-    hash, "str, /",                                         \
-    METH_VARARGS | METH_STATIC, py_fnv1a,                   \
-    "Compute the FNV-1a hash from a given string."          \
+#define FNV1A_METHOD PYTHON_METHOD_DEF                  \
+(                                                       \
+    fnv1a, "str, /",                                    \
+    METH_VARARGS, py,                                   \
+    "Compute the Fowler-Noll-Vo hash (version 1a) of a" \
+    " given string."                                    \
+    "\n"                                                \
+    "The result is 64-bit integer value."               \
 )
 
     ret = PyArg_ParseTuple(args, "s", &str);
@@ -92,48 +87,7 @@ static PyObject *py_fnv1a_hash(PyObject *self, PyObject *args)
 *                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Fournit un accès à une définition de type à diffuser.        *
-*                                                                             *
-*  Retour      : Définition d'objet pour Python.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-PyTypeObject *get_python_fnv1a_type(void)
-{
-    static PyMethodDef py_fnv1a_methods[] = {
-        FNV1A_HASH_METHOD,
-        { NULL }
-    };
-
-    static PyTypeObject py_fnv1a_type = {
-
-        PyVarObject_HEAD_INIT(NULL, 0)
-
-        .tp_name        = "pychrysalide.common.fnv1a",
-        .tp_basicsize   = sizeof(PyObject),
-
-        .tp_flags       = Py_TPFLAGS_DEFAULT,
-
-        .tp_doc         = FNV1A_DOC,
-
-        .tp_methods     = py_fnv1a_methods,
-
-        .tp_new         = no_python_constructor_allowed,
-
-    };
-
-    return &py_fnv1a_type;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : module = module dont la définition est à compléter.          *
-*                                                                             *
-*  Description : Prend en charge l'objet 'pychrysalide.core.fnv1a'.           *
+*  Description : Définit une extension du module 'common' à compléter.        *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -141,25 +95,20 @@ PyTypeObject *get_python_fnv1a_type(void)
 *                                                                             *
 ******************************************************************************/
 
-bool ensure_python_fnv1a_is_registered(void)
+bool populate_common_module_with_fnv1a(void)
 {
-    PyTypeObject *type;                     /* Type Python pour 'fnv1a'    */
+    bool result;                            /* Bilan à retourner           */
     PyObject *module;                       /* Module à recompléter        */
 
-    type = get_python_fnv1a_type();
-
-    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
-    {
-        if (PyType_Ready(type) != 0)
-            return false;
-
-        module = get_access_to_python_module("pychrysalide.common");
+    static PyMethodDef py_fnv1a_methods[] = {
+        FNV1A_METHOD,
+        { NULL }
+    };
 
-        if (!register_python_module_object(module, type))
-            return false;
+    module = get_access_to_python_module("pychrysalide.common");
 
-    }
+    result = register_python_module_methods(module, py_fnv1a_methods);
 
-    return true;
+    return result;
 
 }
diff --git a/plugins/pychrysalide/common/fnv1a.h b/plugins/pychrysalide/common/fnv1a.h
index 0bdd2c8..52b5cf5 100644
--- a/plugins/pychrysalide/common/fnv1a.h
+++ b/plugins/pychrysalide/common/fnv1a.h
@@ -31,11 +31,8 @@
 
 
 
-/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_fnv1a_type(void);
-
-/* Prend en charge l'objet 'pychrysalide.common.fnv1a'. */
-bool ensure_python_fnv1a_is_registered(void);
+/* Définit une extension du module 'common' à compléter. */
+bool populate_common_module_with_fnv1a(void);
 
 
 
diff --git a/plugins/pychrysalide/common/leb128.c b/plugins/pychrysalide/common/leb128.c
index 49ef533..8e1bf28 100644
--- a/plugins/pychrysalide/common/leb128.c
+++ b/plugins/pychrysalide/common/leb128.c
@@ -273,7 +273,7 @@ bool populate_common_module_with_leb128(void)
     bool result;                            /* Bilan à retourner           */
     PyObject *module;                       /* Module à recompléter        */
 
-    static PyMethodDef py_queue_methods[] = {
+    static PyMethodDef py_leb128_methods[] = {
         LEB128_PACK_ULEB128_METHOD,
         LEB128_PACK_LEB128_METHOD,
         LEB128_UNPACK_ULEB128_METHOD,
@@ -283,7 +283,7 @@ bool populate_common_module_with_leb128(void)
 
     module = get_access_to_python_module("pychrysalide.common");
 
-    result = register_python_module_methods(module, py_queue_methods);
+    result = register_python_module_methods(module, py_leb128_methods);
 
     return result;
 
diff --git a/plugins/pychrysalide/common/module.c b/plugins/pychrysalide/common/module.c
index a5cf957..865b7e2 100644
--- a/plugins/pychrysalide/common/module.c
+++ b/plugins/pychrysalide/common/module.c
@@ -95,12 +95,12 @@ bool populate_common_module(void)
 
     result = true;
 
+    if (result) result = populate_common_module_with_fnv1a();
     if (result) result = populate_common_module_with_leb128();
+    if (result) result = populate_common_module_with_pathname();
 
     if (result) result = ensure_python_bitfield_is_registered();
-    if (result) result = ensure_python_fnv1a_is_registered();
     if (result) result = ensure_python_packed_buffer_is_registered();
-    if (result) result = ensure_python_pathname_is_registered();
 
     assert(result);
 
diff --git a/plugins/pychrysalide/common/pathname.c b/plugins/pychrysalide/common/pathname.c
index c83c27d..9ea9a2b 100644
--- a/plugins/pychrysalide/common/pathname.c
+++ b/plugins/pychrysalide/common/pathname.c
@@ -40,18 +40,11 @@
 
 
 
-#define PYTHON_PATHNAME_DOC                                 \
-    "Path manipulations in Python for Chrysalide.\n"        \
-    "\n"                                                    \
-    "There is no constructor for this class: its methods"   \
-    " are static methods only."
-
-
 /* Calcule le chemin relatif entre deux fichiers donnés. */
-static PyObject *py_build_relative_filename(PyObject *, PyObject *);
+static PyObject *py_pathname_build_relative_filename(PyObject *, PyObject *);
 
 /* Calcule le chemin absolu d'un fichier par rapport à un autre. */
-static PyObject *py_build_absolute_filename(PyObject *, PyObject *);
+static PyObject *py_pathname_build_absolute_filename(PyObject *, PyObject *);
 
 
 
@@ -68,7 +61,7 @@ static PyObject *py_build_absolute_filename(PyObject *, PyObject *);
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_build_relative_filename(PyObject *self, PyObject *args)
+static PyObject *py_pathname_build_relative_filename(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
     const char *ref;                        /* Fichier de référence        */
@@ -76,13 +69,16 @@ static PyObject *py_build_relative_filename(PyObject *self, PyObject *args)
     int ret;                                /* Bilan de lecture des args.  */
     char *relative;                         /* Chemin d'accès construit    */
 
-#define BUILD_RELATIVE_FILENAME_METHOD PYTHON_METHOD_DEF    \
-(                                                           \
-    build_relative_filename, "ref, target",                 \
-    METH_VARARGS | METH_STATIC, py,                         \
-    "Compute the relative path between two files.\n"        \
-    "\n"                                                    \
-    "Both arguments must be strings."                       \
+#define BUILD_RELATIVE_FILENAME_METHOD PYTHON_METHOD_DEF            \
+(                                                                   \
+    build_relative_filename, "reference, target",                   \
+    METH_VARARGS, py_pathname,                                      \
+    "Compute the relative path between two files: a *reference*"    \
+    " location as point of view and a *target* file.\n"             \
+    "\n"                                                            \
+    "Both arguments must be strings.\n"                             \
+    "\n"                                                            \
+    "The result is also a string."                                  \
 )
 
     ret = PyArg_ParseTuple(args, "ss", &ref, &target);
@@ -112,7 +108,7 @@ static PyObject *py_build_relative_filename(PyObject *self, PyObject *args)
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_build_absolute_filename(PyObject *self, PyObject *args)
+static PyObject *py_pathname_build_absolute_filename(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
     const char *ref;                        /* Fichier de référence        */
@@ -120,13 +116,17 @@ static PyObject *py_build_absolute_filename(PyObject *self, PyObject *args)
     int ret;                                /* Bilan de lecture des args.  */
     char *relative;                         /* Chemin d'accès construit    */
 
-#define BUILD_ABSOLUTE_FILENAME_METHOD PYTHON_METHOD_DEF    \
-(                                                           \
-    build_absolute_filename, "ref, target",                 \
-    METH_VARARGS | METH_STATIC, py,                         \
-    "Compute the absolute path for a file.\n"               \
-    "\n"                                                    \
-    "Both arguments must be strings."                       \
+#define BUILD_ABSOLUTE_FILENAME_METHOD PYTHON_METHOD_DEF            \
+(                                                                   \
+    build_absolute_filename, "reference, target",                   \
+    METH_VARARGS, py_pathname,                                      \
+    "Compute the absolute path for a *target* file from a"          \
+    " *reference* location.\n"                                      \
+    "\n"                                                            \
+    "Both arguments must be strings.\n"                             \
+    "\n"                                                            \
+    "The result is a string on success. A *ValueError*  exception"  \
+    " is raised on failure."                                        \
 )
 
     ret = PyArg_ParseTuple(args, "ss", &ref, &target);
@@ -154,75 +154,29 @@ static PyObject *py_build_absolute_filename(PyObject *self, PyObject *args)
 *                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Fournit un accès à une définition de type à diffuser.        *
+*  Description : Définit une extension du module 'common' à compléter.        *
 *                                                                             *
-*  Retour      : Définition d'objet pour Python.                              *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-PyTypeObject *get_python_pathname_type(void)
+bool populate_common_module_with_pathname(void)
 {
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Module à recompléter        */
+
     static PyMethodDef py_pathname_methods[] = {
         BUILD_RELATIVE_FILENAME_METHOD,
         BUILD_ABSOLUTE_FILENAME_METHOD,
         { NULL }
     };
 
-    static PyTypeObject py_pathname_type = {
-
-        PyVarObject_HEAD_INIT(NULL, 0)
-
-        .tp_name        = "pychrysalide.common.pathname",
-        .tp_basicsize   = sizeof(PyObject),
-
-        .tp_flags       = Py_TPFLAGS_DEFAULT,
-
-        .tp_doc         = PYTHON_PATHNAME_DOC,
-
-        .tp_methods     =  py_pathname_methods,
+    module = get_access_to_python_module("pychrysalide.common");
 
-        .tp_new         = no_python_constructor_allowed,
+    result = register_python_module_methods(module, py_pathname_methods);
 
-    };
-
-    return &py_pathname_type;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : module = module dont la définition est à compléter.          *
-*                                                                             *
-*  Description : Prend en charge l'objet 'pychrysalide.core.pathname'.        *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool ensure_python_pathname_is_registered(void)
-{
-    PyTypeObject *type;                     /* Type Python pour 'pathname' */
-    PyObject *module;                       /* Module à recompléter        */
-
-    type = get_python_pathname_type();
-
-    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
-    {
-        if (PyType_Ready(type) != 0)
-            return false;
-
-        module = get_access_to_python_module("pychrysalide.common");
-
-        if (!register_python_module_object(module, type))
-            return false;
-
-    }
-
-    return true;
+    return result;
 
 }
diff --git a/plugins/pychrysalide/common/pathname.h b/plugins/pychrysalide/common/pathname.h
index 619053c..3e22aa0 100644
--- a/plugins/pychrysalide/common/pathname.h
+++ b/plugins/pychrysalide/common/pathname.h
@@ -31,11 +31,8 @@
 
 
 
-/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_pathname_type(void);
-
-/* Prend en charge l'objet 'pychrysalide.common.pathname'. */
-bool ensure_python_pathname_is_registered(void);
+/*  Définit une extension du module 'common' à compléter. */
+bool populate_common_module_with_pathname(void);
 
 
 
diff --git a/tests/common/fnv1a.py b/tests/common/fnv1a.py
index 2013afa..3bb7c32 100644
--- a/tests/common/fnv1a.py
+++ b/tests/common/fnv1a.py
@@ -4,22 +4,15 @@ from pychrysalide.common import fnv1a
 
 
 class TestFnv1a(ChrysalideTestCase):
-    """TestCase for common.fnv1a*"""
-
-    def testFnv1aConstructor(self):
-        """Check that no constructor is available for the fnv1a class."""
-
-        with self.assertRaisesRegex(NotImplementedError, 'Chrysalide does not allow building this kind of object from Python'):
-            instance = fnv1a()
-
+    """TestCase for common FNV-1a hashing features."""
 
     def testFnv1aSamples(self):
         """Compute some Fnv1a hashs."""
 
         # Test cases from http://isthe.com/chongo/src/fnv/test_fnv.c
 
-        val = fnv1a.hash('')
+        val = fnv1a('')
         self.assertEqual(val, 0xcbf29ce484222325)
 
-        val = fnv1a.hash('chongo was here!\n')
+        val = fnv1a('chongo was here!\n')
         self.assertEqual(val, 0x46810940eff5f915)
diff --git a/tests/common/pathname.py b/tests/common/pathname.py
index 00a084b..23ca2b0 100644
--- a/tests/common/pathname.py
+++ b/tests/common/pathname.py
@@ -1,10 +1,10 @@
 
 from chrysacase import ChrysalideTestCase
-from pychrysalide.common import pathname
+from pychrysalide.common import build_relative_filename, build_absolute_filename
 
 
 class TestPathnames(ChrysalideTestCase):
-    """TestCase for common.pathname*"""
+    """TestCase for common pathname features."""
 
     @classmethod
     def setUpClass(cls):
@@ -58,11 +58,9 @@ class TestPathnames(ChrysalideTestCase):
     def testBuildingRelative(self):
         """Build valid relative paths."""
 
-        build_relative = pathname.build_relative_filename
-
         for tst in self._tests:
 
-            got = build_relative(tst['ref'], tst['target'])
+            got = build_relative_filename(tst['ref'], tst['target'])
 
             self.assertEqual(got, tst['relative'])
 
@@ -70,11 +68,9 @@ class TestPathnames(ChrysalideTestCase):
     def testBuildingAbsolute(self):
         """Build valid absolute paths."""
 
-        build_absolute = pathname.build_absolute_filename
-
         for tst in self._tests:
 
-            got = build_absolute(tst['ref'], tst['relative'])
+            got = build_absolute_filename(tst['ref'], tst['relative'])
 
             self.assertEqual(got, tst['target'])
 
@@ -82,29 +78,19 @@ class TestPathnames(ChrysalideTestCase):
     def testBuildingWrongAbsolute(self):
         """Build invalid absolute paths."""
 
-        build_absolute = pathname.build_absolute_filename
-
         with self.assertRaisesRegex(Exception, 'Relative path is too deep.'):
 
-            got = build_absolute('/a/b', '../../c')
-
-
-    def testPathnameConstructor(self):
-        """Check that no constructor is available for the pathname class."""
-
-        with self.assertRaisesRegex(NotImplementedError, 'Chrysalide does not allow building this kind of object from Python'):
-
-            instance = pathname()
+            got = build_absolute_filename('/a/b', '../../c')
 
 
     def testPathnameSamples(self):
         """Play with some path samples."""
 
-        filename = pathname.build_absolute_filename('/tmp/deep', '../myfile')
+        filename = build_absolute_filename('/tmp/deep', '../myfile')
         self.assertEqual(filename, '/myfile')
 
-        filename = pathname.build_absolute_filename('/tmp/deep/', '../myfile')
+        filename = build_absolute_filename('/tmp/deep/', '../myfile')
         self.assertEqual(filename, '/tmp/myfile')
 
-        filename = pathname.build_relative_filename('/tmp/deep', '/myfile')
+        filename = build_relative_filename('/tmp/deep', '/myfile')
         self.assertEqual(filename, '../myfile')
-- 
cgit v0.11.2-87-g4458