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 @@
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
This section details the public C API for the :mod:`contextvars` module.
...
...
@@ -56,27 +75,27 @@ Type-check macros:
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
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.
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.
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.
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
current context for the current thread. Returns ``0`` on success,
...
...
@@ -90,14 +109,14 @@ Context object management 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
for introspection and debug purposes. The *def* parameter may optionally
specify the default value for the context variable. If an error has
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
occurred during lookup, and ``0`` if no error occurred, whether or not
...
...
@@ -112,13 +131,13 @@ Context variable functions:
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
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.
.. 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
: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,
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
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;
#define PyContextToken_CheckExact(o) (Py_TYPE(o) == &PyContextToken_Type)
PyAPI_FUNC
(
Py
Contex
t
*
)
PyContext_New
(
void
);
PyAPI_FUNC
(
Py
Context
*
)
PyContext_Copy
(
PyContex
t
*
);
PyAPI_FUNC
(
Py
Contex
t
*
)
PyContext_CopyCurrent
(
void
);
PyAPI_FUNC
(
Py
Objec
t
*
)
PyContext_New
(
void
);
PyAPI_FUNC
(
Py
Object
*
)
PyContext_Copy
(
PyObjec
t
*
);
PyAPI_FUNC
(
Py
Objec
t
*
)
PyContext_CopyCurrent
(
void
);
PyAPI_FUNC
(
int
)
PyContext_Enter
(
Py
Contex
t
*
);
PyAPI_FUNC
(
int
)
PyContext_Exit
(
Py
Contex
t
*
);
PyAPI_FUNC
(
int
)
PyContext_Enter
(
Py
Objec
t
*
);
PyAPI_FUNC
(
int
)
PyContext_Exit
(
Py
Objec
t
*
);
/* Create a new context variable.
default_value can be NULL.
*/
PyAPI_FUNC
(
Py
ContextVar
*
)
PyContextVar_New
(
PyAPI_FUNC
(
Py
Object
*
)
PyContextVar_New
(
const
char
*
name
,
PyObject
*
default_value
);
...
...
@@ -54,21 +54,19 @@ PyAPI_FUNC(PyContextVar *) PyContextVar_New(
'*value' will be a new ref, if not NULL.
*/
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.
Returns NULL if an error occurs.
*/
PyAPI_FUNC
(
PyContextToken
*
)
PyContextVar_Set
(
PyContextVar
*
var
,
PyObject
*
value
);
PyAPI_FUNC
(
PyObject
*
)
PyContextVar_Set
(
PyObject
*
var
,
PyObject
*
value
);
/* Reset a variable to its previous value.
Returns 0 on success, -1 on error.
*/
PyAPI_FUNC
(
int
)
PyContextVar_Reset
(
PyContextVar
*
var
,
PyContextToken
*
token
);
PyAPI_FUNC
(
int
)
PyContextVar_Reset
(
PyObject
*
var
,
PyObject
*
token
);
/* 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 *
_contextvars_copy_context_impl
(
PyObject
*
module
)
/*[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
/*[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
...
...
@@ -50,21 +72,23 @@ _PyContext_NewHamtForTests(void)
}
Py
Contex
t
*
Py
Objec
t
*
PyContext_New
(
void
)
{
return
context_new_empty
();
return
(
PyObject
*
)
context_new_empty
();
}
Py
Contex
t
*
PyContext_Copy
(
Py
Context
*
ctx
)
Py
Objec
t
*
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
*
ctx
=
context_get
();
...
...
@@ -72,13 +96,16 @@ PyContext_CopyCurrent(void)
return
NULL
;
}
return
context_new_from_vars
(
ctx
->
ctx_vars
);
return
(
PyObject
*
)
context_new_from_vars
(
ctx
->
ctx_vars
);
}
int
PyContext_Enter
(
Py
Context
*
ctx
)
PyContext_Enter
(
Py
Object
*
o
ctx
)
{
ENSURE_Context
(
octx
,
-
1
)
PyContext
*
ctx
=
(
PyContext
*
)
octx
;
if
(
ctx
->
ctx_entered
)
{
PyErr_Format
(
PyExc_RuntimeError
,
"cannot enter context: %R is already entered"
,
ctx
);
...
...
@@ -100,8 +127,11 @@ PyContext_Enter(PyContext *ctx)
int
PyContext_Exit
(
Py
Context
*
ctx
)
PyContext_Exit
(
Py
Object
*
o
ctx
)
{
ENSURE_Context
(
octx
,
-
1
)
PyContext
*
ctx
=
(
PyContext
*
)
octx
;
if
(
!
ctx
->
ctx_entered
)
{
PyErr_Format
(
PyExc_RuntimeError
,
"cannot exit context: %R has not been entered"
,
ctx
);
...
...
@@ -129,7 +159,7 @@ PyContext_Exit(PyContext *ctx)
}
Py
ContextVar
*
Py
Object
*
PyContextVar_New
(
const
char
*
name
,
PyObject
*
def
)
{
PyObject
*
pyname
=
PyUnicode_FromString
(
name
);
...
...
@@ -138,14 +168,15 @@ PyContextVar_New(const char *name, PyObject *def)
}
PyContextVar
*
var
=
contextvar_new
(
pyname
,
def
);
Py_DECREF
(
pyname
);
return
var
;
return
(
PyObject
*
)
var
;
}
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
();
assert
(
ts
!=
NULL
);
...
...
@@ -204,9 +235,12 @@ error:
}
Py
ContextToken
*
PyContextVar_Set
(
Py
ContextVar
*
var
,
PyObject
*
val
)
Py
Object
*
PyContextVar_Set
(
Py
Object
*
o
var
,
PyObject
*
val
)
{
ENSURE_ContextVar
(
ovar
,
NULL
)
PyContextVar
*
var
=
(
PyContextVar
*
)
ovar
;
if
(
!
PyContextVar_CheckExact
(
var
))
{
PyErr_SetString
(
PyExc_TypeError
,
"an instance of ContextVar was expected"
);
...
...
@@ -233,13 +267,18 @@ PyContextVar_Set(PyContextVar *var, PyObject *val)
return
NULL
;
}
return
tok
;
return
(
PyObject
*
)
tok
;
}
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
)
{
PyErr_Format
(
PyExc_RuntimeError
,
"%R has already been used once"
,
tok
);
...
...
@@ -376,7 +415,7 @@ context_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyExc_TypeError
,
"Context() does not accept any arguments"
);
return
NULL
;
}
return
(
PyObject
*
)
PyContext_New
();
return
PyContext_New
();
}
static
int
...
...
@@ -587,14 +626,14 @@ context_run(PyContext *self, PyObject *const *args,
return
NULL
;
}
if
(
PyContext_Enter
(
self
))
{
if
(
PyContext_Enter
(
(
PyObject
*
)
self
))
{
return
NULL
;
}
PyObject
*
call_result
=
_PyObject_FastCallKeywords
(
args
[
0
],
args
+
1
,
nargs
-
1
,
kwnames
);
if
(
PyContext_Exit
(
self
))
{
if
(
PyContext_Exit
(
(
PyObject
*
)
self
))
{
return
NULL
;
}
...
...
@@ -908,7 +947,7 @@ _contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value)
}
PyObject
*
val
;
if
(
PyContextVar_Get
(
self
,
default_value
,
&
val
)
<
0
)
{
if
(
PyContextVar_Get
(
(
PyObject
*
)
self
,
default_value
,
&
val
)
<
0
)
{
return
NULL
;
}
...
...
@@ -937,7 +976,7 @@ static PyObject *
_contextvars_ContextVar_set
(
PyContextVar
*
self
,
PyObject
*
value
)
/*[clinic end generated code: output=446ed5e820d6d60b input=c0a6887154227453]*/
{
return
(
PyObject
*
)
PyContextVar_Set
(
self
,
value
);
return
PyContextVar_Set
((
PyObject
*
)
self
,
value
);
}
/*[clinic input]
...
...
@@ -961,7 +1000,7 @@ _contextvars_ContextVar_reset(PyContextVar *self, PyObject *token)
return
NULL
;
}
if
(
PyContextVar_Reset
(
self
,
(
PyContextToken
*
)
token
))
{
if
(
PyContextVar_Reset
(
(
PyObject
*
)
self
,
token
))
{
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