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
5 changes: 5 additions & 0 deletions Doc/library/resource.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ this module for those platforms.
.. data:: RLIM_INFINITY

Constant used to represent the limit for an unlimited resource.
Its value is larger than any limited resource value.

.. versionchanged:: next
It is now always positive.
Previously, it could be negative, such as -1 or -3.


.. function:: getrlimit(resource)
Expand Down
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,12 @@ Porting to Python 3.15
The |pythoncapi_compat_project| can be used to get most of these new
functions on Python 3.14 and older.

* :data:`resource.RLIM_INFINITY` is now always positive.
Passing a negative integer value that corresponded to its old value
(such as ``-1`` or ``-3``, depending on platform) to
:func:`resource.setrlimit` and :func:`resource.prlimit` is now deprecated.
(Contributed by Serhiy Storchaka in :gh:`137044`.)


Deprecated C APIs
-----------------
Expand Down
1 change: 1 addition & 0 deletions Lib/_pyrepl/simple_interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def maybe_run_command(statement: str) -> bool:
input_n += 1
except KeyboardInterrupt:
r = _get_reader()
r.cmpltn_reset()
if r.input_trans is r.isearch_trans:
r.do_cmd(("isearch-end", [""]))
r.pos = len(r.get_unicode())
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/clinic.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -4080,13 +4080,14 @@ test_preprocessor_guarded_if_with_continuation_impl(PyObject *module)
#if CONDITION_E || CONDITION_F
#warning "different type of CPP directive"
/*[clinic input]
@permit_long_summary
test_preprocessor_guarded_if_e_or_f
Makes sure cpp.Monitor handles other directives than preprocessor conditionals.
[clinic start generated code]*/

static PyObject *
test_preprocessor_guarded_if_e_or_f_impl(PyObject *module)
/*[clinic end generated code: output=e49d24ff64ad88bc input=57b9c37f938bc4f1]*/
/*[clinic end generated code: output=e49d24ff64ad88bc input=3ca9ab4e883300ed]*/
#endif

/*[clinic input]
Expand Down
44 changes: 22 additions & 22 deletions Lib/test/test_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ def test_fsize_ismax(self):
# we need to test that the get/setrlimit functions properly convert
# the number to a C long long and that the conversion doesn't raise
# an error.
self.assertGreater(resource.RLIM_INFINITY, 0)
self.assertEqual(resource.RLIM_INFINITY, max)
self.assertLessEqual(cur, max)
resource.setrlimit(resource.RLIMIT_FSIZE, (max, max))
resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))

@unittest.skipIf(sys.platform == "vxworks",
Expand Down Expand Up @@ -113,56 +116,53 @@ def test_fsize_not_too_big(self):
self.addCleanup(resource.setrlimit, resource.RLIMIT_FSIZE, (cur, max))

def expected(cur):
if resource.RLIM_INFINITY < 0:
return [(cur, max), (resource.RLIM_INFINITY, max)]
elif resource.RLIM_INFINITY < cur:
return [(resource.RLIM_INFINITY, max)]
else:
return [(cur, max)]
return (min(cur, resource.RLIM_INFINITY), max)

resource.setrlimit(resource.RLIMIT_FSIZE, (2**31-5, max))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31-5, max))
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**31))
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32-5))

try:
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32, max))
except OverflowError:
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max))
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**31))
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max))
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32-5))
pass
else:
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32))
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31, max))
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32-5, max))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32))

resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-5, max))
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63-5))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63-5))
try:
resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max))
except ValueError:
# There is a hard limit on macOS.
pass
else:
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63))
resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-5, max))
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**64-5))
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**64-5))

@unittest.skipIf(sys.platform == "vxworks",
"setting RLIMIT_FSIZE is not supported on VxWorks")
@unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE')
def test_fsize_negative(self):
self.assertGreater(resource.RLIM_INFINITY, 0)
(cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE)
for value in -5, -2**31, -2**32-5, -2**63, -2**64-5, -2**1000:
with self.subTest(value=value):
# This test assumes that the values don't map to RLIM_INFINITY,
# though Posix doesn't guarantee it.
self.assertNotEqual(value, resource.RLIM_INFINITY)

self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (value, max))
self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (cur, value))

if resource.RLIM_INFINITY in (2**32-3, 2**32-1, 2**64-3, 2**64-1):
value = (resource.RLIM_INFINITY & 0xffff) - 0x10000
with self.assertWarnsRegex(DeprecationWarning, "RLIM_INFINITY"):
resource.setrlimit(resource.RLIMIT_FSIZE, (value, max))
with self.assertWarnsRegex(DeprecationWarning, "RLIM_INFINITY"):
resource.setrlimit(resource.RLIMIT_FSIZE, (cur, value))


@unittest.skipUnless(hasattr(resource, "getrusage"), "needs getrusage")
def test_getrusage(self):
self.assertRaises(TypeError, resource.getrusage)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:data:`resource.RLIM_INFINITY` is now always a positive integer larger than
any limited resource value. This simplifies comparison of the resource
values. Previously, it could be negative, such as -1 or -3, depending on
platform.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix an issue where pressing Ctrl+C during tab completion in the REPL would leave the autocompletion menu in a corrupted state.
12 changes: 8 additions & 4 deletions Modules/_abc.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ compute_abstract_methods(PyObject *self)
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)

/*[clinic input]
@permit_long_summary
_abc._abc_init

self: object
Expand All @@ -494,7 +495,7 @@ Internal ABC helper for class set-up. Should be never used outside abc module.

static PyObject *
_abc__abc_init(PyObject *module, PyObject *self)
/*[clinic end generated code: output=594757375714cda1 input=8d7fe470ff77f029]*/
/*[clinic end generated code: output=594757375714cda1 input=0b3513f947736d39]*/
{
_abcmodule_state *state = get_abc_state(module);
PyObject *data;
Expand Down Expand Up @@ -543,6 +544,7 @@ _abc__abc_init(PyObject *module, PyObject *self)
}

/*[clinic input]
@permit_long_summary
_abc._abc_register

self: object
Expand All @@ -554,7 +556,7 @@ Internal ABC helper for subclasss registration. Should be never used outside abc

static PyObject *
_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass)
/*[clinic end generated code: output=7851e7668c963524 input=ca589f8c3080e67f]*/
/*[clinic end generated code: output=7851e7668c963524 input=135ab13a581b4414]*/
{
if (!PyType_Check(subclass)) {
PyErr_SetString(PyExc_TypeError, "Can only register classes");
Expand Down Expand Up @@ -606,6 +608,7 @@ _abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass)


/*[clinic input]
@permit_long_summary
_abc._abc_instancecheck

self: object
Expand All @@ -618,7 +621,7 @@ Internal ABC helper for instance checks. Should be never used outside abc module
static PyObject *
_abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
PyObject *instance)
/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/
/*[clinic end generated code: output=b8b5148f63b6b56f input=0bbc8da0ea346719]*/
{
PyObject *subtype, *result = NULL, *subclass = NULL;
_abc_data *impl = _get_impl(module, self);
Expand Down Expand Up @@ -692,6 +695,7 @@ static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
PyObject **result);

/*[clinic input]
@permit_long_summary
_abc._abc_subclasscheck

self: object
Expand All @@ -704,7 +708,7 @@ Internal ABC helper for subclasss checks. Should be never used outside abc modul
static PyObject *
_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
PyObject *subclass)
/*[clinic end generated code: output=b56c9e4a530e3894 input=1d947243409d10b8]*/
/*[clinic end generated code: output=b56c9e4a530e3894 input=5bf1ef712f5d3610]*/
{
if (!PyType_Check(subclass)) {
PyErr_SetString(PyExc_TypeError, "issubclass() arg 1 must be a class");
Expand Down
3 changes: 2 additions & 1 deletion Modules/_bz2module.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length)
}

/*[clinic input]
@permit_long_docstring_body
_bz2.BZ2Decompressor.decompress

data: Py_buffer
Expand All @@ -622,7 +623,7 @@ the unused_data attribute.
static PyObject *
_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data,
Py_ssize_t max_length)
/*[clinic end generated code: output=23e41045deb240a3 input=52e1ffc66a8ea624]*/
/*[clinic end generated code: output=23e41045deb240a3 input=3703e78f91757655]*/
{
PyObject *result = NULL;

Expand Down
3 changes: 2 additions & 1 deletion Modules/_codecsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ _codecs_unregister(PyObject *module, PyObject *search_function)
}

/*[clinic input]
@permit_long_summary
_codecs.lookup
encoding: str
/
Expand All @@ -101,7 +102,7 @@ Looks up a codec tuple in the Python codec registry and returns a CodecInfo obje

static PyObject *
_codecs_lookup_impl(PyObject *module, const char *encoding)
/*[clinic end generated code: output=9f0afa572080c36d input=3c572c0db3febe9c]*/
/*[clinic end generated code: output=9f0afa572080c36d input=02227d5429491ab3]*/
{
return _PyCodec_Lookup(encoding);
}
Expand Down
3 changes: 2 additions & 1 deletion Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,7 @@ align_func(PyObject *self, PyObject *obj)


/*[clinic input]
@permit_long_summary
@critical_section obj
_ctypes.byref
obj: object(subclass_of="clinic_state()->PyCData_Type")
Expand All @@ -1798,7 +1799,7 @@ Return a pointer lookalike to a C instance, only usable as function argument.

static PyObject *
_ctypes_byref_impl(PyObject *module, PyObject *obj, Py_ssize_t offset)
/*[clinic end generated code: output=60dec5ed520c71de input=6ec02d95d15fbd56]*/
/*[clinic end generated code: output=60dec5ed520c71de input=870076149a2de427]*/
{
ctypes_state *st = get_module_state(module);

Expand Down
3 changes: 2 additions & 1 deletion Modules/_curses_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ _curses_panel_panel_bottom_impl(PyCursesPanelObject *self)
}

/*[clinic input]
@permit_long_docstring_body
_curses_panel.panel.hide

Hide the panel.
Expand All @@ -369,7 +370,7 @@ This does not delete the object, it just makes the window on screen invisible.

static PyObject *
_curses_panel_panel_hide_impl(PyCursesPanelObject *self)
/*[clinic end generated code: output=a7bbbd523e1eab49 input=f6ab884e99386118]*/
/*[clinic end generated code: output=a7bbbd523e1eab49 input=9071b463a39a1a6a]*/
{
int rtn = hide_panel(self->pan);
return curses_panel_panel_check_err(self, rtn, "hide_panel", "hide");
Expand Down
Loading
Loading