Merge branch 'fix-issue-38681' of https://github.com/samtatasurya/cpython into fix-issue-38681

This commit is contained in:
Samuel Tatasurya 2020-03-07 21:26:26 -08:00
commit d8116e151c
60 changed files with 1283 additions and 653 deletions

View File

@ -374,6 +374,8 @@ Querying the error indicator
own a reference to the return value, so you do not need to :c:func:`Py_DECREF` own a reference to the return value, so you do not need to :c:func:`Py_DECREF`
it. it.
The caller must hold the GIL.
.. note:: .. note::
Do not compare the return value to a specific exception; use Do not compare the return value to a specific exception; use
@ -715,15 +717,21 @@ recursion depth automatically).
case, a :exc:`RecursionError` is set and a nonzero value is returned. case, a :exc:`RecursionError` is set and a nonzero value is returned.
Otherwise, zero is returned. Otherwise, zero is returned.
*where* should be a string such as ``" in instance check"`` to be *where* should be a UTF-8 encoded string such as ``" in instance check"`` to
concatenated to the :exc:`RecursionError` message caused by the recursion be concatenated to the :exc:`RecursionError` message caused by the recursion
depth limit. depth limit.
.. c:function:: void Py_LeaveRecursiveCall() .. versionchanged:: 3.9
This function is now also available in the limited API.
.. c:function:: void Py_LeaveRecursiveCall(void)
Ends a :c:func:`Py_EnterRecursiveCall`. Must be called once for each Ends a :c:func:`Py_EnterRecursiveCall`. Must be called once for each
*successful* invocation of :c:func:`Py_EnterRecursiveCall`. *successful* invocation of :c:func:`Py_EnterRecursiveCall`.
.. versionchanged:: 3.9
This function is now also available in the limited API.
Properly implementing :c:member:`~PyTypeObject.tp_repr` for container types requires Properly implementing :c:member:`~PyTypeObject.tp_repr` for container types requires
special recursion handling. In addition to protecting the stack, special recursion handling. In addition to protecting the stack,
:c:member:`~PyTypeObject.tp_repr` also needs to track objects to prevent cycles. The :c:member:`~PyTypeObject.tp_repr` also needs to track objects to prevent cycles. The

View File

@ -196,6 +196,7 @@ Object Protocol
This function now includes a debug assertion to help ensure that it This function now includes a debug assertion to help ensure that it
does not silently discard an active exception. does not silently discard an active exception.
.. c:function:: PyObject* PyObject_Bytes(PyObject *o) .. c:function:: PyObject* PyObject_Bytes(PyObject *o)
.. index:: builtin: bytes .. index:: builtin: bytes

View File

@ -38,7 +38,7 @@ associated messages through the :class:`http.HTTPStatus` enum:
<HTTPStatus.OK: 200> <HTTPStatus.OK: 200>
>>> HTTPStatus.OK == 200 >>> HTTPStatus.OK == 200
True True
>>> http.HTTPStatus.OK.value >>> HTTPStatus.OK.value
200 200
>>> HTTPStatus.OK.phrase >>> HTTPStatus.OK.phrase
'OK' 'OK'

View File

@ -3539,6 +3539,19 @@ written in Python, such as a mail server's external command delivery program.
.. availability:: Unix. .. availability:: Unix.
.. function:: pidfd_open(pid, flags=0)
Return a file descriptor referring to the process *pid*. This descriptor can
be used to perform process management without races and signals. The *flags*
argument is provided for future extensions; no flag values are currently
defined.
See the :manpage:`pidfd_open(2)` man page for more details.
.. availability:: Linux 5.3+
.. versionadded:: 3.9
.. function:: plock(op) .. function:: plock(op)
Lock program segments into memory. The value of *op* (defined in Lock program segments into memory. The value of *op* (defined in
@ -3908,7 +3921,8 @@ written in Python, such as a mail server's external command delivery program.
.. function:: waitid(idtype, id, options) .. function:: waitid(idtype, id, options)
Wait for the completion of one or more child processes. Wait for the completion of one or more child processes.
*idtype* can be :data:`P_PID`, :data:`P_PGID` or :data:`P_ALL`. *idtype* can be :data:`P_PID`, :data:`P_PGID`, :data:`P_ALL`, or
:data:`P_PIDFD` on Linux.
*id* specifies the pid to wait on. *id* specifies the pid to wait on.
*options* is constructed from the ORing of one or more of :data:`WEXITED`, *options* is constructed from the ORing of one or more of :data:`WEXITED`,
:data:`WSTOPPED` or :data:`WCONTINUED` and additionally may be ORed with :data:`WSTOPPED` or :data:`WCONTINUED` and additionally may be ORed with
@ -3933,6 +3947,15 @@ written in Python, such as a mail server's external command delivery program.
.. versionadded:: 3.3 .. versionadded:: 3.3
.. data:: P_PIDFD
This is a Linux-specific *idtype* that indicates that *id* is a file
descriptor that refers to a process.
.. availability:: Linux 5.4+
.. versionadded:: 3.9
.. data:: WEXITED .. data:: WEXITED
WSTOPPED WSTOPPED
WNOWAIT WNOWAIT

View File

@ -164,7 +164,8 @@ However, for reading convenience, most of the examples show sorted sequences.
The harmonic mean, sometimes called the subcontrary mean, is the The harmonic mean, sometimes called the subcontrary mean, is the
reciprocal of the arithmetic :func:`mean` of the reciprocals of the reciprocal of the arithmetic :func:`mean` of the reciprocals of the
data. For example, the harmonic mean of three values *a*, *b* and *c* data. For example, the harmonic mean of three values *a*, *b* and *c*
will be equivalent to ``3/(1/a + 1/b + 1/c)``. will be equivalent to ``3/(1/a + 1/b + 1/c)``. If one of the values
is zero, the result will be zero.
The harmonic mean is a type of average, a measure of the central The harmonic mean is a type of average, a measure of the central
location of the data. It is often appropriate when averaging location of the data. It is often appropriate when averaging
@ -190,6 +191,10 @@ However, for reading convenience, most of the examples show sorted sequences.
:exc:`StatisticsError` is raised if *data* is empty, or any element :exc:`StatisticsError` is raised if *data* is empty, or any element
is less than zero. is less than zero.
The current algorithm has an early-out when it encounters a zero
in the input. This means that the subsequent inputs are not tested
for validity. (This behavior may change in the future.)
.. versionadded:: 3.6 .. versionadded:: 3.6

View File

@ -83,7 +83,7 @@ module. Specifically, any module that contains a ``__path__`` attribute is
considered a package. considered a package.
All modules have a name. Subpackage names are separated from their parent All modules have a name. Subpackage names are separated from their parent
package name by dots, akin to Python's standard attribute access syntax. Thus package name by a dot, akin to Python's standard attribute access syntax. Thus
you might have a module called :mod:`sys` and a package called :mod:`email`, you might have a module called :mod:`sys` and a package called :mod:`email`,
which in turn has a subpackage called :mod:`email.mime` and a module within which in turn has a subpackage called :mod:`email.mime` and a module within
that subpackage called :mod:`email.mime.text`. that subpackage called :mod:`email.mime.text`.

View File

@ -23,7 +23,7 @@ is an installation option, other places are possible; check with your local
Python guru or system administrator. (E.g., :file:`/usr/local/python` is a Python guru or system administrator. (E.g., :file:`/usr/local/python` is a
popular alternative location.) popular alternative location.)
On Windows machines where you have installed from the :ref:`Microsoft Store On Windows machines where you have installed Python from the :ref:`Microsoft Store
<windows-store>`, the :file:`python3.9` command will be available. If you have <windows-store>`, the :file:`python3.9` command will be available. If you have
the :ref:`py.exe launcher <launcher>` installed, you can use the :file:`py` the :ref:`py.exe launcher <launcher>` installed, you can use the :file:`py`
command. See :ref:`setting-envvars` for other ways to launch Python. command. See :ref:`setting-envvars` for other ways to launch Python.

View File

@ -2152,6 +2152,55 @@ CPython bytecode changes
Demos and Tools Demos and Tools
--------------- ---------------
* Added a benchmark script for timing various ways to access variables: Added a benchmark script for timing various ways to access variables:
``Tools/scripts/var_access_benchmark.py``. ``Tools/scripts/var_access_benchmark.py``.
(Contributed by Raymond Hettinger in :issue:`35884`.) (Contributed by Raymond Hettinger in :issue:`35884`.)
Here's a summary of performance improvements since Python 3.3:
.. code-block:: none
Python version 3.3 3.4 3.5 3.6 3.7 3.8
-------------- --- --- --- --- --- ---
Variable and attribute read access:
read_local 4.0 7.1 7.1 5.4 5.1 3.9
read_nonlocal 5.3 7.1 8.1 5.8 5.4 4.4
read_global 13.3 15.5 19.0 14.3 13.6 7.6
read_builtin 20.0 21.1 21.6 18.5 19.0 7.5
read_classvar_from_class 20.5 25.6 26.5 20.7 19.5 18.4
read_classvar_from_instance 18.5 22.8 23.5 18.8 17.1 16.4
read_instancevar 26.8 32.4 33.1 28.0 26.3 25.4
read_instancevar_slots 23.7 27.8 31.3 20.8 20.8 20.2
read_namedtuple 68.5 73.8 57.5 45.0 46.8 18.4
read_boundmethod 29.8 37.6 37.9 29.6 26.9 27.7
Variable and attribute write access:
write_local 4.6 8.7 9.3 5.5 5.3 4.3
write_nonlocal 7.3 10.5 11.1 5.6 5.5 4.7
write_global 15.9 19.7 21.2 18.0 18.0 15.8
write_classvar 81.9 92.9 96.0 104.6 102.1 39.2
write_instancevar 36.4 44.6 45.8 40.0 38.9 35.5
write_instancevar_slots 28.7 35.6 36.1 27.3 26.6 25.7
Data structure read access:
read_list 19.2 24.2 24.5 20.8 20.8 19.0
read_deque 19.9 24.7 25.5 20.2 20.6 19.8
read_dict 19.7 24.3 25.7 22.3 23.0 21.0
read_strdict 17.9 22.6 24.3 19.5 21.2 18.9
Data structure write access:
write_list 21.2 27.1 28.5 22.5 21.6 20.0
write_deque 23.8 28.7 30.1 22.7 21.8 23.5
write_dict 25.9 31.4 33.3 29.3 29.2 24.7
write_strdict 22.9 28.4 29.9 27.5 25.2 23.1
Stack (or queue) operations:
list_append_pop 144.2 93.4 112.7 75.4 74.2 50.8
deque_append_pop 30.4 43.5 57.0 49.4 49.2 42.5
deque_append_popleft 30.8 43.7 57.3 49.7 49.7 42.8
Timing loop:
loop_overhead 0.3 0.5 0.6 0.4 0.3 0.3
(Measured from the macOS 64-bit builds found at python.org)

View File

@ -150,6 +150,10 @@ os
Added :data:`~os.CLD_KILLED` and :data:`~os.CLD_STOPPED` for :attr:`si_code`. Added :data:`~os.CLD_KILLED` and :data:`~os.CLD_STOPPED` for :attr:`si_code`.
(Contributed by Dong-hee Na in :issue:`38493`.) (Contributed by Dong-hee Na in :issue:`38493`.)
Exposed the Linux-specific :func:`os.pidfd_open` (:issue:`38692`) and
:data:`os.P_PIDFD` (:issue:`38713`) for process management with file
descriptors.
threading threading
--------- ---------
@ -197,6 +201,12 @@ Optimizations
Build and C API Changes Build and C API Changes
======================= =======================
* Provide :c:func:`Py_EnterRecursiveCall` and :c:func:`Py_LeaveRecursiveCall`
as regular functions for the limited API. Previously, there were defined as
macros, but these macros didn't work with the limited API which cannot access
``PyThreadState.recursion_depth`` field. Remove ``_Py_CheckRecursionLimit``
from the stable ABI.
(Contributed by Victor Stinner in :issue:`38644`.)
* Add a new public :c:func:`PyObject_CallNoArgs` function to the C API, which * Add a new public :c:func:`PyObject_CallNoArgs` function to the C API, which
calls a callable Python object without any arguments. It is the most efficient calls a callable Python object without any arguments. It is the most efficient
way to call a callable Python object without any argument. way to call a callable Python object without any argument.

View File

@ -85,41 +85,8 @@ PyAPI_FUNC(int) Py_MakePendingCalls(void);
PyAPI_FUNC(void) Py_SetRecursionLimit(int); PyAPI_FUNC(void) Py_SetRecursionLimit(int);
PyAPI_FUNC(int) Py_GetRecursionLimit(void); PyAPI_FUNC(int) Py_GetRecursionLimit(void);
#define Py_EnterRecursiveCall(where) \ PyAPI_FUNC(int) Py_EnterRecursiveCall(const char *where);
(_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \ PyAPI_FUNC(void) Py_LeaveRecursiveCall(void);
_Py_CheckRecursiveCall(where))
#define Py_LeaveRecursiveCall() \
do{ if(_Py_MakeEndRecCheck(PyThreadState_GET()->recursion_depth)) \
PyThreadState_GET()->overflowed = 0; \
} while(0)
PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where);
/* Due to the macros in which it's used, _Py_CheckRecursionLimit is in
the stable ABI. It should be removed therefrom when possible.
*/
PyAPI_DATA(int) _Py_CheckRecursionLimit;
#ifdef USE_STACKCHECK
/* With USE_STACKCHECK, trigger stack checks in _Py_CheckRecursiveCall()
on every 64th call to Py_EnterRecursiveCall.
*/
# define _Py_MakeRecCheck(x) \
(++(x) > _Py_CheckRecursionLimit || \
++(PyThreadState_GET()->stackcheck_counter) > 64)
#else
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
#endif
/* Compute the "lower-water mark" for a recursion limit. When
* Py_LeaveRecursiveCall() is called with a recursion depth below this mark,
* the overflowed flag is reset to 0. */
#define _Py_RecursionLimitLowerWaterMark(limit) \
(((limit) > 200) \
? ((limit) - 50) \
: (3 * ((limit) >> 2)))
#define _Py_MakeEndRecCheck(x) \
(--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
#define Py_ALLOW_RECURSION \ #define Py_ALLOW_RECURSION \
do { unsigned char _old = PyThreadState_GET()->recursion_critical;\ do { unsigned char _old = PyThreadState_GET()->recursion_critical;\
@ -224,6 +191,12 @@ PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *);
#define FVS_MASK 0x4 #define FVS_MASK 0x4
#define FVS_HAVE_SPEC 0x4 #define FVS_HAVE_SPEC 0x4
#ifndef Py_LIMITED_API
# define Py_CPYTHON_CEVAL_H
# include "cpython/ceval.h"
# undef Py_CPYTHON_CEVAL_H
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -37,9 +37,11 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
40 bytes on the stack. */ 40 bytes on the stack. */
#define _PY_FASTCALL_SMALL_STACK 5 #define _PY_FASTCALL_SMALL_STACK 5
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *callable, PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(
PyObject *result, PyThreadState *tstate,
const char *where); PyObject *callable,
PyObject *result,
const char *where);
/* === Vectorcall protocol (PEP 590) ============================= */ /* === Vectorcall protocol (PEP 590) ============================= */
@ -47,6 +49,7 @@ PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *callable,
or _PyObject_FastCallDict() (both forms are supported), or _PyObject_FastCallDict() (both forms are supported),
except that nargs is plainly the number of arguments without flags. */ except that nargs is plainly the number of arguments without flags. */
PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall( PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall(
PyThreadState *tstate,
PyObject *callable, PyObject *callable,
PyObject *const *args, Py_ssize_t nargs, PyObject *const *args, Py_ssize_t nargs,
PyObject *keywords); PyObject *keywords);
@ -93,18 +96,29 @@ _PyVectorcall_Function(PyObject *callable)
Return the result on success. Raise an exception and return NULL on Return the result on success. Raise an exception and return NULL on
error. */ error. */
static inline PyObject * static inline PyObject *
_PyObject_Vectorcall(PyObject *callable, PyObject *const *args, _PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable,
size_t nargsf, PyObject *kwnames) PyObject *const *args, size_t nargsf,
PyObject *kwnames)
{ {
assert(kwnames == NULL || PyTuple_Check(kwnames)); assert(kwnames == NULL || PyTuple_Check(kwnames));
assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0); assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0);
vectorcallfunc func = _PyVectorcall_Function(callable); vectorcallfunc func = _PyVectorcall_Function(callable);
if (func == NULL) { if (func == NULL) {
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
return _PyObject_MakeTpCall(callable, args, nargs, kwnames); return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames);
} }
PyObject *res = func(callable, args, nargsf, kwnames); PyObject *res = func(callable, args, nargsf, kwnames);
return _Py_CheckFunctionResult(callable, res, NULL); return _Py_CheckFunctionResult(tstate, callable, res, NULL);
}
static inline PyObject *
_PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
size_t nargsf, PyObject *kwnames)
{
PyThreadState *tstate = PyThreadState_GET();
return _PyObject_VectorcallTstate(tstate, callable,
args, nargsf, kwnames);
} }
/* Same as _PyObject_Vectorcall except that keyword arguments are passed as /* Same as _PyObject_Vectorcall except that keyword arguments are passed as

67
Include/cpython/ceval.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef Py_CPYTHON_CEVAL_H
# error "this header file must not be included directly"
#endif
#ifdef __cplusplus
extern "C" {
#endif
PyAPI_DATA(int) _Py_CheckRecursionLimit;
#ifdef USE_STACKCHECK
/* With USE_STACKCHECK macro defined, trigger stack checks in
_Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
return (++tstate->recursion_depth > _Py_CheckRecursionLimit
|| ++tstate->stackcheck_counter > 64);
}
#else
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
return (++tstate->recursion_depth > _Py_CheckRecursionLimit);
}
#endif
PyAPI_FUNC(int) _Py_CheckRecursiveCall(
PyThreadState *tstate,
const char *where);
static inline int _Py_EnterRecursiveCall(PyThreadState *tstate,
const char *where) {
return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
}
static inline int _Py_EnterRecursiveCall_inline(const char *where) {
PyThreadState *tstate = PyThreadState_GET();
return _Py_EnterRecursiveCall(tstate, where);
}
#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where)
/* Compute the "lower-water mark" for a recursion limit. When
* Py_LeaveRecursiveCall() is called with a recursion depth below this mark,
* the overflowed flag is reset to 0. */
#define _Py_RecursionLimitLowerWaterMark(limit) \
(((limit) > 200) \
? ((limit) - 50) \
: (3 * ((limit) >> 2)))
#define _Py_MakeEndRecCheck(x) \
(--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
if (_Py_MakeEndRecCheck(tstate->recursion_depth)) {
tstate->overflowed = 0;
}
}
static inline void _Py_LeaveRecursiveCall_inline(void) {
PyThreadState *tstate = PyThreadState_GET();
_Py_LeaveRecursiveCall(tstate);
}
#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline()
#ifdef __cplusplus
}
#endif

View File

@ -348,6 +348,7 @@ static inline void _Py_Dealloc_inline(PyObject *op)
} }
#define _Py_Dealloc(op) _Py_Dealloc_inline(op) #define _Py_Dealloc(op) _Py_Dealloc_inline(op)
PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
/* Safely decref `op` and set `op` to `op2`. /* Safely decref `op` and set `op` to `op2`.
* *

View File

@ -10,7 +10,8 @@ extern "C" {
static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
{ {
return tstate == NULL ? NULL : tstate->curexc_type; assert(tstate != NULL);
return tstate->curexc_type;
} }
@ -58,6 +59,12 @@ PyAPI_FUNC(void) _PyErr_NormalizeException(
PyObject **val, PyObject **val,
PyObject **tb); PyObject **tb);
PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate(
PyThreadState *tstate,
PyObject *exception,
const char *format,
...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -125,6 +125,15 @@ struct _is {
struct _warnings_runtime_state warnings; struct _warnings_runtime_state warnings;
PyObject *audit_hooks; PyObject *audit_hooks;
/*
* See bpo-36876: miscellaneous ad hoc statics have been moved here.
*/
struct {
struct {
int level;
int atbol;
} listnode;
} parser;
}; };
PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(PY_INT64_T); PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(PY_INT64_T);

View File

@ -48,6 +48,9 @@ class BaseRotatingHandler(logging.FileHandler):
Not meant to be instantiated directly. Instead, use RotatingFileHandler Not meant to be instantiated directly. Instead, use RotatingFileHandler
or TimedRotatingFileHandler. or TimedRotatingFileHandler.
""" """
namer = None
rotator = None
def __init__(self, filename, mode, encoding=None, delay=False, errors=None): def __init__(self, filename, mode, encoding=None, delay=False, errors=None):
""" """
Use the specified filename for streamed logging Use the specified filename for streamed logging
@ -58,8 +61,6 @@ class BaseRotatingHandler(logging.FileHandler):
self.mode = mode self.mode = mode
self.encoding = encoding self.encoding = encoding
self.errors = errors self.errors = errors
self.namer = None
self.rotator = None
def emit(self, record): def emit(self, record):
""" """

View File

@ -74,7 +74,7 @@ class CFunctionCallsErrorMessages(unittest.TestCase):
self.assertRaisesRegex(TypeError, msg, bool, x=2) self.assertRaisesRegex(TypeError, msg, bool, x=2)
def test_varargs4_kw(self): def test_varargs4_kw(self):
msg = r"^index\(\) takes no keyword arguments$" msg = r"^list[.]index\(\) takes no keyword arguments$"
self.assertRaisesRegex(TypeError, msg, [].index, x=2) self.assertRaisesRegex(TypeError, msg, [].index, x=2)
def test_varargs5_kw(self): def test_varargs5_kw(self):
@ -90,19 +90,19 @@ class CFunctionCallsErrorMessages(unittest.TestCase):
self.assertRaisesRegex(TypeError, msg, next, x=2) self.assertRaisesRegex(TypeError, msg, next, x=2)
def test_varargs8_kw(self): def test_varargs8_kw(self):
msg = r"^pack\(\) takes no keyword arguments$" msg = r"^_struct[.]pack\(\) takes no keyword arguments$"
self.assertRaisesRegex(TypeError, msg, struct.pack, x=2) self.assertRaisesRegex(TypeError, msg, struct.pack, x=2)
def test_varargs9_kw(self): def test_varargs9_kw(self):
msg = r"^pack_into\(\) takes no keyword arguments$" msg = r"^_struct[.]pack_into\(\) takes no keyword arguments$"
self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2) self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2)
def test_varargs10_kw(self): def test_varargs10_kw(self):
msg = r"^index\(\) takes no keyword arguments$" msg = r"^deque[.]index\(\) takes no keyword arguments$"
self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2) self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2)
def test_varargs11_kw(self): def test_varargs11_kw(self):
msg = r"^pack\(\) takes no keyword arguments$" msg = r"^Struct[.]pack\(\) takes no keyword arguments$"
self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2) self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2)
def test_varargs12_kw(self): def test_varargs12_kw(self):

View File

@ -1967,7 +1967,7 @@ order (MRO) for bases """
# different error messages. # different error messages.
set_add = set.add set_add = set.add
expected_errmsg = "descriptor 'add' of 'set' object needs an argument" expected_errmsg = "unbound method set.add() needs an argument"
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
set_add() set_add()

View File

@ -52,15 +52,15 @@ Here we add keyword arguments
>>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6}) >>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'a' TypeError: test.test_extcall.f() got multiple values for keyword argument 'a'
>>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6) >>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'a' TypeError: test.test_extcall.f() got multiple values for keyword argument 'a'
>>> f(1, 2, a=3, **{'a': 4}, **{'a': 5}) >>> f(1, 2, a=3, **{'a': 4}, **{'a': 5})
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'a' TypeError: test.test_extcall.f() got multiple values for keyword argument 'a'
>>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7}) >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
(1, 2, 3, 4, 5) {'a': 6, 'b': 7} (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
>>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9}) >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
@ -118,7 +118,7 @@ Verify clearing of SF bug #733667
>>> g(*Nothing()) >>> g(*Nothing())
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() argument after * must be an iterable, not Nothing TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing
>>> class Nothing: >>> class Nothing:
... def __len__(self): return 5 ... def __len__(self): return 5
@ -127,7 +127,7 @@ Verify clearing of SF bug #733667
>>> g(*Nothing()) >>> g(*Nothing())
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() argument after * must be an iterable, not Nothing TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing
>>> class Nothing(): >>> class Nothing():
... def __len__(self): return 5 ... def __len__(self): return 5
@ -247,17 +247,17 @@ What about willful misconduct?
>>> h(*h) >>> h(*h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after * must be an iterable, not function TypeError: test.test_extcall.h() argument after * must be an iterable, not function
>>> h(1, *h) >>> h(1, *h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after * must be an iterable, not function TypeError: test.test_extcall.h() argument after * must be an iterable, not function
>>> h(*[1], *h) >>> h(*[1], *h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after * must be an iterable, not function TypeError: test.test_extcall.h() argument after * must be an iterable, not function
>>> dir(*h) >>> dir(*h)
Traceback (most recent call last): Traceback (most recent call last):
@ -268,38 +268,38 @@ What about willful misconduct?
>>> nothing(*h) >>> nothing(*h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: NoneType object argument after * must be an iterable, \ TypeError: None argument after * must be an iterable, \
not function not function
>>> h(**h) >>> h(**h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not function TypeError: test.test_extcall.h() argument after ** must be a mapping, not function
>>> h(**[]) >>> h(**[])
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not list TypeError: test.test_extcall.h() argument after ** must be a mapping, not list
>>> h(a=1, **h) >>> h(a=1, **h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not function TypeError: test.test_extcall.h() argument after ** must be a mapping, not function
>>> h(a=1, **[]) >>> h(a=1, **[])
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not list TypeError: test.test_extcall.h() argument after ** must be a mapping, not list
>>> h(**{'a': 1}, **h) >>> h(**{'a': 1}, **h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not function TypeError: test.test_extcall.h() argument after ** must be a mapping, not function
>>> h(**{'a': 1}, **[]) >>> h(**{'a': 1}, **[])
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: h() argument after ** must be a mapping, not list TypeError: test.test_extcall.h() argument after ** must be a mapping, not list
>>> dir(**h) >>> dir(**h)
Traceback (most recent call last): Traceback (most recent call last):
@ -309,7 +309,7 @@ not function
>>> nothing(**h) >>> nothing(**h)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: NoneType object argument after ** must be a mapping, \ TypeError: None argument after ** must be a mapping, \
not function not function
>>> dir(b=1, **{'b': 1}) >>> dir(b=1, **{'b': 1})
@ -351,17 +351,17 @@ Test a kwargs mapping with duplicated keys.
>>> g(**MultiDict([('x', 1), ('x', 2)])) >>> g(**MultiDict([('x', 1), ('x', 2)]))
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() got multiple values for keyword argument 'x' TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
>>> g(a=3, **MultiDict([('x', 1), ('x', 2)])) >>> g(a=3, **MultiDict([('x', 1), ('x', 2)]))
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() got multiple values for keyword argument 'x' TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
>>> g(**MultiDict([('a', 3)]), **MultiDict([('x', 1), ('x', 2)])) >>> g(**MultiDict([('a', 3)]), **MultiDict([('x', 1), ('x', 2)]))
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: g() got multiple values for keyword argument 'x' TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
Another helper function Another helper function

View File

@ -5,6 +5,7 @@ import os
import struct import struct
import sys import sys
import unittest import unittest
from multiprocessing import Process
from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, from test.support import (verbose, TESTFN, unlink, run_unittest, import_module,
cpython_only) cpython_only)
@ -12,7 +13,6 @@ from test.support import (verbose, TESTFN, unlink, run_unittest, import_module,
fcntl = import_module('fcntl') fcntl = import_module('fcntl')
# TODO - Write tests for flock() and lockf().
def get_lockdata(): def get_lockdata():
try: try:
@ -138,6 +138,33 @@ class TestFcntl(unittest.TestCase):
self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH) self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH)
self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH) self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH)
def test_lockf_exclusive(self):
self.f = open(TESTFN, 'wb+')
cmd = fcntl.LOCK_EX | fcntl.LOCK_NB
def try_lockf_on_other_process():
self.assertRaises(BlockingIOError, fcntl.lockf, self.f, cmd)
fcntl.lockf(self.f, cmd)
p = Process(target=try_lockf_on_other_process)
p.start()
p.join()
fcntl.lockf(self.f, fcntl.LOCK_UN)
self.assertEqual(p.exitcode, 0)
def test_lockf_share(self):
self.f = open(TESTFN, 'wb+')
cmd = fcntl.LOCK_SH | fcntl.LOCK_NB
def try_lockf_on_other_process():
fcntl.lockf(self.f, cmd)
fcntl.lockf(self.f, fcntl.LOCK_UN)
fcntl.lockf(self.f, cmd)
p = Process(target=try_lockf_on_other_process)
p.start()
p.join()
fcntl.lockf(self.f, fcntl.LOCK_UN)
self.assertEqual(p.exitcode, 0)
@cpython_only @cpython_only
def test_flock_overflow(self): def test_flock_overflow(self):
import _testcapi import _testcapi

View File

@ -1613,7 +1613,7 @@ class ConfigFileTest(BaseTest):
format=%(levelname)s ++ %(message)s format=%(levelname)s ++ %(message)s
""" """
self.apply_config(test_config) self.apply_config(test_config)
self.assertEquals(logging.getLogger().handlers[0].name, 'hand1') self.assertEqual(logging.getLogger().handlers[0].name, 'hand1')
def test_defaults_do_no_interpolation(self): def test_defaults_do_no_interpolation(self):
"""bpo-33802 defaults should not get interpolated""" """bpo-33802 defaults should not get interpolated"""
@ -5030,6 +5030,25 @@ class RotatingFileHandlerTest(BaseFileTest):
self.assertFalse(os.path.exists(namer(self.fn + ".3"))) self.assertFalse(os.path.exists(namer(self.fn + ".3")))
rh.close() rh.close()
def test_namer_rotator_inheritance(self):
class HandlerWithNamerAndRotator(logging.handlers.RotatingFileHandler):
def namer(self, name):
return name + ".test"
def rotator(self, source, dest):
if os.path.exists(source):
os.rename(source, dest + ".rotated")
rh = HandlerWithNamerAndRotator(
self.fn, backupCount=2, maxBytes=1)
self.assertEqual(rh.namer(self.fn), self.fn + ".test")
rh.emit(self.next_rec())
self.assertLogFile(self.fn)
rh.emit(self.next_rec())
self.assertLogFile(rh.namer(self.fn + ".1") + ".rotated")
self.assertFalse(os.path.exists(rh.namer(self.fn + ".1")))
rh.close()
@support.requires_zlib @support.requires_zlib
def test_rotator(self): def test_rotator(self):
def namer(name): def namer(name):

View File

@ -3638,6 +3638,24 @@ class ExportsTests(unittest.TestCase):
self.assertIn('walk', os.__all__) self.assertIn('walk', os.__all__)
class TestDirEntry(unittest.TestCase):
def setUp(self):
self.path = os.path.realpath(support.TESTFN)
self.addCleanup(support.rmtree, self.path)
os.mkdir(self.path)
def test_uninstantiable(self):
self.assertRaises(TypeError, os.DirEntry)
def test_unpickable(self):
filename = create_file(os.path.join(self.path, "file.txt"), b'python')
entry = [entry for entry in os.scandir(self.path)].pop()
self.assertIsInstance(entry, os.DirEntry)
self.assertEqual(entry.name, "file.txt")
import pickle
self.assertRaises(TypeError, pickle.dumps, entry, filename)
class TestScandir(unittest.TestCase): class TestScandir(unittest.TestCase):
check_no_resource_warning = support.check_no_resource_warning check_no_resource_warning = support.check_no_resource_warning
@ -3672,6 +3690,18 @@ class TestScandir(unittest.TestCase):
else: else:
self.assertEqual(stat1, stat2) self.assertEqual(stat1, stat2)
def test_uninstantiable(self):
scandir_iter = os.scandir(self.path)
self.assertRaises(TypeError, type(scandir_iter))
scandir_iter.close()
def test_unpickable(self):
filename = self.create_file("file.txt")
scandir_iter = os.scandir(self.path)
import pickle
self.assertRaises(TypeError, pickle.dumps, scandir_iter, filename)
scandir_iter.close()
def check_entry(self, entry, name, is_dir, is_file, is_symlink): def check_entry(self, entry, name, is_dir, is_file, is_symlink):
self.assertIsInstance(entry, os.DirEntry) self.assertIsInstance(entry, os.DirEntry)
self.assertEqual(entry.name, name) self.assertEqual(entry.name, name)

View File

@ -1470,6 +1470,15 @@ class PosixTester(unittest.TestCase):
open(fn, 'wb').close() open(fn, 'wb').close()
self.assertRaises(ValueError, os.stat, fn_with_NUL) self.assertRaises(ValueError, os.stat, fn_with_NUL)
@unittest.skipUnless(hasattr(os, "pidfd_open"), "pidfd_open unavailable")
def test_pidfd_open(self):
with self.assertRaises(OSError) as cm:
os.pidfd_open(-1)
if cm.exception.errno == errno.ENOSYS:
self.skipTest("system does not support pidfd_open")
self.assertEqual(cm.exception.errno, errno.EINVAL)
os.close(os.pidfd_open(os.getpid(), 0))
class PosixGroupsTester(unittest.TestCase): class PosixGroupsTester(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -236,27 +236,27 @@ Overridden parameters
>>> f(x=5, **{'x': 3}, y=2) >>> f(x=5, **{'x': 3}, y=2)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'x' TypeError: test.test_unpack_ex.f() got multiple values for keyword argument 'x'
>>> f(**{'x': 3}, x=5, y=2) >>> f(**{'x': 3}, x=5, y=2)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'x' TypeError: test.test_unpack_ex.f() got multiple values for keyword argument 'x'
>>> f(**{'x': 3}, **{'x': 5}, y=2) >>> f(**{'x': 3}, **{'x': 5}, y=2)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'x' TypeError: test.test_unpack_ex.f() got multiple values for keyword argument 'x'
>>> f(x=5, **{'x': 3}, **{'x': 2}) >>> f(x=5, **{'x': 3}, **{'x': 2})
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument 'x' TypeError: test.test_unpack_ex.f() got multiple values for keyword argument 'x'
>>> f(**{1: 3}, **{1: 5}) >>> f(**{1: 3}, **{1: 5})
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: f() got multiple values for keyword argument '1' TypeError: test.test_unpack_ex.f() got multiple values for keyword argument '1'
Unpacking non-sequence Unpacking non-sequence

View File

@ -53,7 +53,7 @@ This returns an instance of a class with the following public methods:
-- set all parameters at once -- set all parameters at once
tell() -- return current position in output file tell() -- return current position in output file
writeframesraw(data) writeframesraw(data)
-- write audio frames without pathing up the -- write audio frames without patching up the
file header file header
writeframes(data) writeframes(data)
-- write audio frames and patch up the file header -- write audio frames and patch up the file header

View File

@ -1057,6 +1057,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/Python-ast.h \ $(srcdir)/Include/Python-ast.h \
\ \
$(srcdir)/Include/cpython/abstract.h \ $(srcdir)/Include/cpython/abstract.h \
$(srcdir)/Include/cpython/ceval.h \
$(srcdir)/Include/cpython/dictobject.h \ $(srcdir)/Include/cpython/dictobject.h \
$(srcdir)/Include/cpython/fileobject.h \ $(srcdir)/Include/cpython/fileobject.h \
$(srcdir)/Include/cpython/import.h \ $(srcdir)/Include/cpython/import.h \

View File

@ -0,0 +1 @@
Fix _hashlib build when Blake2 is disabled, but OpenSSL supports it.

View File

@ -0,0 +1,2 @@
Convert posixmodule.c statically allocated types ``DirEntryType`` and
``ScandirIteratorType`` to heap-allocated types.

View File

@ -0,0 +1,2 @@
Add :c:func:`_PyObject_FunctionStr` to get a user-friendly string representation
of a function-like object. Patch by Jeroen Demeyer.

View File

@ -0,0 +1,5 @@
Provide :c:func:`Py_EnterRecursiveCall` and :c:func:`Py_LeaveRecursiveCall`
as regular functions for the limited API. Previously, there were defined as
macros, but these macros didn't work with the limited API which cannot access
``PyThreadState.recursion_depth`` field. Remove ``_Py_CheckRecursionLimit``
from the stable ABI.

View File

@ -0,0 +1 @@
Reëxport some function compatibility wrappers for macros in ``pythonrun.h``.

View File

@ -0,0 +1,3 @@
Optimized some set operations (e.g. ``|``, ``^``, and ``-``) of
``dict_keys``. ``d.keys() | other`` was slower than ``set(d) | other`` but
they are almost same performance for now.

View File

@ -0,0 +1 @@
Expose the Linux ``pidfd_open`` syscall as :func:`os.pidfd_open`.

View File

@ -0,0 +1,2 @@
Add :data:`os.P_PIDFD` constant, which may be passed to :func:`os.waitid` to
wait on a Linux process file descriptor.

View File

@ -0,0 +1 @@
logging: change RotatingHandler namer and rotator to class-level attributes. This stops __init__ from setting them to None in the case where a subclass defines them with eponymous methods.

View File

@ -0,0 +1,2 @@
Transformation performed by certain fixers (e.g. future, itertools_imports) that causes a statement to be replaced by a blank line will generate a Python file that contains a syntax error. Enhancement applied checks whether the statement to be replaced has any siblings or not. If no sibling is found, then the statement gets replaced with a "pass" statement instead of a blank line.
By doing this, Python source files generated by 2to3 are more readily runnable right after the transformation.

View File

@ -132,21 +132,25 @@ partial_dealloc(partialobject *pto)
* if we would need to do that, we stop using vectorcall and fall back * if we would need to do that, we stop using vectorcall and fall back
* to using partial_call() instead. */ * to using partial_call() instead. */
_Py_NO_INLINE static PyObject * _Py_NO_INLINE static PyObject *
partial_vectorcall_fallback(partialobject *pto, PyObject *const *args, partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
size_t nargsf, PyObject *kwnames) PyObject *const *args, size_t nargsf,
PyObject *kwnames)
{ {
pto->vectorcall = NULL; pto->vectorcall = NULL;
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
return _PyObject_MakeTpCall((PyObject *)pto, args, nargs, kwnames); return _PyObject_MakeTpCall(tstate, (PyObject *)pto,
args, nargs, kwnames);
} }
static PyObject * static PyObject *
partial_vectorcall(partialobject *pto, PyObject *const *args, partial_vectorcall(partialobject *pto, PyObject *const *args,
size_t nargsf, PyObject *kwnames) size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
/* pto->kw is mutable, so need to check every time */ /* pto->kw is mutable, so need to check every time */
if (PyDict_GET_SIZE(pto->kw)) { if (PyDict_GET_SIZE(pto->kw)) {
return partial_vectorcall_fallback(pto, args, nargsf, kwnames); return partial_vectorcall_fallback(tstate, pto, args, nargsf, kwnames);
} }
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
@ -160,7 +164,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
/* Fast path if we're called without arguments */ /* Fast path if we're called without arguments */
if (nargs_total == 0) { if (nargs_total == 0) {
return _PyObject_Vectorcall(pto->fn, pto_args, pto_nargs, NULL); return _PyObject_VectorcallTstate(tstate, pto->fn,
pto_args, pto_nargs, NULL);
} }
/* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single /* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
@ -169,7 +174,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
PyObject **newargs = (PyObject **)args - 1; PyObject **newargs = (PyObject **)args - 1;
PyObject *tmp = newargs[0]; PyObject *tmp = newargs[0];
newargs[0] = pto_args[0]; newargs[0] = pto_args[0];
PyObject *ret = _PyObject_Vectorcall(pto->fn, newargs, nargs + 1, kwnames); PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn,
newargs, nargs + 1, kwnames);
newargs[0] = tmp; newargs[0] = tmp;
return ret; return ret;
} }
@ -195,7 +201,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*)); memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*));
memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*)); memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*));
ret = _PyObject_Vectorcall(pto->fn, stack, pto_nargs + nargs, kwnames); ret = _PyObject_VectorcallTstate(tstate, pto->fn,
stack, pto_nargs + nargs, kwnames);
if (stack != small_stack) { if (stack != small_stack) {
PyMem_Free(stack); PyMem_Free(stack);
} }

View File

@ -42,7 +42,7 @@
#define PY_OPENSSL_HAS_SHAKE 1 #define PY_OPENSSL_HAS_SHAKE 1
#endif #endif
#ifdef NID_blake2b512 #if defined(NID_blake2b512) && !defined(OPENSSL_NO_BLAKE2)
#define PY_OPENSSL_HAS_BLAKE2 1 #define PY_OPENSSL_HAS_BLAKE2 1
#endif #endif

View File

@ -12,12 +12,6 @@
#include "structmember.h" #include "structmember.h"
#include "pycore_accu.h" #include "pycore_accu.h"
#ifdef __GNUC__
#define UNUSED __attribute__((__unused__))
#else
#define UNUSED
#endif
#define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType) #define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType)
#define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType) #define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType)
#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType) #define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType)
@ -78,7 +72,7 @@ static PyMemberDef encoder_members[] = {
static PyObject * static PyObject *
ascii_escape_unicode(PyObject *pystr); ascii_escape_unicode(PyObject *pystr);
static PyObject * static PyObject *
py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr); py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr);
void init_json(void); void init_json(void);
static PyObject * static PyObject *
scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
@ -562,7 +556,7 @@ PyDoc_STRVAR(pydoc_scanstring,
); );
static PyObject * static PyObject *
py_scanstring(PyObject* self UNUSED, PyObject *args) py_scanstring(PyObject* Py_UNUSED(self), PyObject *args)
{ {
PyObject *pystr; PyObject *pystr;
PyObject *rval; PyObject *rval;
@ -591,7 +585,7 @@ PyDoc_STRVAR(pydoc_encode_basestring_ascii,
); );
static PyObject * static PyObject *
py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr) py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr)
{ {
PyObject *rval; PyObject *rval;
/* Return an ASCII-only JSON representation of a Python string */ /* Return an ASCII-only JSON representation of a Python string */
@ -616,7 +610,7 @@ PyDoc_STRVAR(pydoc_encode_basestring,
); );
static PyObject * static PyObject *
py_encode_basestring(PyObject* self UNUSED, PyObject *pystr) py_encode_basestring(PyObject* Py_UNUSED(self), PyObject *pystr)
{ {
PyObject *rval; PyObject *rval;
/* Return a JSON representation of a Python string */ /* Return a JSON representation of a Python string */

View File

@ -2838,7 +2838,7 @@ PyDoc_STRVAR(os_sched_param__doc__,
"sched_param(sched_priority)\n" "sched_param(sched_priority)\n"
"--\n" "--\n"
"\n" "\n"
"Current has only one field: sched_priority\");\n" "Currently has only one field: sched_priority\n"
"\n" "\n"
" sched_priority\n" " sched_priority\n"
" A scheduling parameter."); " A scheduling parameter.");
@ -3963,6 +3963,44 @@ os_wait(PyObject *module, PyObject *Py_UNUSED(ignored))
#endif /* defined(HAVE_WAIT) */ #endif /* defined(HAVE_WAIT) */
#if (defined(__linux__) && defined(__NR_pidfd_open))
PyDoc_STRVAR(os_pidfd_open__doc__,
"pidfd_open($module, /, pid, flags=0)\n"
"--\n"
"\n"
"Return a file descriptor referring to the process *pid*.\n"
"\n"
"The descriptor can be used to perform process management without races and\n"
"signals.");
#define OS_PIDFD_OPEN_METHODDEF \
{"pidfd_open", (PyCFunction)(void(*)(void))os_pidfd_open, METH_FASTCALL|METH_KEYWORDS, os_pidfd_open__doc__},
static PyObject *
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags);
static PyObject *
os_pidfd_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"pid", "flags", NULL};
static _PyArg_Parser _parser = {"" _Py_PARSE_PID "|O&:pidfd_open", _keywords, 0};
pid_t pid;
unsigned int flags = 0;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&pid, _PyLong_UnsignedInt_Converter, &flags)) {
goto exit;
}
return_value = os_pidfd_open_impl(module, pid, flags);
exit:
return return_value;
}
#endif /* (defined(__linux__) && defined(__NR_pidfd_open)) */
#if (defined(HAVE_READLINK) || defined(MS_WINDOWS)) #if (defined(HAVE_READLINK) || defined(MS_WINDOWS))
PyDoc_STRVAR(os_readlink__doc__, PyDoc_STRVAR(os_readlink__doc__,
@ -8480,6 +8518,10 @@ exit:
#define OS_WAIT_METHODDEF #define OS_WAIT_METHODDEF
#endif /* !defined(OS_WAIT_METHODDEF) */ #endif /* !defined(OS_WAIT_METHODDEF) */
#ifndef OS_PIDFD_OPEN_METHODDEF
#define OS_PIDFD_OPEN_METHODDEF
#endif /* !defined(OS_PIDFD_OPEN_METHODDEF) */
#ifndef OS_READLINK_METHODDEF #ifndef OS_READLINK_METHODDEF
#define OS_READLINK_METHODDEF #define OS_READLINK_METHODDEF
#endif /* !defined(OS_READLINK_METHODDEF) */ #endif /* !defined(OS_READLINK_METHODDEF) */
@ -8731,4 +8773,4 @@ exit:
#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF #ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF
#define OS__REMOVE_DLL_DIRECTORY_METHODDEF #define OS__REMOVE_DLL_DIRECTORY_METHODDEF
#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ #endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */
/*[clinic end generated code: output=fe7897441fed5402 input=a9049054013a1b77]*/ /*[clinic end generated code: output=51ba5b9536420cea input=a9049054013a1b77]*/

View File

@ -85,6 +85,9 @@ corresponding Unix manual entries for more information on calls.");
#ifdef HAVE_SYS_WAIT_H #ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h> /* For WNOHANG */ #include <sys/wait.h> /* For WNOHANG */
#endif #endif
#ifdef HAVE_LINUX_WAIT_H
#include <linux/wait.h> // For P_PIDFD
#endif
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H
#include <signal.h> #include <signal.h>
@ -217,6 +220,7 @@ corresponding Unix manual entries for more information on calls.");
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#endif /* ! __WATCOMC__ || __QNX__ */ #endif /* ! __WATCOMC__ || __QNX__ */
_Py_IDENTIFIER(__fspath__);
/*[clinic input] /*[clinic input]
# one of the few times we lie about this name! # one of the few times we lie about this name!
@ -537,7 +541,7 @@ _Py_Uid_Converter(PyObject *obj, void *p)
if (index == NULL) { if (index == NULL) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"uid should be integer, not %.200s", "uid should be integer, not %.200s",
Py_TYPE(obj)->tp_name); _PyType_Name(Py_TYPE(obj)));
return 0; return 0;
} }
@ -643,7 +647,7 @@ _Py_Gid_Converter(PyObject *obj, void *p)
if (index == NULL) { if (index == NULL) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"gid should be integer, not %.200s", "gid should be integer, not %.200s",
Py_TYPE(obj)->tp_name); _PyType_Name(Py_TYPE(obj)));
return 0; return 0;
} }
@ -810,11 +814,37 @@ dir_fd_converter(PyObject *o, void *p)
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"argument should be integer or None, not %.200s", "argument should be integer or None, not %.200s",
Py_TYPE(o)->tp_name); _PyType_Name(Py_TYPE(o)));
return 0; return 0;
} }
} }
typedef struct {
PyObject *billion;
PyObject *posix_putenv_garbage;
PyObject *DirEntryType;
PyObject *ScandirIteratorType;
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
PyObject *SchedParamType;
#endif
PyObject *StatResultType;
PyObject *StatVFSResultType;
PyObject *TerminalSizeType;
PyObject *TimesResultType;
PyObject *UnameResultType;
#if defined(HAVE_WAITID) && !defined(__APPLE__)
PyObject *WaitidResultType;
#endif
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
PyObject *struct_rusage;
#endif
PyObject *st_mode;
} _posixstate;
static struct PyModuleDef posixmodule;
#define _posixstate(o) ((_posixstate *)PyModule_GetState(o))
#define _posixstate_global ((_posixstate *)PyModule_GetState(PyState_FindModule(&posixmodule)))
/* /*
* A PyArg_ParseTuple "converter" function * A PyArg_ParseTuple "converter" function
@ -984,7 +1014,6 @@ path_converter(PyObject *o, void *p)
if (!is_index && !is_buffer && !is_unicode && !is_bytes) { if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
/* Inline PyOS_FSPath() for better error messages. */ /* Inline PyOS_FSPath() for better error messages. */
_Py_IDENTIFIER(__fspath__);
PyObject *func, *res; PyObject *func, *res;
func = _PyObject_LookupSpecial(o, &PyId___fspath__); func = _PyObject_LookupSpecial(o, &PyId___fspath__);
@ -1005,8 +1034,8 @@ path_converter(PyObject *o, void *p)
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expected %.200s.__fspath__() to return str or bytes, " "expected %.200s.__fspath__() to return str or bytes, "
"not %.200s", Py_TYPE(o)->tp_name, "not %.200s", _PyType_Name(Py_TYPE(o)),
Py_TYPE(res)->tp_name); _PyType_Name(Py_TYPE(res)));
Py_DECREF(res); Py_DECREF(res);
goto error_exit; goto error_exit;
} }
@ -1058,7 +1087,7 @@ path_converter(PyObject *o, void *p)
path->allow_fd ? "string, bytes, os.PathLike or integer" : path->allow_fd ? "string, bytes, os.PathLike or integer" :
path->nullable ? "string, bytes, os.PathLike or None" : path->nullable ? "string, bytes, os.PathLike or None" :
"string, bytes or os.PathLike", "string, bytes or os.PathLike",
Py_TYPE(o)->tp_name)) { _PyType_Name(Py_TYPE(o)))) {
goto error_exit; goto error_exit;
} }
bytes = PyBytes_FromObject(o); bytes = PyBytes_FromObject(o);
@ -1089,7 +1118,7 @@ path_converter(PyObject *o, void *p)
path->allow_fd ? "string, bytes, os.PathLike or integer" : path->allow_fd ? "string, bytes, os.PathLike or integer" :
path->nullable ? "string, bytes, os.PathLike or None" : path->nullable ? "string, bytes, os.PathLike or None" :
"string, bytes or os.PathLike", "string, bytes or os.PathLike",
Py_TYPE(o)->tp_name); _PyType_Name(Py_TYPE(o)));
goto error_exit; goto error_exit;
} }
@ -2047,14 +2076,6 @@ static PyStructSequence_Desc waitid_result_desc = {
waitid_result_fields, waitid_result_fields,
5 5
}; };
static PyTypeObject* WaitidResultType;
#endif
static int initialized;
static PyTypeObject* StatResultType;
static PyTypeObject* StatVFSResultType;
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
static PyTypeObject* SchedParamType;
#endif #endif
static newfunc structseq_new; static newfunc structseq_new;
@ -2080,8 +2101,61 @@ statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject*)result; return (PyObject*)result;
} }
static int
_posix_clear(PyObject *module)
{
Py_CLEAR(_posixstate(module)->billion);
Py_CLEAR(_posixstate(module)->posix_putenv_garbage);
Py_CLEAR(_posixstate(module)->DirEntryType);
Py_CLEAR(_posixstate(module)->ScandirIteratorType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
Py_CLEAR(_posixstate(module)->SchedParamType);
#endif
Py_CLEAR(_posixstate(module)->StatResultType);
Py_CLEAR(_posixstate(module)->StatVFSResultType);
Py_CLEAR(_posixstate(module)->TerminalSizeType);
Py_CLEAR(_posixstate(module)->TimesResultType);
Py_CLEAR(_posixstate(module)->UnameResultType);
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_CLEAR(_posixstate(module)->WaitidResultType);
#endif
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
Py_CLEAR(_posixstate(module)->struct_rusage);
#endif
Py_CLEAR(_posixstate(module)->st_mode);
return 0;
}
static PyObject *billion = NULL; static int
_posix_traverse(PyObject *module, visitproc visit, void *arg)
{
Py_VISIT(_posixstate(module)->billion);
Py_VISIT(_posixstate(module)->posix_putenv_garbage);
Py_VISIT(_posixstate(module)->DirEntryType);
Py_VISIT(_posixstate(module)->ScandirIteratorType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
Py_VISIT(_posixstate(module)->SchedParamType);
#endif
Py_VISIT(_posixstate(module)->StatResultType);
Py_VISIT(_posixstate(module)->StatVFSResultType);
Py_VISIT(_posixstate(module)->TerminalSizeType);
Py_VISIT(_posixstate(module)->TimesResultType);
Py_VISIT(_posixstate(module)->UnameResultType);
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_VISIT(_posixstate(module)->WaitidResultType);
#endif
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
Py_VISIT(_posixstate(module)->struct_rusage);
#endif
Py_VISIT(_posixstate(module)->st_mode);
return 0;
}
static void
_posix_free(void *module)
{
_posix_clear((PyObject *)module);
}
static void static void
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
@ -2095,7 +2169,7 @@ fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
if (!(s && ns_fractional)) if (!(s && ns_fractional))
goto exit; goto exit;
s_in_ns = PyNumber_Multiply(s, billion); s_in_ns = PyNumber_Multiply(s, _posixstate_global->billion);
if (!s_in_ns) if (!s_in_ns)
goto exit; goto exit;
@ -2128,7 +2202,8 @@ static PyObject*
_pystat_fromstructstat(STRUCT_STAT *st) _pystat_fromstructstat(STRUCT_STAT *st)
{ {
unsigned long ansec, mnsec, cnsec; unsigned long ansec, mnsec, cnsec;
PyObject *v = PyStructSequence_New(StatResultType); PyObject *StatResultType = _posixstate_global->StatResultType;
PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
if (v == NULL) if (v == NULL)
return NULL; return NULL;
@ -4505,15 +4580,12 @@ or via the attributes sysname, nodename, release, version, and machine.\n\
See os.uname for more information."); See os.uname for more information.");
static PyStructSequence_Desc uname_result_desc = { static PyStructSequence_Desc uname_result_desc = {
"uname_result", /* name */ MODNAME ".uname_result", /* name */
uname_result__doc__, /* doc */ uname_result__doc__, /* doc */
uname_result_fields, uname_result_fields,
5 5
}; };
static PyTypeObject* UnameResultType;
#ifdef HAVE_UNAME #ifdef HAVE_UNAME
/*[clinic input] /*[clinic input]
os.uname os.uname
@ -4539,7 +4611,8 @@ os_uname_impl(PyObject *module)
if (res < 0) if (res < 0)
return posix_error(); return posix_error();
value = PyStructSequence_New(UnameResultType); PyObject *UnameResultType = _posixstate(module)->UnameResultType;
value = PyStructSequence_New((PyTypeObject *)UnameResultType);
if (value == NULL) if (value == NULL)
return NULL; return NULL;
@ -4720,13 +4793,13 @@ split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
{ {
int result = 0; int result = 0;
PyObject *divmod; PyObject *divmod;
divmod = PyNumber_Divmod(py_long, billion); divmod = PyNumber_Divmod(py_long, _posixstate_global->billion);
if (!divmod) if (!divmod)
goto exit; goto exit;
if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s.__divmod__() must return a 2-tuple, not %.200s", "%.200s.__divmod__() must return a 2-tuple, not %.200s",
Py_TYPE(py_long)->tp_name, Py_TYPE(divmod)->tp_name); _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
goto exit; goto exit;
} }
*s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
@ -5973,7 +6046,7 @@ check_null_or_callable(PyObject *obj, const char* obj_name)
{ {
if (obj && !PyCallable_Check(obj)) { if (obj && !PyCallable_Check(obj)) {
PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s", PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
obj_name, Py_TYPE(obj)->tp_name); obj_name, _PyType_Name(Py_TYPE(obj)));
return -1; return -1;
} }
return 0; return 0;
@ -6177,12 +6250,12 @@ os.sched_param.__new__
sched_priority: object sched_priority: object
A scheduling parameter. A scheduling parameter.
Current has only one field: sched_priority"); Currently has only one field: sched_priority
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
/*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/ /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
{ {
PyObject *res; PyObject *res;
@ -6194,7 +6267,6 @@ os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
return res; return res;
} }
PyDoc_VAR(os_sched_param__doc__); PyDoc_VAR(os_sched_param__doc__);
static PyStructSequence_Field sched_param_fields[] = { static PyStructSequence_Field sched_param_fields[] = {
@ -6214,7 +6286,8 @@ convert_sched_param(PyObject *param, struct sched_param *res)
{ {
long priority; long priority;
if (Py_TYPE(param) != SchedParamType) { PyObject *SchedParamType = _posixstate_global->SchedParamType;
if (Py_TYPE(param) != (PyTypeObject *)SchedParamType) {
PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
return 0; return 0;
} }
@ -6285,7 +6358,8 @@ os_sched_getparam_impl(PyObject *module, pid_t pid)
if (sched_getparam(pid, &param)) if (sched_getparam(pid, &param))
return posix_error(); return posix_error();
result = PyStructSequence_New(SchedParamType); PyObject *SchedParamType = _posixstate_global->SchedParamType;
result = PyStructSequence_New((PyTypeObject *)SchedParamType);
if (!result) if (!result)
return NULL; return NULL;
priority = PyLong_FromLong(param.sched_priority); priority = PyLong_FromLong(param.sched_priority);
@ -7494,8 +7568,7 @@ static PyObject *
wait_helper(pid_t pid, int status, struct rusage *ru) wait_helper(pid_t pid, int status, struct rusage *ru)
{ {
PyObject *result; PyObject *result;
static PyObject *struct_rusage; PyObject *struct_rusage;
_Py_IDENTIFIER(struct_rusage);
if (pid == -1) if (pid == -1)
return posix_error(); return posix_error();
@ -7506,15 +7579,13 @@ wait_helper(pid_t pid, int status, struct rusage *ru)
memset(ru, 0, sizeof(*ru)); memset(ru, 0, sizeof(*ru));
} }
if (struct_rusage == NULL) { PyObject *m = PyImport_ImportModuleNoBlock("resource");
PyObject *m = PyImport_ImportModuleNoBlock("resource"); if (m == NULL)
if (m == NULL) return NULL;
return NULL; struct_rusage = PyObject_GetAttr(m, _posixstate_global->struct_rusage);
struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage); Py_DECREF(m);
Py_DECREF(m); if (struct_rusage == NULL)
if (struct_rusage == NULL) return NULL;
return NULL;
}
/* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
result = PyStructSequence_New((PyTypeObject*) struct_rusage); result = PyStructSequence_New((PyTypeObject*) struct_rusage);
@ -7668,7 +7739,8 @@ os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
if (si.si_pid == 0) if (si.si_pid == 0)
Py_RETURN_NONE; Py_RETURN_NONE;
result = PyStructSequence_New(WaitidResultType); PyObject *WaitidResultType = _posixstate(module)->WaitidResultType;
result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
if (!result) if (!result)
return NULL; return NULL;
@ -7792,6 +7864,30 @@ os_wait_impl(PyObject *module)
} }
#endif /* HAVE_WAIT */ #endif /* HAVE_WAIT */
#if defined(__linux__) && defined(__NR_pidfd_open)
/*[clinic input]
os.pidfd_open
pid: pid_t
flags: unsigned_int = 0
Return a file descriptor referring to the process *pid*.
The descriptor can be used to perform process management without races and
signals.
[clinic start generated code]*/
static PyObject *
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
{
int fd = syscall(__NR_pidfd_open, pid, flags);
if (fd < 0) {
return posix_error();
}
return PyLong_FromLong(fd);
}
#endif
#if defined(HAVE_READLINK) || defined(MS_WINDOWS) #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
/*[clinic input] /*[clinic input]
@ -8119,8 +8215,6 @@ static PyStructSequence_Desc times_result_desc = {
5 5
}; };
static PyTypeObject* TimesResultType;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
#define HAVE_TIMES /* mandatory, for the method table */ #define HAVE_TIMES /* mandatory, for the method table */
#endif #endif
@ -8132,7 +8226,8 @@ build_times_result(double user, double system,
double children_user, double children_system, double children_user, double children_system,
double elapsed) double elapsed)
{ {
PyObject *value = PyStructSequence_New(TimesResultType); PyObject *TimesResultType = _posixstate_global->TimesResultType;
PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
if (value == NULL) if (value == NULL)
return NULL; return NULL;
@ -9953,10 +10048,6 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
#ifdef HAVE_PUTENV #ifdef HAVE_PUTENV
/* Save putenv() parameters as values here, so we can collect them when they
* get re-set with another call for the same key. */
static PyObject *posix_putenv_garbage;
static void static void
posix_putenv_garbage_setitem(PyObject *name, PyObject *value) posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
{ {
@ -9964,7 +10055,7 @@ posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
* this will cause previous value to be collected. This has to * this will cause previous value to be collected. This has to
* happen after the real putenv() call because the old value * happen after the real putenv() call because the old value
* was still accessible until then. */ * was still accessible until then. */
if (PyDict_SetItem(posix_putenv_garbage, name, value)) if (PyDict_SetItem(_posixstate_global->posix_putenv_garbage, name, value))
/* really not much we can do; just leak */ /* really not much we can do; just leak */
PyErr_Clear(); PyErr_Clear();
else else
@ -10101,7 +10192,7 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
* happen after the real unsetenv() call because the * happen after the real unsetenv() call because the
* old value was still accessible until then. * old value was still accessible until then.
*/ */
if (PyDict_DelItem(posix_putenv_garbage, name)) { if (PyDict_DelItem(_posixstate(module)->posix_putenv_garbage, name)) {
/* really not much we can do; just leak */ /* really not much we can do; just leak */
if (!PyErr_ExceptionMatches(PyExc_KeyError)) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
return NULL; return NULL;
@ -10312,7 +10403,8 @@ os_WSTOPSIG_impl(PyObject *module, int status)
static PyObject* static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st) { _pystatvfs_fromstructstatvfs(struct statvfs st) {
PyObject *v = PyStructSequence_New(StatVFSResultType); PyObject *StatVFSResultType = _posixstate_global->StatVFSResultType;
PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
if (v == NULL) if (v == NULL)
return NULL; return NULL;
@ -12089,8 +12181,6 @@ os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
/* Terminal size querying */ /* Terminal size querying */
static PyTypeObject* TerminalSizeType;
PyDoc_STRVAR(TerminalSize_docstring, PyDoc_STRVAR(TerminalSize_docstring,
"A tuple of (columns, lines) for holding terminal window size"); "A tuple of (columns, lines) for holding terminal window size");
@ -12181,7 +12271,8 @@ get_terminal_size(PyObject *self, PyObject *args)
} }
#endif /* TERMSIZE_USE_CONIO */ #endif /* TERMSIZE_USE_CONIO */
termsize = PyStructSequence_New(TerminalSizeType); PyObject *TerminalSizeType = _posixstate(self)->TerminalSizeType;
termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
if (termsize == NULL) if (termsize == NULL)
return NULL; return NULL;
PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
@ -12379,9 +12470,9 @@ os_set_blocking_impl(PyObject *module, int fd, int blocking)
/*[clinic input] /*[clinic input]
class os.DirEntry "DirEntry *" "&DirEntryType" class os.DirEntry "DirEntry *" "DirEntryType"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
@ -12402,14 +12493,25 @@ typedef struct {
#endif #endif
} DirEntry; } DirEntry;
static PyObject *
_disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyErr_Format(PyExc_TypeError,
"cannot create '%.100s' instances", _PyType_Name(type));
return NULL;
}
static void static void
DirEntry_dealloc(DirEntry *entry) DirEntry_dealloc(DirEntry *entry)
{ {
PyTypeObject *tp = Py_TYPE(entry);
Py_XDECREF(entry->name); Py_XDECREF(entry->name);
Py_XDECREF(entry->path); Py_XDECREF(entry->path);
Py_XDECREF(entry->stat); Py_XDECREF(entry->stat);
Py_XDECREF(entry->lstat); Py_XDECREF(entry->lstat);
Py_TYPE(entry)->tp_free((PyObject *)entry); freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
free_func(entry);
Py_DECREF(tp);
} }
/* Forward reference */ /* Forward reference */
@ -12538,7 +12640,6 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
unsigned long dir_bits; unsigned long dir_bits;
#endif #endif
_Py_IDENTIFIER(st_mode);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
@ -12561,7 +12662,7 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits
} }
goto error; goto error;
} }
st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode); st_mode = PyObject_GetAttr(stat, _posixstate_global->st_mode);
if (!st_mode) if (!st_mode)
goto error; goto error;
@ -12709,39 +12810,24 @@ static PyMethodDef DirEntry_methods[] = {
{NULL} {NULL}
}; };
static PyTypeObject DirEntryType = { static PyType_Slot DirEntryType_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_new, _disabled_new},
MODNAME ".DirEntry", /* tp_name */ {Py_tp_dealloc, DirEntry_dealloc},
sizeof(DirEntry), /* tp_basicsize */ {Py_tp_repr, DirEntry_repr},
0, /* tp_itemsize */ {Py_tp_methods, DirEntry_methods},
/* methods */ {Py_tp_members, DirEntry_members},
(destructor)DirEntry_dealloc, /* tp_dealloc */ {0, 0},
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)DirEntry_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
DirEntry_methods, /* tp_methods */
DirEntry_members, /* tp_members */
}; };
static PyType_Spec DirEntryType_spec = {
MODNAME ".DirEntry",
sizeof(DirEntry),
0,
Py_TPFLAGS_DEFAULT,
DirEntryType_slots
};
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
static wchar_t * static wchar_t *
@ -12785,7 +12871,8 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
ULONG reparse_tag; ULONG reparse_tag;
wchar_t *joined_path; wchar_t *joined_path;
entry = PyObject_New(DirEntry, &DirEntryType); PyObject *DirEntryType = _posixstate_global->DirEntryType;
entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
if (!entry) if (!entry)
return NULL; return NULL;
entry->name = NULL; entry->name = NULL;
@ -12872,7 +12959,8 @@ DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
DirEntry *entry; DirEntry *entry;
char *joined_path; char *joined_path;
entry = PyObject_New(DirEntry, &DirEntryType); PyObject *DirEntryType = _posixstate_global->DirEntryType;
entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
if (!entry) if (!entry)
return NULL; return NULL;
entry->name = NULL; entry->name = NULL;
@ -13134,10 +13222,13 @@ ScandirIterator_finalize(ScandirIterator *iterator)
static void static void
ScandirIterator_dealloc(ScandirIterator *iterator) ScandirIterator_dealloc(ScandirIterator *iterator)
{ {
PyTypeObject *tp = Py_TYPE(iterator);
if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
return; return;
Py_TYPE(iterator)->tp_free((PyObject *)iterator); freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
free_func(iterator);
Py_DECREF(tp);
} }
static PyMethodDef ScandirIterator_methods[] = { static PyMethodDef ScandirIterator_methods[] = {
@ -13147,56 +13238,22 @@ static PyMethodDef ScandirIterator_methods[] = {
{NULL} {NULL}
}; };
static PyTypeObject ScandirIteratorType = { static PyType_Slot ScandirIteratorType_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_new, _disabled_new},
MODNAME ".ScandirIterator", /* tp_name */ {Py_tp_dealloc, ScandirIterator_dealloc},
sizeof(ScandirIterator), /* tp_basicsize */ {Py_tp_finalize, ScandirIterator_finalize},
0, /* tp_itemsize */ {Py_tp_iter, PyObject_SelfIter},
/* methods */ {Py_tp_iternext, ScandirIterator_iternext},
(destructor)ScandirIterator_dealloc, /* tp_dealloc */ {Py_tp_methods, ScandirIterator_methods},
0, /* tp_vectorcall_offset */ {0, 0},
0, /* tp_getattr */ };
0, /* tp_setattr */
0, /* tp_as_async */ static PyType_Spec ScandirIteratorType_spec = {
0, /* tp_repr */ MODNAME ".ScandirIterator",
0, /* tp_as_number */ sizeof(ScandirIterator),
0, /* tp_as_sequence */ 0,
0, /* tp_as_mapping */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
0, /* tp_hash */ ScandirIteratorType_slots
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)ScandirIterator_iternext, /* tp_iternext */
ScandirIterator_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0, /* tp_version_tag */
(destructor)ScandirIterator_finalize, /* tp_finalize */
}; };
/*[clinic input] /*[clinic input]
@ -13232,7 +13289,8 @@ os_scandir_impl(PyObject *module, path_t *path)
return NULL; return NULL;
} }
iterator = PyObject_New(ScandirIterator, &ScandirIteratorType); PyObject *ScandirIteratorType = _posixstate(module)->ScandirIteratorType;
iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
if (!iterator) if (!iterator)
return NULL; return NULL;
@ -13322,7 +13380,6 @@ PyOS_FSPath(PyObject *path)
{ {
/* For error message reasons, this function is manually inlined in /* For error message reasons, this function is manually inlined in
path_converter(). */ path_converter(). */
_Py_IDENTIFIER(__fspath__);
PyObject *func = NULL; PyObject *func = NULL;
PyObject *path_repr = NULL; PyObject *path_repr = NULL;
@ -13336,7 +13393,7 @@ PyOS_FSPath(PyObject *path)
return PyErr_Format(PyExc_TypeError, return PyErr_Format(PyExc_TypeError,
"expected str, bytes or os.PathLike object, " "expected str, bytes or os.PathLike object, "
"not %.200s", "not %.200s",
Py_TYPE(path)->tp_name); _PyType_Name(Py_TYPE(path)));
} }
path_repr = _PyObject_CallNoArg(func); path_repr = _PyObject_CallNoArg(func);
@ -13348,8 +13405,8 @@ PyOS_FSPath(PyObject *path)
if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expected %.200s.__fspath__() to return str or bytes, " "expected %.200s.__fspath__() to return str or bytes, "
"not %.200s", Py_TYPE(path)->tp_name, "not %.200s", _PyType_Name(Py_TYPE(path)),
Py_TYPE(path_repr)->tp_name); _PyType_Name(Py_TYPE(path_repr)));
Py_DECREF(path_repr); Py_DECREF(path_repr);
return NULL; return NULL;
} }
@ -13641,6 +13698,7 @@ static PyMethodDef posix_methods[] = {
OS_WAIT4_METHODDEF OS_WAIT4_METHODDEF
OS_WAITID_METHODDEF OS_WAITID_METHODDEF
OS_WAITPID_METHODDEF OS_WAITPID_METHODDEF
OS_PIDFD_OPEN_METHODDEF
OS_GETSID_METHODDEF OS_GETSID_METHODDEF
OS_SETSID_METHODDEF OS_SETSID_METHODDEF
OS_SETPGID_METHODDEF OS_SETPGID_METHODDEF
@ -14044,6 +14102,9 @@ all_ins(PyObject *m)
if (PyModule_AddIntMacro(m, P_PID)) return -1; if (PyModule_AddIntMacro(m, P_PID)) return -1;
if (PyModule_AddIntMacro(m, P_PGID)) return -1; if (PyModule_AddIntMacro(m, P_PGID)) return -1;
if (PyModule_AddIntMacro(m, P_ALL)) return -1; if (PyModule_AddIntMacro(m, P_ALL)) return -1;
#ifdef P_PIDFD
if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
#endif
#endif #endif
#ifdef WEXITED #ifdef WEXITED
if (PyModule_AddIntMacro(m, WEXITED)) return -1; if (PyModule_AddIntMacro(m, WEXITED)) return -1;
@ -14258,12 +14319,12 @@ static struct PyModuleDef posixmodule = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
MODNAME, MODNAME,
posix__doc__, posix__doc__,
-1, sizeof(_posixstate),
posix_methods, posix_methods,
NULL, NULL,
NULL, _posix_traverse,
NULL, _posix_clear,
NULL _posix_free,
}; };
@ -14408,6 +14469,12 @@ INITFUNC(void)
PyObject *list; PyObject *list;
const char * const *trace; const char * const *trace;
m = PyState_FindModule(&posixmodule);
if (m != NULL) {
Py_INCREF(m);
return m;
}
m = PyModule_Create(&posixmodule); m = PyModule_Create(&posixmodule);
if (m == NULL) if (m == NULL)
return NULL; return NULL;
@ -14429,94 +14496,106 @@ INITFUNC(void)
PyModule_AddObject(m, "error", PyExc_OSError); PyModule_AddObject(m, "error", PyExc_OSError);
#ifdef HAVE_PUTENV #ifdef HAVE_PUTENV
if (posix_putenv_garbage == NULL) /* Save putenv() parameters as values here, so we can collect them when they
posix_putenv_garbage = PyDict_New(); * get re-set with another call for the same key. */
_posixstate(m)->posix_putenv_garbage = PyDict_New();
#endif #endif
if (!initialized) {
#if defined(HAVE_WAITID) && !defined(__APPLE__) #if defined(HAVE_WAITID) && !defined(__APPLE__)
waitid_result_desc.name = MODNAME ".waitid_result"; waitid_result_desc.name = MODNAME ".waitid_result";
WaitidResultType = PyStructSequence_NewType(&waitid_result_desc); PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
if (WaitidResultType == NULL) { if (WaitidResultType == NULL) {
return NULL; return NULL;
} }
Py_INCREF(WaitidResultType);
PyModule_AddObject(m, "waitid_result", WaitidResultType);
_posixstate(m)->WaitidResultType = WaitidResultType;
#endif #endif
stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
StatResultType = PyStructSequence_NewType(&stat_result_desc); PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
if (StatResultType == NULL) { if (StatResultType == NULL) {
return NULL; return NULL;
} }
structseq_new = StatResultType->tp_new; Py_INCREF(StatResultType);
StatResultType->tp_new = statresult_new; PyModule_AddObject(m, "stat_result", StatResultType);
_posixstate(m)->StatResultType = StatResultType;
structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
((PyTypeObject *)StatResultType)->tp_new = statresult_new;
statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc); PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
if (StatVFSResultType == NULL) { if (StatVFSResultType == NULL) {
return NULL; return NULL;
} }
Py_INCREF(StatVFSResultType);
PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
_posixstate(m)->StatVFSResultType = StatVFSResultType;
#ifdef NEED_TICKS_PER_SECOND #ifdef NEED_TICKS_PER_SECOND
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
ticks_per_second = sysconf(_SC_CLK_TCK); ticks_per_second = sysconf(_SC_CLK_TCK);
# elif defined(HZ) # elif defined(HZ)
ticks_per_second = HZ; ticks_per_second = HZ;
# else # else
ticks_per_second = 60; /* magic fallback value; may be bogus */ ticks_per_second = 60; /* magic fallback value; may be bogus */
# endif # endif
#endif #endif
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
sched_param_desc.name = MODNAME ".sched_param"; sched_param_desc.name = MODNAME ".sched_param";
SchedParamType = PyStructSequence_NewType(&sched_param_desc); PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
if (SchedParamType == NULL) { if (SchedParamType == NULL) {
return NULL; return NULL;
}
SchedParamType->tp_new = os_sched_param;
#endif
/* initialize TerminalSize_info */
TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
if (TerminalSizeType == NULL) {
return NULL;
}
/* initialize scandir types */
if (PyType_Ready(&ScandirIteratorType) < 0)
return NULL;
if (PyType_Ready(&DirEntryType) < 0)
return NULL;
} }
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_INCREF((PyObject*) WaitidResultType);
PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
#endif
Py_INCREF((PyObject*) StatResultType);
PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
Py_INCREF((PyObject*) StatVFSResultType);
PyModule_AddObject(m, "statvfs_result",
(PyObject*) StatVFSResultType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
Py_INCREF(SchedParamType); Py_INCREF(SchedParamType);
PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType); PyModule_AddObject(m, "sched_param", SchedParamType);
_posixstate(m)->SchedParamType = SchedParamType;
((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
#endif #endif
/* initialize TerminalSize_info */
PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
if (TerminalSizeType == NULL) {
return NULL;
}
Py_INCREF(TerminalSizeType);
PyModule_AddObject(m, "terminal_size", TerminalSizeType);
_posixstate(m)->TerminalSizeType = TerminalSizeType;
/* initialize scandir types */
PyObject *ScandirIteratorType = PyType_FromSpec(&ScandirIteratorType_spec);
if (ScandirIteratorType == NULL) {
return NULL;
}
_posixstate(m)->ScandirIteratorType = ScandirIteratorType;
PyObject *DirEntryType = PyType_FromSpec(&DirEntryType_spec);
if (DirEntryType == NULL) {
return NULL;
}
Py_INCREF(DirEntryType);
PyModule_AddObject(m, "DirEntry", DirEntryType);
_posixstate(m)->DirEntryType = DirEntryType;
times_result_desc.name = MODNAME ".times_result"; times_result_desc.name = MODNAME ".times_result";
TimesResultType = PyStructSequence_NewType(&times_result_desc); PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
if (TimesResultType == NULL) { if (TimesResultType == NULL) {
return NULL; return NULL;
} }
PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType); Py_INCREF(TimesResultType);
PyModule_AddObject(m, "times_result", TimesResultType);
_posixstate(m)->TimesResultType = TimesResultType;
uname_result_desc.name = MODNAME ".uname_result"; PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
UnameResultType = PyStructSequence_NewType(&uname_result_desc);
if (UnameResultType == NULL) { if (UnameResultType == NULL) {
return NULL; return NULL;
} }
Py_INCREF(UnameResultType);
PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType); PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
_posixstate(m)->UnameResultType = (PyObject *)UnameResultType;
#ifdef __APPLE__ #ifdef __APPLE__
/* /*
@ -14556,11 +14635,15 @@ INITFUNC(void)
#endif /* __APPLE__ */ #endif /* __APPLE__ */
Py_INCREF(TerminalSizeType); if ((_posixstate(m)->billion = PyLong_FromLong(1000000000)) == NULL)
PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType); return NULL;
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
billion = PyLong_FromLong(1000000000); _posixstate(m)->struct_rusage = PyUnicode_InternFromString("struct_rusage");
if (!billion) if (_posixstate(m)->struct_rusage == NULL)
return NULL;
#endif
_posixstate(m)->st_mode = PyUnicode_InternFromString("st_mode");
if (_posixstate(m)->st_mode == NULL)
return NULL; return NULL;
/* suppress "function not used" warnings */ /* suppress "function not used" warnings */
@ -14590,11 +14673,6 @@ INITFUNC(void)
} }
PyModule_AddObject(m, "_have_functions", list); PyModule_AddObject(m, "_have_functions", list);
Py_INCREF((PyObject *) &DirEntryType);
PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
initialized = 1;
return m; return m;
} }

View File

@ -1,6 +1,7 @@
/* Abstract Object Interface (many thanks to Jim Fulton) */ /* Abstract Object Interface (many thanks to Jim Fulton) */
#include "Python.h" #include "Python.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include <ctype.h> #include <ctype.h>
#include "structmember.h" /* we need the offsetof() macro from there */ #include "structmember.h" /* we need the offsetof() macro from there */
@ -2459,8 +2460,8 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
return retval; return retval;
} }
int static int
PyObject_IsInstance(PyObject *inst, PyObject *cls) object_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
{ {
_Py_IDENTIFIER(__instancecheck__); _Py_IDENTIFIER(__instancecheck__);
PyObject *checker; PyObject *checker;
@ -2475,34 +2476,31 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
} }
if (PyTuple_Check(cls)) { if (PyTuple_Check(cls)) {
Py_ssize_t i; if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
Py_ssize_t n;
int r = 0;
if (Py_EnterRecursiveCall(" in __instancecheck__"))
return -1; return -1;
n = PyTuple_GET_SIZE(cls); }
for (i = 0; i < n; ++i) { Py_ssize_t n = PyTuple_GET_SIZE(cls);
int r = 0;
for (Py_ssize_t i = 0; i < n; ++i) {
PyObject *item = PyTuple_GET_ITEM(cls, i); PyObject *item = PyTuple_GET_ITEM(cls, i);
r = PyObject_IsInstance(inst, item); r = object_isinstance(tstate, inst, item);
if (r != 0) if (r != 0)
/* either found it, or got an error */ /* either found it, or got an error */
break; break;
} }
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return r; return r;
} }
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__); checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
if (checker != NULL) { if (checker != NULL) {
PyObject *res;
int ok = -1; int ok = -1;
if (Py_EnterRecursiveCall(" in __instancecheck__")) { if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
Py_DECREF(checker); Py_DECREF(checker);
return ok; return ok;
} }
res = _PyObject_CallOneArg(checker, inst); PyObject *res = _PyObject_CallOneArg(checker, inst);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
Py_DECREF(checker); Py_DECREF(checker);
if (res != NULL) { if (res != NULL) {
ok = PyObject_IsTrue(res); ok = PyObject_IsTrue(res);
@ -2510,12 +2508,23 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
} }
return ok; return ok;
} }
else if (PyErr_Occurred()) else if (_PyErr_Occurred(tstate)) {
return -1; return -1;
}
/* Probably never reached anymore. */ /* Probably never reached anymore. */
return recursive_isinstance(inst, cls); return recursive_isinstance(inst, cls);
} }
int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
PyThreadState *tstate = _PyThreadState_GET();
return object_isinstance(tstate, inst, cls);
}
static int static int
recursive_issubclass(PyObject *derived, PyObject *cls) recursive_issubclass(PyObject *derived, PyObject *cls)
{ {
@ -2534,8 +2543,8 @@ recursive_issubclass(PyObject *derived, PyObject *cls)
return abstract_issubclass(derived, cls); return abstract_issubclass(derived, cls);
} }
int static int
PyObject_IsSubclass(PyObject *derived, PyObject *cls) object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
{ {
_Py_IDENTIFIER(__subclasscheck__); _Py_IDENTIFIER(__subclasscheck__);
PyObject *checker; PyObject *checker;
@ -2549,34 +2558,32 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
} }
if (PyTuple_Check(cls)) { if (PyTuple_Check(cls)) {
Py_ssize_t i;
Py_ssize_t n;
int r = 0;
if (Py_EnterRecursiveCall(" in __subclasscheck__")) if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
return -1; return -1;
n = PyTuple_GET_SIZE(cls); }
for (i = 0; i < n; ++i) { Py_ssize_t n = PyTuple_GET_SIZE(cls);
int r = 0;
for (Py_ssize_t i = 0; i < n; ++i) {
PyObject *item = PyTuple_GET_ITEM(cls, i); PyObject *item = PyTuple_GET_ITEM(cls, i);
r = PyObject_IsSubclass(derived, item); r = object_issubclass(tstate, derived, item);
if (r != 0) if (r != 0)
/* either found it, or got an error */ /* either found it, or got an error */
break; break;
} }
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return r; return r;
} }
checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__); checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__);
if (checker != NULL) { if (checker != NULL) {
PyObject *res;
int ok = -1; int ok = -1;
if (Py_EnterRecursiveCall(" in __subclasscheck__")) { if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
Py_DECREF(checker); Py_DECREF(checker);
return ok; return ok;
} }
res = _PyObject_CallOneArg(checker, derived); PyObject *res = _PyObject_CallOneArg(checker, derived);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
Py_DECREF(checker); Py_DECREF(checker);
if (res != NULL) { if (res != NULL) {
ok = PyObject_IsTrue(res); ok = PyObject_IsTrue(res);
@ -2584,12 +2591,23 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
} }
return ok; return ok;
} }
else if (PyErr_Occurred()) else if (_PyErr_Occurred(tstate)) {
return -1; return -1;
}
/* Probably never reached anymore. */ /* Probably never reached anymore. */
return recursive_issubclass(derived, cls); return recursive_issubclass(derived, cls);
} }
int
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{
PyThreadState *tstate = _PyThreadState_GET();
return object_issubclass(tstate, derived, cls);
}
int int
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls) _PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
{ {

View File

@ -1,13 +1,15 @@
#include "Python.h" #include "Python.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "pycore_tupleobject.h" #include "pycore_tupleobject.h"
#include "frameobject.h" #include "frameobject.h"
static PyObject *const * static PyObject *const *
_PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, _PyStack_UnpackDict(PyThreadState *tstate,
PyObject **p_kwnames); PyObject *const *args, Py_ssize_t nargs,
PyObject *kwargs, PyObject **p_kwnames);
static void static void
_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs, _PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs,
@ -25,22 +27,21 @@ null_error(void)
PyObject* PyObject*
_Py_CheckFunctionResult(PyObject *callable, PyObject *result, const char *where) _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
PyObject *result, const char *where)
{ {
int err_occurred = (PyErr_Occurred() != NULL);
assert((callable != NULL) ^ (where != NULL)); assert((callable != NULL) ^ (where != NULL));
if (result == NULL) { if (result == NULL) {
if (!err_occurred) { if (!_PyErr_Occurred(tstate)) {
if (callable) if (callable)
PyErr_Format(PyExc_SystemError, _PyErr_Format(tstate, PyExc_SystemError,
"%R returned NULL without setting an error", "%R returned NULL without setting an error",
callable); callable);
else else
PyErr_Format(PyExc_SystemError, _PyErr_Format(tstate, PyExc_SystemError,
"%s returned NULL without setting an error", "%s returned NULL without setting an error",
where); where);
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */ /* Ensure that the bug is caught in debug mode */
Py_FatalError("a function returned NULL without setting an error"); Py_FatalError("a function returned NULL without setting an error");
@ -49,18 +50,18 @@ _Py_CheckFunctionResult(PyObject *callable, PyObject *result, const char *where)
} }
} }
else { else {
if (err_occurred) { if (_PyErr_Occurred(tstate)) {
Py_DECREF(result); Py_DECREF(result);
if (callable) { if (callable) {
_PyErr_FormatFromCause(PyExc_SystemError, _PyErr_FormatFromCauseTstate(
"%R returned a result with an error set", tstate, PyExc_SystemError,
callable); "%R returned a result with an error set", callable);
} }
else { else {
_PyErr_FormatFromCause(PyExc_SystemError, _PyErr_FormatFromCauseTstate(
"%s returned a result with an error set", tstate, PyExc_SystemError,
where); "%s returned a result with an error set", where);
} }
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */ /* Ensure that the bug is caught in debug mode */
@ -87,11 +88,13 @@ PyObject *
_PyObject_FastCallDict(PyObject *callable, PyObject *const *args, _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
size_t nargsf, PyObject *kwargs) size_t nargsf, PyObject *kwargs)
{ {
assert(callable != NULL);
PyThreadState *tstate = _PyThreadState_GET();
/* _PyObject_FastCallDict() must not be called with an exception set, /* _PyObject_FastCallDict() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the because it can clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
assert(callable != NULL);
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
assert(nargs >= 0); assert(nargs >= 0);
@ -101,7 +104,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
vectorcallfunc func = _PyVectorcall_Function(callable); vectorcallfunc func = _PyVectorcall_Function(callable);
if (func == NULL) { if (func == NULL) {
/* Use tp_call instead */ /* Use tp_call instead */
return _PyObject_MakeTpCall(callable, args, nargs, kwargs); return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs);
} }
PyObject *res; PyObject *res;
@ -111,7 +114,9 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
else { else {
PyObject *kwnames; PyObject *kwnames;
PyObject *const *newargs; PyObject *const *newargs;
newargs = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames); newargs = _PyStack_UnpackDict(tstate,
args, nargs,
kwargs, &kwnames);
if (newargs == NULL) { if (newargs == NULL) {
return NULL; return NULL;
} }
@ -119,19 +124,22 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
_PyStack_UnpackDict_Free(newargs, nargs, kwnames); _PyStack_UnpackDict_Free(newargs, nargs, kwnames);
} }
return _Py_CheckFunctionResult(callable, res, NULL); return _Py_CheckFunctionResult(tstate, callable, res, NULL);
} }
PyObject * PyObject *
_PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords) _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
PyObject *const *args, Py_ssize_t nargs,
PyObject *keywords)
{ {
/* Slow path: build a temporary tuple for positional arguments and a /* Slow path: build a temporary tuple for positional arguments and a
* temporary dictionary for keyword arguments (if any) */ * temporary dictionary for keyword arguments (if any) */
ternaryfunc call = Py_TYPE(callable)->tp_call; ternaryfunc call = Py_TYPE(callable)->tp_call;
if (call == NULL) { if (call == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", _PyErr_Format(tstate, PyExc_TypeError,
Py_TYPE(callable)->tp_name); "'%.200s' object is not callable",
Py_TYPE(callable)->tp_name);
return NULL; return NULL;
} }
@ -162,10 +170,10 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
} }
PyObject *result = NULL; PyObject *result = NULL;
if (Py_EnterRecursiveCall(" while calling a Python object") == 0) if (_Py_EnterRecursiveCall(tstate, " while calling a Python object") == 0)
{ {
result = call(callable, argstuple, kwdict); result = call(callable, argstuple, kwdict);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
} }
Py_DECREF(argstuple); Py_DECREF(argstuple);
@ -173,7 +181,7 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
Py_DECREF(kwdict); Py_DECREF(kwdict);
} }
result = _Py_CheckFunctionResult(callable, result, NULL); result = _Py_CheckFunctionResult(tstate, callable, result, NULL);
return result; return result;
} }
@ -181,18 +189,22 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
PyObject * PyObject *
PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs) PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
{ {
PyThreadState *tstate = _PyThreadState_GET();
/* get vectorcallfunc as in _PyVectorcall_Function, but without /* get vectorcallfunc as in _PyVectorcall_Function, but without
* the _Py_TPFLAGS_HAVE_VECTORCALL check */ * the _Py_TPFLAGS_HAVE_VECTORCALL check */
Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset; Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset;
if (offset <= 0) { if (offset <= 0) {
PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall", _PyErr_Format(tstate, PyExc_TypeError,
Py_TYPE(callable)->tp_name); "'%.200s' object does not support vectorcall",
Py_TYPE(callable)->tp_name);
return NULL; return NULL;
} }
vectorcallfunc func = *(vectorcallfunc *)(((char *)callable) + offset); vectorcallfunc func = *(vectorcallfunc *)(((char *)callable) + offset);
if (func == NULL) { if (func == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall", _PyErr_Format(tstate, PyExc_TypeError,
Py_TYPE(callable)->tp_name); "'%.200s' object does not support vectorcall",
Py_TYPE(callable)->tp_name);
return NULL; return NULL;
} }
@ -206,27 +218,30 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
/* Convert arguments & call */ /* Convert arguments & call */
PyObject *const *args; PyObject *const *args;
PyObject *kwnames; PyObject *kwnames;
args = _PyStack_UnpackDict(_PyTuple_ITEMS(tuple), nargs, kwargs, &kwnames); args = _PyStack_UnpackDict(tstate,
_PyTuple_ITEMS(tuple), nargs,
kwargs, &kwnames);
if (args == NULL) { if (args == NULL) {
return NULL; return NULL;
} }
PyObject *result = func(callable, args, PyObject *result = func(callable, args,
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
_PyStack_UnpackDict_Free(args, nargs, kwnames); _PyStack_UnpackDict_Free(args, nargs, kwnames);
return _Py_CheckFunctionResult(callable, result, NULL); return _Py_CheckFunctionResult(tstate, callable, result, NULL);
} }
PyObject * PyObject *
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
{ {
PyThreadState *tstate = _PyThreadState_GET();
ternaryfunc call; ternaryfunc call;
PyObject *result; PyObject *result;
/* PyObject_Call() must not be called with an exception set, /* PyObject_Call() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the because it can clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
assert(PyTuple_Check(args)); assert(PyTuple_Check(args));
assert(kwargs == NULL || PyDict_Check(kwargs)); assert(kwargs == NULL || PyDict_Check(kwargs));
@ -236,19 +251,21 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
else { else {
call = callable->ob_type->tp_call; call = callable->ob_type->tp_call;
if (call == NULL) { if (call == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", _PyErr_Format(tstate, PyExc_TypeError,
callable->ob_type->tp_name); "'%.200s' object is not callable",
callable->ob_type->tp_name);
return NULL; return NULL;
} }
if (Py_EnterRecursiveCall(" while calling a Python object")) if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
return NULL; return NULL;
}
result = (*call)(callable, args, kwargs); result = (*call)(callable, args, kwargs);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return _Py_CheckFunctionResult(callable, result, NULL); return _Py_CheckFunctionResult(tstate, callable, result, NULL);
} }
} }
@ -266,30 +283,27 @@ static PyObject* _Py_HOT_FUNCTION
function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs, function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs,
PyObject *globals) PyObject *globals)
{ {
PyFrameObject *f;
PyThreadState *tstate = _PyThreadState_GET();
PyObject **fastlocals;
Py_ssize_t i;
PyObject *result;
assert(globals != NULL); assert(globals != NULL);
PyThreadState *tstate = _PyThreadState_GET();
assert(tstate != NULL);
/* XXX Perhaps we should create a specialized /* XXX Perhaps we should create a specialized
_PyFrame_New_NoTrack() that doesn't take locals, but does _PyFrame_New_NoTrack() that doesn't take locals, but does
take builtins without sanity checking them. take builtins without sanity checking them.
*/ */
assert(tstate != NULL); PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
if (f == NULL) { if (f == NULL) {
return NULL; return NULL;
} }
fastlocals = f->f_localsplus; PyObject **fastlocals = f->f_localsplus;
for (i = 0; i < nargs; i++) { for (Py_ssize_t i = 0; i < nargs; i++) {
Py_INCREF(*args); Py_INCREF(*args);
fastlocals[i] = *args++; fastlocals[i] = *args++;
} }
result = PyEval_EvalFrameEx(f,0); PyObject *result = PyEval_EvalFrameEx(f, 0);
if (Py_REFCNT(f) > 1) { if (Py_REFCNT(f) > 1) {
Py_DECREF(f); Py_DECREF(f);
@ -760,6 +774,7 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
assert(args != NULL); assert(args != NULL);
assert(PyVectorcall_NARGS(nargsf) >= 1); assert(PyVectorcall_NARGS(nargsf) >= 1);
PyThreadState *tstate = _PyThreadState_GET();
PyObject *callable = NULL; PyObject *callable = NULL;
/* Use args[0] as "self" argument */ /* Use args[0] as "self" argument */
int unbound = _PyObject_GetMethod(args[0], name, &callable); int unbound = _PyObject_GetMethod(args[0], name, &callable);
@ -778,7 +793,8 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
args++; args++;
nargsf--; nargsf--;
} }
PyObject *result = _PyObject_Vectorcall(callable, args, nargsf, kwnames); PyObject *result = _PyObject_VectorcallTstate(tstate, callable,
args, nargsf, kwnames);
Py_DECREF(callable); Py_DECREF(callable);
return result; return result;
} }
@ -894,8 +910,9 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames)
When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */ When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */
static PyObject *const * static PyObject *const *
_PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, _PyStack_UnpackDict(PyThreadState *tstate,
PyObject **p_kwnames) PyObject *const *args, Py_ssize_t nargs,
PyObject *kwargs, PyObject **p_kwnames)
{ {
assert(nargs >= 0); assert(nargs >= 0);
assert(kwargs != NULL); assert(kwargs != NULL);
@ -907,14 +924,14 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
* non-negative signed integers, so their difference fits in the type. */ * non-negative signed integers, so their difference fits in the type. */
Py_ssize_t maxnargs = PY_SSIZE_T_MAX / sizeof(args[0]) - 1; Py_ssize_t maxnargs = PY_SSIZE_T_MAX / sizeof(args[0]) - 1;
if (nargs > maxnargs - nkwargs) { if (nargs > maxnargs - nkwargs) {
PyErr_NoMemory(); _PyErr_NoMemory(tstate);
return NULL; return NULL;
} }
/* Add 1 to support PY_VECTORCALL_ARGUMENTS_OFFSET */ /* Add 1 to support PY_VECTORCALL_ARGUMENTS_OFFSET */
PyObject **stack = PyMem_Malloc((1 + nargs + nkwargs) * sizeof(args[0])); PyObject **stack = PyMem_Malloc((1 + nargs + nkwargs) * sizeof(args[0]));
if (stack == NULL) { if (stack == NULL) {
PyErr_NoMemory(); _PyErr_NoMemory(tstate);
return NULL; return NULL;
} }
@ -954,8 +971,8 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
* because it simplifies the deallocation in the failing case. * because it simplifies the deallocation in the failing case.
* It happens to also make the loop above slightly more efficient. */ * It happens to also make the loop above slightly more efficient. */
if (!keys_are_strings) { if (!keys_are_strings) {
PyErr_SetString(PyExc_TypeError, _PyErr_SetString(tstate, PyExc_TypeError,
"keywords must be strings"); "keywords must be strings");
_PyStack_UnpackDict_Free(stack, nargs, kwnames); _PyStack_UnpackDict_Free(stack, nargs, kwnames);
return NULL; return NULL;
} }

View File

@ -2,6 +2,7 @@
#include "Python.h" #include "Python.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pymem.h" #include "pycore_pymem.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "structmember.h" #include "structmember.h"
@ -37,25 +38,28 @@ method_vectorcall(PyObject *method, PyObject *const *args,
size_t nargsf, PyObject *kwnames) size_t nargsf, PyObject *kwnames)
{ {
assert(Py_TYPE(method) == &PyMethod_Type); assert(Py_TYPE(method) == &PyMethod_Type);
PyObject *self, *func, *result;
self = PyMethod_GET_SELF(method); PyThreadState *tstate = _PyThreadState_GET();
func = PyMethod_GET_FUNCTION(method); PyObject *self = PyMethod_GET_SELF(method);
PyObject *func = PyMethod_GET_FUNCTION(method);
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
PyObject *result;
if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) { if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
/* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */ /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
PyObject **newargs = (PyObject**)args - 1; PyObject **newargs = (PyObject**)args - 1;
nargs += 1; nargs += 1;
PyObject *tmp = newargs[0]; PyObject *tmp = newargs[0];
newargs[0] = self; newargs[0] = self;
result = _PyObject_Vectorcall(func, newargs, nargs, kwnames); result = _PyObject_VectorcallTstate(tstate, func, newargs,
nargs, kwnames);
newargs[0] = tmp; newargs[0] = tmp;
} }
else { else {
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
Py_ssize_t totalargs = nargs + nkwargs; Py_ssize_t totalargs = nargs + nkwargs;
if (totalargs == 0) { if (totalargs == 0) {
return _PyObject_Vectorcall(func, &self, 1, NULL); return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL);
} }
PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK]; PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK];
@ -66,7 +70,7 @@ method_vectorcall(PyObject *method, PyObject *const *args,
else { else {
newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *)); newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
if (newargs == NULL) { if (newargs == NULL) {
PyErr_NoMemory(); _PyErr_NoMemory(tstate);
return NULL; return NULL;
} }
} }
@ -77,7 +81,8 @@ method_vectorcall(PyObject *method, PyObject *const *args,
* undefined behaviour. */ * undefined behaviour. */
assert(args != NULL); assert(args != NULL);
memcpy(newargs + 1, args, totalargs * sizeof(PyObject *)); memcpy(newargs + 1, args, totalargs * sizeof(PyObject *));
result = _PyObject_Vectorcall(func, newargs, nargs+1, kwnames); result = _PyObject_VectorcallTstate(tstate, func,
newargs, nargs+1, kwnames);
if (newargs != newargs_stack) { if (newargs != newargs_stack) {
PyMem_Free(newargs); PyMem_Free(newargs);
} }

View File

@ -231,49 +231,42 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
* *
* First, common helpers * First, common helpers
*/ */
static const char *
get_name(PyObject *func) {
assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
return ((PyMethodDescrObject *)func)->d_method->ml_name;
}
typedef void (*funcptr)(void);
static inline int static inline int
method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{ {
assert(!PyErr_Occurred()); assert(!PyErr_Occurred());
assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
if (nargs < 1) { if (nargs < 1) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"descriptor '%.200s' of '%.100s' " if (funcstr != NULL) {
"object needs an argument", PyErr_Format(PyExc_TypeError,
get_name(func), PyDescr_TYPE(func)->tp_name); "unbound method %U needs an argument", funcstr);
Py_DECREF(funcstr);
}
return -1; return -1;
} }
PyObject *self = args[0]; PyObject *self = args[0];
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), PyObject *dummy;
(PyObject *)PyDescr_TYPE(func))) if (descr_check((PyDescrObject *)func, self, &dummy)) {
{
PyErr_Format(PyExc_TypeError,
"descriptor '%.200s' for '%.100s' objects "
"doesn't apply to a '%.100s' object",
get_name(func), PyDescr_TYPE(func)->tp_name,
Py_TYPE(self)->tp_name);
return -1; return -1;
} }
if (kwnames && PyTuple_GET_SIZE(kwnames)) { if (kwnames && PyTuple_GET_SIZE(kwnames)) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s() takes no keyword arguments", get_name(func)); if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes no keyword arguments", funcstr);
Py_DECREF(funcstr);
}
return -1; return -1;
} }
return 0; return 0;
} }
typedef void (*funcptr)(void);
static inline funcptr static inline funcptr
method_enter_call(PyObject *func) method_enter_call(PyThreadState *tstate, PyObject *func)
{ {
if (Py_EnterRecursiveCall(" while calling a Python object")) { if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
return NULL; return NULL;
} }
return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth; return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
@ -284,6 +277,7 @@ static PyObject *
method_vectorcall_VARARGS( method_vectorcall_VARARGS(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (method_check_args(func, args, nargs, kwnames)) { if (method_check_args(func, args, nargs, kwnames)) {
return NULL; return NULL;
@ -292,14 +286,14 @@ method_vectorcall_VARARGS(
if (argstuple == NULL) { if (argstuple == NULL) {
return NULL; return NULL;
} }
PyCFunction meth = (PyCFunction)method_enter_call(func); PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
Py_DECREF(argstuple); Py_DECREF(argstuple);
return NULL; return NULL;
} }
PyObject *result = meth(args[0], argstuple); PyObject *result = meth(args[0], argstuple);
Py_DECREF(argstuple); Py_DECREF(argstuple);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -307,6 +301,7 @@ static PyObject *
method_vectorcall_VARARGS_KEYWORDS( method_vectorcall_VARARGS_KEYWORDS(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (method_check_args(func, args, nargs, NULL)) { if (method_check_args(func, args, nargs, NULL)) {
return NULL; return NULL;
@ -325,12 +320,12 @@ method_vectorcall_VARARGS_KEYWORDS(
} }
} }
PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords) PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
method_enter_call(func); method_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
goto exit; goto exit;
} }
result = meth(args[0], argstuple, kwdict); result = meth(args[0], argstuple, kwdict);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
exit: exit:
Py_DECREF(argstuple); Py_DECREF(argstuple);
Py_XDECREF(kwdict); Py_XDECREF(kwdict);
@ -341,17 +336,18 @@ static PyObject *
method_vectorcall_FASTCALL( method_vectorcall_FASTCALL(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (method_check_args(func, args, nargs, kwnames)) { if (method_check_args(func, args, nargs, kwnames)) {
return NULL; return NULL;
} }
_PyCFunctionFast meth = (_PyCFunctionFast) _PyCFunctionFast meth = (_PyCFunctionFast)
method_enter_call(func); method_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(args[0], args+1, nargs-1); PyObject *result = meth(args[0], args+1, nargs-1);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -359,17 +355,18 @@ static PyObject *
method_vectorcall_FASTCALL_KEYWORDS( method_vectorcall_FASTCALL_KEYWORDS(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (method_check_args(func, args, nargs, NULL)) { if (method_check_args(func, args, nargs, NULL)) {
return NULL; return NULL;
} }
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
method_enter_call(func); method_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(args[0], args+1, nargs-1, kwnames); PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -377,21 +374,26 @@ static PyObject *
method_vectorcall_NOARGS( method_vectorcall_NOARGS(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (method_check_args(func, args, nargs, kwnames)) { if (method_check_args(func, args, nargs, kwnames)) {
return NULL; return NULL;
} }
if (nargs != 1) { if (nargs != 1) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s() takes no arguments (%zd given)", get_name(func), nargs-1); if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes no arguments (%zd given)", funcstr, nargs-1);
Py_DECREF(funcstr);
}
return NULL; return NULL;
} }
PyCFunction meth = (PyCFunction)method_enter_call(func); PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(args[0], NULL); PyObject *result = meth(args[0], NULL);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -399,22 +401,27 @@ static PyObject *
method_vectorcall_O( method_vectorcall_O(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (method_check_args(func, args, nargs, kwnames)) { if (method_check_args(func, args, nargs, kwnames)) {
return NULL; return NULL;
} }
if (nargs != 2) { if (nargs != 2) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s() takes exactly one argument (%zd given)", if (funcstr != NULL) {
get_name(func), nargs-1); PyErr_Format(PyExc_TypeError,
"%U takes exactly one argument (%zd given)",
funcstr, nargs-1);
Py_DECREF(funcstr);
}
return NULL; return NULL;
} }
PyCFunction meth = (PyCFunction)method_enter_call(func); PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(args[0], args[1]); PyObject *result = meth(args[0], args[1]);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }

View File

@ -4162,17 +4162,34 @@ static PySequenceMethods dictkeys_as_sequence = {
(objobjproc)dictkeys_contains, /* sq_contains */ (objobjproc)dictkeys_contains, /* sq_contains */
}; };
// Create an set object from dictviews object.
// Returns a new reference.
// This utility function is used by set operations.
static PyObject* static PyObject*
dictviews_sub(PyObject* self, PyObject *other) dictviews_to_set(PyObject *self)
{ {
PyObject *result = PySet_New(self); PyObject *left = self;
PyObject *tmp; if (PyDictKeys_Check(self)) {
_Py_IDENTIFIER(difference_update); // PySet_New() has fast path for the dict object.
PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
if (PyDict_CheckExact(dict)) {
left = dict;
}
}
return PySet_New(left);
}
if (result == NULL) static PyObject*
dictviews_sub(PyObject *self, PyObject *other)
{
PyObject *result = dictviews_to_set(self);
if (result == NULL) {
return NULL; return NULL;
}
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_difference_update, other); _Py_IDENTIFIER(difference_update);
PyObject *tmp = _PyObject_CallMethodIdOneArg(
result, &PyId_difference_update, other);
if (tmp == NULL) { if (tmp == NULL) {
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
@ -4273,34 +4290,29 @@ error:
static PyObject* static PyObject*
dictviews_or(PyObject* self, PyObject *other) dictviews_or(PyObject* self, PyObject *other)
{ {
PyObject *result = PySet_New(self); PyObject *result = dictviews_to_set(self);
PyObject *tmp; if (result == NULL) {
_Py_IDENTIFIER(update);
if (result == NULL)
return NULL;
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_update, other);
if (tmp == NULL) {
Py_DECREF(result);
return NULL; return NULL;
} }
Py_DECREF(tmp); if (_PySet_Update(result, other) < 0) {
Py_DECREF(result);
return NULL;
}
return result; return result;
} }
static PyObject* static PyObject*
dictviews_xor(PyObject* self, PyObject *other) dictviews_xor(PyObject* self, PyObject *other)
{ {
PyObject *result = PySet_New(self); PyObject *result = dictviews_to_set(self);
PyObject *tmp; if (result == NULL) {
_Py_IDENTIFIER(symmetric_difference_update);
if (result == NULL)
return NULL; return NULL;
}
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_symmetric_difference_update, other); _Py_IDENTIFIER(symmetric_difference_update);
PyObject *tmp = _PyObject_CallMethodIdOneArg(
result, &PyId_symmetric_difference_update, other);
if (tmp == NULL) { if (tmp == NULL) {
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;

View File

@ -3,6 +3,7 @@
#include "Python.h" #include "Python.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pymem.h" #include "pycore_pymem.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "structmember.h" #include "structmember.h"
@ -333,33 +334,30 @@ _PyCFunction_Fini(void)
* *
* First, common helpers * First, common helpers
*/ */
static const char *
get_name(PyObject *func)
{
assert(PyCFunction_Check(func));
PyMethodDef *method = ((PyCFunctionObject *)func)->m_ml;
return method->ml_name;
}
typedef void (*funcptr)(void);
static inline int static inline int
cfunction_check_kwargs(PyObject *func, PyObject *kwnames) cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames)
{ {
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
assert(PyCFunction_Check(func)); assert(PyCFunction_Check(func));
if (kwnames && PyTuple_GET_SIZE(kwnames)) { if (kwnames && PyTuple_GET_SIZE(kwnames)) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s() takes no keyword arguments", get_name(func)); if (funcstr != NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U takes no keyword arguments", funcstr);
Py_DECREF(funcstr);
}
return -1; return -1;
} }
return 0; return 0;
} }
typedef void (*funcptr)(void);
static inline funcptr static inline funcptr
cfunction_enter_call(PyObject *func) cfunction_enter_call(PyThreadState *tstate, PyObject *func)
{ {
if (Py_EnterRecursiveCall(" while calling a Python object")) { if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
return NULL; return NULL;
} }
return (funcptr)PyCFunction_GET_FUNCTION(func); return (funcptr)PyCFunction_GET_FUNCTION(func);
@ -370,17 +368,18 @@ static PyObject *
cfunction_vectorcall_FASTCALL( cfunction_vectorcall_FASTCALL(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
if (cfunction_check_kwargs(func, kwnames)) { PyThreadState *tstate = _PyThreadState_GET();
if (cfunction_check_kwargs(tstate, func, kwnames)) {
return NULL; return NULL;
} }
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
_PyCFunctionFast meth = (_PyCFunctionFast) _PyCFunctionFast meth = (_PyCFunctionFast)
cfunction_enter_call(func); cfunction_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs); PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -388,14 +387,15 @@ static PyObject *
cfunction_vectorcall_FASTCALL_KEYWORDS( cfunction_vectorcall_FASTCALL_KEYWORDS(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
cfunction_enter_call(func); cfunction_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames); PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -403,21 +403,26 @@ static PyObject *
cfunction_vectorcall_NOARGS( cfunction_vectorcall_NOARGS(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
if (cfunction_check_kwargs(func, kwnames)) { PyThreadState *tstate = _PyThreadState_GET();
if (cfunction_check_kwargs(tstate, func, kwnames)) {
return NULL; return NULL;
} }
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (nargs != 0) { if (nargs != 0) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s() takes no arguments (%zd given)", get_name(func), nargs); if (funcstr != NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U takes no arguments (%zd given)", funcstr, nargs);
Py_DECREF(funcstr);
}
return NULL; return NULL;
} }
PyCFunction meth = (PyCFunction)cfunction_enter_call(func); PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), NULL); PyObject *result = meth(PyCFunction_GET_SELF(func), NULL);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -425,22 +430,26 @@ static PyObject *
cfunction_vectorcall_O( cfunction_vectorcall_O(
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{ {
if (cfunction_check_kwargs(func, kwnames)) { PyThreadState *tstate = _PyThreadState_GET();
if (cfunction_check_kwargs(tstate, func, kwnames)) {
return NULL; return NULL;
} }
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (nargs != 1) { if (nargs != 1) {
PyErr_Format(PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s() takes exactly one argument (%zd given)", if (funcstr != NULL) {
get_name(func), nargs); _PyErr_Format(tstate, PyExc_TypeError,
"%U takes exactly one argument (%zd given)", funcstr, nargs);
Py_DECREF(funcstr);
}
return NULL; return NULL;
} }
PyCFunction meth = (PyCFunction)cfunction_enter_call(func); PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
if (meth == NULL) { if (meth == NULL) {
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]); PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
return result; return result;
} }
@ -448,9 +457,11 @@ cfunction_vectorcall_O(
static PyObject * static PyObject *
cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs) cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
{ {
assert(!PyErr_Occurred());
assert(kwargs == NULL || PyDict_Check(kwargs)); assert(kwargs == NULL || PyDict_Check(kwargs));
PyThreadState *tstate = _PyThreadState_GET();
assert(!_PyErr_Occurred(tstate));
int flags = PyCFunction_GET_FLAGS(func); int flags = PyCFunction_GET_FLAGS(func);
if (!(flags & METH_VARARGS)) { if (!(flags & METH_VARARGS)) {
/* If this is not a METH_VARARGS function, delegate to vectorcall */ /* If this is not a METH_VARARGS function, delegate to vectorcall */
@ -468,11 +479,12 @@ cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
} }
else { else {
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", _PyErr_Format(tstate, PyExc_TypeError,
((PyCFunctionObject*)func)->m_ml->ml_name); "%.200s() takes no keyword arguments",
((PyCFunctionObject*)func)->m_ml->ml_name);
return NULL; return NULL;
} }
result = meth(self, args); result = meth(self, args);
} }
return _Py_CheckFunctionResult(func, result, NULL); return _Py_CheckFunctionResult(tstate, func, result, NULL);
} }

View File

@ -2,10 +2,11 @@
/* Generic object operations; and implementation of None */ /* Generic object operations; and implementation of None */
#include "Python.h" #include "Python.h"
#include "pycore_context.h"
#include "pycore_initconfig.h" #include "pycore_initconfig.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "pycore_context.h"
#include "frameobject.h" #include "frameobject.h"
#include "interpreteridobject.h" #include "interpreteridobject.h"
@ -525,31 +526,37 @@ PyObject_Repr(PyObject *v)
return PyUnicode_FromFormat("<%s object at %p>", return PyUnicode_FromFormat("<%s object at %p>",
v->ob_type->tp_name, v); v->ob_type->tp_name, v);
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* PyObject_Repr() must not be called with an exception set, /* PyObject_Repr() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the because it can clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
#endif #endif
/* It is possible for a type to have a tp_repr representation that loops /* It is possible for a type to have a tp_repr representation that loops
infinitely. */ infinitely. */
if (Py_EnterRecursiveCall(" while getting the repr of an object")) if (_Py_EnterRecursiveCall(tstate,
" while getting the repr of an object")) {
return NULL; return NULL;
}
res = (*v->ob_type->tp_repr)(v); res = (*v->ob_type->tp_repr)(v);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
if (res == NULL)
if (res == NULL) {
return NULL; return NULL;
}
if (!PyUnicode_Check(res)) { if (!PyUnicode_Check(res)) {
PyErr_Format(PyExc_TypeError, _PyErr_Format(tstate, PyExc_TypeError,
"__repr__ returned non-string (type %.200s)", "__repr__ returned non-string (type %.200s)",
res->ob_type->tp_name); res->ob_type->tp_name);
Py_DECREF(res); Py_DECREF(res);
return NULL; return NULL;
} }
#ifndef Py_DEBUG #ifndef Py_DEBUG
if (PyUnicode_READY(res) < 0) if (PyUnicode_READY(res) < 0) {
return NULL; return NULL;
}
#endif #endif
return res; return res;
} }
@ -579,31 +586,36 @@ PyObject_Str(PyObject *v)
if (Py_TYPE(v)->tp_str == NULL) if (Py_TYPE(v)->tp_str == NULL)
return PyObject_Repr(v); return PyObject_Repr(v);
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* PyObject_Str() must not be called with an exception set, /* PyObject_Str() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the because it can clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
#endif #endif
/* It is possible for a type to have a tp_str representation that loops /* It is possible for a type to have a tp_str representation that loops
infinitely. */ infinitely. */
if (Py_EnterRecursiveCall(" while getting the str of an object")) if (_Py_EnterRecursiveCall(tstate, " while getting the str of an object")) {
return NULL; return NULL;
}
res = (*Py_TYPE(v)->tp_str)(v); res = (*Py_TYPE(v)->tp_str)(v);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
if (res == NULL)
if (res == NULL) {
return NULL; return NULL;
}
if (!PyUnicode_Check(res)) { if (!PyUnicode_Check(res)) {
PyErr_Format(PyExc_TypeError, _PyErr_Format(tstate, PyExc_TypeError,
"__str__ returned non-string (type %.200s)", "__str__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name); Py_TYPE(res)->tp_name);
Py_DECREF(res); Py_DECREF(res);
return NULL; return NULL;
} }
#ifndef Py_DEBUG #ifndef Py_DEBUG
if (PyUnicode_READY(res) < 0) if (PyUnicode_READY(res) < 0) {
return NULL; return NULL;
}
#endif #endif
assert(_PyUnicode_CheckConsistency(res, 1)); assert(_PyUnicode_CheckConsistency(res, 1));
return res; return res;
@ -669,6 +681,64 @@ PyObject_Bytes(PyObject *v)
return PyBytes_FromObject(v); return PyBytes_FromObject(v);
} }
/*
def _PyObject_FunctionStr(x):
try:
qualname = x.__qualname__
except AttributeError:
return str(x)
try:
mod = x.__module__
if mod is not None and mod != 'builtins':
return f"{x.__module__}.{qualname}()"
except AttributeError:
pass
return qualname
*/
PyObject *
_PyObject_FunctionStr(PyObject *x)
{
_Py_IDENTIFIER(__module__);
_Py_IDENTIFIER(__qualname__);
_Py_IDENTIFIER(builtins);
assert(!PyErr_Occurred());
PyObject *qualname;
int ret = _PyObject_LookupAttrId(x, &PyId___qualname__, &qualname);
if (qualname == NULL) {
if (ret < 0) {
return NULL;
}
return PyObject_Str(x);
}
PyObject *module;
PyObject *result = NULL;
ret = _PyObject_LookupAttrId(x, &PyId___module__, &module);
if (module != NULL && module != Py_None) {
PyObject *builtinsname = _PyUnicode_FromId(&PyId_builtins);
if (builtinsname == NULL) {
goto done;
}
ret = PyObject_RichCompareBool(module, builtinsname, Py_NE);
if (ret < 0) {
// error
goto done;
}
if (ret > 0) {
result = PyUnicode_FromFormat("%S.%S()", module, qualname);
goto done;
}
}
else if (ret < 0) {
goto done;
}
result = PyUnicode_FromFormat("%S()", qualname);
done:
Py_DECREF(qualname);
Py_XDECREF(module);
return result;
}
/* For Python 3.0.1 and later, the old three-way comparison has been /* For Python 3.0.1 and later, the old three-way comparison has been
completely removed in favour of rich comparisons. PyObject_Compare() and completely removed in favour of rich comparisons. PyObject_Compare() and
PyObject_Cmp() are gone, and the builtin cmp function no longer exists. PyObject_Cmp() are gone, and the builtin cmp function no longer exists.
@ -707,7 +777,7 @@ static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
/* Perform a rich comparison, raising TypeError when the requested comparison /* Perform a rich comparison, raising TypeError when the requested comparison
operator is not supported. */ operator is not supported. */
static PyObject * static PyObject *
do_richcompare(PyObject *v, PyObject *w, int op) do_richcompare(PyThreadState *tstate, PyObject *v, PyObject *w, int op)
{ {
richcmpfunc f; richcmpfunc f;
PyObject *res; PyObject *res;
@ -744,11 +814,11 @@ do_richcompare(PyObject *v, PyObject *w, int op)
res = (v != w) ? Py_True : Py_False; res = (v != w) ? Py_True : Py_False;
break; break;
default: default:
PyErr_Format(PyExc_TypeError, _PyErr_Format(tstate, PyExc_TypeError,
"'%s' not supported between instances of '%.100s' and '%.100s'", "'%s' not supported between instances of '%.100s' and '%.100s'",
opstrings[op], opstrings[op],
v->ob_type->tp_name, v->ob_type->tp_name,
w->ob_type->tp_name); w->ob_type->tp_name);
return NULL; return NULL;
} }
Py_INCREF(res); Py_INCREF(res);
@ -761,18 +831,20 @@ do_richcompare(PyObject *v, PyObject *w, int op)
PyObject * PyObject *
PyObject_RichCompare(PyObject *v, PyObject *w, int op) PyObject_RichCompare(PyObject *v, PyObject *w, int op)
{ {
PyObject *res; PyThreadState *tstate = _PyThreadState_GET();
assert(Py_LT <= op && op <= Py_GE); assert(Py_LT <= op && op <= Py_GE);
if (v == NULL || w == NULL) { if (v == NULL || w == NULL) {
if (!PyErr_Occurred()) if (!_PyErr_Occurred(tstate)) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
}
return NULL; return NULL;
} }
if (Py_EnterRecursiveCall(" in comparison")) if (_Py_EnterRecursiveCall(tstate, " in comparison")) {
return NULL; return NULL;
res = do_richcompare(v, w, op); }
Py_LeaveRecursiveCall(); PyObject *res = do_richcompare(tstate, v, w, op);
_Py_LeaveRecursiveCall(tstate);
return res; return res;
} }

View File

@ -2313,12 +2313,13 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
return data; return data;
} }
static void static inline void
_PyMem_DebugCheckGIL(void) _PyMem_DebugCheckGIL(void)
{ {
if (!PyGILState_Check()) if (!PyGILState_Check()) {
Py_FatalError("Python memory allocator called " Py_FatalError("Python memory allocator called "
"without holding the GIL"); "without holding the GIL");
}
} }
static void * static void *

View File

@ -2,6 +2,7 @@
#include "Python.h" #include "Python.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "frameobject.h" #include "frameobject.h"
#include "structmember.h" #include "structmember.h"
@ -952,12 +953,12 @@ type_repr(PyTypeObject *type)
static PyObject * static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
PyObject *obj; PyThreadState *tstate = _PyThreadState_GET();
if (type->tp_new == NULL) { if (type->tp_new == NULL) {
PyErr_Format(PyExc_TypeError, _PyErr_Format(tstate, PyExc_TypeError,
"cannot create '%.100s' instances", "cannot create '%.100s' instances",
type->tp_name); type->tp_name);
return NULL; return NULL;
} }
@ -965,11 +966,11 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* type_call() must not be called with an exception set, /* type_call() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the because it can clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
#endif #endif
obj = type->tp_new(type, args, kwds); PyObject *obj = type->tp_new(type, args, kwds);
obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL); obj = _Py_CheckFunctionResult(tstate, (PyObject*)type, obj, NULL);
if (obj == NULL) if (obj == NULL)
return NULL; return NULL;
@ -990,12 +991,12 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (type->tp_init != NULL) { if (type->tp_init != NULL) {
int res = type->tp_init(obj, args, kwds); int res = type->tp_init(obj, args, kwds);
if (res < 0) { if (res < 0) {
assert(PyErr_Occurred()); assert(_PyErr_Occurred(tstate));
Py_DECREF(obj); Py_DECREF(obj);
obj = NULL; obj = NULL;
} }
else { else {
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
} }
} }
return obj; return obj;
@ -1444,7 +1445,7 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
static inline PyObject* static inline PyObject*
vectorcall_unbound(int unbound, PyObject *func, vectorcall_unbound(PyThreadState *tstate, int unbound, PyObject *func,
PyObject *const *args, Py_ssize_t nargs) PyObject *const *args, Py_ssize_t nargs)
{ {
size_t nargsf = nargs; size_t nargsf = nargs;
@ -1454,7 +1455,7 @@ vectorcall_unbound(int unbound, PyObject *func,
args++; args++;
nargsf = nargsf - 1 + PY_VECTORCALL_ARGUMENTS_OFFSET; nargsf = nargsf - 1 + PY_VECTORCALL_ARGUMENTS_OFFSET;
} }
return _PyObject_Vectorcall(func, args, nargsf, NULL); return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL);
} }
static PyObject* static PyObject*
@ -1478,13 +1479,15 @@ vectorcall_method(_Py_Identifier *name,
PyObject *const *args, Py_ssize_t nargs) PyObject *const *args, Py_ssize_t nargs)
{ {
assert(nargs >= 1); assert(nargs >= 1);
PyThreadState *tstate = _PyThreadState_GET();
int unbound; int unbound;
PyObject *self = args[0]; PyObject *self = args[0];
PyObject *func = lookup_method(self, name, &unbound); PyObject *func = lookup_method(self, name, &unbound);
if (func == NULL) { if (func == NULL) {
return NULL; return NULL;
} }
PyObject *retval = vectorcall_unbound(unbound, func, args, nargs); PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);
Py_DECREF(func); Py_DECREF(func);
return retval; return retval;
} }
@ -1492,10 +1495,11 @@ vectorcall_method(_Py_Identifier *name,
/* Clone of vectorcall_method() that returns NotImplemented /* Clone of vectorcall_method() that returns NotImplemented
* when the lookup fails. */ * when the lookup fails. */
static PyObject * static PyObject *
vectorcall_maybe(_Py_Identifier *name, vectorcall_maybe(PyThreadState *tstate, _Py_Identifier *name,
PyObject *const *args, Py_ssize_t nargs) PyObject *const *args, Py_ssize_t nargs)
{ {
assert(nargs >= 1); assert(nargs >= 1);
int unbound; int unbound;
PyObject *self = args[0]; PyObject *self = args[0];
PyObject *func = lookup_maybe_method(self, name, &unbound); PyObject *func = lookup_maybe_method(self, name, &unbound);
@ -1504,7 +1508,7 @@ vectorcall_maybe(_Py_Identifier *name,
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
return NULL; return NULL;
} }
PyObject *retval = vectorcall_unbound(unbound, func, args, nargs); PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);
Py_DECREF(func); Py_DECREF(func);
return retval; return retval;
} }
@ -6176,6 +6180,7 @@ static PyObject * \
FUNCNAME(PyObject *self, PyObject *other) \ FUNCNAME(PyObject *self, PyObject *other) \
{ \ { \
PyObject* stack[2]; \ PyObject* stack[2]; \
PyThreadState *tstate = _PyThreadState_GET(); \
_Py_static_string(op_id, OPSTR); \ _Py_static_string(op_id, OPSTR); \
_Py_static_string(rop_id, ROPSTR); \ _Py_static_string(rop_id, ROPSTR); \
int do_other = Py_TYPE(self) != Py_TYPE(other) && \ int do_other = Py_TYPE(self) != Py_TYPE(other) && \
@ -6192,7 +6197,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
if (ok) { \ if (ok) { \
stack[0] = other; \ stack[0] = other; \
stack[1] = self; \ stack[1] = self; \
r = vectorcall_maybe(&rop_id, stack, 2); \ r = vectorcall_maybe(tstate, &rop_id, stack, 2); \
if (r != Py_NotImplemented) \ if (r != Py_NotImplemented) \
return r; \ return r; \
Py_DECREF(r); \ Py_DECREF(r); \
@ -6201,7 +6206,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
} \ } \
stack[0] = self; \ stack[0] = self; \
stack[1] = other; \ stack[1] = other; \
r = vectorcall_maybe(&op_id, stack, 2); \ r = vectorcall_maybe(tstate, &op_id, stack, 2); \
if (r != Py_NotImplemented || \ if (r != Py_NotImplemented || \
Py_TYPE(other) == Py_TYPE(self)) \ Py_TYPE(other) == Py_TYPE(self)) \
return r; \ return r; \
@ -6210,7 +6215,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
if (do_other) { \ if (do_other) { \
stack[0] = other; \ stack[0] = other; \
stack[1] = self; \ stack[1] = self; \
return vectorcall_maybe(&rop_id, stack, 2); \ return vectorcall_maybe(tstate, &rop_id, stack, 2); \
} \ } \
Py_RETURN_NOTIMPLEMENTED; \ Py_RETURN_NOTIMPLEMENTED; \
} }
@ -6292,6 +6297,7 @@ slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)
static int static int
slot_sq_contains(PyObject *self, PyObject *value) slot_sq_contains(PyObject *self, PyObject *value)
{ {
PyThreadState *tstate = _PyThreadState_GET();
PyObject *func, *res; PyObject *func, *res;
int result = -1, unbound; int result = -1, unbound;
_Py_IDENTIFIER(__contains__); _Py_IDENTIFIER(__contains__);
@ -6306,7 +6312,7 @@ slot_sq_contains(PyObject *self, PyObject *value)
} }
if (func != NULL) { if (func != NULL) {
PyObject *args[2] = {self, value}; PyObject *args[2] = {self, value};
res = vectorcall_unbound(unbound, func, args, 2); res = vectorcall_unbound(tstate, unbound, func, args, 2);
Py_DECREF(func); Py_DECREF(func);
if (res != NULL) { if (res != NULL) {
result = PyObject_IsTrue(res); result = PyObject_IsTrue(res);
@ -6681,6 +6687,7 @@ static _Py_Identifier name_op[] = {
static PyObject * static PyObject *
slot_tp_richcompare(PyObject *self, PyObject *other, int op) slot_tp_richcompare(PyObject *self, PyObject *other, int op)
{ {
PyThreadState *tstate = _PyThreadState_GET();
int unbound; int unbound;
PyObject *func, *res; PyObject *func, *res;
@ -6691,7 +6698,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op)
} }
PyObject *stack[2] = {self, other}; PyObject *stack[2] = {self, other};
res = vectorcall_unbound(unbound, func, stack, 2); res = vectorcall_unbound(tstate, unbound, func, stack, 2);
Py_DECREF(func); Py_DECREF(func);
return res; return res;
} }

View File

@ -127,6 +127,7 @@
<ClInclude Include="..\Include\complexobject.h" /> <ClInclude Include="..\Include\complexobject.h" />
<ClInclude Include="..\Include\context.h" /> <ClInclude Include="..\Include\context.h" />
<ClInclude Include="..\Include\cpython\abstract.h" /> <ClInclude Include="..\Include\cpython\abstract.h" />
<ClInclude Include="..\Include\cpython\ceval.h" />
<ClInclude Include="..\Include\cpython\dictobject.h" /> <ClInclude Include="..\Include\cpython\dictobject.h" />
<ClInclude Include="..\Include\cpython\fileobject.h" /> <ClInclude Include="..\Include\cpython\fileobject.h" />
<ClInclude Include="..\Include\cpython\import.h" /> <ClInclude Include="..\Include\cpython\import.h" />

View File

@ -84,6 +84,9 @@
<ClInclude Include="..\Include\cpython\abstract.h"> <ClInclude Include="..\Include\cpython\abstract.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\cpython\ceval.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\cpython\dictobject.h"> <ClInclude Include="..\Include\cpython\dictobject.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>

View File

@ -2,6 +2,7 @@
/* List a node on a file */ /* List a node on a file */
#include "Python.h" #include "Python.h"
#include "pycore_pystate.h"
#include "token.h" #include "token.h"
#include "node.h" #include "node.h"
@ -15,19 +16,21 @@ PyNode_ListTree(node *n)
listnode(stdout, n); listnode(stdout, n);
} }
static int level, atbol;
static void static void
listnode(FILE *fp, node *n) listnode(FILE *fp, node *n)
{ {
level = 0; PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
atbol = 1;
interp->parser.listnode.level = 0;
interp->parser.listnode.atbol = 1;
list1node(fp, n); list1node(fp, n);
} }
static void static void
list1node(FILE *fp, node *n) list1node(FILE *fp, node *n)
{ {
PyInterpreterState *interp;
if (n == NULL) if (n == NULL)
return; return;
if (ISNONTERMINAL(TYPE(n))) { if (ISNONTERMINAL(TYPE(n))) {
@ -36,25 +39,26 @@ list1node(FILE *fp, node *n)
list1node(fp, CHILD(n, i)); list1node(fp, CHILD(n, i));
} }
else if (ISTERMINAL(TYPE(n))) { else if (ISTERMINAL(TYPE(n))) {
interp = _PyInterpreterState_GET_UNSAFE();
switch (TYPE(n)) { switch (TYPE(n)) {
case INDENT: case INDENT:
++level; interp->parser.listnode.level++;
break; break;
case DEDENT: case DEDENT:
--level; interp->parser.listnode.level--;
break; break;
default: default:
if (atbol) { if (interp->parser.listnode.atbol) {
int i; int i;
for (i = 0; i < level; ++i) for (i = 0; i < interp->parser.listnode.level; ++i)
fprintf(fp, "\t"); fprintf(fp, "\t");
atbol = 0; interp->parser.listnode.atbol = 0;
} }
if (TYPE(n) == NEWLINE) { if (TYPE(n) == NEWLINE) {
if (STR(n) != NULL) if (STR(n) != NULL)
fprintf(fp, "%s", STR(n)); fprintf(fp, "%s", STR(n));
fprintf(fp, "\n"); fprintf(fp, "\n");
atbol = 1; interp->parser.listnode.atbol = 1;
} }
else else
fprintf(fp, "%s ", STR(n)); fprintf(fp, "%s ", STR(n));

View File

@ -659,16 +659,15 @@ Py_SetRecursionLimit(int new_limit)
_Py_CheckRecursionLimit = ceval->recursion_limit; _Py_CheckRecursionLimit = ceval->recursion_limit;
} }
/* the macro Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() /* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall()
if the recursion_depth reaches _Py_CheckRecursionLimit. if the recursion_depth reaches _Py_CheckRecursionLimit.
If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit
to guarantee that _Py_CheckRecursiveCall() is regularly called. to guarantee that _Py_CheckRecursiveCall() is regularly called.
Without USE_STACKCHECK, there is no need for this. */ Without USE_STACKCHECK, there is no need for this. */
int int
_Py_CheckRecursiveCall(const char *where) _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
{ {
_PyRuntimeState *runtime = &_PyRuntime; _PyRuntimeState *runtime = &_PyRuntime;
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
int recursion_limit = runtime->ceval.recursion_limit; int recursion_limit = runtime->ceval.recursion_limit;
#ifdef USE_STACKCHECK #ifdef USE_STACKCHECK
@ -1073,8 +1072,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
/* Start of code */ /* Start of code */
/* push frame */ /* push frame */
if (Py_EnterRecursiveCall("")) if (_Py_EnterRecursiveCall(tstate, "")) {
return NULL; return NULL;
}
tstate->frame = f; tstate->frame = f;
@ -3810,11 +3810,11 @@ exit_yielding:
exit_eval_frame: exit_eval_frame:
if (PyDTrace_FUNCTION_RETURN_ENABLED()) if (PyDTrace_FUNCTION_RETURN_ENABLED())
dtrace_function_return(f); dtrace_function_return(f);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall(tstate);
f->f_executing = 0; f->f_executing = 0;
tstate->frame = f->f_back; tstate->frame = f->f_back;
return _Py_CheckFunctionResult(NULL, retval, "PyEval_EvalFrameEx"); return _Py_CheckFunctionResult(tstate, NULL, retval, "PyEval_EvalFrameEx");
} }
static void static void
@ -5351,12 +5351,17 @@ static int
check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args) check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)
{ {
if (args->ob_type->tp_iter == NULL && !PySequence_Check(args)) { if (args->ob_type->tp_iter == NULL && !PySequence_Check(args)) {
_PyErr_Format(tstate, PyExc_TypeError, /* check_args_iterable() may be called with a live exception:
"%.200s%.200s argument after * " * clear it to prevent calling _PyObject_FunctionStr() with an
"must be an iterable, not %.200s", * exception set. */
PyEval_GetFuncName(func), PyErr_Clear();
PyEval_GetFuncDesc(func), PyObject *funcstr = _PyObject_FunctionStr(func);
args->ob_type->tp_name); if (funcstr != NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U argument after * must be an iterable, not %.200s",
funcstr, Py_TYPE(args)->tp_name);
Py_DECREF(funcstr);
}
return -1; return -1;
} }
return 0; return 0;
@ -5372,24 +5377,30 @@ format_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs)
* is not a mapping. * is not a mapping.
*/ */
if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
_PyErr_Format(tstate, PyExc_TypeError, PyErr_Clear();
"%.200s%.200s argument after ** " PyObject *funcstr = _PyObject_FunctionStr(func);
"must be a mapping, not %.200s", if (funcstr != NULL) {
PyEval_GetFuncName(func), _PyErr_Format(
PyEval_GetFuncDesc(func), tstate, PyExc_TypeError,
kwargs->ob_type->tp_name); "%U argument after ** must be a mapping, not %.200s",
funcstr, Py_TYPE(kwargs)->tp_name);
Py_DECREF(funcstr);
}
} }
else if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { else if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
PyObject *exc, *val, *tb; PyObject *exc, *val, *tb;
_PyErr_Fetch(tstate, &exc, &val, &tb); _PyErr_Fetch(tstate, &exc, &val, &tb);
if (val && PyTuple_Check(val) && PyTuple_GET_SIZE(val) == 1) { if (val && PyTuple_Check(val) && PyTuple_GET_SIZE(val) == 1) {
PyObject *key = PyTuple_GET_ITEM(val, 0); PyErr_Clear();
_PyErr_Format(tstate, PyExc_TypeError, PyObject *funcstr = _PyObject_FunctionStr(func);
"%.200s%.200s got multiple " if (funcstr != NULL) {
"values for keyword argument '%S'", PyObject *key = PyTuple_GET_ITEM(val, 0);
PyEval_GetFuncName(func), _PyErr_Format(
PyEval_GetFuncDesc(func), tstate, PyExc_TypeError,
key); "%U got multiple values for keyword argument '%S'",
funcstr, key);
Py_DECREF(funcstr);
}
Py_XDECREF(exc); Py_XDECREF(exc);
Py_XDECREF(val); Py_XDECREF(val);
Py_XDECREF(tb); Py_XDECREF(tb);
@ -5632,3 +5643,21 @@ maybe_dtrace_line(PyFrameObject *frame,
} }
*instr_prev = frame->f_lasti; *instr_prev = frame->f_lasti;
} }
/* Implement Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() as functions
for the limited API. */
#undef Py_EnterRecursiveCall
int Py_EnterRecursiveCall(const char *where)
{
return _Py_EnterRecursiveCall_inline(where);
}
#undef Py_LeaveRecursiveCall
void Py_LeaveRecursiveCall(void)
{
_Py_LeaveRecursiveCall_inline();
}

View File

@ -3,6 +3,7 @@
#include "pycore_context.h" #include "pycore_context.h"
#include "pycore_hamt.h" #include "pycore_hamt.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "structmember.h" #include "structmember.h"
@ -101,21 +102,18 @@ PyContext_CopyCurrent(void)
} }
int static int
PyContext_Enter(PyObject *octx) _PyContext_Enter(PyThreadState *ts, PyObject *octx)
{ {
ENSURE_Context(octx, -1) ENSURE_Context(octx, -1)
PyContext *ctx = (PyContext *)octx; PyContext *ctx = (PyContext *)octx;
if (ctx->ctx_entered) { if (ctx->ctx_entered) {
PyErr_Format(PyExc_RuntimeError, _PyErr_Format(ts, PyExc_RuntimeError,
"cannot enter context: %R is already entered", ctx); "cannot enter context: %R is already entered", ctx);
return -1; return -1;
} }
PyThreadState *ts = _PyThreadState_GET();
assert(ts != NULL);
ctx->ctx_prev = (PyContext *)ts->context; /* borrow */ ctx->ctx_prev = (PyContext *)ts->context; /* borrow */
ctx->ctx_entered = 1; ctx->ctx_entered = 1;
@ -128,7 +126,16 @@ PyContext_Enter(PyObject *octx)
int int
PyContext_Exit(PyObject *octx) PyContext_Enter(PyObject *octx)
{
PyThreadState *ts = _PyThreadState_GET();
assert(ts != NULL);
return _PyContext_Enter(ts, octx);
}
static int
_PyContext_Exit(PyThreadState *ts, PyObject *octx)
{ {
ENSURE_Context(octx, -1) ENSURE_Context(octx, -1)
PyContext *ctx = (PyContext *)octx; PyContext *ctx = (PyContext *)octx;
@ -139,9 +146,6 @@ PyContext_Exit(PyObject *octx)
return -1; return -1;
} }
PyThreadState *ts = _PyThreadState_GET();
assert(ts != NULL);
if (ts->context != (PyObject *)ctx) { if (ts->context != (PyObject *)ctx) {
/* Can only happen if someone misuses the C API */ /* Can only happen if someone misuses the C API */
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
@ -159,6 +163,14 @@ PyContext_Exit(PyObject *octx)
return 0; return 0;
} }
int
PyContext_Exit(PyObject *octx)
{
PyThreadState *ts = _PyThreadState_GET();
assert(ts != NULL);
return _PyContext_Exit(ts, octx);
}
PyObject * PyObject *
PyContextVar_New(const char *name, PyObject *def) PyContextVar_New(const char *name, PyObject *def)
@ -621,20 +633,22 @@ static PyObject *
context_run(PyContext *self, PyObject *const *args, context_run(PyContext *self, PyObject *const *args,
Py_ssize_t nargs, PyObject *kwnames) Py_ssize_t nargs, PyObject *kwnames)
{ {
PyThreadState *ts = _PyThreadState_GET();
if (nargs < 1) { if (nargs < 1) {
PyErr_SetString(PyExc_TypeError, _PyErr_SetString(ts, PyExc_TypeError,
"run() missing 1 required positional argument"); "run() missing 1 required positional argument");
return NULL; return NULL;
} }
if (PyContext_Enter((PyObject *)self)) { if (_PyContext_Enter(ts, (PyObject *)self)) {
return NULL; return NULL;
} }
PyObject *call_result = _PyObject_Vectorcall( PyObject *call_result = _PyObject_VectorcallTstate(
args[0], args + 1, nargs - 1, kwnames); ts, args[0], args + 1, nargs - 1, kwnames);
if (PyContext_Exit((PyObject *)self)) { if (_PyContext_Exit(ts, (PyObject *)self)) {
return NULL; return NULL;
} }

View File

@ -218,6 +218,9 @@ PyErr_SetString(PyObject *exception, const char *string)
PyObject* _Py_HOT_FUNCTION PyObject* _Py_HOT_FUNCTION
PyErr_Occurred(void) PyErr_Occurred(void)
{ {
/* The caller must hold the GIL. */
assert(PyGILState_Check());
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
return _PyErr_Occurred(tstate); return _PyErr_Occurred(tstate);
} }
@ -520,6 +523,21 @@ _PyErr_FormatVFromCause(PyThreadState *tstate, PyObject *exception,
return NULL; return NULL;
} }
PyObject *
_PyErr_FormatFromCauseTstate(PyThreadState *tstate, PyObject *exception,
const char *format, ...)
{
va_list vargs;
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, format);
#else
va_start(vargs);
#endif
_PyErr_FormatVFromCause(tstate, exception, format, vargs);
va_end(vargs);
return NULL;
}
PyObject * PyObject *
_PyErr_FormatFromCause(PyObject *exception, const char *format, ...) _PyErr_FormatFromCause(PyObject *exception, const char *format, ...)
{ {

View File

@ -1648,56 +1648,56 @@ PyOS_CheckStack(void)
/* Deprecated C API functions still provided for binary compatibility */ /* Deprecated C API functions still provided for binary compatibility */
#undef PyParser_SimpleParseFile #undef PyParser_SimpleParseFile
node * PyAPI_FUNC(node *)
PyParser_SimpleParseFile(FILE *fp, const char *filename, int start) PyParser_SimpleParseFile(FILE *fp, const char *filename, int start)
{ {
return PyParser_SimpleParseFileFlags(fp, filename, start, 0); return PyParser_SimpleParseFileFlags(fp, filename, start, 0);
} }
#undef PyParser_SimpleParseString #undef PyParser_SimpleParseString
node * PyAPI_FUNC(node *)
PyParser_SimpleParseString(const char *str, int start) PyParser_SimpleParseString(const char *str, int start)
{ {
return PyParser_SimpleParseStringFlags(str, start, 0); return PyParser_SimpleParseStringFlags(str, start, 0);
} }
#undef PyRun_AnyFile #undef PyRun_AnyFile
int PyAPI_FUNC(int)
PyRun_AnyFile(FILE *fp, const char *name) PyRun_AnyFile(FILE *fp, const char *name)
{ {
return PyRun_AnyFileExFlags(fp, name, 0, NULL); return PyRun_AnyFileExFlags(fp, name, 0, NULL);
} }
#undef PyRun_AnyFileEx #undef PyRun_AnyFileEx
int PyAPI_FUNC(int)
PyRun_AnyFileEx(FILE *fp, const char *name, int closeit) PyRun_AnyFileEx(FILE *fp, const char *name, int closeit)
{ {
return PyRun_AnyFileExFlags(fp, name, closeit, NULL); return PyRun_AnyFileExFlags(fp, name, closeit, NULL);
} }
#undef PyRun_AnyFileFlags #undef PyRun_AnyFileFlags
int PyAPI_FUNC(int)
PyRun_AnyFileFlags(FILE *fp, const char *name, PyCompilerFlags *flags) PyRun_AnyFileFlags(FILE *fp, const char *name, PyCompilerFlags *flags)
{ {
return PyRun_AnyFileExFlags(fp, name, 0, flags); return PyRun_AnyFileExFlags(fp, name, 0, flags);
} }
#undef PyRun_File #undef PyRun_File
PyObject * PyAPI_FUNC(PyObject *)
PyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l) PyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l)
{ {
return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL); return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL);
} }
#undef PyRun_FileEx #undef PyRun_FileEx
PyObject * PyAPI_FUNC(PyObject *)
PyRun_FileEx(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, int c) PyRun_FileEx(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, int c)
{ {
return PyRun_FileExFlags(fp, p, s, g, l, c, NULL); return PyRun_FileExFlags(fp, p, s, g, l, c, NULL);
} }
#undef PyRun_FileFlags #undef PyRun_FileFlags
PyObject * PyAPI_FUNC(PyObject *)
PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l,
PyCompilerFlags *flags) PyCompilerFlags *flags)
{ {
@ -1705,14 +1705,14 @@ PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l,
} }
#undef PyRun_SimpleFile #undef PyRun_SimpleFile
int PyAPI_FUNC(int)
PyRun_SimpleFile(FILE *f, const char *p) PyRun_SimpleFile(FILE *f, const char *p)
{ {
return PyRun_SimpleFileExFlags(f, p, 0, NULL); return PyRun_SimpleFileExFlags(f, p, 0, NULL);
} }
#undef PyRun_SimpleFileEx #undef PyRun_SimpleFileEx
int PyAPI_FUNC(int)
PyRun_SimpleFileEx(FILE *f, const char *p, int c) PyRun_SimpleFileEx(FILE *f, const char *p, int c)
{ {
return PyRun_SimpleFileExFlags(f, p, c, NULL); return PyRun_SimpleFileExFlags(f, p, c, NULL);
@ -1720,28 +1720,28 @@ PyRun_SimpleFileEx(FILE *f, const char *p, int c)
#undef PyRun_String #undef PyRun_String
PyObject * PyAPI_FUNC(PyObject *)
PyRun_String(const char *str, int s, PyObject *g, PyObject *l) PyRun_String(const char *str, int s, PyObject *g, PyObject *l)
{ {
return PyRun_StringFlags(str, s, g, l, NULL); return PyRun_StringFlags(str, s, g, l, NULL);
} }
#undef PyRun_SimpleString #undef PyRun_SimpleString
int PyAPI_FUNC(int)
PyRun_SimpleString(const char *s) PyRun_SimpleString(const char *s)
{ {
return PyRun_SimpleStringFlags(s, NULL); return PyRun_SimpleStringFlags(s, NULL);
} }
#undef Py_CompileString #undef Py_CompileString
PyObject * PyAPI_FUNC(PyObject *)
Py_CompileString(const char *str, const char *p, int s) Py_CompileString(const char *str, const char *p, int s)
{ {
return Py_CompileStringExFlags(str, p, s, NULL, -1); return Py_CompileStringExFlags(str, p, s, NULL, -1);
} }
#undef Py_CompileStringFlags #undef Py_CompileStringFlags
PyObject * PyAPI_FUNC(PyObject *)
Py_CompileStringFlags(const char *str, const char *p, int s, Py_CompileStringFlags(const char *str, const char *p, int s,
PyCompilerFlags *flags) PyCompilerFlags *flags)
{ {
@ -1749,14 +1749,14 @@ Py_CompileStringFlags(const char *str, const char *p, int s,
} }
#undef PyRun_InteractiveOne #undef PyRun_InteractiveOne
int PyAPI_FUNC(int)
PyRun_InteractiveOne(FILE *f, const char *p) PyRun_InteractiveOne(FILE *f, const char *p)
{ {
return PyRun_InteractiveOneFlags(f, p, NULL); return PyRun_InteractiveOneFlags(f, p, NULL);
} }
#undef PyRun_InteractiveLoop #undef PyRun_InteractiveLoop
int PyAPI_FUNC(int)
PyRun_InteractiveLoop(FILE *f, const char *p) PyRun_InteractiveLoop(FILE *f, const char *p)
{ {
return PyRun_InteractiveLoopFlags(f, p, NULL); return PyRun_InteractiveLoopFlags(f, p, NULL);

16
configure vendored
View File

@ -782,6 +782,7 @@ infodir
docdir docdir
oldincludedir oldincludedir
includedir includedir
runstatedir
localstatedir localstatedir
sharedstatedir sharedstatedir
sysconfdir sysconfdir
@ -895,6 +896,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc' sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com' sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var' localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include' includedir='${prefix}/include'
oldincludedir='/usr/include' oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1147,6 +1149,15 @@ do
| -silent | --silent | --silen | --sile | --sil) | -silent | --silent | --silen | --sile | --sil)
silent=yes ;; silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;; ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1284,7 +1295,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \ datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir libdir localedir mandir runstatedir
do do
eval ac_val=\$$ac_var eval ac_val=\$$ac_var
# Remove trailing slashes. # Remove trailing slashes.
@ -1437,6 +1448,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var] --localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib] --libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include] --includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include] --oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -7917,7 +7929,7 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
sys/endian.h sys/sysmacros.h linux/memfd.h sys/memfd.h sys/mman.h sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h sys/mman.h
do : do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"

View File

@ -2161,7 +2161,7 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
sys/endian.h sys/sysmacros.h linux/memfd.h sys/memfd.h sys/mman.h) sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h sys/mman.h)
AC_HEADER_DIRENT AC_HEADER_DIRENT
AC_HEADER_MAJOR AC_HEADER_MAJOR

View File

@ -642,6 +642,9 @@
/* Define to 1 if you have the <linux/vm_sockets.h> header file. */ /* Define to 1 if you have the <linux/vm_sockets.h> header file. */
#undef HAVE_LINUX_VM_SOCKETS_H #undef HAVE_LINUX_VM_SOCKETS_H
/* Define to 1 if you have the <linux/wait.h> header file. */
#undef HAVE_LINUX_WAIT_H
/* Define to 1 if you have the `lockf' function. */ /* Define to 1 if you have the `lockf' function. */
#undef HAVE_LOCKF #undef HAVE_LOCKF