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

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

View File

@ -374,6 +374,8 @@ Querying the error indicator
own a reference to the return value, so you do not need to :c:func:`Py_DECREF`
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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -164,7 +164,8 @@ However, for reading convenience, most of the examples show sorted sequences.
The harmonic mean, sometimes called the subcontrary mean, is the
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

View File

@ -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`.

View File

@ -23,7 +23,7 @@ is an installation option, other places are possible; check with your local
Python guru or system administrator. (E.g., :file:`/usr/local/python` is a
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.

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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

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

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

View File

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

View File

@ -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

View File

@ -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);

View File

@ -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):
"""

View File

@ -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):

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -132,21 +132,25 @@ partial_dealloc(partialobject *pto)
* if we would need to do that, we stop using vectorcall and fall back
* 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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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]*/

View File

@ -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, &param))
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(&times_result_desc);
PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_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;
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 *

View File

@ -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;
}

View File

@ -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" />

View File

@ -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>

View File

@ -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));

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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, ...)
{

View File

@ -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);

16
configure vendored
View File

@ -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"

View File

@ -2161,7 +2161,7 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
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

View File

@ -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