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
2 changes: 1 addition & 1 deletion Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ additional methods of invocation:
appropriately named script from that directory.
* When called with ``-c command``, it executes the Python statement(s) given as
*command*. Here *command* may contain multiple statements separated by
newlines. Leading whitespace is significant in Python statements!
newlines.
* When called with ``-m module-name``, the given module is located on the
Python module path and executed as a script.

Expand Down
3 changes: 1 addition & 2 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -897,8 +897,7 @@ Command line and environment
(Contributed by Noah Kim and Adam Turner in :gh:`118655`.)

* The command-line option :option:`-c` now automatically dedents its code
argument before execution. The auto-dedentation behavior mirrors
:func:`textwrap.dedent`.
argument before execution.
(Contributed by Jon Crall and Steven Sun in :gh:`103998`.)

* :option:`!-J` is no longer a reserved flag for Jython_,
Expand Down
31 changes: 18 additions & 13 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,30 @@ Summary -- Release highlights
.. PEP-sized items next.

* :pep:`810`: :ref:`Explicit lazy imports for faster startup times
<whatsnew315-pep810>`
<whatsnew315-lazy-imports>`
* :pep:`814`: :ref:`Add frozendict built-in type
<whatsnew315-frozendict>`
* :pep:`799`: :ref:`A dedicated profiling package for organizing Python
profiling tools <whatsnew315-profiling-package>`
* :pep:`799`: :ref:`Tachyon: High frequency statistical sampling profiler
<whatsnew315-sampling-profiler>`
* :pep:`798`: :ref:`Unpacking in Comprehensions
* :pep:`798`: :ref:`Unpacking in comprehensions
<whatsnew315-unpacking-in-comprehensions>`
* :pep:`686`: :ref:`Python now uses UTF-8 as the default encoding
<whatsnew315-utf8-default>`
* :pep:`728`: ``TypedDict`` with typed extra items
* :pep:`747`: :ref:`Annotating type forms with TypeForm
<whatsnew315-typeform>`
* :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object
<whatsnew315-pep782>`
<whatsnew315-pybyteswriter>`
* :ref:`The JIT compiler has been significantly upgraded <whatsnew315-jit>`
* :ref:`Improved error messages <whatsnew315-improved-error-messages>`


New features
============

.. _whatsnew315-pep810:
.. _whatsnew315-lazy-imports:

:pep:`810`: Explicit lazy imports
---------------------------------
Expand Down Expand Up @@ -120,12 +123,12 @@ name:
.. code-block:: python

lazy import json
lazy from datetime import datetime
lazy from pathlib import Path

print("Starting up...") # json and datetime not loaded yet
print("Starting up...") # json and pathlib not loaded yet

data = json.loads('{"key": "value"}') # json gets loads here
now = datetime() # datetime loads here
data = json.loads('{"key": "value"}') # json loads here
p = Path(".") # pathlib loads here

This mechanism is particularly useful for applications that import many
modules at the top level but may only use a subset of them in any given run.
Expand Down Expand Up @@ -189,9 +192,9 @@ raise :exc:`SyntaxError`).
----------------------------------------

A new :term:`immutable` type, :class:`frozendict`, is added to the :mod:`builtins` module.
It does not allow modification after creation. A ``frozendict`` is not a subclass of ``dict``;
it inherits directly from ``object``. A ``frozendict`` is :term:`hashable`
as long as all of its keys and values are hashable. A ``frozendict`` preserves
It does not allow modification after creation. A :class:`!frozendict` is not a subclass of ``dict``;
it inherits directly from ``object``. A :class:`!frozendict` is :term:`hashable`
as long as all of its keys and values are hashable. A :class:`!frozendict` preserves
insertion order, but comparison does not take order into account.

For example::
Expand Down Expand Up @@ -1273,7 +1276,7 @@ csv
.. _whatsnew315-jit:

Upgraded JIT compiler
=====================
---------------------

Results from the `pyperformance <https://github.com/python/pyperformance>`__
benchmark suite report
Expand Down Expand Up @@ -1438,6 +1441,8 @@ threading
typing
------

.. _whatsnew315-typeform:

* :pep:`747`: Add :data:`~typing.TypeForm`, a new special form for annotating
values that are themselves type expressions.
``TypeForm[T]`` means "a type form object describing ``T`` (or a type
Expand Down Expand Up @@ -1636,7 +1641,7 @@ New features
and :c:data:`Py_mod_abi`.
(Contributed by Petr Viktorin in :gh:`137210`.)

.. _whatsnew315-pep782:
.. _whatsnew315-pybyteswriter:

* Implement :pep:`782`, the :ref:`PyBytesWriter API <pybyteswriter>`.
Add functions:
Expand Down
3 changes: 3 additions & 0 deletions Include/internal/pycore_tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRe
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
PyAPI_FUNC(PyObject *) _PyTuple_BinarySlice(PyObject *, PyObject *, PyObject *);

PyAPI_FUNC(PyObject *) _PyTuple_FromPair(PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyTuple_FromPairSteal(PyObject *, PyObject *);

typedef struct {
PyObject_HEAD
Py_ssize_t it_index;
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ extern PyObject* _PyUnicode_XStrip(


/* Dedent a string.
Behaviour is expected to be an exact match of `textwrap.dedent`.
Intended to dedent Python source. Unlike `textwrap.dedent`, this
only supports spaces and tabs and doesn't normalize empty lines.
Return a new reference on success, NULL with exception set on error.
*/
extern PyObject* _PyUnicode_Dedent(PyObject *unicode);
Expand Down
26 changes: 18 additions & 8 deletions Lib/test/test_bz2.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,28 @@ class BaseTest(unittest.TestCase):
EMPTY_DATA = b'BZh9\x17rE8P\x90\x00\x00\x00\x00'
BAD_DATA = b'this is not a valid bzip2 file'

# Some tests need more than one block of uncompressed data. Since one block
# is at least 100,000 bytes, we gather some data dynamically and compress it.
# Note that this assumes that compression works correctly, so we cannot
# simply use the bigger test data for all tests.
# Some tests need more than one block of data. The bz2 module does not
# support flushing a block during compression, so we must read in data until
# there are at least 2 blocks. Since different orderings of Python files may
# be compressed differently, we need to check the compression output for
# more than one bzip2 block header magic, a hex encoding of Pi
# (0x314159265359)
bz2_block_magic = bytes.fromhex('314159265359')
test_size = 0
BIG_TEXT = bytearray(128*1024)
BIG_TEXT = b''
BIG_DATA = b''
compressor = BZ2Compressor(1)
for fname in glob.glob(os.path.join(glob.escape(os.path.dirname(__file__)), '*.py')):
with open(fname, 'rb') as fh:
test_size += fh.readinto(memoryview(BIG_TEXT)[test_size:])
if test_size > 128*1024:
data = fh.read()
BIG_DATA += compressor.compress(data)
BIG_TEXT += data
# TODO(emmatyping): if it is impossible for a block header to cross
# multiple outputs, we can just search the output of each compress call
# which should be more efficient
if BIG_DATA.count(bz2_block_magic) > 1:
BIG_DATA += compressor.flush()
break
BIG_DATA = bz2.compress(BIG_TEXT, compresslevel=1)

def setUp(self):
fd, self.filename = tempfile.mkstemp()
Expand Down
37 changes: 37 additions & 0 deletions Lib/test/test_capi/test_tuple.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import unittest
import gc
from sys import getrefcount
from test.support import import_helper

_testcapi = import_helper.import_module('_testcapi')
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
_testinternalcapi = import_helper.import_module('_testinternalcapi')

NULL = None
PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN
Expand Down Expand Up @@ -118,6 +120,41 @@ def test_tuple_pack(self):
# CRASHES pack(1, NULL)
# CRASHES pack(2, [1])

def check_tuple_from_pair(self, from_pair):
self.assertEqual(type(from_pair(1, 2)), tuple)
self.assertEqual(from_pair(1, 145325), (1, 145325))
self.assertEqual(from_pair(None, None), (None, None))
self.assertEqual(from_pair(True, False), (True, False))

# user class supports gc
class Temp:
pass
temp = Temp()
temp_rc = getrefcount(temp)
self.assertEqual(from_pair(temp, temp), (temp, temp))
self.assertEqual(getrefcount(temp), temp_rc)

self._not_tracked(from_pair(1, 2))
self._not_tracked(from_pair(None, None))
self._not_tracked(from_pair(True, False))
self._tracked(from_pair(temp, (1, 2)))
self._tracked(from_pair(temp, 1))
self._tracked(from_pair([], {}))

self.assertRaises(TypeError, from_pair, 1, 2, 3)
self.assertRaises(TypeError, from_pair, 1)
self.assertRaises(TypeError, from_pair)

def test_tuple_from_pair(self):
# Test _PyTuple_FromPair()
from_pair = _testinternalcapi.tuple_from_pair
self.check_tuple_from_pair(from_pair)

def test_tuple_from_pair_steal(self):
# Test _PyTuple_FromPairSteal()
from_pair = _testinternalcapi.tuple_from_pair_steal
self.check_tuple_from_pair(from_pair)

def test_tuple_size(self):
# Test PyTuple_Size()
size = _testlimitedcapi.tuple_size
Expand Down
4 changes: 2 additions & 2 deletions Misc/NEWS.d/3.14.0b1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1881,8 +1881,8 @@ Improve error message when :exc:`TypeError` occurs during
.. nonce: BS3uVt
.. section: Core and Builtins

String arguments passed to "-c" are now automatically dedented as if by
:func:`textwrap.dedent`. This allows "python -c" invocations to be indented
String arguments passed to "-c" are now automatically dedented.
This allows "python -c" invocations to be indented
in shell scripts without causing indentation errors. (Patch by Jon Crall and
Steven Sun)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix negative timestamp during DST on Windows. Patch by Hugo van Kemenade.
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
@MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c _testinternalcapi/tuple.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
Expand Down
3 changes: 3 additions & 0 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2987,6 +2987,9 @@ module_exec(PyObject *module)
if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) {
return 1;
}
if (_PyTestInternalCapi_Init_Tuple(module) < 0) {
return 1;
}

Py_ssize_t sizeof_gc_head = 0;
#ifndef Py_GIL_DISABLED
Expand Down
1 change: 1 addition & 0 deletions Modules/_testinternalcapi/parts.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ int _PyTestInternalCapi_Init_PyTime(PyObject *module);
int _PyTestInternalCapi_Init_Set(PyObject *module);
int _PyTestInternalCapi_Init_Complex(PyObject *module);
int _PyTestInternalCapi_Init_CriticalSection(PyObject *module);
int _PyTestInternalCapi_Init_Tuple(PyObject *module);

#endif // Py_TESTINTERNALCAPI_PARTS_H
39 changes: 39 additions & 0 deletions Modules/_testinternalcapi/tuple.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "parts.h"

#include "pycore_tuple.h"


static PyObject *
tuple_from_pair(PyObject *Py_UNUSED(module), PyObject *args)
{
PyObject *first, *second;
if (!PyArg_ParseTuple(args, "OO", &first, &second)) {
return NULL;
}

return _PyTuple_FromPair(first, second);
}

static PyObject *
tuple_from_pair_steal(PyObject *Py_UNUSED(module), PyObject *args)
{
PyObject *first, *second;
if (!PyArg_ParseTuple(args, "OO", &first, &second)) {
return NULL;
}

return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second));
}


static PyMethodDef test_methods[] = {
{"tuple_from_pair", tuple_from_pair, METH_VARARGS},
{"tuple_from_pair_steal", tuple_from_pair_steal, METH_VARARGS},
{NULL},
};

int
_PyTestInternalCapi_Init_Tuple(PyObject *m)
{
return PyModule_AddFunctions(m, test_methods);
}
29 changes: 29 additions & 0 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,35 @@ PyTuple_Pack(Py_ssize_t n, ...)
return (PyObject *)result;
}

PyObject *
_PyTuple_FromPair(PyObject *first, PyObject *second)
{
assert(first != NULL);
assert(second != NULL);

return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second));
}

PyObject *
_PyTuple_FromPairSteal(PyObject *first, PyObject *second)
{
assert(first != NULL);
assert(second != NULL);

PyTupleObject *op = tuple_alloc(2);
if (op == NULL) {
Py_DECREF(first);
Py_DECREF(second);
return NULL;
}
PyObject **items = op->ob_item;
items[0] = first;
items[1] = second;
if (maybe_tracked(first) || maybe_tracked(second)) {
_PyObject_GC_TRACK(op);
}
return (PyObject *)op;
}

/* Methods */

Expand Down
3 changes: 2 additions & 1 deletion Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -13581,7 +13581,8 @@ search_longest_common_leading_whitespace(
}

/* Dedent a string.
Behaviour is expected to be an exact match of `textwrap.dedent`.
Intended to dedent Python source. Unlike `textwrap.dedent`, this
only supports spaces and tabs and doesn't normalize empty lines.
Return a new reference on success, NULL with exception set on error.
*/
PyObject *
Expand Down
1 change: 1 addition & 0 deletions PCbuild/_testinternalcapi.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
<ClCompile Include="..\Modules\_testinternalcapi\set.c" />
<ClCompile Include="..\Modules\_testinternalcapi\complex.c" />
<ClCompile Include="..\Modules\_testinternalcapi\interpreter.c" />
<ClCompile Include="..\Modules\_testinternalcapi\tuple.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc" />
Expand Down
3 changes: 3 additions & 0 deletions PCbuild/_testinternalcapi.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<ClCompile Include="..\Modules\_testinternalcapi\complex.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_testinternalcapi\tuple.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc">
Expand Down
1 change: 1 addition & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,7 @@ _PyEval_ExceptionGroupMatch(_PyInterpreterFrame *frame, PyObject* exc_value,
if (f != NULL) {
PyObject *tb = _PyTraceBack_FromFrame(NULL, f);
if (tb == NULL) {
Py_DECREF(wrapped);
return -1;
}
PyException_SetTraceback(wrapped, tb);
Expand Down
8 changes: 4 additions & 4 deletions Python/crossinterp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,12 +1103,12 @@ _convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc)
}

PyObject *tbexc = PyObject_Call(create, args, kwargs);
Py_DECREF(args);
Py_DECREF(kwargs);
Py_DECREF(create);
if (tbexc == NULL) {
goto error;
}
Py_DECREF(args);
Py_DECREF(kwargs);
Py_DECREF(create);

*p_tbexc = tbexc;
return 0;
Expand Down Expand Up @@ -1497,7 +1497,7 @@ _PyXI_excinfo_Apply(_PyXI_excinfo *info, PyObject *exctype)

PyObject *formatted = _PyXI_excinfo_format(info);
PyErr_SetObject(exctype, formatted);
Py_DECREF(formatted);
Py_XDECREF(formatted);

if (tbexc != NULL) {
PyObject *exc = PyErr_GetRaisedException();
Expand Down
Loading
Loading