Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1dddc99

Browse filesBrowse files
Merge branch 'main' (early part) into python-cli-help
2 parents 31bd5c2 + 61733a2 commit 1dddc99
Copy full SHA for 1dddc99

File tree

Expand file treeCollapse file tree

9 files changed

+88
-71
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+88
-71
lines changed

‎Doc/library/itertools.rst

Copy file name to clipboardExpand all lines: Doc/library/itertools.rst
+43-43Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -785,8 +785,8 @@ well as with the built-in itertools such as ``map()``, ``filter()``,
785785

786786
A secondary purpose of the recipes is to serve as an incubator. The
787787
``accumulate()``, ``compress()``, and ``pairwise()`` itertools started out as
788-
recipes. Currently, the ``sliding_window()`` and ``iter_index()`` recipes
789-
are being tested to see whether they prove their worth.
788+
recipes. Currently, the ``sliding_window()``, ``iter_index()``, and ``sieve()``
789+
recipes are being tested to see whether they prove their worth.
790790

791791
Substantially all of these recipes and many, many others can be installed from
792792
the `more-itertools project <https://pypi.org/project/more-itertools/>`_ found
@@ -795,12 +795,12 @@ on the Python Package Index::
795795
python -m pip install more-itertools
796796

797797
Many of the recipes offer the same high performance as the underlying toolset.
798-
Superior memory performance is kept by processing elements one at a time
799-
rather than bringing the whole iterable into memory all at once. Code volume is
800-
kept small by linking the tools together in a functional style which helps
801-
eliminate temporary variables. High speed is retained by preferring
802-
"vectorized" building blocks over the use of for-loops and :term:`generator`\s
803-
which incur interpreter overhead.
798+
Superior memory performance is kept by processing elements one at a time rather
799+
than bringing the whole iterable into memory all at once. Code volume is kept
800+
small by linking the tools together in a `functional style
801+
<https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`_. High speed
802+
is retained by preferring "vectorized" building blocks over the use of for-loops
803+
and :term:`generators <generator>` which incur interpreter overhead.
804804

805805
.. testcode::
806806

@@ -873,6 +873,14 @@ which incur interpreter overhead.
873873
"Returns True if all the elements are equal to each other."
874874
return len(take(2, groupby(iterable, key))) <= 1
875875

876+
def unique_justseen(iterable, key=None):
877+
"List unique elements, preserving order. Remember only the element just seen."
878+
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
879+
# unique_justseen('ABBcCAD', str.casefold) --> A B c A D
880+
if key is None:
881+
return map(operator.itemgetter(0), groupby(iterable))
882+
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
883+
876884
def unique_everseen(iterable, key=None):
877885
"List unique elements, preserving order. Remember all elements ever seen."
878886
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
@@ -889,35 +897,6 @@ which incur interpreter overhead.
889897
seen.add(k)
890898
yield element
891899

892-
def unique_justseen(iterable, key=None):
893-
"List unique elements, preserving order. Remember only the element just seen."
894-
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
895-
# unique_justseen('ABBcCAD', str.casefold) --> A B c A D
896-
if key is None:
897-
return map(operator.itemgetter(0), groupby(iterable))
898-
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
899-
900-
def iter_index(iterable, value, start=0, stop=None):
901-
"Return indices where a value occurs in a sequence or iterable."
902-
# iter_index('AABCADEAF', 'A') --> 0 1 4 7
903-
seq_index = getattr(iterable, 'index', None)
904-
if seq_index is None:
905-
# Path for general iterables
906-
it = islice(iterable, start, stop)
907-
for i, element in enumerate(it, start):
908-
if element is value or element == value:
909-
yield i
910-
else:
911-
# Path for sequences with an index() method
912-
stop = len(iterable) if stop is None else stop
913-
i = start
914-
try:
915-
while True:
916-
yield (i := seq_index(value, i, stop))
917-
i += 1
918-
except ValueError:
919-
pass
920-
921900
def sliding_window(iterable, n):
922901
"Collect data into overlapping fixed-length chunks or blocks."
923902
# sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
@@ -967,6 +946,27 @@ which incur interpreter overhead.
967946
slices = starmap(slice, combinations(range(len(seq) + 1), 2))
968947
return map(operator.getitem, repeat(seq), slices)
969948

949+
def iter_index(iterable, value, start=0, stop=None):
950+
"Return indices where a value occurs in a sequence or iterable."
951+
# iter_index('AABCADEAF', 'A') --> 0 1 4 7
952+
seq_index = getattr(iterable, 'index', None)
953+
if seq_index is None:
954+
# Path for general iterables
955+
it = islice(iterable, start, stop)
956+
for i, element in enumerate(it, start):
957+
if element is value or element == value:
958+
yield i
959+
else:
960+
# Path for sequences with an index() method
961+
stop = len(iterable) if stop is None else stop
962+
i = start
963+
try:
964+
while True:
965+
yield (i := seq_index(value, i, stop))
966+
i += 1
967+
except ValueError:
968+
pass
969+
970970
def iter_except(func, exception, first=None):
971971
""" Call a function repeatedly until an exception is raised.
972972

@@ -1047,8 +1047,8 @@ The following recipes have a more mathematical flavor:
10471047

10481048
Computes with better numeric stability than Horner's method.
10491049
"""
1050-
# Evaluate x³ -4x² -17x + 60 at x = 2.5
1051-
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
1050+
# Evaluate x³ -4x² -17x + 60 at x = 5
1051+
# polynomial_eval([1, -4, -17, 60], x=5) --> 0
10521052
n = len(coefficients)
10531053
if not n:
10541054
return type(x)(0)
@@ -1311,10 +1311,10 @@ The following recipes have a more mathematical flavor:
13111311

13121312
>>> from fractions import Fraction
13131313
>>> from decimal import Decimal
1314-
>>> polynomial_eval([1, -4, -17, 60], x=2)
1315-
18
1316-
>>> x = 2; x**3 - 4*x**2 -17*x + 60
1317-
18
1314+
>>> polynomial_eval([1, -4, -17, 60], x=5)
1315+
0
1316+
>>> x = 5; x**3 - 4*x**2 -17*x + 60
1317+
0
13181318
>>> polynomial_eval([1, -4, -17, 60], x=2.5)
13191319
8.125
13201320
>>> x = 2.5; x**3 - 4*x**2 -17*x + 60

‎Lib/test/test_importlib/extension/test_case_sensitivity.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/extension/test_case_sensitivity.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
machinery = util.import_importlib('importlib.machinery')
99

1010

11-
@unittest.skipIf(util.EXTENSIONS.filename is None, f'{util.EXTENSIONS.name} not available')
11+
@unittest.skipIf(util.EXTENSIONS is None or util.EXTENSIONS.filename is None,
12+
'dynamic loading not supported or test module not available')
1213
@util.case_insensitive_tests
1314
class ExtensionModuleCaseSensitivityTest(util.CASEOKTestBase):
1415

‎Lib/test/test_importlib/extension/test_finder.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/extension/test_finder.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class FinderTests(abc.FinderTests):
1111
"""Test the finder for extension modules."""
1212

1313
def setUp(self):
14-
if not self.machinery.EXTENSION_SUFFIXES:
14+
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
1515
raise unittest.SkipTest("Requires dynamic loading support.")
1616
if util.EXTENSIONS.name in sys.builtin_module_names:
1717
raise unittest.SkipTest(

‎Lib/test/test_importlib/extension/test_loader.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/extension/test_loader.py
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class LoaderTests:
1717
"""Test ExtensionFileLoader."""
1818

1919
def setUp(self):
20-
if not self.machinery.EXTENSION_SUFFIXES:
20+
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
2121
raise unittest.SkipTest("Requires dynamic loading support.")
2222
if util.EXTENSIONS.name in sys.builtin_module_names:
2323
raise unittest.SkipTest(
@@ -99,7 +99,7 @@ class SinglePhaseExtensionModuleTests(abc.LoaderTests):
9999
# Test loading extension modules without multi-phase initialization.
100100

101101
def setUp(self):
102-
if not self.machinery.EXTENSION_SUFFIXES:
102+
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
103103
raise unittest.SkipTest("Requires dynamic loading support.")
104104
self.name = '_testsinglephase'
105105
if self.name in sys.builtin_module_names:
@@ -180,7 +180,7 @@ class MultiPhaseExtensionModuleTests(abc.LoaderTests):
180180
# Test loading extension modules with multi-phase initialization (PEP 489).
181181

182182
def setUp(self):
183-
if not self.machinery.EXTENSION_SUFFIXES:
183+
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
184184
raise unittest.SkipTest("Requires dynamic loading support.")
185185
self.name = '_testmultiphase'
186186
if self.name in sys.builtin_module_names:

‎Lib/test/test_importlib/extension/test_path_hook.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/extension/test_path_hook.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import unittest
66

77

8+
@unittest.skipIf(util.EXTENSIONS is None or util.EXTENSIONS.filename is None,
9+
'dynamic loading not supported or test module not available')
810
class PathHookTests:
911

1012
"""Test the path hook for extension modules."""

‎Lib/test/test_importlib/test_spec.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/test_spec.py
+6-3Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ def test_spec_from_loader_is_package_true_with_fileloader(self):
502502
self.assertEqual(spec.loader, self.fileloader)
503503
self.assertEqual(spec.origin, self.path)
504504
self.assertIs(spec.loader_state, None)
505-
self.assertEqual(spec.submodule_search_locations, [os.getcwd()])
505+
location = cwd if (cwd := os.getcwd()) != '/' else ''
506+
self.assertEqual(spec.submodule_search_locations, [location])
506507
self.assertEqual(spec.cached, self.cached)
507508
self.assertTrue(spec.has_location)
508509

@@ -601,7 +602,8 @@ def test_spec_from_file_location_smsl_empty(self):
601602
self.assertEqual(spec.loader, self.fileloader)
602603
self.assertEqual(spec.origin, self.path)
603604
self.assertIs(spec.loader_state, None)
604-
self.assertEqual(spec.submodule_search_locations, [os.getcwd()])
605+
location = cwd if (cwd := os.getcwd()) != '/' else ''
606+
self.assertEqual(spec.submodule_search_locations, [location])
605607
self.assertEqual(spec.cached, self.cached)
606608
self.assertTrue(spec.has_location)
607609

@@ -626,7 +628,8 @@ def test_spec_from_file_location_smsl_default(self):
626628
self.assertEqual(spec.loader, self.pkgloader)
627629
self.assertEqual(spec.origin, self.path)
628630
self.assertIs(spec.loader_state, None)
629-
self.assertEqual(spec.submodule_search_locations, [os.getcwd()])
631+
location = cwd if (cwd := os.getcwd()) != '/' else ''
632+
self.assertEqual(spec.submodule_search_locations, [location])
630633
self.assertEqual(spec.cached, self.cached)
631634
self.assertTrue(spec.has_location)
632635

‎Lib/test/test_importlib/test_util.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/test_util.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ def test_cache_from_source_respects_pycache_prefix_relative(self):
577577
with util.temporary_pycache_prefix(pycache_prefix):
578578
self.assertEqual(
579579
self.util.cache_from_source(path, optimization=''),
580-
expect)
580+
os.path.normpath(expect))
581581

582582
@unittest.skipIf(sys.implementation.cache_tag is None,
583583
'requires sys.implementation.cache_tag to not be None')

‎Lib/test/test_importlib/util.py

Copy file name to clipboardExpand all lines: Lib/test/test_importlib/util.py
+29-19Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import marshal
77
import os
88
import os.path
9+
from test import support
910
from test.support import import_helper
1011
from test.support import os_helper
1112
import unittest
@@ -22,25 +23,34 @@
2223
if 'importlib' not in sys.builtin_module_names:
2324
BUILTINS.bad_name = 'importlib'
2425

25-
EXTENSIONS = types.SimpleNamespace()
26-
EXTENSIONS.path = None
27-
EXTENSIONS.ext = None
28-
EXTENSIONS.filename = None
29-
EXTENSIONS.file_path = None
30-
EXTENSIONS.name = '_testsinglephase'
31-
32-
def _extension_details():
33-
global EXTENSIONS
34-
for path in sys.path:
35-
for ext in machinery.EXTENSION_SUFFIXES:
36-
filename = EXTENSIONS.name + ext
37-
file_path = os.path.join(path, filename)
38-
if os.path.exists(file_path):
39-
EXTENSIONS.path = path
40-
EXTENSIONS.ext = ext
41-
EXTENSIONS.filename = filename
42-
EXTENSIONS.file_path = file_path
43-
return
26+
if support.is_wasi:
27+
# dlopen() is a shim for WASI as of WASI SDK which fails by default.
28+
# We don't provide an implementation, so tests will fail.
29+
# But we also don't want to turn off dynamic loading for those that provide
30+
# a working implementation.
31+
def _extension_details():
32+
global EXTENSIONS
33+
EXTENSIONS = None
34+
else:
35+
EXTENSIONS = types.SimpleNamespace()
36+
EXTENSIONS.path = None
37+
EXTENSIONS.ext = None
38+
EXTENSIONS.filename = None
39+
EXTENSIONS.file_path = None
40+
EXTENSIONS.name = '_testsinglephase'
41+
42+
def _extension_details():
43+
global EXTENSIONS
44+
for path in sys.path:
45+
for ext in machinery.EXTENSION_SUFFIXES:
46+
filename = EXTENSIONS.name + ext
47+
file_path = os.path.join(path, filename)
48+
if os.path.exists(file_path):
49+
EXTENSIONS.path = path
50+
EXTENSIONS.ext = ext
51+
EXTENSIONS.filename = filename
52+
EXTENSIONS.file_path = file_path
53+
return
4454

4555
_extension_details()
4656

+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update test_importlib so that it passes under WASI SDK 21.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.