From 063383ee06a472515ddd39a071c449a7e34f5c6b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 7 Feb 2020 00:13:32 +0100
Subject: Improved the documentation for the Dex format Python bindings.

---
 plugins/dex/python/class.c     | 137 +++++++++++++++++++++++++++--------------
 plugins/dex/python/constants.c |  89 +++++++++++---------------
 plugins/dex/python/constants.h |   4 +-
 plugins/dex/python/field.c     |  28 ++++++---
 plugins/dex/python/format.c    |  20 ++++--
 plugins/dex/python/method.c    |  59 +++++++++++++-----
 plugins/dex/python/module.c    |  10 ++-
 plugins/dex/python/routine.c   |  24 ++++++--
 8 files changed, 234 insertions(+), 137 deletions(-)

diff --git a/plugins/dex/python/class.c b/plugins/dex/python/class.c
index 82c893e..e344124 100644
--- a/plugins/dex/python/class.c
+++ b/plugins/dex/python/class.c
@@ -37,6 +37,10 @@
 
 
 
+#define DEX_CLASS_DOC                                               \
+    "The DexClass object handles a class defined in a DEX file."
+
+
 /* Fournit la définition brute d'une classe. */
 static PyObject *py_dex_class_get_definition(PyObject *, void *);
 
@@ -44,13 +48,13 @@ static PyObject *py_dex_class_get_definition(PyObject *, void *);
 static PyObject *py_dex_class_get_data(PyObject *, void *);
 
 /* Indique le type Android d'une classe. */
-static PyObject *py_dex_class_get_class_type(PyObject *, void *);
+static PyObject *py_dex_class_get_type(PyObject *, void *);
 
 /* Indique le type Android parent d'une classe. */
-static PyObject *py_dex_class_get_superclass_type(PyObject *, void *);
+static PyObject *py_dex_class_get_super(PyObject *, void *);
 
 /* Indique le type Android des interfaces d'une classe. */
-static PyObject *py_dex_class_get_interface_types(PyObject *, void *);
+static PyObject *py_dex_class_get_interfaces(PyObject *, void *);
 
 /* Fournit les champs chargés correspondant à une classe donnée. */
 static PyObject *py_dex_class_get_fields(PyObject *, void *);
@@ -82,6 +86,12 @@ static PyObject *py_dex_class_get_definition(PyObject *self, void *closure)
     GDexClass *class;                       /* Version native              */
     const class_def_item *item;             /* Elément à traiter           */
 
+#define DEX_CLASS_DEFINITION_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                           \
+    definition, py_dex_class,                               \
+    "Native definition of the Dex class."                   \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     item = g_dex_class_get_definition(class);
@@ -112,6 +122,12 @@ static PyObject *py_dex_class_get_data(PyObject *self, void *closure)
     GDexClass *class;                       /* Version native              */
     const class_data_item *item;            /* Elément à traiter           */
 
+#define DEX_CLASS_DATA_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                   \
+    data, py_dex_class,                             \
+    "Native data of the Dex class, if any."         \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     item = g_dex_class_get_data(class);
@@ -143,12 +159,18 @@ static PyObject *py_dex_class_get_data(PyObject *self, void *closure)
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_dex_class_get_class_type(PyObject *self, void *closure)
+static PyObject *py_dex_class_get_type(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Valeur à retourner          */
     GDexClass *class;                       /* Version native              */
     GDataType *type;                        /* Type de classe              */
 
+#define DEX_CLASS_TYPE_ATTRIB PYTHON_GET_DEF_FULL       \
+(                                                       \
+    type, py_dex_class,                                 \
+    "Android type of the Dex class, None on error."     \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     type = g_dex_class_get_class_type(class);
@@ -185,12 +207,18 @@ static PyObject *py_dex_class_get_class_type(PyObject *self, void *closure)
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_dex_class_get_superclass_type(PyObject *self, void *closure)
+static PyObject *py_dex_class_get_super(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Valeur à retourner          */
     GDexClass *class;                       /* Version native              */
     GDataType *type;                        /* Type de classe              */
 
+#define DEX_CLASS_SUPER_ATTRIB PYTHON_GET_DEF_FULL          \
+(                                                           \
+    super, py_dex_class,                                    \
+    "Android type of the parent Dex class, None on error."  \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     type = g_dex_class_get_superclass_type(class);
@@ -227,7 +255,7 @@ static PyObject *py_dex_class_get_superclass_type(PyObject *self, void *closure)
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_dex_class_get_interface_types(PyObject *self, void *closure)
+static PyObject *py_dex_class_get_interfaces(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Valeur à retourner          */
     GDexClass *class;                       /* Version native              */
@@ -236,6 +264,13 @@ static PyObject *py_dex_class_get_interface_types(PyObject *self, void *closure)
     size_t i;                               /* Boucle de parcours          */
     PyObject *type;                         /* Type à ajouter à la liste   */
 
+#define DEX_CLASS_INTERFACES_ATTRIB PYTHON_GET_DEF_FULL             \
+(                                                                   \
+    interfaces, py_dex_class,                                       \
+    "Interface Android types of the Dex class, None if none and"    \
+    " None on error."                                               \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     types = g_dex_class_get_interface_types(class, &count);
@@ -300,6 +335,22 @@ static PyObject *py_dex_class_get_fields(PyObject *self, void *closure)
     GDexField *field;                       /* Champ à convertir           */
     PyObject *fld;                          /* Objet à ajouter à la liste  */
 
+#define DEX_CLASS_STATIC_FIELDS_ATTRIB PYTHON_GETSET_DEF            \
+(                                                                   \
+    "static_fields", py_dex_class_get_fields, NULL,                 \
+    "List of static fields of the Dex class, None if none and"      \
+    " None on error.",                                              \
+    NULL                                                            \
+)
+
+#define DEX_CLASS_INSTANCE_FIELDS_ATTRIB PYTHON_GETSET_DEF          \
+(                                                                   \
+    "static_fields", py_dex_class_get_fields, NULL,                 \
+    "List of instance fields of the Dex class, None if none and"    \
+    " None on error.",                                              \
+    (void *)1                                                       \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     instance = (closure != NULL);
@@ -365,6 +416,22 @@ static PyObject *py_dex_class_get_methods(PyObject *self, void *closure)
     GDexMethod *method;                     /* Méthode à convertir         */
     PyObject *meth;                         /* Objet à ajouter à la liste  */
 
+#define DEX_CLASS_DIRECT_METHODS_ATTRIB PYTHON_GETSET_DEF           \
+(                                                                   \
+    "direct_methods", py_dex_class_get_methods, NULL,               \
+    "List of direct methods of the Dex class, None if none and"     \
+    " None on error.",                                              \
+    (void *)1                                                       \
+)
+
+#define DEX_CLASS_VIRTUAL_METHODS_ATTRIB PYTHON_GETSET_DEF          \
+(                                                                   \
+    "virtual_methods", py_dex_class_get_methods, NULL,              \
+    "List of virtual methods of the Dex class, None if none and"    \
+    " None on error.",                                              \
+    NULL                                                            \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     virtual = (closure == NULL);
@@ -426,6 +493,12 @@ static PyObject *py_dex_class_get_source_file(PyObject *self, void *closure)
     GDexClass *class;                       /* Version native              */
     const char *file;                       /* Fichier à l'origine du code */
 
+#define DEX_CLASS_SOURCE_FILE_ATTRIB PYTHON_GET_DEF_FULL        \
+(                                                                   \
+    source_file, py_dex_class,                                  \
+    "Source file of the Dex class, None on error."                                               \
+)
+
     class = G_DEX_CLASS(pygobject_get(self));
 
     file = g_dex_class_get_source_file(class);
@@ -463,46 +536,16 @@ PyTypeObject *get_python_dex_class_type(void)
     };
 
     static PyGetSetDef py_dex_class_getseters[] = {
-        {
-            "definition", py_dex_class_get_definition, NULL,
-            "Native definition of the Dex class.", NULL
-        },
-        {
-            "data", py_dex_class_get_data, NULL,
-            "Native data of the Dex class, if any.", NULL
-        },
-        {
-            "type", py_dex_class_get_class_type, NULL,
-            "Android type of the Dex class, None on error.", NULL
-        },
-        {
-            "super", py_dex_class_get_superclass_type, NULL,
-            "Android type of the parent Dex class, None on error.", NULL
-        },
-        {
-            "interfaces", py_dex_class_get_interface_types, NULL,
-            "Interface Android types of the Dex class, None if none and None on error.", NULL
-        },
-        {
-            "static_fields", py_dex_class_get_fields, NULL,
-            "List of static fields of the Dex class, None if none and None on error.", NULL
-        },
-        {
-            "instance_fields", py_dex_class_get_fields, NULL,
-            "List of static fields of the Dex class, None if none and None on error.", py_dex_class_get_fields
-        },
-        {
-            "direct_methods", py_dex_class_get_methods, NULL,
-            "List of direct methods of the Dex class, None if none and None on error.", py_dex_class_get_methods
-        },
-        {
-            "virtual_methods", py_dex_class_get_methods, NULL,
-            "List of virtual methods of the Dex class, None if none and None on error.", NULL
-        },
-        {
-            "source_file", py_dex_class_get_source_file, NULL,
-            "Source file of the Dex class, None on error.", NULL
-        },
+        DEX_CLASS_DEFINITION_ATTRIB,
+        DEX_CLASS_DATA_ATTRIB,
+        DEX_CLASS_TYPE_ATTRIB,
+        DEX_CLASS_SUPER_ATTRIB,
+        DEX_CLASS_INTERFACES_ATTRIB,
+        DEX_CLASS_STATIC_FIELDS_ATTRIB,
+        DEX_CLASS_INSTANCE_FIELDS_ATTRIB,
+        DEX_CLASS_DIRECT_METHODS_ATTRIB,
+        DEX_CLASS_VIRTUAL_METHODS_ATTRIB,
+        DEX_CLASS_SOURCE_FILE_ATTRIB,
         { NULL }
     };
 
@@ -515,7 +558,7 @@ PyTypeObject *get_python_dex_class_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide Dex class.",
+        .tp_doc         = DEX_CLASS_DOC,
 
         .tp_methods     = py_dex_class_methods,
         .tp_getset      = py_dex_class_getseters
diff --git a/plugins/dex/python/constants.c b/plugins/dex/python/constants.c
index 3e77fd6..b43e3f1 100644
--- a/plugins/dex/python/constants.c
+++ b/plugins/dex/python/constants.c
@@ -32,13 +32,9 @@
 
 
 
-/* Définit les constantes communes pour le format Dex. */
-static bool define_python_dex_format_common_constants(PyTypeObject *);
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
+*  Paramètres  : type = type dont le dictionnaire est à compléter.            *
 *                                                                             *
 *  Description : Définit les constantes communes pour le format Dex.          *
 *                                                                             *
@@ -48,56 +44,43 @@ static bool define_python_dex_format_common_constants(PyTypeObject *);
 *                                                                             *
 ******************************************************************************/
 
-static bool define_python_dex_format_common_constants(PyTypeObject *obj_type)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = true;
-
-    /* Définition des drapeaux d'accès */
-
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_PUBLIC);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_PRIVATE);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_PROTECTED);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_STATIC);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_FINAL);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_SYNCHRONIZED);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_VOLATILE);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_BRIDGE);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_TRANSIENT);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_VARARGS);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_NATIVE);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_INTERFACE);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_ABSTRACT);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_STRICT);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_SYNTHETIC);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_ANNOTATION);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_ENUM);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_CONSTRUCTOR);
-    if (result) result = PyDict_AddULongMacro(obj_type, ACC_DECLARED_SYNCHRONIZED);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
-*                                                                             *
-*  Description : Définit les constantes pour le format Dex.                   *
-*                                                                             *
-*  Retour      : true en cas de succès de l'opération, false sinon.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool define_python_dex_format_constants(PyTypeObject *obj_type)
+bool define_python_dex_format_common_constants(PyTypeObject *type)
 {
     bool result;                            /* Bilan à retourner           */
-
-    result = define_python_dex_format_common_constants(obj_type);
+    PyObject *values;                       /* Groupe de valeurs à établir */
+
+    values = PyDict_New();
+
+    result = add_const_to_group(values, "PUBLIC", ACC_PUBLIC);
+    if (result) result = add_const_to_group(values, "PRIVATE", ACC_PRIVATE);
+    if (result) result = add_const_to_group(values, "PROTECTED", ACC_PROTECTED);
+    if (result) result = add_const_to_group(values, "STATIC", ACC_STATIC);
+    if (result) result = add_const_to_group(values, "FINAL", ACC_FINAL);
+    if (result) result = add_const_to_group(values, "SYNCHRONIZED", ACC_SYNCHRONIZED);
+    if (result) result = add_const_to_group(values, "VOLATILE", ACC_VOLATILE);
+    if (result) result = add_const_to_group(values, "BRIDGE", ACC_BRIDGE);
+    if (result) result = add_const_to_group(values, "TRANSIENT", ACC_TRANSIENT);
+    if (result) result = add_const_to_group(values, "VARARGS", ACC_VARARGS);
+    if (result) result = add_const_to_group(values, "NATIVE", ACC_NATIVE);
+    if (result) result = add_const_to_group(values, "INTERFACE", ACC_INTERFACE);
+    if (result) result = add_const_to_group(values, "ABSTRACT", ACC_ABSTRACT);
+    if (result) result = add_const_to_group(values, "STRICT", ACC_STRICT);
+    if (result) result = add_const_to_group(values, "SYNTHETIC", ACC_SYNTHETIC);
+    if (result) result = add_const_to_group(values, "ANNOTATION", ACC_ANNOTATION);
+    if (result) result = add_const_to_group(values, "ENUM", ACC_ENUM);
+    if (result) result = add_const_to_group(values, "CONSTRUCTOR", ACC_CONSTRUCTOR);
+    if (result) result = add_const_to_group(values, "DECLARED_SYNCHRONIZED", ACC_DECLARED_SYNCHRONIZED);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, true, "AccessFlags", values,
+                                            "Accessibility and overall properties of classes and class members.");
+
+ exit:
 
     return result;
 
diff --git a/plugins/dex/python/constants.h b/plugins/dex/python/constants.h
index 802bf2f..41618a4 100644
--- a/plugins/dex/python/constants.h
+++ b/plugins/dex/python/constants.h
@@ -31,8 +31,8 @@
 
 
 
-/* Définit les constantes pour le format Dex. */
-bool define_python_dex_format_constants(PyTypeObject *);
+/* Définit les constantes communes pour le format Dex. */
+bool define_python_dex_format_common_constants(PyTypeObject *);
 
 
 
diff --git a/plugins/dex/python/field.c b/plugins/dex/python/field.c
index 69faccc..1381af6 100644
--- a/plugins/dex/python/field.c
+++ b/plugins/dex/python/field.c
@@ -36,6 +36,10 @@
 
 
 
+#define DEX_FIELD_DOC                                               \
+    "The DexField object handles a field linked to a DEX class."
+
+
 /* Fournit les indications Dex concernant le champ de classe. */
 static PyObject *py_dex_field_get_encoded(PyObject *, void *);
 
@@ -63,6 +67,12 @@ static PyObject *py_dex_field_get_encoded(PyObject *self, void *closure)
     GDexField *field;                       /* Version native              */
     const encoded_field *info;              /* Elément à traiter           */
 
+#define DEX_FIELD_ENCODED_ATTRIB PYTHON_GET_DEF_FULL    \
+(                                                       \
+    encoded, py_dex_field,                              \
+    "Encoded information about the Dex field."          \
+)
+
     field = G_DEX_FIELD(pygobject_get(self));
 
     info = g_dex_field_get_dex_info(field);
@@ -93,6 +103,12 @@ static PyObject *py_dex_field_get_variable(PyObject *self, void *closure)
     GDexField *field;                       /* Version native              */
     GBinVariable *variable;                 /* Variable correspondante     */
 
+#define DEX_FIELD_VARIABLE_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                       \
+    variable, py_dex_field,                             \
+    "Chrysalide variable for the Dex field."            \
+)
+
     field = G_DEX_FIELD(pygobject_get(self));
 
     variable = g_dex_field_get_variable(field);
@@ -125,14 +141,8 @@ PyTypeObject *get_python_dex_field_type(void)
     };
 
     static PyGetSetDef py_dex_field_getseters[] = {
-        {
-            "encoded", py_dex_field_get_encoded, NULL,
-            "Encoded information about the Dex field.", NULL
-        },
-        {
-            "variable", py_dex_field_get_variable, NULL,
-            "Chrysalide variable for the Dex field.", NULL
-        },
+        DEX_FIELD_ENCODED_ATTRIB,
+        DEX_FIELD_VARIABLE_ATTRIB,
         { NULL }
     };
 
@@ -145,7 +155,7 @@ PyTypeObject *get_python_dex_field_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide Dex class field.",
+        .tp_doc         = DEX_FIELD_DOC,
 
         .tp_methods     = py_dex_field_methods,
         .tp_getset      = py_dex_field_getseters
diff --git a/plugins/dex/python/format.c b/plugins/dex/python/format.c
index 6e3d7d7..c1e4c40 100644
--- a/plugins/dex/python/format.c
+++ b/plugins/dex/python/format.c
@@ -73,6 +73,15 @@ static PyObject *py_dex_format_new(PyTypeObject *type, PyObject *args, PyObject
     int ret;                                /* Bilan de lecture des args.  */
     GExeFormat *format;                     /* Création GLib à transmettre */
 
+#define DEX_FORMAT_DOC                                                  \
+    "DexFormat deals with DEX format.\n"                                \
+    "\n"                                                                \
+    "Instances can be created using the following constructor:\n"       \
+    "\n"                                                                \
+    "    DexFormat(content)"                                            \
+    "\n"                                                                \
+    "Where content is a pychrysalide.analysis.BinContent object."       \
+
     ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
     if (!ret) return NULL;
 
@@ -238,7 +247,7 @@ PyTypeObject *get_python_dex_format_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide Dex format",
+        .tp_doc         = DEX_FORMAT_DOC,
 
         .tp_methods     = py_dex_format_methods,
         .tp_getset      = py_dex_format_getseters,
@@ -265,18 +274,17 @@ PyTypeObject *get_python_dex_format_type(void)
 
 bool register_python_dex_format(PyObject *module)
 {
-    PyTypeObject *py_dex_format_type;       /* Type Python 'DexFormat'     */
+    PyTypeObject *type;                     /* Type Python 'DexFormat'     */
     PyObject *dict;                         /* Dictionnaire du module      */
 
-    py_dex_format_type = get_python_dex_format_type();
+    type = get_python_dex_format_type();
 
     dict = PyModule_GetDict(module);
 
-    if (!register_class_for_pygobject(dict, G_TYPE_DEX_FORMAT,
-                                  py_dex_format_type, get_python_executable_format_type()))
+    if (!register_class_for_pygobject(dict, G_TYPE_DEX_FORMAT, type, get_python_executable_format_type()))
         return false;
 
-    if (!define_python_dex_format_constants(py_dex_format_type))
+    if (!define_python_dex_format_common_constants(type))
         return false;
 
     return true;
diff --git a/plugins/dex/python/method.c b/plugins/dex/python/method.c
index 6cf9abd..fab8e2e 100644
--- a/plugins/dex/python/method.c
+++ b/plugins/dex/python/method.c
@@ -36,6 +36,11 @@
 
 
 
+#define DEX_METHOD_DOC                                                  \
+    "The DexMethod handles a method defined in a DEX format."           \
+
+
+
 /* Fournit les identifiants Dex concernant la méthode. */
 static PyObject *py_dex_method_get_id_item(PyObject *, void *);
 
@@ -77,7 +82,7 @@ static PyObject *py_dex_method_get_id_item(PyObject *self, void *closure)
     "All the fields are extracted from the Dex *method_id_item* structure:\n"           \
     "* class_idx: index into the *type_ids* list for the definer of the method ;\n"     \
     "* proto_idx: index into the *proto_ids* list for the prototype of the method ;\n"  \
-    "* name_idx: index  into the *string_ids* list for the name of the method."         \
+    "* name_idx: index into the *string_ids* list for the name of the method."          \
 )
 
     method = G_DEX_METHOD(pygobject_get(self));
@@ -110,6 +115,17 @@ static PyObject *py_dex_method_get_encoded(PyObject *self, void *closure)
     GDexMethod *method;                     /* Version native              */
     const encoded_method *info;             /* Elément à traiter           */
 
+#define DEX_METHOD_ENCODED_ATTRIB PYTHON_GET_DEF_FULL                                           \
+(                                                                                               \
+    encoded, py_dex_method,                                                                     \
+    "pychrysalide.PyStructObject instance for encoded information about the Dex method.\n"      \
+    "\n"                                                                                        \
+    "All the fields are extracted from the Dex *encoded_method* structure:\n"                   \
+    "* method_idx_diff: index into the *method_ids* list for the identity of the method ;\n"    \
+    "* access_flags: access flags for the method ;\n"                                           \
+    "* code_off: offset from the start of the file to the code structure for the method."       \
+)
+
     method = G_DEX_METHOD(pygobject_get(self));
 
     info = g_dex_method_get_dex_info(method);
@@ -140,6 +156,22 @@ static PyObject *py_dex_method_get_code_item(PyObject *self, void *closure)
     GDexMethod *method;                     /* Version native              */
     const code_item *body;                  /* Elément à traiter           */
 
+#define DEX_METHOD_CODE_ITEM_ATTRIB PYTHON_GET_DEF_FULL                                         \
+(                                                                                               \
+    code_item, py_dex_method,                                                                   \
+    "pychrysalide.PyStructObject instance of code information about the Dex method,"            \
+    " or None if none.\n"                                                                       \
+    "\n"                                                                                        \
+    "All the fields are extracted from the Dex *code_item* structure:\n"                        \
+    "* registers_size: the number of registers used by the code ;\n"                            \
+    "* ins_size: number of words of incoming arguments to the method that the code is for ;\n"  \
+    "* outs_size: number of words of outgoing argument space required for invocation ;\n"       \
+    "* tries_size: number of *try_items* for the instance ;\n"                                  \
+    "* debug_info_off: offset from the start of the file to the debug info sequence"            \
+    " for this code, or 0 no such information ;\n"                                              \
+    "* insns_size: size of the instructions list, in 16-bit code units."                        \
+)
+
     method = G_DEX_METHOD(pygobject_get(self));
 
     body = g_dex_method_get_dex_body(method);
@@ -177,6 +209,14 @@ static PyObject *py_dex_method_get_routine(PyObject *self, void *closure)
     GDexMethod *method;                     /* Version native              */
     GBinRoutine *routine;                   /* Routine correspondante      */
 
+#define DEX_METHOD_ROUTINE_ATTRIB PYTHON_GET_DEF_FULL                       \
+(                                                                           \
+    routine, py_dex_method,                                                 \
+    "DEX method as seen from Chrysalide.\n"                                 \
+    "\n"                                                                    \
+    "The result is a pychrysalide.analysis.BinRoutine instance or None."    \
+)
+
     method = G_DEX_METHOD(pygobject_get(self));
 
     routine = g_dex_method_get_routine(method);
@@ -210,18 +250,9 @@ PyTypeObject *get_python_dex_method_type(void)
 
     static PyGetSetDef py_dex_method_getseters[] = {
         DEX_METHOD_ID_ITEM_ATTRIB,
-        {
-            "encoded", py_dex_method_get_encoded, NULL,
-            "Encoded information about the Dex method.", NULL
-        },
-        {
-            "code_item", py_dex_method_get_code_item, NULL,
-            "Code information about the Dex method, None if none.", NULL
-        },
-        {
-            "routine", py_dex_method_get_routine, NULL,
-            "Chrysalide routine for the Dex method.", NULL
-        },
+        DEX_METHOD_ENCODED_ATTRIB,
+        DEX_METHOD_CODE_ITEM_ATTRIB,
+        DEX_METHOD_ROUTINE_ATTRIB,
         { NULL }
     };
 
@@ -234,7 +265,7 @@ PyTypeObject *get_python_dex_method_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide Dex method.",
+        .tp_doc         = DEX_METHOD_DOC,
 
         .tp_methods     = py_dex_method_methods,
         .tp_getset      = py_dex_method_getseters
diff --git a/plugins/dex/python/module.c b/plugins/dex/python/module.c
index e375ad7..9fbc29c 100644
--- a/plugins/dex/python/module.c
+++ b/plugins/dex/python/module.c
@@ -59,12 +59,20 @@ bool add_format_dex_module_to_python_module(void)
     PyObject *super;                        /* Module à compléter          */
     PyObject *module;                       /* Sous-module mis en place    */
 
+#define DEX_MODULE_DOC                                                          \
+    "This module provides several features to deal with the Dalvik Executable"  \
+    " (DEX) format.\n"                                                          \
+    "\n"                                                                        \
+    "The layout of such a format is described at:"                              \
+    " https://source.android.com/devices/tech/dalvik/dex-format"
+
+
     static PyModuleDef py_chrysalide_dex_module = {
 
         .m_base = PyModuleDef_HEAD_INIT,
 
         .m_name = "pychrysalide.format.dex",
-        .m_doc = "Python module for Chrysalide.format.dex",
+        .m_doc = DEX_MODULE_DOC,
 
         .m_size = -1,
 
diff --git a/plugins/dex/python/routine.c b/plugins/dex/python/routine.c
index ef85cc7..31410c7 100644
--- a/plugins/dex/python/routine.c
+++ b/plugins/dex/python/routine.c
@@ -36,6 +36,15 @@
 
 
 
+#define DEX_ROUTINE_DOC                                                 \
+    "The DexRoutine is a definition of binary routine for DEX methods." \
+    "\n"                                                                \
+    "The only reason for such an object to exist is to provide a link"  \
+    " to a pychrysalide.format.dex.DexMethod from a"                    \
+    " pychrysalide.analysis.BinRoutine."
+
+
+
 /* Fournit la méthode liée à une routine d'origine Dex. */
 static PyObject *py_dex_routine_get_method(PyObject *, void *);
 
@@ -61,6 +70,14 @@ static PyObject *py_dex_routine_get_method(PyObject *self, void *closure)
     GDexRoutine *routine;                   /* Version native              */
     GDexMethod *method;                     /* Méthode correspondante      */
 
+#define DEX_ROUTINE_METHOD_ATTRIB PYTHON_GET_DEF_FULL                       \
+(                                                                           \
+    method, py_dex_routine,                                                 \
+    "Dex method attached to the Dex routine."                               \
+    "\n"                                                                    \
+    "The result is a pychrysalide.format.dex.DexMethod instance or None."   \
+)
+
     routine = G_DEX_ROUTINE(pygobject_get(self));
 
     method = g_dex_routine_get_method(routine);
@@ -102,10 +119,7 @@ PyTypeObject *get_python_dex_routine_type(void)
     };
 
     static PyGetSetDef py_dex_routine_getseters[] = {
-        {
-            "method", py_dex_routine_get_method, NULL,
-            "Dex method attached to the Dex routine.", NULL
-        },
+        DEX_ROUTINE_METHOD_ATTRIB,
         { NULL }
     };
 
@@ -118,7 +132,7 @@ PyTypeObject *get_python_dex_routine_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide Dex routine.",
+        .tp_doc         = DEX_ROUTINE_DOC,
 
         .tp_methods     = py_dex_routine_methods,
         .tp_getset      = py_dex_routine_getseters
-- 
cgit v0.11.2-87-g4458