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`
|
||||
it.
|
||||
|
||||
The caller must hold the GIL.
|
||||
|
||||
.. note::
|
||||
|
||||
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.
|
||||
Otherwise, zero is returned.
|
||||
|
||||
*where* should be a string such as ``" in instance check"`` to be
|
||||
concatenated to the :exc:`RecursionError` message caused by the recursion
|
||||
*where* should be a UTF-8 encoded string such as ``" in instance check"`` to
|
||||
be concatenated to the :exc:`RecursionError` message caused by the recursion
|
||||
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
|
||||
*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
|
||||
special recursion handling. In addition to protecting the stack,
|
||||
: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
|
||||
does not silently discard an active exception.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyObject_Bytes(PyObject *o)
|
||||
|
||||
.. index:: builtin: bytes
|
||||
|
|
|
@ -38,7 +38,7 @@ associated messages through the :class:`http.HTTPStatus` enum:
|
|||
<HTTPStatus.OK: 200>
|
||||
>>> HTTPStatus.OK == 200
|
||||
True
|
||||
>>> http.HTTPStatus.OK.value
|
||||
>>> HTTPStatus.OK.value
|
||||
200
|
||||
>>> HTTPStatus.OK.phrase
|
||||
'OK'
|
||||
|
|
|
@ -3539,6 +3539,19 @@ written in Python, such as a mail server's external command delivery program.
|
|||
.. 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)
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
*options* is constructed from the ORing of one or more of :data:`WEXITED`,
|
||||
: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
|
||||
|
||||
.. 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
|
||||
WSTOPPED
|
||||
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
|
||||
reciprocal of the arithmetic :func:`mean` of the reciprocals of the
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ module. Specifically, any module that contains a ``__path__`` attribute is
|
|||
considered a package.
|
||||
|
||||
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`,
|
||||
which in turn has a subpackage called :mod:`email.mime` and a module within
|
||||
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
|
||||
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
|
||||
the :ref:`py.exe launcher <launcher>` installed, you can use the :file:`py`
|
||||
command. See :ref:`setting-envvars` for other ways to launch Python.
|
||||
|
|
|
@ -2152,6 +2152,55 @@ CPython bytecode changes
|
|||
Demos and Tools
|
||||
---------------
|
||||
|
||||
* Added a benchmark script for timing various ways to access variables:
|
||||
``Tools/scripts/var_access_benchmark.py``.
|
||||
(Contributed by Raymond Hettinger in :issue:`35884`.)
|
||||
Added a benchmark script for timing various ways to access variables:
|
||||
``Tools/scripts/var_access_benchmark.py``.
|
||||
(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`.
|
||||
(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
|
||||
---------
|
||||
|
||||
|
@ -197,6 +201,12 @@ Optimizations
|
|||
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
|
||||
calls a callable Python object without any arguments. It is the most efficient
|
||||
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(int) Py_GetRecursionLimit(void);
|
||||
|
||||
#define Py_EnterRecursiveCall(where) \
|
||||
(_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \
|
||||
_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))
|
||||
PyAPI_FUNC(int) Py_EnterRecursiveCall(const char *where);
|
||||
PyAPI_FUNC(void) Py_LeaveRecursiveCall(void);
|
||||
|
||||
#define Py_ALLOW_RECURSION \
|
||||
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_HAVE_SPEC 0x4
|
||||
|
||||
#ifndef Py_LIMITED_API
|
||||
# define Py_CPYTHON_CEVAL_H
|
||||
# include "cpython/ceval.h"
|
||||
# undef Py_CPYTHON_CEVAL_H
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,9 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
|
|||
40 bytes on the stack. */
|
||||
#define _PY_FASTCALL_SMALL_STACK 5
|
||||
|
||||
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *callable,
|
||||
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(
|
||||
PyThreadState *tstate,
|
||||
PyObject *callable,
|
||||
PyObject *result,
|
||||
const char *where);
|
||||
|
||||
|
@ -47,6 +49,7 @@ PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *callable,
|
|||
or _PyObject_FastCallDict() (both forms are supported),
|
||||
except that nargs is plainly the number of arguments without flags. */
|
||||
PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall(
|
||||
PyThreadState *tstate,
|
||||
PyObject *callable,
|
||||
PyObject *const *args, Py_ssize_t nargs,
|
||||
PyObject *keywords);
|
||||
|
@ -93,18 +96,29 @@ _PyVectorcall_Function(PyObject *callable)
|
|||
Return the result on success. Raise an exception and return NULL on
|
||||
error. */
|
||||
static inline PyObject *
|
||||
_PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable,
|
||||
PyObject *const *args, size_t nargsf,
|
||||
PyObject *kwnames)
|
||||
{
|
||||
assert(kwnames == NULL || PyTuple_Check(kwnames));
|
||||
assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0);
|
||||
|
||||
vectorcallfunc func = _PyVectorcall_Function(callable);
|
||||
if (func == NULL) {
|
||||
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);
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
|
||||
|
||||
/* Safely decref `op` and set `op` to `op2`.
|
||||
*
|
||||
|
|
|
@ -10,7 +10,8 @@ extern "C" {
|
|||
|
||||
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 **tb);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate(
|
||||
PyThreadState *tstate,
|
||||
PyObject *exception,
|
||||
const char *format,
|
||||
...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -125,6 +125,15 @@ struct _is {
|
|||
struct _warnings_runtime_state warnings;
|
||||
|
||||
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);
|
||||
|
|
|
@ -48,6 +48,9 @@ class BaseRotatingHandler(logging.FileHandler):
|
|||
Not meant to be instantiated directly. Instead, use RotatingFileHandler
|
||||
or TimedRotatingFileHandler.
|
||||
"""
|
||||
namer = None
|
||||
rotator = None
|
||||
|
||||
def __init__(self, filename, mode, encoding=None, delay=False, errors=None):
|
||||
"""
|
||||
Use the specified filename for streamed logging
|
||||
|
@ -58,8 +61,6 @@ class BaseRotatingHandler(logging.FileHandler):
|
|||
self.mode = mode
|
||||
self.encoding = encoding
|
||||
self.errors = errors
|
||||
self.namer = None
|
||||
self.rotator = None
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
|
|
|
@ -74,7 +74,7 @@ class CFunctionCallsErrorMessages(unittest.TestCase):
|
|||
self.assertRaisesRegex(TypeError, msg, bool, x=2)
|
||||
|
||||
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)
|
||||
|
||||
def test_varargs5_kw(self):
|
||||
|
@ -90,19 +90,19 @@ class CFunctionCallsErrorMessages(unittest.TestCase):
|
|||
self.assertRaisesRegex(TypeError, msg, next, x=2)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
def test_varargs12_kw(self):
|
||||
|
|
|
@ -1967,7 +1967,7 @@ order (MRO) for bases """
|
|||
# different error messages.
|
||||
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:
|
||||
set_add()
|
||||
|
|
|
@ -52,15 +52,15 @@ Here we add keyword arguments
|
|||
>>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
|
||||
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)
|
||||
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})
|
||||
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})
|
||||
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
||||
>>> 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())
|
||||
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:
|
||||
... def __len__(self): return 5
|
||||
|
@ -127,7 +127,7 @@ Verify clearing of SF bug #733667
|
|||
>>> g(*Nothing())
|
||||
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():
|
||||
... def __len__(self): return 5
|
||||
|
@ -247,17 +247,17 @@ What about willful misconduct?
|
|||
>>> h(*h)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
Traceback (most recent call last):
|
||||
|
@ -268,38 +268,38 @@ What about willful misconduct?
|
|||
>>> nothing(*h)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: NoneType object argument after * must be an iterable, \
|
||||
TypeError: None argument after * must be an iterable, \
|
||||
not function
|
||||
|
||||
>>> h(**h)
|
||||
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(**[])
|
||||
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)
|
||||
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, **[])
|
||||
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)
|
||||
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}, **[])
|
||||
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)
|
||||
Traceback (most recent call last):
|
||||
|
@ -309,7 +309,7 @@ not function
|
|||
>>> nothing(**h)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: NoneType object argument after ** must be a mapping, \
|
||||
TypeError: None argument after ** must be a mapping, \
|
||||
not function
|
||||
|
||||
>>> dir(b=1, **{'b': 1})
|
||||
|
@ -351,17 +351,17 @@ Test a kwargs mapping with duplicated keys.
|
|||
>>> g(**MultiDict([('x', 1), ('x', 2)]))
|
||||
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)]))
|
||||
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)]))
|
||||
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
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import os
|
|||
import struct
|
||||
import sys
|
||||
import unittest
|
||||
from multiprocessing import Process
|
||||
from test.support import (verbose, TESTFN, unlink, run_unittest, import_module,
|
||||
cpython_only)
|
||||
|
||||
|
@ -12,7 +13,6 @@ from test.support import (verbose, TESTFN, unlink, run_unittest, import_module,
|
|||
fcntl = import_module('fcntl')
|
||||
|
||||
|
||||
# TODO - Write tests for flock() and lockf().
|
||||
|
||||
def get_lockdata():
|
||||
try:
|
||||
|
@ -138,6 +138,33 @@ class TestFcntl(unittest.TestCase):
|
|||
self.assertRaises(ValueError, fcntl.flock, -1, 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
|
||||
def test_flock_overflow(self):
|
||||
import _testcapi
|
||||
|
|
|
@ -1613,7 +1613,7 @@ class ConfigFileTest(BaseTest):
|
|||
format=%(levelname)s ++ %(message)s
|
||||
"""
|
||||
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):
|
||||
"""bpo-33802 defaults should not get interpolated"""
|
||||
|
@ -5030,6 +5030,25 @@ class RotatingFileHandlerTest(BaseFileTest):
|
|||
self.assertFalse(os.path.exists(namer(self.fn + ".3")))
|
||||
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
|
||||
def test_rotator(self):
|
||||
def namer(name):
|
||||
|
|
|
@ -3638,6 +3638,24 @@ class ExportsTests(unittest.TestCase):
|
|||
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):
|
||||
check_no_resource_warning = support.check_no_resource_warning
|
||||
|
||||
|
@ -3672,6 +3690,18 @@ class TestScandir(unittest.TestCase):
|
|||
else:
|
||||
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):
|
||||
self.assertIsInstance(entry, os.DirEntry)
|
||||
self.assertEqual(entry.name, name)
|
||||
|
|
|
@ -1470,6 +1470,15 @@ class PosixTester(unittest.TestCase):
|
|||
open(fn, 'wb').close()
|
||||
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):
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -236,27 +236,27 @@ Overridden parameters
|
|||
>>> f(x=5, **{'x': 3}, y=2)
|
||||
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)
|
||||
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)
|
||||
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})
|
||||
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})
|
||||
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
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ This returns an instance of a class with the following public methods:
|
|||
-- set all parameters at once
|
||||
tell() -- return current position in output file
|
||||
writeframesraw(data)
|
||||
-- write audio frames without pathing up the
|
||||
-- write audio frames without patching up the
|
||||
file header
|
||||
writeframes(data)
|
||||
-- write audio frames and patch up the file header
|
||||
|
|
|
@ -1057,6 +1057,7 @@ PYTHON_HEADERS= \
|
|||
$(srcdir)/Include/Python-ast.h \
|
||||
\
|
||||
$(srcdir)/Include/cpython/abstract.h \
|
||||
$(srcdir)/Include/cpython/ceval.h \
|
||||
$(srcdir)/Include/cpython/dictobject.h \
|
||||
$(srcdir)/Include/cpython/fileobject.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
|
||||
* to using partial_call() instead. */
|
||||
_Py_NO_INLINE static PyObject *
|
||||
partial_vectorcall_fallback(partialobject *pto, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
|
||||
PyObject *const *args, size_t nargsf,
|
||||
PyObject *kwnames)
|
||||
{
|
||||
pto->vectorcall = NULL;
|
||||
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 *
|
||||
partial_vectorcall(partialobject *pto, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
|
||||
/* pto->kw is mutable, so need to check every time */
|
||||
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);
|
||||
|
@ -160,7 +164,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
|
|||
|
||||
/* Fast path if we're called without arguments */
|
||||
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
|
||||
|
@ -169,7 +174,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
|
|||
PyObject **newargs = (PyObject **)args - 1;
|
||||
PyObject *tmp = newargs[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;
|
||||
return ret;
|
||||
}
|
||||
|
@ -195,7 +201,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
|
|||
memcpy(stack, pto_args, pto_nargs * 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) {
|
||||
PyMem_Free(stack);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#define PY_OPENSSL_HAS_SHAKE 1
|
||||
#endif
|
||||
|
||||
#ifdef NID_blake2b512
|
||||
#if defined(NID_blake2b512) && !defined(OPENSSL_NO_BLAKE2)
|
||||
#define PY_OPENSSL_HAS_BLAKE2 1
|
||||
#endif
|
||||
|
||||
|
|
|
@ -12,12 +12,6 @@
|
|||
#include "structmember.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_CheckExact(op) (Py_TYPE(op) == &PyScannerType)
|
||||
#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType)
|
||||
|
@ -78,7 +72,7 @@ static PyMemberDef encoder_members[] = {
|
|||
static PyObject *
|
||||
ascii_escape_unicode(PyObject *pystr);
|
||||
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);
|
||||
static PyObject *
|
||||
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 *
|
||||
py_scanstring(PyObject* self UNUSED, PyObject *args)
|
||||
py_scanstring(PyObject* Py_UNUSED(self), PyObject *args)
|
||||
{
|
||||
PyObject *pystr;
|
||||
PyObject *rval;
|
||||
|
@ -591,7 +585,7 @@ PyDoc_STRVAR(pydoc_encode_basestring_ascii,
|
|||
);
|
||||
|
||||
static PyObject *
|
||||
py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr)
|
||||
py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr)
|
||||
{
|
||||
PyObject *rval;
|
||||
/* Return an ASCII-only JSON representation of a Python string */
|
||||
|
@ -616,7 +610,7 @@ PyDoc_STRVAR(pydoc_encode_basestring,
|
|||
);
|
||||
|
||||
static PyObject *
|
||||
py_encode_basestring(PyObject* self UNUSED, PyObject *pystr)
|
||||
py_encode_basestring(PyObject* Py_UNUSED(self), PyObject *pystr)
|
||||
{
|
||||
PyObject *rval;
|
||||
/* Return a JSON representation of a Python string */
|
||||
|
|
|
@ -2838,7 +2838,7 @@ PyDoc_STRVAR(os_sched_param__doc__,
|
|||
"sched_param(sched_priority)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Current has only one field: sched_priority\");\n"
|
||||
"Currently has only one field: sched_priority\n"
|
||||
"\n"
|
||||
" sched_priority\n"
|
||||
" A scheduling parameter.");
|
||||
|
@ -3963,6 +3963,44 @@ os_wait(PyObject *module, PyObject *Py_UNUSED(ignored))
|
|||
|
||||
#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))
|
||||
|
||||
PyDoc_STRVAR(os_readlink__doc__,
|
||||
|
@ -8480,6 +8518,10 @@ exit:
|
|||
#define 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
|
||||
#define OS_READLINK_METHODDEF
|
||||
#endif /* !defined(OS_READLINK_METHODDEF) */
|
||||
|
@ -8731,4 +8773,4 @@ exit:
|
|||
#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF
|
||||
#define 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
|
||||
#include <sys/wait.h> /* For WNOHANG */
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_WAIT_H
|
||||
#include <linux/wait.h> // For P_PIDFD
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
|
@ -217,6 +220,7 @@ corresponding Unix manual entries for more information on calls.");
|
|||
#endif /* _MSC_VER */
|
||||
#endif /* ! __WATCOMC__ || __QNX__ */
|
||||
|
||||
_Py_IDENTIFIER(__fspath__);
|
||||
|
||||
/*[clinic input]
|
||||
# one of the few times we lie about this name!
|
||||
|
@ -537,7 +541,7 @@ _Py_Uid_Converter(PyObject *obj, void *p)
|
|||
if (index == NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"uid should be integer, not %.200s",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
_PyType_Name(Py_TYPE(obj)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -643,7 +647,7 @@ _Py_Gid_Converter(PyObject *obj, void *p)
|
|||
if (index == NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"gid should be integer, not %.200s",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
_PyType_Name(Py_TYPE(obj)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -810,11 +814,37 @@ dir_fd_converter(PyObject *o, void *p)
|
|||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"argument should be integer or None, not %.200s",
|
||||
Py_TYPE(o)->tp_name);
|
||||
_PyType_Name(Py_TYPE(o)));
|
||||
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
|
||||
|
@ -984,7 +1014,6 @@ path_converter(PyObject *o, void *p)
|
|||
|
||||
if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
|
||||
/* Inline PyOS_FSPath() for better error messages. */
|
||||
_Py_IDENTIFIER(__fspath__);
|
||||
PyObject *func, *res;
|
||||
|
||||
func = _PyObject_LookupSpecial(o, &PyId___fspath__);
|
||||
|
@ -1005,8 +1034,8 @@ path_converter(PyObject *o, void *p)
|
|||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"expected %.200s.__fspath__() to return str or bytes, "
|
||||
"not %.200s", Py_TYPE(o)->tp_name,
|
||||
Py_TYPE(res)->tp_name);
|
||||
"not %.200s", _PyType_Name(Py_TYPE(o)),
|
||||
_PyType_Name(Py_TYPE(res)));
|
||||
Py_DECREF(res);
|
||||
goto error_exit;
|
||||
}
|
||||
|
@ -1058,7 +1087,7 @@ path_converter(PyObject *o, void *p)
|
|||
path->allow_fd ? "string, bytes, os.PathLike or integer" :
|
||||
path->nullable ? "string, bytes, os.PathLike or None" :
|
||||
"string, bytes or os.PathLike",
|
||||
Py_TYPE(o)->tp_name)) {
|
||||
_PyType_Name(Py_TYPE(o)))) {
|
||||
goto error_exit;
|
||||
}
|
||||
bytes = PyBytes_FromObject(o);
|
||||
|
@ -1089,7 +1118,7 @@ path_converter(PyObject *o, void *p)
|
|||
path->allow_fd ? "string, bytes, os.PathLike or integer" :
|
||||
path->nullable ? "string, bytes, os.PathLike or None" :
|
||||
"string, bytes or os.PathLike",
|
||||
Py_TYPE(o)->tp_name);
|
||||
_PyType_Name(Py_TYPE(o)));
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
|
@ -2047,14 +2076,6 @@ static PyStructSequence_Desc waitid_result_desc = {
|
|||
waitid_result_fields,
|
||||
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
|
||||
static newfunc structseq_new;
|
||||
|
||||
|
@ -2080,8 +2101,61 @@ statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
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
|
||||
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))
|
||||
goto exit;
|
||||
|
||||
s_in_ns = PyNumber_Multiply(s, billion);
|
||||
s_in_ns = PyNumber_Multiply(s, _posixstate_global->billion);
|
||||
if (!s_in_ns)
|
||||
goto exit;
|
||||
|
||||
|
@ -2128,7 +2202,8 @@ static PyObject*
|
|||
_pystat_fromstructstat(STRUCT_STAT *st)
|
||||
{
|
||||
unsigned long ansec, mnsec, cnsec;
|
||||
PyObject *v = PyStructSequence_New(StatResultType);
|
||||
PyObject *StatResultType = _posixstate_global->StatResultType;
|
||||
PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -4505,15 +4580,12 @@ or via the attributes sysname, nodename, release, version, and machine.\n\
|
|||
See os.uname for more information.");
|
||||
|
||||
static PyStructSequence_Desc uname_result_desc = {
|
||||
"uname_result", /* name */
|
||||
MODNAME ".uname_result", /* name */
|
||||
uname_result__doc__, /* doc */
|
||||
uname_result_fields,
|
||||
5
|
||||
};
|
||||
|
||||
static PyTypeObject* UnameResultType;
|
||||
|
||||
|
||||
#ifdef HAVE_UNAME
|
||||
/*[clinic input]
|
||||
os.uname
|
||||
|
@ -4539,7 +4611,8 @@ os_uname_impl(PyObject *module)
|
|||
if (res < 0)
|
||||
return posix_error();
|
||||
|
||||
value = PyStructSequence_New(UnameResultType);
|
||||
PyObject *UnameResultType = _posixstate(module)->UnameResultType;
|
||||
value = PyStructSequence_New((PyTypeObject *)UnameResultType);
|
||||
if (value == 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;
|
||||
PyObject *divmod;
|
||||
divmod = PyNumber_Divmod(py_long, billion);
|
||||
divmod = PyNumber_Divmod(py_long, _posixstate_global->billion);
|
||||
if (!divmod)
|
||||
goto exit;
|
||||
if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.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;
|
||||
}
|
||||
*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)) {
|
||||
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 0;
|
||||
|
@ -6177,12 +6250,12 @@ os.sched_param.__new__
|
|||
sched_priority: object
|
||||
A scheduling parameter.
|
||||
|
||||
Current has only one field: sched_priority");
|
||||
Currently has only one field: sched_priority
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
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;
|
||||
|
||||
|
@ -6194,7 +6267,6 @@ os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_VAR(os_sched_param__doc__);
|
||||
|
||||
static PyStructSequence_Field sched_param_fields[] = {
|
||||
|
@ -6214,7 +6286,8 @@ convert_sched_param(PyObject *param, struct sched_param *res)
|
|||
{
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
@ -6285,7 +6358,8 @@ os_sched_getparam_impl(PyObject *module, pid_t pid)
|
|||
|
||||
if (sched_getparam(pid, ¶m))
|
||||
return posix_error();
|
||||
result = PyStructSequence_New(SchedParamType);
|
||||
PyObject *SchedParamType = _posixstate_global->SchedParamType;
|
||||
result = PyStructSequence_New((PyTypeObject *)SchedParamType);
|
||||
if (!result)
|
||||
return NULL;
|
||||
priority = PyLong_FromLong(param.sched_priority);
|
||||
|
@ -7494,8 +7568,7 @@ static PyObject *
|
|||
wait_helper(pid_t pid, int status, struct rusage *ru)
|
||||
{
|
||||
PyObject *result;
|
||||
static PyObject *struct_rusage;
|
||||
_Py_IDENTIFIER(struct_rusage);
|
||||
PyObject *struct_rusage;
|
||||
|
||||
if (pid == -1)
|
||||
return posix_error();
|
||||
|
@ -7506,15 +7579,13 @@ wait_helper(pid_t pid, int status, struct rusage *ru)
|
|||
memset(ru, 0, sizeof(*ru));
|
||||
}
|
||||
|
||||
if (struct_rusage == NULL) {
|
||||
PyObject *m = PyImport_ImportModuleNoBlock("resource");
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
|
||||
struct_rusage = PyObject_GetAttr(m, _posixstate_global->struct_rusage);
|
||||
Py_DECREF(m);
|
||||
if (struct_rusage == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
|
||||
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)
|
||||
Py_RETURN_NONE;
|
||||
|
||||
result = PyStructSequence_New(WaitidResultType);
|
||||
PyObject *WaitidResultType = _posixstate(module)->WaitidResultType;
|
||||
result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
|
@ -7792,6 +7864,30 @@ os_wait_impl(PyObject *module)
|
|||
}
|
||||
#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)
|
||||
/*[clinic input]
|
||||
|
@ -8119,8 +8215,6 @@ static PyStructSequence_Desc times_result_desc = {
|
|||
5
|
||||
};
|
||||
|
||||
static PyTypeObject* TimesResultType;
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#define HAVE_TIMES /* mandatory, for the method table */
|
||||
#endif
|
||||
|
@ -8132,7 +8226,8 @@ build_times_result(double user, double system,
|
|||
double children_user, double children_system,
|
||||
double elapsed)
|
||||
{
|
||||
PyObject *value = PyStructSequence_New(TimesResultType);
|
||||
PyObject *TimesResultType = _posixstate_global->TimesResultType;
|
||||
PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -9953,10 +10048,6 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
|
|||
|
||||
#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
|
||||
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
|
||||
* happen after the real putenv() call because the old value
|
||||
* 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 */
|
||||
PyErr_Clear();
|
||||
else
|
||||
|
@ -10101,7 +10192,7 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
|
|||
* happen after the real unsetenv() call because the
|
||||
* 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 */
|
||||
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
|
||||
return NULL;
|
||||
|
@ -10312,7 +10403,8 @@ os_WSTOPSIG_impl(PyObject *module, int status)
|
|||
|
||||
static PyObject*
|
||||
_pystatvfs_fromstructstatvfs(struct statvfs st) {
|
||||
PyObject *v = PyStructSequence_New(StatVFSResultType);
|
||||
PyObject *StatVFSResultType = _posixstate_global->StatVFSResultType;
|
||||
PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -12089,8 +12181,6 @@ os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
|
|||
|
||||
/* Terminal size querying */
|
||||
|
||||
static PyTypeObject* TerminalSizeType;
|
||||
|
||||
PyDoc_STRVAR(TerminalSize_docstring,
|
||||
"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 */
|
||||
|
||||
termsize = PyStructSequence_New(TerminalSizeType);
|
||||
PyObject *TerminalSizeType = _posixstate(self)->TerminalSizeType;
|
||||
termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
|
||||
if (termsize == NULL)
|
||||
return NULL;
|
||||
PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
|
||||
|
@ -12379,9 +12470,9 @@ os_set_blocking_impl(PyObject *module, int fd, int blocking)
|
|||
|
||||
|
||||
/*[clinic input]
|
||||
class os.DirEntry "DirEntry *" "&DirEntryType"
|
||||
class os.DirEntry "DirEntry *" "DirEntryType"
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
@ -12402,14 +12493,25 @@ typedef struct {
|
|||
#endif
|
||||
} 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
|
||||
DirEntry_dealloc(DirEntry *entry)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(entry);
|
||||
Py_XDECREF(entry->name);
|
||||
Py_XDECREF(entry->path);
|
||||
Py_XDECREF(entry->stat);
|
||||
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 */
|
||||
|
@ -12538,7 +12640,6 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits
|
|||
#ifdef MS_WINDOWS
|
||||
unsigned long dir_bits;
|
||||
#endif
|
||||
_Py_IDENTIFIER(st_mode);
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
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;
|
||||
}
|
||||
st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
|
||||
st_mode = PyObject_GetAttr(stat, _posixstate_global->st_mode);
|
||||
if (!st_mode)
|
||||
goto error;
|
||||
|
||||
|
@ -12709,39 +12810,24 @@ static PyMethodDef DirEntry_methods[] = {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
static PyTypeObject DirEntryType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
MODNAME ".DirEntry", /* tp_name */
|
||||
sizeof(DirEntry), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)DirEntry_dealloc, /* tp_dealloc */
|
||||
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_Slot DirEntryType_slots[] = {
|
||||
{Py_tp_new, _disabled_new},
|
||||
{Py_tp_dealloc, DirEntry_dealloc},
|
||||
{Py_tp_repr, DirEntry_repr},
|
||||
{Py_tp_methods, DirEntry_methods},
|
||||
{Py_tp_members, DirEntry_members},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static PyType_Spec DirEntryType_spec = {
|
||||
MODNAME ".DirEntry",
|
||||
sizeof(DirEntry),
|
||||
0,
|
||||
Py_TPFLAGS_DEFAULT,
|
||||
DirEntryType_slots
|
||||
};
|
||||
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
|
||||
static wchar_t *
|
||||
|
@ -12785,7 +12871,8 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
|
|||
ULONG reparse_tag;
|
||||
wchar_t *joined_path;
|
||||
|
||||
entry = PyObject_New(DirEntry, &DirEntryType);
|
||||
PyObject *DirEntryType = _posixstate_global->DirEntryType;
|
||||
entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
|
||||
if (!entry)
|
||||
return 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;
|
||||
char *joined_path;
|
||||
|
||||
entry = PyObject_New(DirEntry, &DirEntryType);
|
||||
PyObject *DirEntryType = _posixstate_global->DirEntryType;
|
||||
entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
entry->name = NULL;
|
||||
|
@ -13134,10 +13222,13 @@ ScandirIterator_finalize(ScandirIterator *iterator)
|
|||
static void
|
||||
ScandirIterator_dealloc(ScandirIterator *iterator)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(iterator);
|
||||
if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
|
||||
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[] = {
|
||||
|
@ -13147,56 +13238,22 @@ static PyMethodDef ScandirIterator_methods[] = {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
static PyTypeObject ScandirIteratorType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
MODNAME ".ScandirIterator", /* tp_name */
|
||||
sizeof(ScandirIterator), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)ScandirIterator_dealloc, /* tp_dealloc */
|
||||
0, /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
0, /* 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 */
|
||||
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 */
|
||||
static PyType_Slot ScandirIteratorType_slots[] = {
|
||||
{Py_tp_new, _disabled_new},
|
||||
{Py_tp_dealloc, ScandirIterator_dealloc},
|
||||
{Py_tp_finalize, ScandirIterator_finalize},
|
||||
{Py_tp_iter, PyObject_SelfIter},
|
||||
{Py_tp_iternext, ScandirIterator_iternext},
|
||||
{Py_tp_methods, ScandirIterator_methods},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static PyType_Spec ScandirIteratorType_spec = {
|
||||
MODNAME ".ScandirIterator",
|
||||
sizeof(ScandirIterator),
|
||||
0,
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
|
||||
ScandirIteratorType_slots
|
||||
};
|
||||
|
||||
/*[clinic input]
|
||||
|
@ -13232,7 +13289,8 @@ os_scandir_impl(PyObject *module, path_t *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
|
||||
PyObject *ScandirIteratorType = _posixstate(module)->ScandirIteratorType;
|
||||
iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
|
||||
if (!iterator)
|
||||
return NULL;
|
||||
|
||||
|
@ -13322,7 +13380,6 @@ PyOS_FSPath(PyObject *path)
|
|||
{
|
||||
/* For error message reasons, this function is manually inlined in
|
||||
path_converter(). */
|
||||
_Py_IDENTIFIER(__fspath__);
|
||||
PyObject *func = NULL;
|
||||
PyObject *path_repr = NULL;
|
||||
|
||||
|
@ -13336,7 +13393,7 @@ PyOS_FSPath(PyObject *path)
|
|||
return PyErr_Format(PyExc_TypeError,
|
||||
"expected str, bytes or os.PathLike object, "
|
||||
"not %.200s",
|
||||
Py_TYPE(path)->tp_name);
|
||||
_PyType_Name(Py_TYPE(path)));
|
||||
}
|
||||
|
||||
path_repr = _PyObject_CallNoArg(func);
|
||||
|
@ -13348,8 +13405,8 @@ PyOS_FSPath(PyObject *path)
|
|||
if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"expected %.200s.__fspath__() to return str or bytes, "
|
||||
"not %.200s", Py_TYPE(path)->tp_name,
|
||||
Py_TYPE(path_repr)->tp_name);
|
||||
"not %.200s", _PyType_Name(Py_TYPE(path)),
|
||||
_PyType_Name(Py_TYPE(path_repr)));
|
||||
Py_DECREF(path_repr);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -13641,6 +13698,7 @@ static PyMethodDef posix_methods[] = {
|
|||
OS_WAIT4_METHODDEF
|
||||
OS_WAITID_METHODDEF
|
||||
OS_WAITPID_METHODDEF
|
||||
OS_PIDFD_OPEN_METHODDEF
|
||||
OS_GETSID_METHODDEF
|
||||
OS_SETSID_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_PGID)) return -1;
|
||||
if (PyModule_AddIntMacro(m, P_ALL)) return -1;
|
||||
#ifdef P_PIDFD
|
||||
if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WEXITED
|
||||
if (PyModule_AddIntMacro(m, WEXITED)) return -1;
|
||||
|
@ -14258,12 +14319,12 @@ static struct PyModuleDef posixmodule = {
|
|||
PyModuleDef_HEAD_INIT,
|
||||
MODNAME,
|
||||
posix__doc__,
|
||||
-1,
|
||||
sizeof(_posixstate),
|
||||
posix_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
_posix_traverse,
|
||||
_posix_clear,
|
||||
_posix_free,
|
||||
};
|
||||
|
||||
|
||||
|
@ -14408,6 +14469,12 @@ INITFUNC(void)
|
|||
PyObject *list;
|
||||
const char * const *trace;
|
||||
|
||||
m = PyState_FindModule(&posixmodule);
|
||||
if (m != NULL) {
|
||||
Py_INCREF(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
m = PyModule_Create(&posixmodule);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
@ -14429,35 +14496,44 @@ INITFUNC(void)
|
|||
PyModule_AddObject(m, "error", PyExc_OSError);
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
if (posix_putenv_garbage == NULL)
|
||||
posix_putenv_garbage = PyDict_New();
|
||||
/* Save putenv() parameters as values here, so we can collect them when they
|
||||
* get re-set with another call for the same key. */
|
||||
_posixstate(m)->posix_putenv_garbage = PyDict_New();
|
||||
#endif
|
||||
|
||||
if (!initialized) {
|
||||
#if defined(HAVE_WAITID) && !defined(__APPLE__)
|
||||
waitid_result_desc.name = MODNAME ".waitid_result";
|
||||
WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
|
||||
PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
|
||||
if (WaitidResultType == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(WaitidResultType);
|
||||
PyModule_AddObject(m, "waitid_result", WaitidResultType);
|
||||
_posixstate(m)->WaitidResultType = WaitidResultType;
|
||||
#endif
|
||||
|
||||
stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
|
||||
stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
|
||||
stat_result_desc.fields[8].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) {
|
||||
return NULL;
|
||||
}
|
||||
structseq_new = StatResultType->tp_new;
|
||||
StatResultType->tp_new = statresult_new;
|
||||
Py_INCREF(StatResultType);
|
||||
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 */
|
||||
StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
|
||||
PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
|
||||
if (StatVFSResultType == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(StatVFSResultType);
|
||||
PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
|
||||
_posixstate(m)->StatVFSResultType = StatVFSResultType;
|
||||
#ifdef NEED_TICKS_PER_SECOND
|
||||
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
|
||||
ticks_per_second = sysconf(_SC_CLK_TCK);
|
||||
|
@ -14470,53 +14546,56 @@ INITFUNC(void)
|
|||
|
||||
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
|
||||
sched_param_desc.name = MODNAME ".sched_param";
|
||||
SchedParamType = PyStructSequence_NewType(&sched_param_desc);
|
||||
PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
|
||||
if (SchedParamType == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
SchedParamType->tp_new = os_sched_param;
|
||||
Py_INCREF(SchedParamType);
|
||||
PyModule_AddObject(m, "sched_param", SchedParamType);
|
||||
_posixstate(m)->SchedParamType = SchedParamType;
|
||||
((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
|
||||
#endif
|
||||
|
||||
/* initialize TerminalSize_info */
|
||||
TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
|
||||
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 */
|
||||
if (PyType_Ready(&ScandirIteratorType) < 0)
|
||||
return NULL;
|
||||
if (PyType_Ready(&DirEntryType) < 0)
|
||||
PyObject *ScandirIteratorType = PyType_FromSpec(&ScandirIteratorType_spec);
|
||||
if (ScandirIteratorType == NULL) {
|
||||
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);
|
||||
_posixstate(m)->ScandirIteratorType = ScandirIteratorType;
|
||||
|
||||
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
|
||||
Py_INCREF(SchedParamType);
|
||||
PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
|
||||
#endif
|
||||
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";
|
||||
TimesResultType = PyStructSequence_NewType(×_result_desc);
|
||||
PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
|
||||
if (TimesResultType == 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";
|
||||
UnameResultType = PyStructSequence_NewType(&uname_result_desc);
|
||||
PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
|
||||
if (UnameResultType == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(UnameResultType);
|
||||
PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
|
||||
_posixstate(m)->UnameResultType = (PyObject *)UnameResultType;
|
||||
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
|
@ -14556,11 +14635,15 @@ INITFUNC(void)
|
|||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
Py_INCREF(TerminalSizeType);
|
||||
PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
|
||||
|
||||
billion = PyLong_FromLong(1000000000);
|
||||
if (!billion)
|
||||
if ((_posixstate(m)->billion = PyLong_FromLong(1000000000)) == NULL)
|
||||
return NULL;
|
||||
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
|
||||
_posixstate(m)->struct_rusage = PyUnicode_InternFromString("struct_rusage");
|
||||
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;
|
||||
|
||||
/* suppress "function not used" warnings */
|
||||
|
@ -14590,11 +14673,6 @@ INITFUNC(void)
|
|||
}
|
||||
PyModule_AddObject(m, "_have_functions", list);
|
||||
|
||||
Py_INCREF((PyObject *) &DirEntryType);
|
||||
PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
|
||||
|
||||
initialized = 1;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Abstract Object Interface (many thanks to Jim Fulton) */
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include <ctype.h>
|
||||
#include "structmember.h" /* we need the offsetof() macro from there */
|
||||
|
@ -2459,8 +2460,8 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
|
|||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||
static int
|
||||
object_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
|
||||
{
|
||||
_Py_IDENTIFIER(__instancecheck__);
|
||||
PyObject *checker;
|
||||
|
@ -2475,34 +2476,31 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
|||
}
|
||||
|
||||
if (PyTuple_Check(cls)) {
|
||||
Py_ssize_t i;
|
||||
Py_ssize_t n;
|
||||
int r = 0;
|
||||
|
||||
if (Py_EnterRecursiveCall(" in __instancecheck__"))
|
||||
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
||||
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);
|
||||
r = PyObject_IsInstance(inst, item);
|
||||
r = object_isinstance(tstate, inst, item);
|
||||
if (r != 0)
|
||||
/* either found it, or got an error */
|
||||
break;
|
||||
}
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return r;
|
||||
}
|
||||
|
||||
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
|
||||
if (checker != NULL) {
|
||||
PyObject *res;
|
||||
int ok = -1;
|
||||
if (Py_EnterRecursiveCall(" in __instancecheck__")) {
|
||||
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
||||
Py_DECREF(checker);
|
||||
return ok;
|
||||
}
|
||||
res = _PyObject_CallOneArg(checker, inst);
|
||||
Py_LeaveRecursiveCall();
|
||||
PyObject *res = _PyObject_CallOneArg(checker, inst);
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
Py_DECREF(checker);
|
||||
if (res != NULL) {
|
||||
ok = PyObject_IsTrue(res);
|
||||
|
@ -2510,12 +2508,23 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
|||
}
|
||||
return ok;
|
||||
}
|
||||
else if (PyErr_Occurred())
|
||||
else if (_PyErr_Occurred(tstate)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Probably never reached anymore. */
|
||||
return recursive_isinstance(inst, cls);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
return object_isinstance(tstate, inst, cls);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
recursive_issubclass(PyObject *derived, PyObject *cls)
|
||||
{
|
||||
|
@ -2534,8 +2543,8 @@ recursive_issubclass(PyObject *derived, PyObject *cls)
|
|||
return abstract_issubclass(derived, cls);
|
||||
}
|
||||
|
||||
int
|
||||
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||
static int
|
||||
object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
|
||||
{
|
||||
_Py_IDENTIFIER(__subclasscheck__);
|
||||
PyObject *checker;
|
||||
|
@ -2549,34 +2558,32 @@ PyObject_IsSubclass(PyObject *derived, PyObject *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;
|
||||
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);
|
||||
r = PyObject_IsSubclass(derived, item);
|
||||
r = object_issubclass(tstate, derived, item);
|
||||
if (r != 0)
|
||||
/* either found it, or got an error */
|
||||
break;
|
||||
}
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return r;
|
||||
}
|
||||
|
||||
checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__);
|
||||
if (checker != NULL) {
|
||||
PyObject *res;
|
||||
int ok = -1;
|
||||
if (Py_EnterRecursiveCall(" in __subclasscheck__")) {
|
||||
if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
|
||||
Py_DECREF(checker);
|
||||
return ok;
|
||||
}
|
||||
res = _PyObject_CallOneArg(checker, derived);
|
||||
Py_LeaveRecursiveCall();
|
||||
PyObject *res = _PyObject_CallOneArg(checker, derived);
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
Py_DECREF(checker);
|
||||
if (res != NULL) {
|
||||
ok = PyObject_IsTrue(res);
|
||||
|
@ -2584,12 +2591,23 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
|||
}
|
||||
return ok;
|
||||
}
|
||||
else if (PyErr_Occurred())
|
||||
else if (_PyErr_Occurred(tstate)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Probably never reached anymore. */
|
||||
return recursive_issubclass(derived, cls);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
return object_issubclass(tstate, derived, cls);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
|
||||
{
|
||||
|
|
119
Objects/call.c
119
Objects/call.c
|
@ -1,13 +1,15 @@
|
|||
#include "Python.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "pycore_tupleobject.h"
|
||||
#include "frameobject.h"
|
||||
|
||||
|
||||
static PyObject *const *
|
||||
_PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
|
||||
PyObject **p_kwnames);
|
||||
_PyStack_UnpackDict(PyThreadState *tstate,
|
||||
PyObject *const *args, Py_ssize_t nargs,
|
||||
PyObject *kwargs, PyObject **p_kwnames);
|
||||
|
||||
static void
|
||||
_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs,
|
||||
|
@ -25,20 +27,19 @@ null_error(void)
|
|||
|
||||
|
||||
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));
|
||||
|
||||
if (result == NULL) {
|
||||
if (!err_occurred) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
if (callable)
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
_PyErr_Format(tstate, PyExc_SystemError,
|
||||
"%R returned NULL without setting an error",
|
||||
callable);
|
||||
else
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
_PyErr_Format(tstate, PyExc_SystemError,
|
||||
"%s returned NULL without setting an error",
|
||||
where);
|
||||
#ifdef Py_DEBUG
|
||||
|
@ -49,18 +50,18 @@ _Py_CheckFunctionResult(PyObject *callable, PyObject *result, const char *where)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (err_occurred) {
|
||||
if (_PyErr_Occurred(tstate)) {
|
||||
Py_DECREF(result);
|
||||
|
||||
if (callable) {
|
||||
_PyErr_FormatFromCause(PyExc_SystemError,
|
||||
"%R returned a result with an error set",
|
||||
callable);
|
||||
_PyErr_FormatFromCauseTstate(
|
||||
tstate, PyExc_SystemError,
|
||||
"%R returned a result with an error set", callable);
|
||||
}
|
||||
else {
|
||||
_PyErr_FormatFromCause(PyExc_SystemError,
|
||||
"%s returned a result with an error set",
|
||||
where);
|
||||
_PyErr_FormatFromCauseTstate(
|
||||
tstate, PyExc_SystemError,
|
||||
"%s returned a result with an error set", where);
|
||||
}
|
||||
#ifdef Py_DEBUG
|
||||
/* Ensure that the bug is caught in debug mode */
|
||||
|
@ -87,11 +88,13 @@ PyObject *
|
|||
_PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwargs)
|
||||
{
|
||||
assert(callable != NULL);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
/* _PyObject_FastCallDict() must not be called with an exception set,
|
||||
because it can clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
assert(callable != NULL);
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
assert(nargs >= 0);
|
||||
|
@ -101,7 +104,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
|
|||
vectorcallfunc func = _PyVectorcall_Function(callable);
|
||||
if (func == NULL) {
|
||||
/* Use tp_call instead */
|
||||
return _PyObject_MakeTpCall(callable, args, nargs, kwargs);
|
||||
return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs);
|
||||
}
|
||||
|
||||
PyObject *res;
|
||||
|
@ -111,7 +114,9 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
|
|||
else {
|
||||
PyObject *kwnames;
|
||||
PyObject *const *newargs;
|
||||
newargs = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames);
|
||||
newargs = _PyStack_UnpackDict(tstate,
|
||||
args, nargs,
|
||||
kwargs, &kwnames);
|
||||
if (newargs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -119,18 +124,21 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
|
|||
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
|
||||
_PyStack_UnpackDict_Free(newargs, nargs, kwnames);
|
||||
}
|
||||
return _Py_CheckFunctionResult(callable, res, NULL);
|
||||
return _Py_CheckFunctionResult(tstate, callable, res, NULL);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
* temporary dictionary for keyword arguments (if any) */
|
||||
ternaryfunc call = Py_TYPE(callable)->tp_call;
|
||||
if (call == NULL) {
|
||||
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object is not callable",
|
||||
Py_TYPE(callable)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -162,10 +170,10 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
|
|||
}
|
||||
|
||||
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);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
}
|
||||
|
||||
Py_DECREF(argstuple);
|
||||
|
@ -173,7 +181,7 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
|
|||
Py_DECREF(kwdict);
|
||||
}
|
||||
|
||||
result = _Py_CheckFunctionResult(callable, result, NULL);
|
||||
result = _Py_CheckFunctionResult(tstate, callable, result, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -181,17 +189,21 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
|
|||
PyObject *
|
||||
PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
|
||||
/* get vectorcallfunc as in _PyVectorcall_Function, but without
|
||||
* the _Py_TPFLAGS_HAVE_VECTORCALL check */
|
||||
Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset;
|
||||
if (offset <= 0) {
|
||||
PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall",
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support vectorcall",
|
||||
Py_TYPE(callable)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
vectorcallfunc func = *(vectorcallfunc *)(((char *)callable) + offset);
|
||||
if (func == NULL) {
|
||||
PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall",
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support vectorcall",
|
||||
Py_TYPE(callable)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -206,27 +218,30 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
|
|||
/* Convert arguments & call */
|
||||
PyObject *const *args;
|
||||
PyObject *kwnames;
|
||||
args = _PyStack_UnpackDict(_PyTuple_ITEMS(tuple), nargs, kwargs, &kwnames);
|
||||
args = _PyStack_UnpackDict(tstate,
|
||||
_PyTuple_ITEMS(tuple), nargs,
|
||||
kwargs, &kwnames);
|
||||
if (args == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = func(callable, args,
|
||||
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
|
||||
_PyStack_UnpackDict_Free(args, nargs, kwnames);
|
||||
return _Py_CheckFunctionResult(callable, result, NULL);
|
||||
return _Py_CheckFunctionResult(tstate, callable, result, NULL);
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
ternaryfunc call;
|
||||
PyObject *result;
|
||||
|
||||
/* PyObject_Call() must not be called with an exception set,
|
||||
because it can clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(PyTuple_Check(args));
|
||||
assert(kwargs == NULL || PyDict_Check(kwargs));
|
||||
|
||||
|
@ -236,19 +251,21 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
|
|||
else {
|
||||
call = callable->ob_type->tp_call;
|
||||
if (call == NULL) {
|
||||
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object is not callable",
|
||||
callable->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Py_EnterRecursiveCall(" while calling a Python object"))
|
||||
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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,
|
||||
PyObject *globals)
|
||||
{
|
||||
PyFrameObject *f;
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject **fastlocals;
|
||||
Py_ssize_t i;
|
||||
PyObject *result;
|
||||
|
||||
assert(globals != NULL);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
assert(tstate != NULL);
|
||||
|
||||
/* XXX Perhaps we should create a specialized
|
||||
_PyFrame_New_NoTrack() that doesn't take locals, but does
|
||||
take builtins without sanity checking them.
|
||||
*/
|
||||
assert(tstate != NULL);
|
||||
f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
|
||||
PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
|
||||
if (f == 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);
|
||||
fastlocals[i] = *args++;
|
||||
}
|
||||
result = PyEval_EvalFrameEx(f,0);
|
||||
PyObject *result = PyEval_EvalFrameEx(f, 0);
|
||||
|
||||
if (Py_REFCNT(f) > 1) {
|
||||
Py_DECREF(f);
|
||||
|
@ -760,6 +774,7 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
|
|||
assert(args != NULL);
|
||||
assert(PyVectorcall_NARGS(nargsf) >= 1);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject *callable = NULL;
|
||||
/* Use args[0] as "self" argument */
|
||||
int unbound = _PyObject_GetMethod(args[0], name, &callable);
|
||||
|
@ -778,7 +793,8 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
|
|||
args++;
|
||||
nargsf--;
|
||||
}
|
||||
PyObject *result = _PyObject_Vectorcall(callable, args, nargsf, kwnames);
|
||||
PyObject *result = _PyObject_VectorcallTstate(tstate, callable,
|
||||
args, nargsf, kwnames);
|
||||
Py_DECREF(callable);
|
||||
return result;
|
||||
}
|
||||
|
@ -894,8 +910,9 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames)
|
|||
|
||||
When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */
|
||||
static PyObject *const *
|
||||
_PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
|
||||
PyObject **p_kwnames)
|
||||
_PyStack_UnpackDict(PyThreadState *tstate,
|
||||
PyObject *const *args, Py_ssize_t nargs,
|
||||
PyObject *kwargs, PyObject **p_kwnames)
|
||||
{
|
||||
assert(nargs >= 0);
|
||||
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. */
|
||||
Py_ssize_t maxnargs = PY_SSIZE_T_MAX / sizeof(args[0]) - 1;
|
||||
if (nargs > maxnargs - nkwargs) {
|
||||
PyErr_NoMemory();
|
||||
_PyErr_NoMemory(tstate);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add 1 to support PY_VECTORCALL_ARGUMENTS_OFFSET */
|
||||
PyObject **stack = PyMem_Malloc((1 + nargs + nkwargs) * sizeof(args[0]));
|
||||
if (stack == NULL) {
|
||||
PyErr_NoMemory();
|
||||
_PyErr_NoMemory(tstate);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -954,7 +971,7 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
|
|||
* because it simplifies the deallocation in the failing case.
|
||||
* It happens to also make the loop above slightly more efficient. */
|
||||
if (!keys_are_strings) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"keywords must be strings");
|
||||
_PyStack_UnpackDict_Free(stack, nargs, kwnames);
|
||||
return NULL;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "Python.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pymem.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "structmember.h"
|
||||
|
@ -37,25 +38,28 @@ method_vectorcall(PyObject *method, PyObject *const *args,
|
|||
size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
assert(Py_TYPE(method) == &PyMethod_Type);
|
||||
PyObject *self, *func, *result;
|
||||
self = PyMethod_GET_SELF(method);
|
||||
func = PyMethod_GET_FUNCTION(method);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject *self = PyMethod_GET_SELF(method);
|
||||
PyObject *func = PyMethod_GET_FUNCTION(method);
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
|
||||
PyObject *result;
|
||||
if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
|
||||
/* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
|
||||
PyObject **newargs = (PyObject**)args - 1;
|
||||
nargs += 1;
|
||||
PyObject *tmp = newargs[0];
|
||||
newargs[0] = self;
|
||||
result = _PyObject_Vectorcall(func, newargs, nargs, kwnames);
|
||||
result = _PyObject_VectorcallTstate(tstate, func, newargs,
|
||||
nargs, kwnames);
|
||||
newargs[0] = tmp;
|
||||
}
|
||||
else {
|
||||
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
|
||||
Py_ssize_t totalargs = nargs + nkwargs;
|
||||
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];
|
||||
|
@ -66,7 +70,7 @@ method_vectorcall(PyObject *method, PyObject *const *args,
|
|||
else {
|
||||
newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
|
||||
if (newargs == NULL) {
|
||||
PyErr_NoMemory();
|
||||
_PyErr_NoMemory(tstate);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +81,8 @@ method_vectorcall(PyObject *method, PyObject *const *args,
|
|||
* undefined behaviour. */
|
||||
assert(args != NULL);
|
||||
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) {
|
||||
PyMem_Free(newargs);
|
||||
}
|
||||
|
|
|
@ -231,49 +231,42 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
|
|||
*
|
||||
* 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
|
||||
method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
assert(!PyErr_Occurred());
|
||||
assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
|
||||
if (nargs < 1) {
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"descriptor '%.200s' of '%.100s' "
|
||||
"object needs an argument",
|
||||
get_name(func), PyDescr_TYPE(func)->tp_name);
|
||||
"unbound method %U needs an argument", funcstr);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
PyObject *self = args[0];
|
||||
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
|
||||
(PyObject *)PyDescr_TYPE(func)))
|
||||
{
|
||||
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);
|
||||
PyObject *dummy;
|
||||
if (descr_check((PyDescrObject *)func, self, &dummy)) {
|
||||
return -1;
|
||||
}
|
||||
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes no keyword arguments", get_name(func));
|
||||
"%U takes no keyword arguments", funcstr);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef void (*funcptr)(void);
|
||||
|
||||
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 (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
|
||||
|
@ -284,6 +277,7 @@ static PyObject *
|
|||
method_vectorcall_VARARGS(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (method_check_args(func, args, nargs, kwnames)) {
|
||||
return NULL;
|
||||
|
@ -292,14 +286,14 @@ method_vectorcall_VARARGS(
|
|||
if (argstuple == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyCFunction meth = (PyCFunction)method_enter_call(func);
|
||||
PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
Py_DECREF(argstuple);
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(args[0], argstuple);
|
||||
Py_DECREF(argstuple);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -307,6 +301,7 @@ static PyObject *
|
|||
method_vectorcall_VARARGS_KEYWORDS(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (method_check_args(func, args, nargs, NULL)) {
|
||||
return NULL;
|
||||
|
@ -325,12 +320,12 @@ method_vectorcall_VARARGS_KEYWORDS(
|
|||
}
|
||||
}
|
||||
PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
|
||||
method_enter_call(func);
|
||||
method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
result = meth(args[0], argstuple, kwdict);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
exit:
|
||||
Py_DECREF(argstuple);
|
||||
Py_XDECREF(kwdict);
|
||||
|
@ -341,17 +336,18 @@ static PyObject *
|
|||
method_vectorcall_FASTCALL(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (method_check_args(func, args, nargs, kwnames)) {
|
||||
return NULL;
|
||||
}
|
||||
_PyCFunctionFast meth = (_PyCFunctionFast)
|
||||
method_enter_call(func);
|
||||
method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(args[0], args+1, nargs-1);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -359,17 +355,18 @@ static PyObject *
|
|||
method_vectorcall_FASTCALL_KEYWORDS(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (method_check_args(func, args, nargs, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
||||
method_enter_call(func);
|
||||
method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -377,21 +374,26 @@ static PyObject *
|
|||
method_vectorcall_NOARGS(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (method_check_args(func, args, nargs, kwnames)) {
|
||||
return NULL;
|
||||
}
|
||||
if (nargs != 1) {
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes no arguments (%zd given)", get_name(func), nargs-1);
|
||||
"%U takes no arguments (%zd given)", funcstr, nargs-1);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
PyCFunction meth = (PyCFunction)method_enter_call(func);
|
||||
PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(args[0], NULL);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -399,22 +401,27 @@ static PyObject *
|
|||
method_vectorcall_O(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (method_check_args(func, args, nargs, kwnames)) {
|
||||
return NULL;
|
||||
}
|
||||
if (nargs != 2) {
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes exactly one argument (%zd given)",
|
||||
get_name(func), nargs-1);
|
||||
"%U takes exactly one argument (%zd given)",
|
||||
funcstr, nargs-1);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
PyCFunction meth = (PyCFunction)method_enter_call(func);
|
||||
PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(args[0], args[1]);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -4162,17 +4162,34 @@ static PySequenceMethods dictkeys_as_sequence = {
|
|||
(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*
|
||||
dictviews_sub(PyObject* self, PyObject *other)
|
||||
dictviews_to_set(PyObject *self)
|
||||
{
|
||||
PyObject *result = PySet_New(self);
|
||||
PyObject *tmp;
|
||||
_Py_IDENTIFIER(difference_update);
|
||||
PyObject *left = self;
|
||||
if (PyDictKeys_Check(self)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_difference_update, other);
|
||||
_Py_IDENTIFIER(difference_update);
|
||||
PyObject *tmp = _PyObject_CallMethodIdOneArg(
|
||||
result, &PyId_difference_update, other);
|
||||
if (tmp == NULL) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
|
@ -4273,34 +4290,29 @@ error:
|
|||
static PyObject*
|
||||
dictviews_or(PyObject* self, PyObject *other)
|
||||
{
|
||||
PyObject *result = PySet_New(self);
|
||||
PyObject *tmp;
|
||||
_Py_IDENTIFIER(update);
|
||||
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
tmp = _PyObject_CallMethodIdOneArg(result, &PyId_update, other);
|
||||
if (tmp == NULL) {
|
||||
Py_DECREF(result);
|
||||
PyObject *result = dictviews_to_set(self);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_DECREF(tmp);
|
||||
if (_PySet_Update(result, other) < 0) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
dictviews_xor(PyObject* self, PyObject *other)
|
||||
{
|
||||
PyObject *result = PySet_New(self);
|
||||
PyObject *tmp;
|
||||
_Py_IDENTIFIER(symmetric_difference_update);
|
||||
|
||||
if (result == NULL)
|
||||
PyObject *result = dictviews_to_set(self);
|
||||
if (result == 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) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "Python.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pymem.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "structmember.h"
|
||||
|
@ -333,33 +334,30 @@ _PyCFunction_Fini(void)
|
|||
*
|
||||
* 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
|
||||
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));
|
||||
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes no keyword arguments", get_name(func));
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%U takes no keyword arguments", funcstr);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef void (*funcptr)(void);
|
||||
|
||||
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 (funcptr)PyCFunction_GET_FUNCTION(func);
|
||||
|
@ -370,17 +368,18 @@ static PyObject *
|
|||
cfunction_vectorcall_FASTCALL(
|
||||
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;
|
||||
}
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
_PyCFunctionFast meth = (_PyCFunctionFast)
|
||||
cfunction_enter_call(func);
|
||||
cfunction_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -388,14 +387,15 @@ static PyObject *
|
|||
cfunction_vectorcall_FASTCALL_KEYWORDS(
|
||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
||||
cfunction_enter_call(func);
|
||||
cfunction_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -403,21 +403,26 @@ static PyObject *
|
|||
cfunction_vectorcall_NOARGS(
|
||||
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;
|
||||
}
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (nargs != 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes no arguments (%zd given)", get_name(func), nargs);
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%U takes no arguments (%zd given)", funcstr, nargs);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
PyCFunction meth = (PyCFunction)cfunction_enter_call(func);
|
||||
PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(PyCFunction_GET_SELF(func), NULL);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -425,22 +430,26 @@ static PyObject *
|
|||
cfunction_vectorcall_O(
|
||||
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;
|
||||
}
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
if (nargs != 1) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes exactly one argument (%zd given)",
|
||||
get_name(func), nargs);
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%U takes exactly one argument (%zd given)", funcstr, nargs);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
PyCFunction meth = (PyCFunction)cfunction_enter_call(func);
|
||||
PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -448,9 +457,11 @@ cfunction_vectorcall_O(
|
|||
static PyObject *
|
||||
cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
assert(!PyErr_Occurred());
|
||||
assert(kwargs == NULL || PyDict_Check(kwargs));
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
|
||||
int flags = PyCFunction_GET_FLAGS(func);
|
||||
if (!(flags & METH_VARARGS)) {
|
||||
/* If this is not a METH_VARARGS function, delegate to vectorcall */
|
||||
|
@ -468,11 +479,12 @@ cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
|
|||
}
|
||||
else {
|
||||
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%.200s() takes no keyword arguments",
|
||||
((PyCFunctionObject*)func)->m_ml->ml_name);
|
||||
return NULL;
|
||||
}
|
||||
result = meth(self, args);
|
||||
}
|
||||
return _Py_CheckFunctionResult(func, result, NULL);
|
||||
return _Py_CheckFunctionResult(tstate, func, result, NULL);
|
||||
}
|
||||
|
|
112
Objects/object.c
112
Objects/object.c
|
@ -2,10 +2,11 @@
|
|||
/* Generic object operations; and implementation of None */
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_context.h"
|
||||
#include "pycore_initconfig.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "pycore_context.h"
|
||||
#include "frameobject.h"
|
||||
#include "interpreteridobject.h"
|
||||
|
||||
|
@ -525,31 +526,37 @@ PyObject_Repr(PyObject *v)
|
|||
return PyUnicode_FromFormat("<%s object at %p>",
|
||||
v->ob_type->tp_name, v);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
#ifdef Py_DEBUG
|
||||
/* PyObject_Repr() must not be called with an exception set,
|
||||
because it can clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
#endif
|
||||
|
||||
/* It is possible for a type to have a tp_repr representation that loops
|
||||
infinitely. */
|
||||
if (Py_EnterRecursiveCall(" while getting the repr of an object"))
|
||||
if (_Py_EnterRecursiveCall(tstate,
|
||||
" while getting the repr of an object")) {
|
||||
return NULL;
|
||||
}
|
||||
res = (*v->ob_type->tp_repr)(v);
|
||||
Py_LeaveRecursiveCall();
|
||||
if (res == NULL)
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyUnicode_Check(res)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"__repr__ returned non-string (type %.200s)",
|
||||
res->ob_type->tp_name);
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
#ifndef Py_DEBUG
|
||||
if (PyUnicode_READY(res) < 0)
|
||||
if (PyUnicode_READY(res) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
@ -579,31 +586,36 @@ PyObject_Str(PyObject *v)
|
|||
if (Py_TYPE(v)->tp_str == NULL)
|
||||
return PyObject_Repr(v);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
#ifdef Py_DEBUG
|
||||
/* PyObject_Str() must not be called with an exception set,
|
||||
because it can clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
#endif
|
||||
|
||||
/* It is possible for a type to have a tp_str representation that loops
|
||||
infinitely. */
|
||||
if (Py_EnterRecursiveCall(" while getting the str of an object"))
|
||||
if (_Py_EnterRecursiveCall(tstate, " while getting the str of an object")) {
|
||||
return NULL;
|
||||
}
|
||||
res = (*Py_TYPE(v)->tp_str)(v);
|
||||
Py_LeaveRecursiveCall();
|
||||
if (res == NULL)
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyUnicode_Check(res)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"__str__ returned non-string (type %.200s)",
|
||||
Py_TYPE(res)->tp_name);
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
#ifndef Py_DEBUG
|
||||
if (PyUnicode_READY(res) < 0)
|
||||
if (PyUnicode_READY(res) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
assert(_PyUnicode_CheckConsistency(res, 1));
|
||||
return res;
|
||||
|
@ -669,6 +681,64 @@ PyObject_Bytes(PyObject *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
|
||||
completely removed in favour of rich comparisons. PyObject_Compare() and
|
||||
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
|
||||
operator is not supported. */
|
||||
static PyObject *
|
||||
do_richcompare(PyObject *v, PyObject *w, int op)
|
||||
do_richcompare(PyThreadState *tstate, PyObject *v, PyObject *w, int op)
|
||||
{
|
||||
richcmpfunc f;
|
||||
PyObject *res;
|
||||
|
@ -744,7 +814,7 @@ do_richcompare(PyObject *v, PyObject *w, int op)
|
|||
res = (v != w) ? Py_True : Py_False;
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%s' not supported between instances of '%.100s' and '%.100s'",
|
||||
opstrings[op],
|
||||
v->ob_type->tp_name,
|
||||
|
@ -761,18 +831,20 @@ do_richcompare(PyObject *v, PyObject *w, int op)
|
|||
PyObject *
|
||||
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
|
||||
{
|
||||
PyObject *res;
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
|
||||
assert(Py_LT <= op && op <= Py_GE);
|
||||
if (v == NULL || w == NULL) {
|
||||
if (!PyErr_Occurred())
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
PyErr_BadInternalCall();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (Py_EnterRecursiveCall(" in comparison"))
|
||||
if (_Py_EnterRecursiveCall(tstate, " in comparison")) {
|
||||
return NULL;
|
||||
res = do_richcompare(v, w, op);
|
||||
Py_LeaveRecursiveCall();
|
||||
}
|
||||
PyObject *res = do_richcompare(tstate, v, w, op);
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -2313,12 +2313,13 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
|||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
_PyMem_DebugCheckGIL(void)
|
||||
{
|
||||
if (!PyGILState_Check())
|
||||
if (!PyGILState_Check()) {
|
||||
Py_FatalError("Python memory allocator called "
|
||||
"without holding the GIL");
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "Python.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "frameobject.h"
|
||||
#include "structmember.h"
|
||||
|
@ -952,10 +953,10 @@ type_repr(PyTypeObject *type)
|
|||
static PyObject *
|
||||
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *obj;
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
|
||||
if (type->tp_new == NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"cannot create '%.100s' instances",
|
||||
type->tp_name);
|
||||
return NULL;
|
||||
|
@ -965,11 +966,11 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
/* type_call() must not be called with an exception set,
|
||||
because it can clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
#endif
|
||||
|
||||
obj = type->tp_new(type, args, kwds);
|
||||
obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
|
||||
PyObject *obj = type->tp_new(type, args, kwds);
|
||||
obj = _Py_CheckFunctionResult(tstate, (PyObject*)type, obj, NULL);
|
||||
if (obj == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -990,12 +991,12 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
if (type->tp_init != NULL) {
|
||||
int res = type->tp_init(obj, args, kwds);
|
||||
if (res < 0) {
|
||||
assert(PyErr_Occurred());
|
||||
assert(_PyErr_Occurred(tstate));
|
||||
Py_DECREF(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
else {
|
||||
assert(!PyErr_Occurred());
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
@ -1444,7 +1445,7 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
|
|||
|
||||
|
||||
static inline PyObject*
|
||||
vectorcall_unbound(int unbound, PyObject *func,
|
||||
vectorcall_unbound(PyThreadState *tstate, int unbound, PyObject *func,
|
||||
PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
size_t nargsf = nargs;
|
||||
|
@ -1454,7 +1455,7 @@ vectorcall_unbound(int unbound, PyObject *func,
|
|||
args++;
|
||||
nargsf = nargsf - 1 + PY_VECTORCALL_ARGUMENTS_OFFSET;
|
||||
}
|
||||
return _PyObject_Vectorcall(func, args, nargsf, NULL);
|
||||
return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
@ -1478,13 +1479,15 @@ vectorcall_method(_Py_Identifier *name,
|
|||
PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
assert(nargs >= 1);
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
int unbound;
|
||||
PyObject *self = args[0];
|
||||
PyObject *func = lookup_method(self, name, &unbound);
|
||||
if (func == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *retval = vectorcall_unbound(unbound, func, args, nargs);
|
||||
PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);
|
||||
Py_DECREF(func);
|
||||
return retval;
|
||||
}
|
||||
|
@ -1492,10 +1495,11 @@ vectorcall_method(_Py_Identifier *name,
|
|||
/* Clone of vectorcall_method() that returns NotImplemented
|
||||
* when the lookup fails. */
|
||||
static PyObject *
|
||||
vectorcall_maybe(_Py_Identifier *name,
|
||||
vectorcall_maybe(PyThreadState *tstate, _Py_Identifier *name,
|
||||
PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
assert(nargs >= 1);
|
||||
|
||||
int unbound;
|
||||
PyObject *self = args[0];
|
||||
PyObject *func = lookup_maybe_method(self, name, &unbound);
|
||||
|
@ -1504,7 +1508,7 @@ vectorcall_maybe(_Py_Identifier *name,
|
|||
Py_RETURN_NOTIMPLEMENTED;
|
||||
return NULL;
|
||||
}
|
||||
PyObject *retval = vectorcall_unbound(unbound, func, args, nargs);
|
||||
PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);
|
||||
Py_DECREF(func);
|
||||
return retval;
|
||||
}
|
||||
|
@ -6176,6 +6180,7 @@ static PyObject * \
|
|||
FUNCNAME(PyObject *self, PyObject *other) \
|
||||
{ \
|
||||
PyObject* stack[2]; \
|
||||
PyThreadState *tstate = _PyThreadState_GET(); \
|
||||
_Py_static_string(op_id, OPSTR); \
|
||||
_Py_static_string(rop_id, ROPSTR); \
|
||||
int do_other = Py_TYPE(self) != Py_TYPE(other) && \
|
||||
|
@ -6192,7 +6197,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
|
|||
if (ok) { \
|
||||
stack[0] = other; \
|
||||
stack[1] = self; \
|
||||
r = vectorcall_maybe(&rop_id, stack, 2); \
|
||||
r = vectorcall_maybe(tstate, &rop_id, stack, 2); \
|
||||
if (r != Py_NotImplemented) \
|
||||
return r; \
|
||||
Py_DECREF(r); \
|
||||
|
@ -6201,7 +6206,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
|
|||
} \
|
||||
stack[0] = self; \
|
||||
stack[1] = other; \
|
||||
r = vectorcall_maybe(&op_id, stack, 2); \
|
||||
r = vectorcall_maybe(tstate, &op_id, stack, 2); \
|
||||
if (r != Py_NotImplemented || \
|
||||
Py_TYPE(other) == Py_TYPE(self)) \
|
||||
return r; \
|
||||
|
@ -6210,7 +6215,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
|
|||
if (do_other) { \
|
||||
stack[0] = other; \
|
||||
stack[1] = self; \
|
||||
return vectorcall_maybe(&rop_id, stack, 2); \
|
||||
return vectorcall_maybe(tstate, &rop_id, stack, 2); \
|
||||
} \
|
||||
Py_RETURN_NOTIMPLEMENTED; \
|
||||
}
|
||||
|
@ -6292,6 +6297,7 @@ slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)
|
|||
static int
|
||||
slot_sq_contains(PyObject *self, PyObject *value)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject *func, *res;
|
||||
int result = -1, unbound;
|
||||
_Py_IDENTIFIER(__contains__);
|
||||
|
@ -6306,7 +6312,7 @@ slot_sq_contains(PyObject *self, PyObject *value)
|
|||
}
|
||||
if (func != NULL) {
|
||||
PyObject *args[2] = {self, value};
|
||||
res = vectorcall_unbound(unbound, func, args, 2);
|
||||
res = vectorcall_unbound(tstate, unbound, func, args, 2);
|
||||
Py_DECREF(func);
|
||||
if (res != NULL) {
|
||||
result = PyObject_IsTrue(res);
|
||||
|
@ -6681,6 +6687,7 @@ static _Py_Identifier name_op[] = {
|
|||
static PyObject *
|
||||
slot_tp_richcompare(PyObject *self, PyObject *other, int op)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
int unbound;
|
||||
PyObject *func, *res;
|
||||
|
||||
|
@ -6691,7 +6698,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op)
|
|||
}
|
||||
|
||||
PyObject *stack[2] = {self, other};
|
||||
res = vectorcall_unbound(unbound, func, stack, 2);
|
||||
res = vectorcall_unbound(tstate, unbound, func, stack, 2);
|
||||
Py_DECREF(func);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@
|
|||
<ClInclude Include="..\Include\complexobject.h" />
|
||||
<ClInclude Include="..\Include\context.h" />
|
||||
<ClInclude Include="..\Include\cpython\abstract.h" />
|
||||
<ClInclude Include="..\Include\cpython\ceval.h" />
|
||||
<ClInclude Include="..\Include\cpython\dictobject.h" />
|
||||
<ClInclude Include="..\Include\cpython\fileobject.h" />
|
||||
<ClInclude Include="..\Include\cpython\import.h" />
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
<ClInclude Include="..\Include\cpython\abstract.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\cpython\ceval.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\cpython\dictobject.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/* List a node on a file */
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "token.h"
|
||||
#include "node.h"
|
||||
|
||||
|
@ -15,19 +16,21 @@ PyNode_ListTree(node *n)
|
|||
listnode(stdout, n);
|
||||
}
|
||||
|
||||
static int level, atbol;
|
||||
|
||||
static void
|
||||
listnode(FILE *fp, node *n)
|
||||
{
|
||||
level = 0;
|
||||
atbol = 1;
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
|
||||
|
||||
interp->parser.listnode.level = 0;
|
||||
interp->parser.listnode.atbol = 1;
|
||||
list1node(fp, n);
|
||||
}
|
||||
|
||||
static void
|
||||
list1node(FILE *fp, node *n)
|
||||
{
|
||||
PyInterpreterState *interp;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
if (ISNONTERMINAL(TYPE(n))) {
|
||||
|
@ -36,25 +39,26 @@ list1node(FILE *fp, node *n)
|
|||
list1node(fp, CHILD(n, i));
|
||||
}
|
||||
else if (ISTERMINAL(TYPE(n))) {
|
||||
interp = _PyInterpreterState_GET_UNSAFE();
|
||||
switch (TYPE(n)) {
|
||||
case INDENT:
|
||||
++level;
|
||||
interp->parser.listnode.level++;
|
||||
break;
|
||||
case DEDENT:
|
||||
--level;
|
||||
interp->parser.listnode.level--;
|
||||
break;
|
||||
default:
|
||||
if (atbol) {
|
||||
if (interp->parser.listnode.atbol) {
|
||||
int i;
|
||||
for (i = 0; i < level; ++i)
|
||||
for (i = 0; i < interp->parser.listnode.level; ++i)
|
||||
fprintf(fp, "\t");
|
||||
atbol = 0;
|
||||
interp->parser.listnode.atbol = 0;
|
||||
}
|
||||
if (TYPE(n) == NEWLINE) {
|
||||
if (STR(n) != NULL)
|
||||
fprintf(fp, "%s", STR(n));
|
||||
fprintf(fp, "\n");
|
||||
atbol = 1;
|
||||
interp->parser.listnode.atbol = 1;
|
||||
}
|
||||
else
|
||||
fprintf(fp, "%s ", STR(n));
|
||||
|
|
|
@ -659,16 +659,15 @@ Py_SetRecursionLimit(int new_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 USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit
|
||||
to guarantee that _Py_CheckRecursiveCall() is regularly called.
|
||||
Without USE_STACKCHECK, there is no need for this. */
|
||||
int
|
||||
_Py_CheckRecursiveCall(const char *where)
|
||||
_Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
|
||||
{
|
||||
_PyRuntimeState *runtime = &_PyRuntime;
|
||||
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
|
||||
int recursion_limit = runtime->ceval.recursion_limit;
|
||||
|
||||
#ifdef USE_STACKCHECK
|
||||
|
@ -1073,8 +1072,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
|||
/* Start of code */
|
||||
|
||||
/* push frame */
|
||||
if (Py_EnterRecursiveCall(""))
|
||||
if (_Py_EnterRecursiveCall(tstate, "")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tstate->frame = f;
|
||||
|
||||
|
@ -3810,11 +3810,11 @@ exit_yielding:
|
|||
exit_eval_frame:
|
||||
if (PyDTrace_FUNCTION_RETURN_ENABLED())
|
||||
dtrace_function_return(f);
|
||||
Py_LeaveRecursiveCall();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
f->f_executing = 0;
|
||||
tstate->frame = f->f_back;
|
||||
|
||||
return _Py_CheckFunctionResult(NULL, retval, "PyEval_EvalFrameEx");
|
||||
return _Py_CheckFunctionResult(tstate, NULL, retval, "PyEval_EvalFrameEx");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -5351,12 +5351,17 @@ static int
|
|||
check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)
|
||||
{
|
||||
if (args->ob_type->tp_iter == NULL && !PySequence_Check(args)) {
|
||||
/* check_args_iterable() may be called with a live exception:
|
||||
* clear it to prevent calling _PyObject_FunctionStr() with an
|
||||
* exception set. */
|
||||
PyErr_Clear();
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%.200s%.200s argument after * "
|
||||
"must be an iterable, not %.200s",
|
||||
PyEval_GetFuncName(func),
|
||||
PyEval_GetFuncDesc(func),
|
||||
args->ob_type->tp_name);
|
||||
"%U argument after * must be an iterable, not %.200s",
|
||||
funcstr, Py_TYPE(args)->tp_name);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -5372,24 +5377,30 @@ format_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs)
|
|||
* is not a mapping.
|
||||
*/
|
||||
if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%.200s%.200s argument after ** "
|
||||
"must be a mapping, not %.200s",
|
||||
PyEval_GetFuncName(func),
|
||||
PyEval_GetFuncDesc(func),
|
||||
kwargs->ob_type->tp_name);
|
||||
PyErr_Clear();
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
_PyErr_Format(
|
||||
tstate, PyExc_TypeError,
|
||||
"%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)) {
|
||||
PyObject *exc, *val, *tb;
|
||||
_PyErr_Fetch(tstate, &exc, &val, &tb);
|
||||
if (val && PyTuple_Check(val) && PyTuple_GET_SIZE(val) == 1) {
|
||||
PyErr_Clear();
|
||||
PyObject *funcstr = _PyObject_FunctionStr(func);
|
||||
if (funcstr != NULL) {
|
||||
PyObject *key = PyTuple_GET_ITEM(val, 0);
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"%.200s%.200s got multiple "
|
||||
"values for keyword argument '%S'",
|
||||
PyEval_GetFuncName(func),
|
||||
PyEval_GetFuncDesc(func),
|
||||
key);
|
||||
_PyErr_Format(
|
||||
tstate, PyExc_TypeError,
|
||||
"%U got multiple values for keyword argument '%S'",
|
||||
funcstr, key);
|
||||
Py_DECREF(funcstr);
|
||||
}
|
||||
Py_XDECREF(exc);
|
||||
Py_XDECREF(val);
|
||||
Py_XDECREF(tb);
|
||||
|
@ -5632,3 +5643,21 @@ maybe_dtrace_line(PyFrameObject *frame,
|
|||
}
|
||||
*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_hamt.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_pystate.h"
|
||||
#include "structmember.h"
|
||||
|
||||
|
@ -101,21 +102,18 @@ PyContext_CopyCurrent(void)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
PyContext_Enter(PyObject *octx)
|
||||
static int
|
||||
_PyContext_Enter(PyThreadState *ts, PyObject *octx)
|
||||
{
|
||||
ENSURE_Context(octx, -1)
|
||||
PyContext *ctx = (PyContext *)octx;
|
||||
|
||||
if (ctx->ctx_entered) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
_PyErr_Format(ts, PyExc_RuntimeError,
|
||||
"cannot enter context: %R is already entered", ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyThreadState *ts = _PyThreadState_GET();
|
||||
assert(ts != NULL);
|
||||
|
||||
ctx->ctx_prev = (PyContext *)ts->context; /* borrow */
|
||||
ctx->ctx_entered = 1;
|
||||
|
||||
|
@ -128,7 +126,16 @@ PyContext_Enter(PyObject *octx)
|
|||
|
||||
|
||||
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)
|
||||
PyContext *ctx = (PyContext *)octx;
|
||||
|
@ -139,9 +146,6 @@ PyContext_Exit(PyObject *octx)
|
|||
return -1;
|
||||
}
|
||||
|
||||
PyThreadState *ts = _PyThreadState_GET();
|
||||
assert(ts != NULL);
|
||||
|
||||
if (ts->context != (PyObject *)ctx) {
|
||||
/* Can only happen if someone misuses the C API */
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
|
@ -159,6 +163,14 @@ PyContext_Exit(PyObject *octx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyContext_Exit(PyObject *octx)
|
||||
{
|
||||
PyThreadState *ts = _PyThreadState_GET();
|
||||
assert(ts != NULL);
|
||||
return _PyContext_Exit(ts, octx);
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
PyContextVar_New(const char *name, PyObject *def)
|
||||
|
@ -621,20 +633,22 @@ static PyObject *
|
|||
context_run(PyContext *self, PyObject *const *args,
|
||||
Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyThreadState *ts = _PyThreadState_GET();
|
||||
|
||||
if (nargs < 1) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
_PyErr_SetString(ts, PyExc_TypeError,
|
||||
"run() missing 1 required positional argument");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyContext_Enter((PyObject *)self)) {
|
||||
if (_PyContext_Enter(ts, (PyObject *)self)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *call_result = _PyObject_Vectorcall(
|
||||
args[0], args + 1, nargs - 1, kwnames);
|
||||
PyObject *call_result = _PyObject_VectorcallTstate(
|
||||
ts, args[0], args + 1, nargs - 1, kwnames);
|
||||
|
||||
if (PyContext_Exit((PyObject *)self)) {
|
||||
if (_PyContext_Exit(ts, (PyObject *)self)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,6 +218,9 @@ PyErr_SetString(PyObject *exception, const char *string)
|
|||
PyObject* _Py_HOT_FUNCTION
|
||||
PyErr_Occurred(void)
|
||||
{
|
||||
/* The caller must hold the GIL. */
|
||||
assert(PyGILState_Check());
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
return _PyErr_Occurred(tstate);
|
||||
}
|
||||
|
@ -520,6 +523,21 @@ _PyErr_FormatVFromCause(PyThreadState *tstate, PyObject *exception,
|
|||
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 *
|
||||
_PyErr_FormatFromCause(PyObject *exception, const char *format, ...)
|
||||
{
|
||||
|
|
|
@ -1648,56 +1648,56 @@ PyOS_CheckStack(void)
|
|||
/* Deprecated C API functions still provided for binary compatibility */
|
||||
|
||||
#undef PyParser_SimpleParseFile
|
||||
node *
|
||||
PyAPI_FUNC(node *)
|
||||
PyParser_SimpleParseFile(FILE *fp, const char *filename, int start)
|
||||
{
|
||||
return PyParser_SimpleParseFileFlags(fp, filename, start, 0);
|
||||
}
|
||||
|
||||
#undef PyParser_SimpleParseString
|
||||
node *
|
||||
PyAPI_FUNC(node *)
|
||||
PyParser_SimpleParseString(const char *str, int start)
|
||||
{
|
||||
return PyParser_SimpleParseStringFlags(str, start, 0);
|
||||
}
|
||||
|
||||
#undef PyRun_AnyFile
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_AnyFile(FILE *fp, const char *name)
|
||||
{
|
||||
return PyRun_AnyFileExFlags(fp, name, 0, NULL);
|
||||
}
|
||||
|
||||
#undef PyRun_AnyFileEx
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_AnyFileEx(FILE *fp, const char *name, int closeit)
|
||||
{
|
||||
return PyRun_AnyFileExFlags(fp, name, closeit, NULL);
|
||||
}
|
||||
|
||||
#undef PyRun_AnyFileFlags
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_AnyFileFlags(FILE *fp, const char *name, PyCompilerFlags *flags)
|
||||
{
|
||||
return PyRun_AnyFileExFlags(fp, name, 0, flags);
|
||||
}
|
||||
|
||||
#undef PyRun_File
|
||||
PyObject *
|
||||
PyAPI_FUNC(PyObject *)
|
||||
PyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l)
|
||||
{
|
||||
return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL);
|
||||
}
|
||||
|
||||
#undef PyRun_FileEx
|
||||
PyObject *
|
||||
PyAPI_FUNC(PyObject *)
|
||||
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);
|
||||
}
|
||||
|
||||
#undef PyRun_FileFlags
|
||||
PyObject *
|
||||
PyAPI_FUNC(PyObject *)
|
||||
PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l,
|
||||
PyCompilerFlags *flags)
|
||||
{
|
||||
|
@ -1705,14 +1705,14 @@ PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l,
|
|||
}
|
||||
|
||||
#undef PyRun_SimpleFile
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_SimpleFile(FILE *f, const char *p)
|
||||
{
|
||||
return PyRun_SimpleFileExFlags(f, p, 0, NULL);
|
||||
}
|
||||
|
||||
#undef PyRun_SimpleFileEx
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_SimpleFileEx(FILE *f, const char *p, int c)
|
||||
{
|
||||
return PyRun_SimpleFileExFlags(f, p, c, NULL);
|
||||
|
@ -1720,28 +1720,28 @@ PyRun_SimpleFileEx(FILE *f, const char *p, int c)
|
|||
|
||||
|
||||
#undef PyRun_String
|
||||
PyObject *
|
||||
PyAPI_FUNC(PyObject *)
|
||||
PyRun_String(const char *str, int s, PyObject *g, PyObject *l)
|
||||
{
|
||||
return PyRun_StringFlags(str, s, g, l, NULL);
|
||||
}
|
||||
|
||||
#undef PyRun_SimpleString
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_SimpleString(const char *s)
|
||||
{
|
||||
return PyRun_SimpleStringFlags(s, NULL);
|
||||
}
|
||||
|
||||
#undef Py_CompileString
|
||||
PyObject *
|
||||
PyAPI_FUNC(PyObject *)
|
||||
Py_CompileString(const char *str, const char *p, int s)
|
||||
{
|
||||
return Py_CompileStringExFlags(str, p, s, NULL, -1);
|
||||
}
|
||||
|
||||
#undef Py_CompileStringFlags
|
||||
PyObject *
|
||||
PyAPI_FUNC(PyObject *)
|
||||
Py_CompileStringFlags(const char *str, const char *p, int s,
|
||||
PyCompilerFlags *flags)
|
||||
{
|
||||
|
@ -1749,14 +1749,14 @@ Py_CompileStringFlags(const char *str, const char *p, int s,
|
|||
}
|
||||
|
||||
#undef PyRun_InteractiveOne
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_InteractiveOne(FILE *f, const char *p)
|
||||
{
|
||||
return PyRun_InteractiveOneFlags(f, p, NULL);
|
||||
}
|
||||
|
||||
#undef PyRun_InteractiveLoop
|
||||
int
|
||||
PyAPI_FUNC(int)
|
||||
PyRun_InteractiveLoop(FILE *f, const char *p)
|
||||
{
|
||||
return PyRun_InteractiveLoopFlags(f, p, NULL);
|
||||
|
|
|
@ -782,6 +782,7 @@ infodir
|
|||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
|
@ -895,6 +896,7 @@ datadir='${datarootdir}'
|
|||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
|
@ -1147,6 +1149,15 @@ do
|
|||
| -silent | --silent | --silen | --sile | --sil)
|
||||
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)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
|
@ -1284,7 +1295,7 @@ fi
|
|||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
|
@ -1437,6 +1448,7 @@ Fine tuning of the installation directories:
|
|||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/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 \
|
||||
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 \
|
||||
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 :
|
||||
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"
|
||||
|
|
|
@ -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 \
|
||||
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 \
|
||||
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_MAJOR
|
||||
|
||||
|
|
|
@ -642,6 +642,9 @@
|
|||
/* Define to 1 if you have the <linux/vm_sockets.h> header file. */
|
||||
#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. */
|
||||
#undef HAVE_LOCKF
|
||||
|
||||
|
|
Loading…
Reference in New Issue