Skip to content

Commit

Permalink
Issue python#25701: Document that some C APIs can both set and delete…
Browse files Browse the repository at this point in the history
… items

Also document that using the dedicated functions to delete items is
preferred. Using PyObject_SetAttr/String() and PySequence_SetItem/Slice() for
deletion is deprecated.
  • Loading branch information
vadmium committed Nov 30, 2016
1 parent a52b567 commit ed82604
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 32 deletions.
27 changes: 19 additions & 8 deletions Doc/c-api/object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,35 @@ Object Protocol
.. c:function:: int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v)
Set the value of the attribute named *attr_name*, for object *o*, to the value
*v*. Returns ``-1`` on failure. This is the equivalent of the Python statement
*v*. Raise an exception and return ``-1`` on failure;
return ``0`` on success. This is the equivalent of the Python statement
``o.attr_name = v``.
If *v* is *NULL*, the attribute is deleted, however this feature is
deprecated in favour of using :c:func:`PyObject_DelAttr`.
.. c:function:: int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v)
Set the value of the attribute named *attr_name*, for object *o*, to the value
*v*. Returns ``-1`` on failure. This is the equivalent of the Python statement
*v*. Raise an exception and return ``-1`` on failure;
return ``0`` on success. This is the equivalent of the Python statement
``o.attr_name = v``.
If *v* is *NULL*, the attribute is deleted, however this feature is
deprecated in favour of using :c:func:`PyObject_DelAttrString`.
.. c:function:: int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
Generic attribute setter function that is meant to be put into a type
object's ``tp_setattro`` slot. It looks for a data descriptor in the
Generic attribute setter and deleter function that is meant
to be put into a type object's :c:member:`~PyTypeObject.tp_setattro`
slot. It looks for a data descriptor in the
dictionary of classes in the object's MRO, and if found it takes preference
over setting the attribute in the instance dictionary. Otherwise, the
attribute is set in the object's :attr:`~object.__dict__` (if present).
Otherwise, an :exc:`AttributeError` is raised and ``-1`` is returned.
over setting or deleting the attribute in the instance dictionary. Otherwise, the
attribute is set or deleted in the object's :attr:`~object.__dict__` (if present).
On success, ``0`` is returned, otherwise an :exc:`AttributeError`
is raised and ``-1`` is returned.
.. c:function:: int PyObject_DelAttr(PyObject *o, PyObject *attr_name)
Expand Down Expand Up @@ -367,7 +377,8 @@ attribute is considered sufficient for this determination.
.. c:function:: int PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v)
Map the object *key* to the value *v*. Returns ``-1`` on failure. This is the
Map the object *key* to the value *v*. Raise an exception and
return ``-1`` on failure; return ``0`` on success. This is the
equivalent of the Python statement ``o[key] = v``.
Expand Down
12 changes: 10 additions & 2 deletions Doc/c-api/sequence.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ Sequence Protocol
.. c:function:: int PySequence_SetItem(PyObject *o, Py_ssize_t i, PyObject *v)
Assign object *v* to the *i*\ th element of *o*. Returns ``-1`` on failure. This
Assign object *v* to the *i*\ th element of *o*. Raise an exception
and return ``-1`` on failure; return ``0`` on success. This
is the equivalent of the Python statement ``o[i] = v``. This function *does
not* steal a reference to *v*.
If *v* is *NULL*, the element is deleted, however this feature is
deprecated in favour of using :c:func:`PySequence_DelItem`.
.. versionchanged:: 2.5
This function used an :c:type:`int` type for *i*. This might require
changes in your code for properly supporting 64-bit systems.
Expand All @@ -104,7 +108,11 @@ Sequence Protocol
.. c:function:: int PySequence_SetSlice(PyObject *o, Py_ssize_t i1, Py_ssize_t i2, PyObject *v)
Assign the sequence object *v* to the slice in sequence object *o* from *i1* to
*i2*. This is the equivalent of the Python statement ``o[i1:i2] = v``.
*i2*. Raise an exception and return ``-1`` on failure; return ``0`` on success.
This is the equivalent of the Python statement ``o[i1:i2] = v``.
If *v* is *NULL*, the slice is deleted, however this feature is
deprecated in favour of using :c:func:`PySequence_DelSlice`.
.. versionchanged:: 2.5
This function used an :c:type:`int` type for *i1* and *i2*. This might
Expand Down
26 changes: 16 additions & 10 deletions Doc/c-api/typeobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,13 @@ type objects) *must* have the :attr:`ob_size` field.

.. c:member:: setattrfunc PyTypeObject.tp_setattr
An optional pointer to the set-attribute-string function.
An optional pointer to the function for setting and deleting attributes.

This field is deprecated. When it is defined, it should point to a function
that acts the same as the :c:member:`~PyTypeObject.tp_setattro` function, but taking a C string
instead of a Python string object to give the attribute name. The signature is
the same as for :c:func:`PyObject_SetAttrString`.
the same as for :c:func:`PyObject_SetAttrString`, but setting
*v* to *NULL* to delete an attribute must be supported.

This field is inherited by subtypes together with :c:member:`~PyTypeObject.tp_setattro`: a subtype
inherits both :c:member:`~PyTypeObject.tp_setattr` and :c:member:`~PyTypeObject.tp_setattro` from its base type when
Expand Down Expand Up @@ -389,9 +390,10 @@ type objects) *must* have the :attr:`ob_size` field.

.. c:member:: setattrofunc PyTypeObject.tp_setattro
An optional pointer to the set-attribute function.
An optional pointer to the function for setting and deleting attributes.

The signature is the same as for :c:func:`PyObject_SetAttr`. It is usually
The signature is the same as for :c:func:`PyObject_SetAttr`, but setting
*v* to *NULL* to delete an attribute must be supported. It is usually
convenient to set this field to :c:func:`PyObject_GenericSetAttr`, which
implements the normal way of setting object attributes.

Expand Down Expand Up @@ -831,7 +833,7 @@ The next fields, up to and including :c:member:`~PyTypeObject.tp_weaklist`, only
typedef struct PyGetSetDef {
char *name; /* attribute name */
getter get; /* C function to get the attribute */
setter set; /* C function to set the attribute */
setter set; /* C function to set or delete the attribute */
char *doc; /* optional doc string */
void *closure; /* optional additional data for getter and setter */
} PyGetSetDef;
Expand Down Expand Up @@ -877,12 +879,14 @@ The next fields, up to and including :c:member:`~PyTypeObject.tp_weaklist`, only

.. c:member:: descrsetfunc PyTypeObject.tp_descr_set
An optional pointer to a "descriptor set" function.
An optional pointer to a function for setting and deleting
a descriptor's value.

The function signature is ::

int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);

The *value* argument is set to *NULL* to delete the value.
This field is inherited by subtypes.

.. XXX explain.
Expand Down Expand Up @@ -1263,9 +1267,11 @@ Mapping Object Structures

.. c:member:: objobjargproc PyMappingMethods.mp_ass_subscript
This function is used by :c:func:`PyObject_SetItem` and has the same
signature. If this slot is *NULL*, the object does not support item
assignment.
This function is used by :c:func:`PyObject_SetItem` and
:c:func:`PyObject_DelItem`. It has the same signature as
:c:func:`PyObject_SetItem`, but *v* can also be set to *NULL* to delete
an item. If this slot is *NULL*, the object does not support item
assignment and deletion.


.. _sequence-structs:
Expand Down Expand Up @@ -1314,7 +1320,7 @@ Sequence Object Structures
This function is used by :c:func:`PySequence_SetItem` and has the same
signature. This slot may be left to *NULL* if the object does not support
item assignment.
item assignment and deletion.

.. c:member:: objobjproc PySequenceMethods.sq_contains
Expand Down
24 changes: 12 additions & 12 deletions Include/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
int PyObject_SetAttrString(PyObject *o, char *attr_name, PyObject *v);
Set the value of the attribute named attr_name, for object o,
to the value, v. Returns -1 on failure. This is
the equivalent of the Python statement: o.attr_name=v.
to the value v. Raise an exception and return -1 on failure; return 0 on
success. This is the equivalent of the Python statement o.attr_name=v.
*/

Expand All @@ -201,8 +201,8 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v);
Set the value of the attribute named attr_name, for object o,
to the value, v. Returns -1 on failure. This is
the equivalent of the Python statement: o.attr_name=v.
to the value v. Raise an exception and return -1 on failure; return 0 on
success. This is the equivalent of the Python statement o.attr_name=v.
*/

Expand Down Expand Up @@ -453,9 +453,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
PyAPI_FUNC(int) PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v);

/*
Map the object, key, to the value, v. Returns
-1 on failure. This is the equivalent of the Python
statement: o[key]=v.
Map the object key to the value v. Raise an exception and return -1
on failure; return 0 on success. This is the equivalent of the Python
statement o[key]=v.
*/

PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, char *key);
Expand Down Expand Up @@ -1102,10 +1102,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
PyAPI_FUNC(int) PySequence_SetItem(PyObject *o, Py_ssize_t i, PyObject *v);

/*
Assign object v to the ith element of o. Returns
-1 on failure. This is the equivalent of the Python
statement: o[i]=v.
Assign object v to the ith element of o. Raise an exception and return
-1 on failure; return 0 on success. This is the equivalent of the
Python statement o[i]=v.
*/

PyAPI_FUNC(int) PySequence_DelItem(PyObject *o, Py_ssize_t i);
Expand All @@ -1121,7 +1120,8 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

/*
Assign the sequence object, v, to the slice in sequence
object, o, from i1 to i2. Returns -1 on failure. This is the
object, o, from i1 to i2. Raise an exception and return
-1 on failure; return 0 on success. This is the
equivalent of the Python statement: o[i1:i2]=v.
*/

Expand Down

0 comments on commit ed82604

Please sign in to comment.