Merge branch 'fix-issue-38681' of https://github.com/samtatasurya/cpython into fix-issue-38681
This commit is contained in:
commit
d8116e151c
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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`.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix _hashlib build when Blake2 is disabled, but OpenSSL supports it.
|
|
@ -0,0 +1,2 @@
|
||||||
|
Convert posixmodule.c statically allocated types ``DirEntryType`` and
|
||||||
|
``ScandirIteratorType`` to heap-allocated types.
|
|
@ -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.
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
||||||
|
Reëxport some function compatibility wrappers for macros in ``pythonrun.h``.
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
||||||
|
Expose the Linux ``pidfd_open`` syscall as :func:`os.pidfd_open`.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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]*/
|
||||||
|
|
|
@ -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, ¶m))
|
if (sched_getparam(pid, ¶m))
|
||||||
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(×_result_desc);
|
PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
137
Objects/call.c
137
Objects/call.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
128
Objects/object.c
128
Objects/object.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, ...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue