Skip to content

bpo-35134: Split warnings.h and weakrefobject.h #29042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,8 @@ Removed

Remove also the ``Py_MARSHAL_VERSION`` macro from the limited C API.
(Contributed by Victor Stinner in :issue:`45474`.)

* Exclude :c:func:`PyWeakref_GET_OBJECT` from the limited C API. It never
worked since the :c:type:`PyWeakReference` structure is opaque in the
limited C API.
(Contributed by Victor Stinner in :issue:`35134`.)
20 changes: 20 additions & 0 deletions Include/cpython/warnings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef Py_CPYTHON_WARNINGS_H
# error "this header file must not be included directly"
#endif

PyAPI_FUNC(int) PyErr_WarnExplicitObject(
PyObject *category,
PyObject *message,
PyObject *filename,
int lineno,
PyObject *module,
PyObject *registry);

PyAPI_FUNC(int) PyErr_WarnExplicitFormat(
PyObject *category,
const char *filename, int lineno,
const char *module, PyObject *registry,
const char *format, ...);

// DEPRECATED: Use PyErr_WarnEx() instead.
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
47 changes: 47 additions & 0 deletions Include/cpython/weakrefobject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef Py_CPYTHON_WEAKREFOBJECT_H
# error "this header file must not be included directly"
#endif

/* PyWeakReference is the base struct for the Python ReferenceType, ProxyType,
* and CallableProxyType.
*/
struct _PyWeakReference {
PyObject_HEAD

/* The object to which this is a weak reference, or Py_None if none.
* Note that this is a stealth reference: wr_object's refcount is
* not incremented to reflect this pointer.
*/
PyObject *wr_object;

/* A callable to invoke when wr_object dies, or NULL if none. */
PyObject *wr_callback;

/* A cache for wr_object's hash code. As usual for hashes, this is -1
* if the hash code isn't known yet.
*/
Py_hash_t hash;

/* If wr_object is weakly referenced, wr_object has a doubly-linked NULL-
* terminated list of weak references to it. These are the list pointers.
* If wr_object goes away, wr_object is set to Py_None, and these pointers
* have no meaning then.
*/
PyWeakReference *wr_prev;
PyWeakReference *wr_next;
};

PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head);

PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);

/* Explanation for the Py_REFCNT() check: when a weakref's target is part
of a long chain of deallocations which triggers the trashcan mechanism,
clearing the weakrefs can be delayed long after the target's refcount
has dropped to zero. In the meantime, code accessing the weakref will
be able to "see" the target object even though it is supposed to be
unreachable. See issue #16602. */
#define PyWeakref_GET_OBJECT(ref) \
(Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0 \
? ((PyWeakReference *)(ref))->wr_object \
: Py_None)
4 changes: 4 additions & 0 deletions Include/internal/pycore_warnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ struct _warnings_runtime_state {

extern int _PyWarnings_InitState(PyInterpreterState *interp);

PyAPI_FUNC(PyObject*) _PyWarnings_Init(void);

extern void _PyErr_WarnUnawaitedCoroutine(PyObject *coro);

#ifdef __cplusplus
}
#endif
Expand Down
32 changes: 5 additions & 27 deletions Include/warnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
extern "C" {
#endif

#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject*) _PyWarnings_Init(void);
#endif

PyAPI_FUNC(int) PyErr_WarnEx(
PyObject *category,
const char *message, /* UTF-8 encoded string */
Py_ssize_t stack_level);

PyAPI_FUNC(int) PyErr_WarnFormat(
PyObject *category,
Py_ssize_t stack_level,
Expand All @@ -26,15 +23,7 @@ PyAPI_FUNC(int) PyErr_ResourceWarning(
const char *format, /* ASCII-encoded string */
...);
#endif
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) PyErr_WarnExplicitObject(
PyObject *category,
PyObject *message,
PyObject *filename,
int lineno,
PyObject *module,
PyObject *registry);
#endif

PyAPI_FUNC(int) PyErr_WarnExplicit(
PyObject *category,
const char *message, /* UTF-8 encoded string */
Expand All @@ -44,20 +33,9 @@ PyAPI_FUNC(int) PyErr_WarnExplicit(
PyObject *registry);

#ifndef Py_LIMITED_API
PyAPI_FUNC(int)
PyErr_WarnExplicitFormat(PyObject *category,
const char *filename, int lineno,
const char *module, PyObject *registry,
const char *format, ...);
#endif

/* DEPRECATED: Use PyErr_WarnEx() instead. */
#ifndef Py_LIMITED_API
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
#endif

#ifndef Py_LIMITED_API
void _PyErr_WarnUnawaitedCoroutine(PyObject *coro);
# define Py_CPYTHON_WARNINGS_H
# include "cpython/warnings.h"
# undef Py_CPYTHON_WARNINGS_H
#endif

#ifdef __cplusplus
Expand Down
56 changes: 6 additions & 50 deletions Include/weakrefobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,8 @@
extern "C" {
#endif


typedef struct _PyWeakReference PyWeakReference;

/* PyWeakReference is the base struct for the Python ReferenceType, ProxyType,
* and CallableProxyType.
*/
#ifndef Py_LIMITED_API
struct _PyWeakReference {
PyObject_HEAD

/* The object to which this is a weak reference, or Py_None if none.
* Note that this is a stealth reference: wr_object's refcount is
* not incremented to reflect this pointer.
*/
PyObject *wr_object;

/* A callable to invoke when wr_object dies, or NULL if none. */
PyObject *wr_callback;

/* A cache for wr_object's hash code. As usual for hashes, this is -1
* if the hash code isn't known yet.
*/
Py_hash_t hash;

/* If wr_object is weakly referenced, wr_object has a doubly-linked NULL-
* terminated list of weak references to it. These are the list pointers.
* If wr_object goes away, wr_object is set to Py_None, and these pointers
* have no meaning then.
*/
PyWeakReference *wr_prev;
PyWeakReference *wr_next;
};
#endif

PyAPI_DATA(PyTypeObject) _PyWeakref_RefType;
PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType;
PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType;
Expand All @@ -56,30 +24,18 @@ PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType;


PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob,
PyObject *callback);
PyObject *callback);
PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob,
PyObject *callback);
PyObject *callback);
PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref);

#ifndef Py_LIMITED_API
PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head);

PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
#ifndef Py_LIMITED_API
# define Py_CPYTHON_WEAKREFOBJECT_H
# include "cpython/weakrefobject.h"
# undef Py_CPYTHON_WEAKREFOBJECT_H
#endif

/* Explanation for the Py_REFCNT() check: when a weakref's target is part
of a long chain of deallocations which triggers the trashcan mechanism,
clearing the weakrefs can be delayed long after the target's refcount
has dropped to zero. In the meantime, code accessing the weakref will
be able to "see" the target object even though it is supposed to be
unreachable. See issue #16602. */

#define PyWeakref_GET_OBJECT(ref) \
(Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0 \
? ((PyWeakReference *)(ref))->wr_object \
: Py_None)


#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,8 @@ PYTHON_HEADERS= \
$(srcdir)/Include/cpython/traceback.h \
$(srcdir)/Include/cpython/tupleobject.h \
$(srcdir)/Include/cpython/unicodeobject.h \
$(srcdir)/Include/cpython/warnings.h \
$(srcdir)/Include/cpython/weakrefobject.h \
\
$(srcdir)/Include/internal/pycore_abstract.h \
$(srcdir)/Include/internal/pycore_accu.h \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Exclude :c:func:`PyWeakref_GET_OBJECT` from the limited C API. It never
worked since the :c:type:`PyWeakReference` structure is opaque in the
limited C API.
2 changes: 2 additions & 0 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@
<ClInclude Include="..\Include\cpython\traceback.h" />
<ClInclude Include="..\Include\cpython\tupleobject.h" />
<ClInclude Include="..\Include\cpython\unicodeobject.h" />
<ClInclude Include="..\Include\cpython\warnings.h" />
<ClInclude Include="..\Include\cpython\weakrefobject.h" />
<ClInclude Include="..\Include\datetime.h" />
<ClInclude Include="..\Include\descrobject.h" />
<ClInclude Include="..\Include\dictobject.h" />
Expand Down
6 changes: 6 additions & 0 deletions PCbuild/pythoncore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@
<ClInclude Include="..\Include\cpython\unicodeobject.h">
<Filter>Include\cpython</Filter>
</ClInclude>
<ClInclude Include="..\Include\cpython\warnings.h">
<Filter>Include\cpython</Filter>
</ClInclude>
<ClInclude Include="..\Include\cpython\weakrefobject.h">
<Filter>Include\cpython</Filter>
</ClInclude>
<ClInclude Include="..\Include\cpython\methodobject.h">
<Filter>Include\cpython</Filter>
</ClInclude>
Expand Down