# Modernization

Before porting a C extension to Python 3, you’ll need to make sure that you’re not using features deprecated even in Python 2. Also, many of Python 3’s improvements have been backported to Python 2.6, and using them will make the porting process easier.

For all changes you do, be sure add tests to ensure you do not break anything.

## PyObject Structure Members

To conform to C’s strict aliasing rules, PyObject_HEAD, which provides members such as `ob_type` and `ob_refcnt`, is a separate struct in Python 3. Access to these members is provided by macros, which have been ported to Python 2.6:

Instead of | use
--- | ---
obj->ob_type | Py_TYPE(obj)
obj->ob_refcnt | Py_REFCNT(obj)
obj->ob_size | Py_SIZE(obj)

And for initialization of type objects, the sequence

    PyObject_HEAD_INIT(NULL)
    0, /* ob_size */

must be replaced with

    PyVarObject_HEAD_INIT(NULL, 0)

## Adding module-level constants

Often, module initialization uses code like this:

    PyModule_AddObject(m, "RDWR", PyInt_FromLong(O_RDWR));
    PyModule_AddObject(m, "__version__", PyString_FromString("6.28"));

Python 2.6 introduced convenience functions, which are shorter to write:

    PyModule_AddIntConstant(m, "RDWR", O_RDWR)
    PyModule_AddStringConstant(m, "__version__", "6.28")

These will use native int and str types in both Python versions.

## New-Style Classes

The old-style classes (`PyClass_*` and `PyInstance_*`) will be removed in Python 3. Instead, use type objects, which have been available since Python 2.2.

## PyCObject to PyCapsule

The PyCObject API has been removed in Python 3.3. You should instead use its replacement, PyCapsule, which is available in Python 2.7 and 3.1+. For the rationale behind Capsules, see CPython issue 5630.

If you need to support Python 2.6, you can use `capsulethunk.h`, which implements the PyCapsule API (with some limitations) in terms of PyCObject. For instructions, see the chapter PyCapsule API for Python 2.6.

The port to PyCapsule API should be straightforward:

- Instead of `PyCObject_FromVoidPtr(obj, destr)`, use `PyCapsule_New(obj, name, destr)`. If the capsule will be available as a module attribute, use `"<modulename>.<attrname>"` for name. Otherwise, use your best judgment, but try making the name unique.

- Instead of `PyCObject_FromVoidPtrAndDesc(obj, desc, destr)`, use `py3:PyCapsule_New()` as above; then call `PyCapsule_SetContext(obj, desc)`.

- Instead of `PyCObject_AsVoidPtr(obj)`, use `PyCapsule_GetPointer(obj, name)`. You will need to provide a capsule name, which is checked at runtime as a form of type safety.

- Instead of `py2:PyCObject_GetDesc()`, use `py3:PyCapsule_GetContext()`.

- Instead of `py2:PyCObject_SetVoidPtr()`, use `py3:PyCapsule_SetPointer()`.

- Change all CObject destructors to `PyCapsule destructors`, which take the PyCapsule object as their only argument.

## Comparisons

Note

In previous versions, this chapter talked about rich comparison, but those changes are better left to porting.

## Done!

When your project is sufficiently modernized, and the tests still pass under Python 2, you’re ready to start the actual Porting.