Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ Miscellaneous options
.. option:: -R

Turn on hash randomization. This option only has an effect if the
:envvar:`PYTHONHASHSEED` environment variable is set to ``0``, since hash
randomization is enabled by default.
:envvar:`PYTHONHASHSEED` environment variable is set to anything other
than ``random``, since hash randomization is enabled by default.

On previous versions of Python, this option turns on hash randomization,
so that the :meth:`~object.__hash__` values of str and bytes objects
Expand Down
4 changes: 2 additions & 2 deletions Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);
#define PyTrace_OPCODE 7

/* Remote debugger support */
#define Py_MAX_SCRIPT_PATH_SIZE 512
#define _Py_MAX_SCRIPT_PATH_SIZE 512
typedef struct {
int32_t debugger_pending_call;
char debugger_script_path[Py_MAX_SCRIPT_PATH_SIZE];
char debugger_script_path[_Py_MAX_SCRIPT_PATH_SIZE];
} _PyRemoteDebuggerSupport;

typedef struct _err_stackitem {
Expand Down
4 changes: 4 additions & 0 deletions Include/internal/pycore_abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ extern int _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls);
// Export for '_bisect' shared extension.
PyAPI_FUNC(int) _Py_convert_optional_to_ssize_t(PyObject *, void *);

// Convert Python int to Py_ssize_t. Do nothing if the argument is None.
// Raises ValueError if argument is negative.
PyAPI_FUNC(int) _Py_convert_optional_to_non_negative_ssize_t(PyObject *, void *);

// Same as PyNumber_Index() but can return an instance of a subclass of int.
// Export for 'math' shared extension.
PyAPI_FUNC(PyObject*) _PyNumber_Index(PyObject *o);
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_debug_offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ typedef struct _Py_DebugOffsets {
.remote_debugging_enabled = offsetof(PyInterpreterState, config.remote_debug), \
.debugger_pending_call = offsetof(_PyRemoteDebuggerSupport, debugger_pending_call), \
.debugger_script_path = offsetof(_PyRemoteDebuggerSupport, debugger_script_path), \
.debugger_script_path_size = Py_MAX_SCRIPT_PATH_SIZE, \
.debugger_script_path_size = _Py_MAX_SCRIPT_PATH_SIZE, \
}, \
}

Expand Down
70 changes: 64 additions & 6 deletions Lib/test/clinic.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,12 +1612,17 @@ test_Py_ssize_t_converter
a: Py_ssize_t = 12
b: Py_ssize_t(accept={int}) = 34
c: Py_ssize_t(accept={int, NoneType}) = 56
d: Py_ssize_t(accept={int}, allow_negative=False) = 78
e: Py_ssize_t(accept={int, NoneType}, allow_negative=False) = 90
f: Py_ssize_t(accept={int}, allow_negative=True) = -12
g: Py_ssize_t(accept={int, NoneType}, allow_negative=True) = -34
/

[clinic start generated code]*/

PyDoc_STRVAR(test_Py_ssize_t_converter__doc__,
"test_Py_ssize_t_converter($module, a=12, b=34, c=56, /)\n"
"test_Py_ssize_t_converter($module, a=12, b=34, c=56, d=78, e=90, f=-12,\n"
" g=-34, /)\n"
"--\n"
"\n");

Expand All @@ -1626,7 +1631,8 @@ PyDoc_STRVAR(test_Py_ssize_t_converter__doc__,

static PyObject *
test_Py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
Py_ssize_t c);
Py_ssize_t c, Py_ssize_t d, Py_ssize_t e,
Py_ssize_t f, Py_ssize_t g);

static PyObject *
test_Py_ssize_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
Expand All @@ -1635,8 +1641,12 @@ test_Py_ssize_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t na
Py_ssize_t a = 12;
Py_ssize_t b = 34;
Py_ssize_t c = 56;
Py_ssize_t d = 78;
Py_ssize_t e = 90;
Py_ssize_t f = -12;
Py_ssize_t g = -34;

if (!_PyArg_CheckPositional("test_Py_ssize_t_converter", nargs, 0, 3)) {
if (!_PyArg_CheckPositional("test_Py_ssize_t_converter", nargs, 0, 7)) {
goto exit;
}
if (nargs < 1) {
Expand Down Expand Up @@ -1675,17 +1685,65 @@ test_Py_ssize_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t na
if (!_Py_convert_optional_to_ssize_t(args[2], &c)) {
goto exit;
}
if (nargs < 4) {
goto skip_optional;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[3]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
d = ival;
if (d < 0) {
PyErr_SetString(PyExc_ValueError,
"d cannot be negative");
goto exit;
}
}
if (nargs < 5) {
goto skip_optional;
}
if (!_Py_convert_optional_to_non_negative_ssize_t(args[4], &e)) {
goto exit;
}
if (nargs < 6) {
goto skip_optional;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[5]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
f = ival;
}
if (nargs < 7) {
goto skip_optional;
}
if (!_Py_convert_optional_to_ssize_t(args[6], &g)) {
goto exit;
}
skip_optional:
return_value = test_Py_ssize_t_converter_impl(module, a, b, c);
return_value = test_Py_ssize_t_converter_impl(module, a, b, c, d, e, f, g);

exit:
return return_value;
}

static PyObject *
test_Py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
Py_ssize_t c)
/*[clinic end generated code: output=48214bc3d01f4dd7 input=3855f184bb3f299d]*/
Py_ssize_t c, Py_ssize_t d, Py_ssize_t e,
Py_ssize_t f, Py_ssize_t g)
/*[clinic end generated code: output=4ae0a56a1447fba9 input=a25bac8ecf2890aa]*/


/*[clinic input]
Expand Down
21 changes: 19 additions & 2 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,19 @@ def test_disallow_defining_class_at_module_level(self):
"""
self.expect_failure(block, err, lineno=2)

def test_allow_negative_accepted_by_py_ssize_t_converter_only(self):
errmsg = re.escape("converter_init() got an unexpected keyword argument 'allow_negative'")
unsupported_converters = [converter_name for converter_name in converters.keys()
if converter_name != "Py_ssize_t"]
for converter in unsupported_converters:
with self.subTest(converter=converter):
block = f"""
module m
m.func
a: {converter}(allow_negative=True)
"""
with self.assertRaisesRegex((AssertionError, TypeError), errmsg):
self.parse_function(block)

class ClinicExternalTest(TestCase):
maxDiff = None
Expand Down Expand Up @@ -3194,8 +3207,12 @@ def test_py_ssize_t_converter(self):
ac_tester.py_ssize_t_converter(PY_SSIZE_T_MAX + 1)
with self.assertRaises(TypeError):
ac_tester.py_ssize_t_converter([])
self.assertEqual(ac_tester.py_ssize_t_converter(), (12, 34, 56))
self.assertEqual(ac_tester.py_ssize_t_converter(1, 2, None), (1, 2, 56))
with self.assertRaises(ValueError):
ac_tester.py_ssize_t_converter(12, 34, 56, -1)
with self.assertRaises(ValueError):
ac_tester.py_ssize_t_converter(12, 34, 56, 78, -1)
self.assertEqual(ac_tester.py_ssize_t_converter(), (12, 34, 56, 78, 90, -12, -34))
self.assertEqual(ac_tester.py_ssize_t_converter(1, 2, None, 3, None, 4, None), (1, 2, 56, 3, 90, 4, -34))

def test_slice_index_converter(self):
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_free_threading/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def writelines(barrier, b, *ignore):
def truncate(barrier, b, *ignore):
barrier.wait()
try: b.truncate(0)
except: BufferError # ignore exported buffer
except BufferError: pass # ignore exported buffer

def read(barrier, b, *ignore):
barrier.wait()
Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_opcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,21 @@ def binary_op_add_int():
self.assert_specialized(binary_op_add_int, "BINARY_OP_ADD_INT")
self.assert_no_opcode(binary_op_add_int, "BINARY_OP")

def binary_op_int_non_compact():
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
a, b = 10000000000, 1
c = a + b
self.assertEqual(c, 10000000001)
c = a - b
self.assertEqual(c, 9999999999)
c = a * b
self.assertEqual(c, 10000000000)

binary_op_int_non_compact()
self.assert_no_opcode(binary_op_int_non_compact, "BINARY_OP_ADD_INT")
self.assert_no_opcode(binary_op_int_non_compact, "BINARY_OP_SUBTRACT_INT")
self.assert_no_opcode(binary_op_int_non_compact, "BINARY_OP_MULTIPLY_INT")

def binary_op_add_unicode():
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
a, b = "foo", "bar"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``BINARY_OP`` now specializes to ``BINARY_OP_ADD_INT``,
``BINARY_OP_SUBTRACT_INT`` or ``BINARY_OP_MULTIPLY_INT`` if operands
are compact ints.
11 changes: 8 additions & 3 deletions Modules/_testclinic.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,16 +443,21 @@ py_ssize_t_converter
a: Py_ssize_t = 12
b: Py_ssize_t(accept={int}) = 34
c: Py_ssize_t(accept={int, NoneType}) = 56
d: Py_ssize_t(accept={int}, allow_negative=False) = 78
e: Py_ssize_t(accept={int, NoneType}, allow_negative=False) = 90
f: Py_ssize_t(accept={int}, allow_negative=False) = -12
g: Py_ssize_t(accept={int, NoneType}, py_default="-34", allow_negative=False) = -34
/

[clinic start generated code]*/

static PyObject *
py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
Py_ssize_t c)
/*[clinic end generated code: output=ce252143e0ed0372 input=76d0f342e9317a1f]*/
Py_ssize_t c, Py_ssize_t d, Py_ssize_t e,
Py_ssize_t f, Py_ssize_t g)
/*[clinic end generated code: output=ecf8e1a4a9abc95e input=7b7fa954780c1cb0]*/
{
RETURN_PACKED_ARGS(3, PyLong_FromSsize_t, Py_ssize_t, a, b, c);
RETURN_PACKED_ARGS(7, PyLong_FromSsize_t, Py_ssize_t, a, b, c, d, e, f, g);
}


Expand Down
68 changes: 63 additions & 5 deletions Modules/clinic/_testclinic.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ reset_remotedebug_data(PyThreadState *tstate)
{
tstate->remote_debugger_support.debugger_pending_call = 0;
memset(tstate->remote_debugger_support.debugger_script_path, 0,
Py_MAX_SCRIPT_PATH_SIZE);
_Py_MAX_SCRIPT_PATH_SIZE);
}


Expand Down
13 changes: 13 additions & 0 deletions Python/modsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ _Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
return 1;
}

int
_Py_convert_optional_to_non_negative_ssize_t(PyObject *obj, void *result)
{
if (!_Py_convert_optional_to_ssize_t(obj, result)) {
return 0;
}
if (obj != Py_None && *((Py_ssize_t *)result) < 0) {
PyErr_SetString(PyExc_ValueError, "argument cannot be negative");
return 0;
}
return 1;
}


/* Helper for mkvalue() to scan the length of a format */

Expand Down
Loading
Loading