Skip to content

Commit a6fce96

Browse files
committed
Review edits of canonical_function.rst and exceptions.rst
1 parent bb99210 commit a6fce96

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

doc/sphinx/source/canonical_function.rst

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44
.. index::
55
single: C Functions; Coding Pattern
66

7+
.. _chapter_function_pattern:
8+
79
===========================================
810
A Pythonic Coding Pattern for C Functions
911
===========================================
1012

1113
Principle
1214
===============
1315

14-
To avoid all the errors we have seen it is useful to have a C coding pattern for handling ``PyObjects`` that does the following:
16+
To avoid all the errors we have seen, particularly in :ref:`chapter_refcount` it is useful to have a C coding pattern
17+
for handling ``PyObjects`` that does the following:
1518

1619
* No early returns and a single place for clean up code.
1720
* Borrowed references incref'd and decref'd correctly.
18-
* No stale Exception from previous execution path.
21+
* No stale Exception from a previous execution path.
1922
* Exceptions set and tested.
2023
* NULL is returned when an exception is set.
2124
* Non-NULL is returned when no exception is set.
@@ -56,15 +59,17 @@ Check that there are no lingering Exceptions:
5659
5760
assert(! PyErr_Occurred());
5861
59-
An alternative check for no lingering Exceptions:
62+
An alternative check for no lingering Exceptions with non-debug builds:
6063

6164
.. code-block:: c
6265
6366
if(PyErr_Occurred()) {
67+
PyObject_Print(PyErr_Occurred(), stdout, Py_PRINT_RAW);
6468
goto except;
6569
}
6670
67-
Now we assume that any argument is a "Borrowed" reference so we increment it (we need a matching ``Py_DECREF`` before function exit, see below). The first pattern assumes a non-NULL argument.
71+
Now we assume that any argument is a "Borrowed" reference so we increment it (we need a matching ``Py_DECREF`` before
72+
function exit, see below). The first pattern assumes a non-NULL argument.
6873

6974
.. code-block:: c
7075
@@ -79,9 +84,10 @@ If you are willing to accept NULL arguments then this pattern would be more suit
7984
Py_INCREF(arg_1);
8085
}
8186
82-
Of course the same test must be used when calling ``Py_DECREF``, or just use ``Py_XDECREF``.
87+
Or just use ``Py_XINCREF``.
8388

84-
Now we create any local objects, if they are "Borrowed" references we need to incref them. With any abnormal behaviour we do a local jump straight to the cleanup code.
89+
Now we create any local objects, if they are "Borrowed" references we need to incref them.
90+
With any abnormal behaviour we do a local jump straight to the cleanup code.
8591

8692
.. code-block:: c
8793
@@ -173,7 +179,8 @@ Here is the complete code with minimal comments:
173179
assert(arg_1);
174180
Py_INCREF(arg_1);
175181
176-
/* obj_a = ...; */
182+
/* Create obj_a = ...; */
183+
177184
if (! obj_a) {
178185
PyErr_SetString(PyExc_ValueError, "Ooops.");
179186
goto except;

doc/sphinx/source/exceptions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ These CPython calls are the most useful:
2222
* ``PyErr_Format(...)`` - To set an exception type with a formatted string.
2323
`PyErr_Format() documentation <https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Format>`_
2424
* ``PyErr_Occurred()`` - To check if an exception has already been set in the flow of control.
25+
This returns the current exception or NULL if nothing set.
2526
`PyErr_Occurred() documentation <https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Occurred>`_
2627
* ``PyErr_Clear()`` - Clearing any set exceptions, have good reason to do this!
2728
`PyErr_Clear() documentation <https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Clear>`_

0 commit comments

Comments
 (0)