Skip to content

Commit 2aacadf

Browse files
authored
Merge branch 'main' into uuid-v7-method-1
2 parents 06befca + 2313f84 commit 2aacadf

File tree

16 files changed

+162
-187
lines changed

16 files changed

+162
-187
lines changed

Doc/library/platform.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,15 @@ Android Platform
359359
<https://storage.googleapis.com/play_public/supported_devices.html>`__.
360360

361361
.. versionadded:: 3.13
362+
363+
364+
Miscellaneous
365+
-------------
366+
367+
.. function:: invalidate_caches()
368+
369+
Clear out the internal cache of information, such as the :func:`uname`.
370+
This is typically useful when the platform's :func:`node` is changed
371+
by an external process and one needs to retrieve the updated value.
372+
373+
.. versionadded:: 3.14

Doc/library/urllib.parse.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,15 @@ or on combining URL components into a URL string.
407407
If you do not want that behavior, preprocess the *url* with :func:`urlsplit` and
408408
:func:`urlunsplit`, removing possible *scheme* and *netloc* parts.
409409

410+
.. warning::
411+
412+
Because an absolute URL may be passed as the ``url`` parameter, it is
413+
generally **not secure** to use ``urljoin`` with an attacker-controlled
414+
``url``. For example in,
415+
``urljoin("https://website.com/users/", username)``, if ``username`` can
416+
contain an absolute URL, the result of ``urljoin`` will be the absolute
417+
URL.
418+
410419

411420
.. versionchanged:: 3.5
412421

Doc/reference/simple_stmts.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,9 @@ The extended form, ``assert expression1, expression2``, is equivalent to ::
408408

409409
These equivalences assume that :const:`__debug__` and :exc:`AssertionError` refer to
410410
the built-in variables with those names. In the current implementation, the
411-
built-in variable :const:`__debug__` is ``True`` under normal circumstances,
411+
built-in variable ``__debug__`` is ``True`` under normal circumstances,
412412
``False`` when optimization is requested (command line option :option:`-O`). The current
413-
code generator emits no code for an assert statement when optimization is
413+
code generator emits no code for an :keyword:`assert` statement when optimization is
414414
requested at compile time. Note that it is unnecessary to include the source
415415
code for the expression that failed in the error message; it will be displayed
416416
as part of the stack trace.
@@ -533,8 +533,8 @@ The :keyword:`!yield` statement
533533
yield_stmt: `yield_expression`
534534

535535
A :keyword:`yield` statement is semantically equivalent to a :ref:`yield
536-
expression <yieldexpr>`. The yield statement can be used to omit the parentheses
537-
that would otherwise be required in the equivalent yield expression
536+
expression <yieldexpr>`. The ``yield`` statement can be used to omit the
537+
parentheses that would otherwise be required in the equivalent yield expression
538538
statement. For example, the yield statements ::
539539

540540
yield <expr>
@@ -546,7 +546,7 @@ are equivalent to the yield expression statements ::
546546
(yield from <expr>)
547547

548548
Yield expressions and statements are only used when defining a :term:`generator`
549-
function, and are only used in the body of the generator function. Using yield
549+
function, and are only used in the body of the generator function. Using :keyword:`yield`
550550
in a function definition is sufficient to cause that definition to create a
551551
generator function instead of a normal function.
552552

@@ -966,12 +966,12 @@ The :keyword:`!global` statement
966966
.. productionlist:: python-grammar
967967
global_stmt: "global" `identifier` ("," `identifier`)*
968968

969-
The :keyword:`global` causes the listed identifiers to be interpreted
969+
The :keyword:`global` statement causes the listed identifiers to be interpreted
970970
as globals. It would be impossible to assign to a global variable without
971971
:keyword:`!global`, although free variables may refer to globals without being
972972
declared global.
973973

974-
The global statement applies to the entire scope of a function or
974+
The :keyword:`global` statement applies to the entire scope of a function or
975975
class body. A :exc:`SyntaxError` is raised if a variable is used or
976976
assigned to prior to its global declaration in the scope.
977977

@@ -1009,7 +1009,7 @@ identifiers. If a name is bound in more than one nonlocal scope, the
10091009
nearest binding is used. If a name is not bound in any nonlocal scope,
10101010
or if there is no nonlocal scope, a :exc:`SyntaxError` is raised.
10111011

1012-
The nonlocal statement applies to the entire scope of a function or
1012+
The :keyword:`nonlocal` statement applies to the entire scope of a function or
10131013
class body. A :exc:`SyntaxError` is raised if a variable is used or
10141014
assigned to prior to its nonlocal declaration in the scope.
10151015

Doc/using/configure.rst

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -454,15 +454,6 @@ Options for third-party dependencies
454454
WebAssembly Options
455455
-------------------
456456

457-
.. option:: --with-emscripten-target=[browser|node]
458-
459-
Set build flavor for ``wasm32-emscripten``.
460-
461-
* ``browser`` (default): preload minimal stdlib, default MEMFS.
462-
* ``node``: NODERAWFS and pthread support.
463-
464-
.. versionadded:: 3.11
465-
466457
.. option:: --enable-wasm-dynamic-linking
467458

468459
Turn on dynamic linking support for WASM.
@@ -1097,7 +1088,8 @@ CPython project) this is usually the ``all`` target. The
10971088
all`` will build. The three choices are:
10981089

10991090
* ``profile-opt`` (configured with ``--enable-optimizations``)
1100-
* ``build_wasm`` (configured with ``--with-emscripten-target``)
1091+
* ``build_wasm`` (chosen if the host platform matches ``wasm32-wasi*`` or
1092+
``wasm32-emscripten``)
11011093
* ``build_all`` (configured without explicitly using either of the others)
11021094

11031095
Depending on the most recent source file changes, Make will rebuild

Doc/whatsnew/3.14.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,14 @@ pathlib
454454
(Contributed by Barney Gale in :gh:`125413`.)
455455

456456

457+
platform
458+
--------
459+
460+
* Add :func:`platform.invalidate_caches` to invalidate the cached results.
461+
462+
(Contributed by Bénédikt Tran in :gh:`122549`.)
463+
464+
457465
pdb
458466
---
459467

@@ -786,6 +794,16 @@ Changes in the Python API
786794
Build changes
787795
=============
788796

797+
PEP 761: Discontinuation of PGP signatures
798+
------------------------------------------
799+
800+
PGP signatures will not be available for CPython 3.14 and onwards.
801+
Users verifying artifacts must use `Sigstore verification materials`_ for
802+
verifying CPython artifacts. This change in release process is specified
803+
in :pep:`761`.
804+
805+
.. _Sigstore verification materials: https://www.python.org/downloads/metadata/sigstore/
806+
789807

790808
C API changes
791809
=============

Lib/calendar.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
error = ValueError
2828

2929
# Exceptions raised for bad input
30-
class IllegalMonthError(ValueError):
30+
# This is trick for backward compatibility. Since 3.13, we will raise IllegalMonthError instead of
31+
# IndexError for bad month number(out of 1-12). But we can't remove IndexError for backward compatibility.
32+
class IllegalMonthError(ValueError, IndexError):
3133
def __init__(self, month):
3234
self.month = month
3335
def __str__(self):
@@ -158,11 +160,14 @@ def weekday(year, month, day):
158160
return Day(datetime.date(year, month, day).weekday())
159161

160162

163+
def _validate_month(month):
164+
if not 1 <= month <= 12:
165+
raise IllegalMonthError(month)
166+
161167
def monthrange(year, month):
162168
"""Return weekday of first day of month (0-6 ~ Mon-Sun)
163169
and number of days (28-31) for year, month."""
164-
if not 1 <= month <= 12:
165-
raise IllegalMonthError(month)
170+
_validate_month(month)
166171
day1 = weekday(year, month, 1)
167172
ndays = mdays[month] + (month == FEBRUARY and isleap(year))
168173
return day1, ndays
@@ -370,6 +375,8 @@ def formatmonthname(self, theyear, themonth, width, withyear=True):
370375
"""
371376
Return a formatted month name.
372377
"""
378+
_validate_month(themonth)
379+
373380
s = month_name[themonth]
374381
if withyear:
375382
s = "%s %r" % (s, theyear)
@@ -500,6 +507,7 @@ def formatmonthname(self, theyear, themonth, withyear=True):
500507
"""
501508
Return a month name as a table row.
502509
"""
510+
_validate_month(themonth)
503511
if withyear:
504512
s = '%s %s' % (month_name[themonth], theyear)
505513
else:
@@ -786,6 +794,8 @@ def main(args=None):
786794
if options.month is None:
787795
optdict["c"] = options.spacing
788796
optdict["m"] = options.months
797+
if options.month is not None:
798+
_validate_month(options.month)
789799
if options.year is None:
790800
result = cal.formatyear(datetime.date.today().year, **optdict)
791801
elif options.month is None:

Lib/platform.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#
3232
# <see CVS and SVN checkin messages for history>
3333
#
34+
# 1.0.9 - added invalidate_caches() function to invalidate cached values
3435
# 1.0.8 - changed Windows support to read version from kernel32.dll
3536
# 1.0.7 - added DEV_NULL
3637
# 1.0.6 - added linux_distribution()
@@ -109,7 +110,7 @@
109110
110111
"""
111112

112-
__version__ = '1.0.8'
113+
__version__ = '1.0.9'
113114

114115
import collections
115116
import os
@@ -1441,6 +1442,18 @@ def freedesktop_os_release():
14411442
return _os_release_cache.copy()
14421443

14431444

1445+
def invalidate_caches():
1446+
"""Invalidate the cached results."""
1447+
global _uname_cache
1448+
_uname_cache = None
1449+
1450+
global _os_release_cache
1451+
_os_release_cache = None
1452+
1453+
_sys_version_cache.clear()
1454+
_platform_cache.clear()
1455+
1456+
14441457
### Command line interface
14451458

14461459
if __name__ == '__main__':

Lib/test/test_calendar.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ def test_formatmonth(self):
457457
calendar.TextCalendar().formatmonth(0, 2),
458458
result_0_02_text
459459
)
460+
def test_formatmonth_with_invalid_month(self):
461+
with self.assertRaises(calendar.IllegalMonthError):
462+
calendar.TextCalendar().formatmonth(2017, 13)
463+
with self.assertRaises(calendar.IllegalMonthError):
464+
calendar.TextCalendar().formatmonth(2017, -1)
460465

461466
def test_formatmonthname_with_year(self):
462467
self.assertEqual(
@@ -1121,7 +1126,7 @@ def test__all__(self):
11211126
not_exported = {
11221127
'mdays', 'January', 'February', 'EPOCH',
11231128
'different_locale', 'c', 'prweek', 'week', 'format',
1124-
'formatstring', 'main', 'monthlen', 'prevmonth', 'nextmonth'}
1129+
'formatstring', 'main', 'monthlen', 'prevmonth', 'nextmonth', ""}
11251130
support.check__all__(self, calendar, not_exported=not_exported)
11261131

11271132

@@ -1149,6 +1154,13 @@ def test_formatmonth(self):
11491154
self.assertIn('class="text-center month"',
11501155
self.cal.formatmonth(2017, 5))
11511156

1157+
def test_formatmonth_with_invalid_month(self):
1158+
with self.assertRaises(calendar.IllegalMonthError):
1159+
self.cal.formatmonth(2017, 13)
1160+
with self.assertRaises(calendar.IllegalMonthError):
1161+
self.cal.formatmonth(2017, -1)
1162+
1163+
11521164
def test_formatweek(self):
11531165
weeks = self.cal.monthdays2calendar(2017, 5)
11541166
self.assertIn('class="wed text-nowrap"', self.cal.formatweek(weeks[0]))

Lib/test/test_platform.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,38 @@ def clear_caches(self):
8383
platform._uname_cache = None
8484
platform._os_release_cache = None
8585

86+
def test_invalidate_caches(self):
87+
self.clear_caches()
88+
89+
self.assertDictEqual(platform._platform_cache, {})
90+
self.assertDictEqual(platform._sys_version_cache, {})
91+
self.assertIsNone(platform._uname_cache)
92+
self.assertIsNone(platform._os_release_cache)
93+
94+
# fill the cached entries (some have side effects on others)
95+
platform.platform() # for platform._platform_cache
96+
platform.python_implementation() # for platform._sys_version_cache
97+
platform.uname() # for platform._uname_cache
98+
99+
# check that the cache are filled
100+
self.assertNotEqual(platform._platform_cache, {})
101+
self.assertNotEqual(platform._sys_version_cache, {})
102+
self.assertIsNotNone(platform._uname_cache)
103+
104+
try:
105+
platform.freedesktop_os_release()
106+
except OSError:
107+
self.assertIsNone(platform._os_release_cache)
108+
else:
109+
self.assertIsNotNone(platform._os_release_cache)
110+
111+
with self.subTest('clear platform caches'):
112+
platform.invalidate_caches()
113+
self.assertDictEqual(platform._platform_cache, {})
114+
self.assertDictEqual(platform._sys_version_cache, {})
115+
self.assertIsNone(platform._uname_cache)
116+
self.assertIsNone(platform._os_release_cache)
117+
86118
def test_architecture(self):
87119
res = platform.architecture()
88120

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Removed the ``--with-emscripten-target`` configure flag. We unified the
2+
``node`` and ``browser`` options and the same build can now be used, independent
3+
of target runtime.

0 commit comments

Comments
 (0)