Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into pythongh-112536-tsa…
Browse files Browse the repository at this point in the history
…n-tests
  • Loading branch information
corona10 committed Mar 12, 2024
2 parents b571b9d + 3325699 commit 8f28847
Show file tree
Hide file tree
Showing 105 changed files with 1,171 additions and 652 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ jobs:
- name: SSL tests
run: ./python Lib/test/ssltests.py

build_wasi:
name: 'WASI'
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
uses: ./.github/workflows/reusable-wasi.yml
with:
config_hash: ${{ needs.check_source.outputs.config_hash }}

test_hypothesis:
name: "Hypothesis tests on Ubuntu"
runs-on: ubuntu-20.04
Expand Down Expand Up @@ -525,6 +533,7 @@ jobs:
- build_ubuntu
- build_ubuntu_free_threading
- build_ubuntu_ssltests
- build_wasi
- build_windows
- build_windows_free_threading
- test_hypothesis
Expand Down Expand Up @@ -558,6 +567,7 @@ jobs:
build_ubuntu,
build_ubuntu_free_threading,
build_ubuntu_ssltests,
build_wasi,
build_windows,
build_windows_free_threading,
build_asan,
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/reusable-wasi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
on:
workflow_call:
inputs:
config_hash:
required: true
type: string

jobs:
build_wasi_reusable:
name: 'build and test'
timeout-minutes: 60
runs-on: ubuntu-20.04
env:
WASMTIME_VERSION: 18.0.2
WASI_SDK_VERSION: 20
WASI_SDK_PATH: /opt/wasi-sdk
CROSS_BUILD_PYTHON: cross-build/build
CROSS_BUILD_WASI: cross-build/wasm32-wasi
steps:
- uses: actions/checkout@v4
# No problem resolver registered as one doesn't currently exist for Clang.
- name: "Install wasmtime"
uses: jcbhmr/setup-wasmtime@v2
with:
wasmtime-version: ${{ env.WASMTIME_VERSION }}
- name: "Restore WASI SDK"
id: cache-wasi-sdk
uses: actions/cache@v4
with:
path: ${{ env.WASI_SDK_PATH }}
key: ${{ runner.os }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}
- name: "Install WASI SDK"
if: steps.cache-wasi-sdk.outputs.cache-hit != 'true'
run: |
mkdir ${{ env.WASI_SDK_PATH }} && \
curl -s -S --location https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${{ env.WASI_SDK_VERSION }}/wasi-sdk-${{ env.WASI_SDK_VERSION }}.0-linux.tar.gz | \
tar --strip-components 1 --directory ${{ env.WASI_SDK_PATH }} --extract --gunzip
- name: "Configure ccache action"
uses: hendrikmuhs/ccache-action@v1.2
with:
save: ${{ github.event_name == 'push' }}
max-size: "200M"
- name: "Add ccache to PATH"
run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
- name: "Install Python"
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: "Restore Python build config.cache"
uses: actions/cache@v4
with:
path: ${{ env.CROSS_BUILD_PYTHON }}/config.cache
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
- name: "Configure build Python"
run: python3 Tools/wasm/wasi.py configure-build-python -- --config-cache --with-pydebug
- name: "Make build Python"
run: python3 Tools/wasm/wasi.py make-build-python
- name: "Restore host config.cache"
uses: actions/cache@v4
with:
path: ${{ env.CROSS_BUILD_WASI }}/config.cache
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}-${{ inputs.config_hash }}
- name: "Configure host"
# `--with-pydebug` inferred from configure-build-python
run: python3 Tools/wasm/wasi.py configure-host -- --config-cache
- name: "Make host"
run: python3 Tools/wasm/wasi.py make-host
- name: "Display build info"
run: make --directory ${{ env.CROSS_BUILD_WASI }} pythoninfo
- name: "Test"
run: make --directory ${{ env.CROSS_BUILD_WASI }} test
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Mark stale pull requests

on:
schedule:
- cron: "0 0 * * *"
- cron: "0 */12 * * *"

permissions:
pull-requests: write
Expand Down
112 changes: 103 additions & 9 deletions Doc/library/itertools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ The following recipes have a more mathematical flavor:

def sum_of_squares(it):
"Add up the squares of the input values."
# sum_of_squares([10, 20, 30]) -> 1400
# sum_of_squares([10, 20, 30]) --> 1400
return math.sumprod(*tee(it))
def reshape(matrix, cols):
Expand All @@ -1019,17 +1019,16 @@ The following recipes have a more mathematical flavor:

def convolve(signal, kernel):
"""Discrete linear convolution of two iterables.
Equivalent to polynomial multiplication.

The kernel is fully consumed before the calculations begin.
The signal is consumed lazily and can be infinite.

Convolutions are mathematically commutative.
If the signal and kernel are swapped,
the output will be the same.
Convolutions are mathematically commutative; however, the inputs are
evaluated differently. The signal is consumed lazily and can be
infinite. The kernel is fully consumed before the calculations begin.

Article: https://betterexplained.com/articles/intuitive-convolution/
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
"""
# convolve([1, -1, -20], [1, -3]) --> 1 -4 -17 60
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
# convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
# convolve(data, [1, -2, 1]) --> 2nd derivative estimate
Expand Down Expand Up @@ -1067,7 +1066,7 @@ The following recipes have a more mathematical flavor:
f(x) = x³ -4x² -17x + 60
f'(x) = 3x² -8x -17
"""
# polynomial_derivative([1, -4, -17, 60]) -> [3, -8, -17]
# polynomial_derivative([1, -4, -17, 60]) --> [3, -8, -17]
n = len(coefficients)
powers = reversed(range(1, n))
return list(map(operator.mul, coefficients, powers))
Expand Down Expand Up @@ -1169,6 +1168,12 @@ The following recipes have a more mathematical flavor:

>>> take(10, count())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> # Verify that the input is consumed lazily
>>> it = iter('abcdef')
>>> take(3, it)
['a', 'b', 'c']
>>> list(it)
['d', 'e', 'f']

>>> list(prepend(1, [2, 3, 4]))
[1, 2, 3, 4]
Expand All @@ -1181,25 +1186,45 @@ The following recipes have a more mathematical flavor:

>>> list(tail(3, 'ABCDEFG'))
['E', 'F', 'G']
>>> # Verify the input is consumed greedily
>>> input_iterator = iter('ABCDEFG')
>>> output_iterator = tail(3, input_iterator)
>>> list(input_iterator)
[]

>>> it = iter(range(10))
>>> consume(it, 3)
>>> # Verify the input is consumed lazily
>>> next(it)
3
>>> # Verify the input is consumed completely
>>> consume(it)
>>> next(it, 'Done')
'Done'

>>> nth('abcde', 3)
'd'

>>> nth('abcde', 9) is None
True
>>> # Verify that the input is consumed lazily
>>> it = iter('abcde')
>>> nth(it, 2)
'c'
>>> list(it)
['d', 'e']

>>> [all_equal(s) for s in ('', 'A', 'AAAA', 'AAAB', 'AAABA')]
[True, True, True, False, False]
>>> [all_equal(s, key=str.casefold) for s in ('', 'A', 'AaAa', 'AAAB', 'AAABA')]
[True, True, True, False, False]
>>> # Verify that the input is consumed lazily and that only
>>> # one element of a second equivalence class is used to disprove
>>> # the assertion that all elements are equal.
>>> it = iter('aaabbbccc')
>>> all_equal(it)
False
>>> ''.join(it)
'bbccc'

>>> quantify(range(99), lambda x: x%2==0)
50
Expand All @@ -1222,6 +1247,11 @@ The following recipes have a more mathematical flavor:

>>> list(ncycles('abc', 3))
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']
>>> # Verify greedy consumption of input iterator
>>> input_iterator = iter('abc')
>>> output_iterator = ncycles(input_iterator, 3)
>>> list(input_iterator)
[]

>>> sum_of_squares([10, 20, 30])
1400
Expand All @@ -1248,19 +1278,41 @@ The following recipes have a more mathematical flavor:

>>> list(transpose([(1, 2, 3), (11, 22, 33)]))
[(1, 11), (2, 22), (3, 33)]
>>> # Verify that the inputs are consumed lazily
>>> input1 = iter([1, 2, 3])
>>> input2 = iter([11, 22, 33])
>>> output_iterator = transpose([input1, input2])
>>> next(output_iterator)
(1, 11)
>>> list(zip(input1, input2))
[(2, 22), (3, 33)]

>>> list(matmul([(7, 5), (3, 5)], [[2, 5], [7, 9]]))
[(49, 80), (41, 60)]
>>> list(matmul([[2, 5], [7, 9], [3, 4]], [[7, 11, 5, 4, 9], [3, 5, 2, 6, 3]]))
[(29, 47, 20, 38, 33), (76, 122, 53, 82, 90), (33, 53, 23, 36, 39)]

>>> list(convolve([1, -1, -20], [1, -3])) == [1, -4, -17, 60]
True
>>> data = [20, 40, 24, 32, 20, 28, 16]
>>> list(convolve(data, [0.25, 0.25, 0.25, 0.25]))
[5.0, 15.0, 21.0, 29.0, 29.0, 26.0, 24.0, 16.0, 11.0, 4.0]
>>> list(convolve(data, [1, -1]))
[20, 20, -16, 8, -12, 8, -12, -16]
>>> list(convolve(data, [1, -2, 1]))
[20, 0, -36, 24, -20, 20, -20, -4, 16]
>>> # Verify signal is consumed lazily and the kernel greedily
>>> signal_iterator = iter([10, 20, 30, 40, 50])
>>> kernel_iterator = iter([1, 2, 3])
>>> output_iterator = convolve(signal_iterator, kernel_iterator)
>>> list(kernel_iterator)
[]
>>> next(output_iterator)
10
>>> next(output_iterator)
40
>>> list(signal_iterator)
[30, 40, 50]

>>> from fractions import Fraction
>>> from decimal import Decimal
Expand Down Expand Up @@ -1348,6 +1400,17 @@ The following recipes have a more mathematical flavor:
>>> # Test list input. Lists do not support None for the stop argument
>>> list(iter_index(list('AABCADEAF'), 'A'))
[0, 1, 4, 7]
>>> # Verify that input is consumed lazily
>>> input_iterator = iter('AABCADEAF')
>>> output_iterator = iter_index(input_iterator, 'A')
>>> next(output_iterator)
0
>>> next(output_iterator)
1
>>> next(output_iterator)
4
>>> ''.join(input_iterator)
'DEAF'

>>> list(sieve(30))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Expand Down Expand Up @@ -1499,6 +1562,17 @@ The following recipes have a more mathematical flavor:
[0, 2, 4, 6, 8]
>>> list(odds)
[1, 3, 5, 7, 9]
>>> # Verify that the input is consumed lazily
>>> input_iterator = iter(range(10))
>>> evens, odds = partition(is_odd, input_iterator)
>>> next(odds)
1
>>> next(odds)
3
>>> next(evens)
0
>>> list(input_iterator)
[4, 5, 6, 7, 8, 9]

>>> list(subslices('ABCD'))
['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
Expand All @@ -1518,13 +1592,27 @@ The following recipes have a more mathematical flavor:
['A', 'B', 'C', 'D']
>>> list(unique_everseen('ABBcCAD', str.casefold))
['A', 'B', 'c', 'D']
>>> # Verify that the input is consumed lazily
>>> input_iterator = iter('AAAABBBCCDAABBB')
>>> output_iterator = unique_everseen(input_iterator)
>>> next(output_iterator)
'A'
>>> ''.join(input_iterator)
'AAABBBCCDAABBB'

>>> list(unique_justseen('AAAABBBCCDAABBB'))
['A', 'B', 'C', 'D', 'A', 'B']
>>> list(unique_justseen('ABBCcAD', str.casefold))
['A', 'B', 'C', 'A', 'D']
>>> list(unique_justseen('ABBcCAD', str.casefold))
['A', 'B', 'c', 'A', 'D']
>>> # Verify that the input is consumed lazily
>>> input_iterator = iter('AAAABBBCCDAABBB')
>>> output_iterator = unique_justseen(input_iterator)
>>> next(output_iterator)
'A'
>>> ''.join(input_iterator)
'AAABBBCCDAABBB'

>>> d = dict(a=1, b=2, c=3)
>>> it = iter_except(d.popitem, KeyError)
Expand All @@ -1545,6 +1633,12 @@ The following recipes have a more mathematical flavor:

>>> first_true('ABC0DEF1', '9', str.isdigit)
'0'
>>> # Verify that inputs are consumed lazily
>>> it = iter('ABC0DEF1')
>>> first_true(it, predicate=str.isdigit)
'0'
>>> ''.join(it)
'DEF1'


.. testcode::
Expand Down
Loading

0 comments on commit 8f28847

Please sign in to comment.