Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
2ec872b3
Commit
2ec872b3
authored
Sep 21, 2018
by
Yury Selivanov
Committed by
GitHub
Sep 21, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-34762: Fix contextvars C API to use PyObject* pointer types. (GH-9473)
parent
b46ad543
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
106 additions
and
45 deletions
+106
-45
Doc/c-api/contextvars.rst
Doc/c-api/contextvars.rst
+29
-10
Doc/whatsnew/3.7.rst
Doc/whatsnew/3.7.rst
+4
-0
Include/context.h
Include/context.h
+9
-11
Misc/NEWS.d/next/Core and Builtins/2018-09-21-11-06-56.bpo-34762.1nN53m.rst
...ore and Builtins/2018-09-21-11-06-56.bpo-34762.1nN53m.rst
+1
-0
Modules/_contextvarsmodule.c
Modules/_contextvarsmodule.c
+1
-1
Python/context.c
Python/context.c
+62
-23
No files found.
Doc/c-api/contextvars.rst
View file @
2ec872b3
...
@@ -5,6 +5,25 @@
...
@@ -5,6 +5,25 @@
Context Variables Objects
Context Variables Objects
-------------------------
-------------------------
.. _contextvarsobjects_pointertype_change:
.. versionchanged:: 3.7.1
.. note::
In Python 3.7.1 the signatures of all context variables
C APIs were **changed** to use :c:type:`PyObject` pointers instead
of :c:type:`PyContext`, :c:type:`PyContextVar`, and
:c:type:`PyContextToken`, e.g.::
// in 3.7.0:
PyContext *PyContext_New(void);
// in 3.7.1+:
PyObject *PyContext_New(void);
See :issue:`34762` for more details.
.. versionadded:: 3.7
.. versionadded:: 3.7
This section details the public C API for the :mod:`contextvars` module.
This section details the public C API for the :mod:`contextvars` module.
...
@@ -56,27 +75,27 @@ Type-check macros:
...
@@ -56,27 +75,27 @@ Type-check macros:
Context object management functions:
Context object management functions:
.. c:function:: Py
Contex
t *PyContext_New(void)
.. c:function:: Py
Objec
t *PyContext_New(void)
Create a new empty context object. Returns ``NULL`` if an error
Create a new empty context object. Returns ``NULL`` if an error
has occurred.
has occurred.
.. c:function:: Py
Context *PyContext_Copy(PyContex
t *ctx)
.. c:function:: Py
Object *PyContext_Copy(PyObjec
t *ctx)
Create a shallow copy of the passed *ctx* context object.
Create a shallow copy of the passed *ctx* context object.
Returns ``NULL`` if an error has occurred.
Returns ``NULL`` if an error has occurred.
.. c:function:: Py
Contex
t *PyContext_CopyCurrent(void)
.. c:function:: Py
Objec
t *PyContext_CopyCurrent(void)
Create a shallow copy of the current thread context.
Create a shallow copy of the current thread context.
Returns ``NULL`` if an error has occurred.
Returns ``NULL`` if an error has occurred.
.. c:function:: int PyContext_Enter(Py
Contex
t *ctx)
.. c:function:: int PyContext_Enter(Py
Objec
t *ctx)
Set *ctx* as the current context for the current thread.
Set *ctx* as the current context for the current thread.
Returns ``0`` on success, and ``-1`` on error.
Returns ``0`` on success, and ``-1`` on error.
.. c:function:: int PyContext_Exit(Py
Contex
t *ctx)
.. c:function:: int PyContext_Exit(Py
Objec
t *ctx)
Deactivate the *ctx* context and restore the previous context as the
Deactivate the *ctx* context and restore the previous context as the
current context for the current thread. Returns ``0`` on success,
current context for the current thread. Returns ``0`` on success,
...
@@ -90,14 +109,14 @@ Context object management functions:
...
@@ -90,14 +109,14 @@ Context object management functions:
Context variable functions:
Context variable functions:
.. c:function:: Py
ContextVar
*PyContextVar_New(const char *name, PyObject *def)
.. c:function:: Py
Object
*PyContextVar_New(const char *name, PyObject *def)
Create a new ``ContextVar`` object. The *name* parameter is used
Create a new ``ContextVar`` object. The *name* parameter is used
for introspection and debug purposes. The *def* parameter may optionally
for introspection and debug purposes. The *def* parameter may optionally
specify the default value for the context variable. If an error has
specify the default value for the context variable. If an error has
occurred, this function returns ``NULL``.
occurred, this function returns ``NULL``.
.. c:function:: int PyContextVar_Get(Py
ContextVar
*var, PyObject *default_value, PyObject **value)
.. c:function:: int PyContextVar_Get(Py
Object
*var, PyObject *default_value, PyObject **value)
Get the value of a context variable. Returns ``-1`` if an error has
Get the value of a context variable. Returns ``-1`` if an error has
occurred during lookup, and ``0`` if no error occurred, whether or not
occurred during lookup, and ``0`` if no error occurred, whether or not
...
@@ -112,13 +131,13 @@ Context variable functions:
...
@@ -112,13 +131,13 @@ Context variable functions:
If the value was found, the function will create a new reference to it.
If the value was found, the function will create a new reference to it.
.. c:function:: Py
ContextToken *PyContextVar_Set(PyContextVar
*var, PyObject *value)
.. c:function:: Py
Object *PyContextVar_Set(PyObject
*var, PyObject *value)
Set the value of *var* to *value* in the current context. Returns a
Set the value of *var* to *value* in the current context. Returns a
pointer to a :c:type:`Py
ContextToken
` object, or ``NULL`` if an error
pointer to a :c:type:`Py
Object
` object, or ``NULL`` if an error
has occurred.
has occurred.
.. c:function:: int PyContextVar_Reset(Py
ContextVar *var, PyContextToken
*token)
.. c:function:: int PyContextVar_Reset(Py
Object *var, PyObject
*token)
Reset the state of the *var* context variable to that it was in before
Reset the state of the *var* context variable to that it was in before
:c:func:`PyContextVar_Set` that returned the *token* was called.
:c:func:`PyContextVar_Set` that returned the *token* was called.
...
...
Doc/whatsnew/3.7.rst
View file @
2ec872b3
...
@@ -2494,3 +2494,7 @@ versions, it respected an ill-defined subset of those environment variables,
...
@@ -2494,3 +2494,7 @@ versions, it respected an ill-defined subset of those environment variables,
while in Python 3.7.0 it didn't read any of them due to :issue:`34247`). If
while in Python 3.7.0 it didn't read any of them due to :issue:`34247`). If
this behavior is unwanted, set :c:data:`Py_IgnoreEnvironmentFlag` to 1 before
this behavior is unwanted, set :c:data:`Py_IgnoreEnvironmentFlag` to 1 before
calling :c:func:`Py_Initialize`.
calling :c:func:`Py_Initialize`.
In 3.7.1 the C API for Context Variables
:ref:`was updated <contextvarsobjects_pointertype_change>` to use
:c:type:`PyObject` pointers. See also :issue:`34762`.
Include/context.h
View file @
2ec872b3
...
@@ -22,19 +22,19 @@ typedef struct _pycontexttokenobject PyContextToken;
...
@@ -22,19 +22,19 @@ typedef struct _pycontexttokenobject PyContextToken;
#define PyContextToken_CheckExact(o) (Py_TYPE(o) == &PyContextToken_Type)
#define PyContextToken_CheckExact(o) (Py_TYPE(o) == &PyContextToken_Type)
PyAPI_FUNC
(
Py
Contex
t
*
)
PyContext_New
(
void
);
PyAPI_FUNC
(
Py
Objec
t
*
)
PyContext_New
(
void
);
PyAPI_FUNC
(
Py
Context
*
)
PyContext_Copy
(
PyContex
t
*
);
PyAPI_FUNC
(
Py
Object
*
)
PyContext_Copy
(
PyObjec
t
*
);
PyAPI_FUNC
(
Py
Contex
t
*
)
PyContext_CopyCurrent
(
void
);
PyAPI_FUNC
(
Py
Objec
t
*
)
PyContext_CopyCurrent
(
void
);
PyAPI_FUNC
(
int
)
PyContext_Enter
(
Py
Contex
t
*
);
PyAPI_FUNC
(
int
)
PyContext_Enter
(
Py
Objec
t
*
);
PyAPI_FUNC
(
int
)
PyContext_Exit
(
Py
Contex
t
*
);
PyAPI_FUNC
(
int
)
PyContext_Exit
(
Py
Objec
t
*
);
/* Create a new context variable.
/* Create a new context variable.
default_value can be NULL.
default_value can be NULL.
*/
*/
PyAPI_FUNC
(
Py
ContextVar
*
)
PyContextVar_New
(
PyAPI_FUNC
(
Py
Object
*
)
PyContextVar_New
(
const
char
*
name
,
PyObject
*
default_value
);
const
char
*
name
,
PyObject
*
default_value
);
...
@@ -54,21 +54,19 @@ PyAPI_FUNC(PyContextVar *) PyContextVar_New(
...
@@ -54,21 +54,19 @@ PyAPI_FUNC(PyContextVar *) PyContextVar_New(
'*value' will be a new ref, if not NULL.
'*value' will be a new ref, if not NULL.
*/
*/
PyAPI_FUNC
(
int
)
PyContextVar_Get
(
PyAPI_FUNC
(
int
)
PyContextVar_Get
(
Py
ContextVar
*
var
,
PyObject
*
default_value
,
PyObject
**
value
);
Py
Object
*
var
,
PyObject
*
default_value
,
PyObject
**
value
);
/* Set a new value for the variable.
/* Set a new value for the variable.
Returns NULL if an error occurs.
Returns NULL if an error occurs.
*/
*/
PyAPI_FUNC
(
PyContextToken
*
)
PyContextVar_Set
(
PyAPI_FUNC
(
PyObject
*
)
PyContextVar_Set
(
PyObject
*
var
,
PyObject
*
value
);
PyContextVar
*
var
,
PyObject
*
value
);
/* Reset a variable to its previous value.
/* Reset a variable to its previous value.
Returns 0 on success, -1 on error.
Returns 0 on success, -1 on error.
*/
*/
PyAPI_FUNC
(
int
)
PyContextVar_Reset
(
PyAPI_FUNC
(
int
)
PyContextVar_Reset
(
PyObject
*
var
,
PyObject
*
token
);
PyContextVar
*
var
,
PyContextToken
*
token
);
/* This method is exposed only for CPython tests. Don not use it. */
/* This method is exposed only for CPython tests. Don not use it. */
...
...
Misc/NEWS.d/next/Core and Builtins/2018-09-21-11-06-56.bpo-34762.1nN53m.rst
0 → 100644
View file @
2ec872b3
Fix contextvars C API to use PyObject* pointer types.
Modules/_contextvarsmodule.c
View file @
2ec872b3
...
@@ -16,7 +16,7 @@ static PyObject *
...
@@ -16,7 +16,7 @@ static PyObject *
_contextvars_copy_context_impl
(
PyObject
*
module
)
_contextvars_copy_context_impl
(
PyObject
*
module
)
/*[clinic end generated code: output=1fcd5da7225c4fa9 input=89bb9ae485888440]*/
/*[clinic end generated code: output=1fcd5da7225c4fa9 input=89bb9ae485888440]*/
{
{
return
(
PyObject
*
)
PyContext_CopyCurrent
();
return
PyContext_CopyCurrent
();
}
}
...
...
Python/context.c
View file @
2ec872b3
...
@@ -18,6 +18,28 @@ module _contextvars
...
@@ -18,6 +18,28 @@ module _contextvars
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a0955718c8b8cea6]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a0955718c8b8cea6]*/
#define ENSURE_Context(o, err_ret) \
if (!PyContext_CheckExact(o)) { \
PyErr_SetString(PyExc_TypeError, \
"an instance of Context was expected"); \
return err_ret; \
}
#define ENSURE_ContextVar(o, err_ret) \
if (!PyContextVar_CheckExact(o)) { \
PyErr_SetString(PyExc_TypeError, \
"an instance of ContextVar was expected"); \
return err_ret; \
}
#define ENSURE_ContextToken(o, err_ret) \
if (!PyContextToken_CheckExact(o)) { \
PyErr_SetString(PyExc_TypeError, \
"an instance of Token was expected"); \
return err_ret; \
}
/////////////////////////// Context API
/////////////////////////// Context API
...
@@ -50,21 +72,23 @@ _PyContext_NewHamtForTests(void)
...
@@ -50,21 +72,23 @@ _PyContext_NewHamtForTests(void)
}
}
Py
Contex
t
*
Py
Objec
t
*
PyContext_New
(
void
)
PyContext_New
(
void
)
{
{
return
context_new_empty
();
return
(
PyObject
*
)
context_new_empty
();
}
}
Py
Contex
t
*
Py
Objec
t
*
PyContext_Copy
(
Py
Context
*
ctx
)
PyContext_Copy
(
Py
Object
*
o
ctx
)
{
{
return
context_new_from_vars
(
ctx
->
ctx_vars
);
ENSURE_Context
(
octx
,
NULL
)
PyContext
*
ctx
=
(
PyContext
*
)
octx
;
return
(
PyObject
*
)
context_new_from_vars
(
ctx
->
ctx_vars
);
}
}
Py
Contex
t
*
Py
Objec
t
*
PyContext_CopyCurrent
(
void
)
PyContext_CopyCurrent
(
void
)
{
{
PyContext
*
ctx
=
context_get
();
PyContext
*
ctx
=
context_get
();
...
@@ -72,13 +96,16 @@ PyContext_CopyCurrent(void)
...
@@ -72,13 +96,16 @@ PyContext_CopyCurrent(void)
return
NULL
;
return
NULL
;
}
}
return
context_new_from_vars
(
ctx
->
ctx_vars
);
return
(
PyObject
*
)
context_new_from_vars
(
ctx
->
ctx_vars
);
}
}
int
int
PyContext_Enter
(
Py
Context
*
ctx
)
PyContext_Enter
(
Py
Object
*
o
ctx
)
{
{
ENSURE_Context
(
octx
,
-
1
)
PyContext
*
ctx
=
(
PyContext
*
)
octx
;
if
(
ctx
->
ctx_entered
)
{
if
(
ctx
->
ctx_entered
)
{
PyErr_Format
(
PyExc_RuntimeError
,
PyErr_Format
(
PyExc_RuntimeError
,
"cannot enter context: %R is already entered"
,
ctx
);
"cannot enter context: %R is already entered"
,
ctx
);
...
@@ -100,8 +127,11 @@ PyContext_Enter(PyContext *ctx)
...
@@ -100,8 +127,11 @@ PyContext_Enter(PyContext *ctx)
int
int
PyContext_Exit
(
Py
Context
*
ctx
)
PyContext_Exit
(
Py
Object
*
o
ctx
)
{
{
ENSURE_Context
(
octx
,
-
1
)
PyContext
*
ctx
=
(
PyContext
*
)
octx
;
if
(
!
ctx
->
ctx_entered
)
{
if
(
!
ctx
->
ctx_entered
)
{
PyErr_Format
(
PyExc_RuntimeError
,
PyErr_Format
(
PyExc_RuntimeError
,
"cannot exit context: %R has not been entered"
,
ctx
);
"cannot exit context: %R has not been entered"
,
ctx
);
...
@@ -129,7 +159,7 @@ PyContext_Exit(PyContext *ctx)
...
@@ -129,7 +159,7 @@ PyContext_Exit(PyContext *ctx)
}
}
Py
ContextVar
*
Py
Object
*
PyContextVar_New
(
const
char
*
name
,
PyObject
*
def
)
PyContextVar_New
(
const
char
*
name
,
PyObject
*
def
)
{
{
PyObject
*
pyname
=
PyUnicode_FromString
(
name
);
PyObject
*
pyname
=
PyUnicode_FromString
(
name
);
...
@@ -138,14 +168,15 @@ PyContextVar_New(const char *name, PyObject *def)
...
@@ -138,14 +168,15 @@ PyContextVar_New(const char *name, PyObject *def)
}
}
PyContextVar
*
var
=
contextvar_new
(
pyname
,
def
);
PyContextVar
*
var
=
contextvar_new
(
pyname
,
def
);
Py_DECREF
(
pyname
);
Py_DECREF
(
pyname
);
return
var
;
return
(
PyObject
*
)
var
;
}
}
int
int
PyContextVar_Get
(
Py
ContextVar
*
var
,
PyObject
*
def
,
PyObject
**
val
)
PyContextVar_Get
(
Py
Object
*
o
var
,
PyObject
*
def
,
PyObject
**
val
)
{
{
assert
(
PyContextVar_CheckExact
(
var
));
ENSURE_ContextVar
(
ovar
,
-
1
)
PyContextVar
*
var
=
(
PyContextVar
*
)
ovar
;
PyThreadState
*
ts
=
PyThreadState_GET
();
PyThreadState
*
ts
=
PyThreadState_GET
();
assert
(
ts
!=
NULL
);
assert
(
ts
!=
NULL
);
...
@@ -204,9 +235,12 @@ error:
...
@@ -204,9 +235,12 @@ error:
}
}
Py
ContextToken
*
Py
Object
*
PyContextVar_Set
(
Py
ContextVar
*
var
,
PyObject
*
val
)
PyContextVar_Set
(
Py
Object
*
o
var
,
PyObject
*
val
)
{
{
ENSURE_ContextVar
(
ovar
,
NULL
)
PyContextVar
*
var
=
(
PyContextVar
*
)
ovar
;
if
(
!
PyContextVar_CheckExact
(
var
))
{
if
(
!
PyContextVar_CheckExact
(
var
))
{
PyErr_SetString
(
PyErr_SetString
(
PyExc_TypeError
,
"an instance of ContextVar was expected"
);
PyExc_TypeError
,
"an instance of ContextVar was expected"
);
...
@@ -233,13 +267,18 @@ PyContextVar_Set(PyContextVar *var, PyObject *val)
...
@@ -233,13 +267,18 @@ PyContextVar_Set(PyContextVar *var, PyObject *val)
return
NULL
;
return
NULL
;
}
}
return
tok
;
return
(
PyObject
*
)
tok
;
}
}
int
int
PyContextVar_Reset
(
Py
ContextVar
*
var
,
PyContextToken
*
tok
)
PyContextVar_Reset
(
Py
Object
*
ovar
,
PyObject
*
o
tok
)
{
{
ENSURE_ContextVar
(
ovar
,
-
1
)
ENSURE_ContextToken
(
otok
,
-
1
)
PyContextVar
*
var
=
(
PyContextVar
*
)
ovar
;
PyContextToken
*
tok
=
(
PyContextToken
*
)
otok
;
if
(
tok
->
tok_used
)
{
if
(
tok
->
tok_used
)
{
PyErr_Format
(
PyExc_RuntimeError
,
PyErr_Format
(
PyExc_RuntimeError
,
"%R has already been used once"
,
tok
);
"%R has already been used once"
,
tok
);
...
@@ -376,7 +415,7 @@ context_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
...
@@ -376,7 +415,7 @@ context_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyExc_TypeError
,
"Context() does not accept any arguments"
);
PyExc_TypeError
,
"Context() does not accept any arguments"
);
return
NULL
;
return
NULL
;
}
}
return
(
PyObject
*
)
PyContext_New
();
return
PyContext_New
();
}
}
static
int
static
int
...
@@ -587,14 +626,14 @@ context_run(PyContext *self, PyObject *const *args,
...
@@ -587,14 +626,14 @@ context_run(PyContext *self, PyObject *const *args,
return
NULL
;
return
NULL
;
}
}
if
(
PyContext_Enter
(
self
))
{
if
(
PyContext_Enter
(
(
PyObject
*
)
self
))
{
return
NULL
;
return
NULL
;
}
}
PyObject
*
call_result
=
_PyObject_FastCallKeywords
(
PyObject
*
call_result
=
_PyObject_FastCallKeywords
(
args
[
0
],
args
+
1
,
nargs
-
1
,
kwnames
);
args
[
0
],
args
+
1
,
nargs
-
1
,
kwnames
);
if
(
PyContext_Exit
(
self
))
{
if
(
PyContext_Exit
(
(
PyObject
*
)
self
))
{
return
NULL
;
return
NULL
;
}
}
...
@@ -908,7 +947,7 @@ _contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value)
...
@@ -908,7 +947,7 @@ _contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value)
}
}
PyObject
*
val
;
PyObject
*
val
;
if
(
PyContextVar_Get
(
self
,
default_value
,
&
val
)
<
0
)
{
if
(
PyContextVar_Get
(
(
PyObject
*
)
self
,
default_value
,
&
val
)
<
0
)
{
return
NULL
;
return
NULL
;
}
}
...
@@ -937,7 +976,7 @@ static PyObject *
...
@@ -937,7 +976,7 @@ static PyObject *
_contextvars_ContextVar_set
(
PyContextVar
*
self
,
PyObject
*
value
)
_contextvars_ContextVar_set
(
PyContextVar
*
self
,
PyObject
*
value
)
/*[clinic end generated code: output=446ed5e820d6d60b input=c0a6887154227453]*/
/*[clinic end generated code: output=446ed5e820d6d60b input=c0a6887154227453]*/
{
{
return
(
PyObject
*
)
PyContextVar_Set
(
self
,
value
);
return
PyContextVar_Set
((
PyObject
*
)
self
,
value
);
}
}
/*[clinic input]
/*[clinic input]
...
@@ -961,7 +1000,7 @@ _contextvars_ContextVar_reset(PyContextVar *self, PyObject *token)
...
@@ -961,7 +1000,7 @@ _contextvars_ContextVar_reset(PyContextVar *self, PyObject *token)
return
NULL
;
return
NULL
;
}
}
if
(
PyContextVar_Reset
(
self
,
(
PyContextToken
*
)
token
))
{
if
(
PyContextVar_Reset
(
(
PyObject
*
)
self
,
token
))
{
return
NULL
;
return
NULL
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment