Simple Python module to test dictionaries
Just reviewing get_conf.


Support for Python 2.7 is planned to end in 2020, so it is not a good time to be starting new projects that run on Python 2.7 only.
The line:

PyDict_SetItemString(dict, "num_foo", PyLong_FromLong(42));


has three problems! First, PyLong_FromLong can fail (returning NULL), but your code does not check for this. Second, PyLong_FromLong returns a "new reference" which you never decrement, so this object will leak. Third, PyDict_SetItemString can also fail (returning -1), but your code does not check for this.

So, inconvenient as it may seem, you must write something like:

PyObject *num_foo = PyLong_FromLong(42);
if (num_foo == NULL) {
    /* handle failure somehow */
}
if (PyDict_SetItemString(dict, "num_foo", num_foo) != 0) {
    /* handle failure somehow */
}
Py_DECREF(num_foo);

One approach to writing a function that has many error cases is to have an error-handling section which is responsible for decrementing all the references that were acquired by the code. The error handlers should be arranged in reverse order, like this:

static PyObject *get_conf(PyObject *self, PyObject *args)
{
    PyObject *dict = PyDict_New(); /* (1) */
    if (dict == NULL) {
        goto fail_dict;
    }
    PyObject *enabled = g_enabled ? Py_True : Py_False;
    if (PyDict_SetItemString(dict, "enabled", enabled) != 0) {
        goto fail_set_enabled;
    }
    PyObject *num_foo = PyLong_FromLong(42);
    if (num_foo == NULL) {
        goto fail_num_foo;
    }
    if (PyDict_SetItemString(dict, "num_foo", num_foo) != 0) {
        goto fail_set_num_foo;
    }
    Py_DECREF(num_foo);
    return dict; /* (2) */

fail_set_num_foo:
    Py_DECREF(num_foo);    
fail_num_foo:
fail_set_enabled:
    Py_DECREF(dict); /* (3) */
fail_dict:
    return NULL;
}


You can then check the reference-counting behaviour for each object. For example, the dict object gets one reference at (1), which is either returned to the caller at (2), or else decremented at (3). So this object does not leak.
The general inconvenience and delicacy of reference counting in C extension modules suggests that you might be better off with a hybrid approach where you implement a minimal hardware interface layer in C, and then package this up in Python to provide a friendlier interface.

The way this would work is that in C you would make a module _myfoo which contains functions like this:

static PyObject *get_enabled(PyObject *self, PyObject *args)
{
    return PyBool_FromLong(g_enabled);
}

static PyObject *get_num_foo(PyObject *self, PyObject *args)
{
    return PyLong_FromLong(g_val);
}


which are so simple that there is little risk of getting the reference counting wrong, and then in Python you would write a module myfoo containing:

import _myfoo

def get_conf():
    """Return hardware configuration dictionary with keys:

    enabled: bool -- [documentation here]
    num_foo: int -- [documentation here]
    """
    return dict(enabled=_myfoo.get_enabled(),
                num_foo=_myfoo.get_num_foo())


which you can see is much simpler than trying to allocate a dictionary in C.