diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ecbb02f7..c35bb42d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,7 +4,6 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - # Check for updates on Sunday, 8PM UTC - interval: "weekly" - day: "sunday" - time: "20:00" + # Check for updates on the first Sunday of every month, 8PM UTC + interval: "cron" + cronjob: "0 20 * * sun#1" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2a78d775..d0ecffce 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,10 +1,6 @@ name: CI on: pull_request: - push: - branches: - - main - - 3.* workflow_call: inputs: build-number: @@ -24,9 +20,6 @@ on: LIBFFI_VERSION: description: "The libFFI version used for the build." value: ${{ jobs.config.outputs.LIBFFI_VERSION }} - MPDECIMAL_VERSION: - description: "The mpdecimal version used for the build." - value: ${{ jobs.config.outputs.MPDECIMAL_VERSION }} OPENSSL_VERSION: description: "The OpenSSL version used for the build." value: ${{ jobs.config.outputs.OPENSSL_VERSION }} @@ -55,91 +48,252 @@ jobs: BUILD_NUMBER: ${{ steps.extract.outputs.BUILD_NUMBER }} BZIP2_VERSION: ${{ steps.extract.outputs.BZIP2_VERSION }} LIBFFI_VERSION: ${{ steps.extract.outputs.LIBFFI_VERSION }} - MPDECIMAL_VERSION: ${{ steps.extract.outputs.MPDECIMAL_VERSION }} OPENSSL_VERSION: ${{ steps.extract.outputs.OPENSSL_VERSION }} XZ_VERSION: ${{ steps.extract.outputs.XZ_VERSION }} steps: - - uses: actions/checkout@v4.1.7 - - - name: Extract config variables - id: extract - run: | - PYTHON_VER=$(make config | grep "PYTHON_VER=" | cut -d "=" -f 2) - PYTHON_VERSION=$(make config | grep "PYTHON_VERSION=" | cut -d "=" -f 2) - BZIP2_VERSION=$(make config | grep "BZIP2_VERSION=" | cut -d "=" -f 2) - LIBFFI_VERSION=$(make config | grep "LIBFFI_VERSION=" | cut -d "=" -f 2) - MPDECIMAL_VERSION=$(make config | grep "MPDECIMAL_VERSION=" | cut -d "=" -f 2) - OPENSSL_VERSION=$(make config | grep "OPENSSL_VERSION=" | cut -d "=" -f 2) - XZ_VERSION=$(make config | grep "XZ_VERSION=" | cut -d "=" -f 2) - if [ -z "${{ inputs.build-number }}" ]; then - BUILD_NUMBER=custom - else - BUILD_NUMBER=${{ inputs.build-number }} - fi - - echo "PYTHON_VER=${PYTHON_VER}" | tee -a ${GITHUB_OUTPUT} - echo "PYTHON_VERSION=${PYTHON_VERSION}" | tee -a ${GITHUB_OUTPUT} - echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a ${GITHUB_OUTPUT} - echo "BZIP2_VERSION=${BZIP2_VERSION}" | tee -a ${GITHUB_OUTPUT} - echo "LIBFFI_VERSION=${LIBFFI_VERSION}" | tee -a ${GITHUB_OUTPUT} - echo "MPDECIMAL_VERSION=${MPDECIMAL_VERSION}" | tee -a ${GITHUB_OUTPUT} - echo "OPENSSL_VERSION=${OPENSSL_VERSION}" | tee -a ${GITHUB_OUTPUT} - echo "XZ_VERSION=${XZ_VERSION}" | tee -a ${GITHUB_OUTPUT} + - uses: actions/checkout@v6 + + - name: Extract config variables + id: extract + run: | + PYTHON_VER=$(make config | grep "PYTHON_VER=" | cut -d "=" -f 2) + PYTHON_VERSION=$(make config | grep "PYTHON_VERSION=" | cut -d "=" -f 2) + BZIP2_VERSION=$(make config | grep "BZIP2_VERSION=" | cut -d "=" -f 2) + LIBFFI_VERSION=$(make config | grep "LIBFFI_VERSION=" | cut -d "=" -f 2) + OPENSSL_VERSION=$(make config | grep "OPENSSL_VERSION=" | cut -d "=" -f 2) + XZ_VERSION=$(make config | grep "XZ_VERSION=" | cut -d "=" -f 2) + if [ -z "${{ inputs.build-number }}" ]; then + BUILD_NUMBER=custom + else + BUILD_NUMBER=${{ inputs.build-number }} + fi + + echo "PYTHON_VER=${PYTHON_VER}" | tee -a ${GITHUB_OUTPUT} + echo "PYTHON_VERSION=${PYTHON_VERSION}" | tee -a ${GITHUB_OUTPUT} + echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a ${GITHUB_OUTPUT} + echo "BZIP2_VERSION=${BZIP2_VERSION}" | tee -a ${GITHUB_OUTPUT} + echo "LIBFFI_VERSION=${LIBFFI_VERSION}" | tee -a ${GITHUB_OUTPUT} + echo "OPENSSL_VERSION=${OPENSSL_VERSION}" | tee -a ${GITHUB_OUTPUT} + echo "XZ_VERSION=${XZ_VERSION}" | tee -a ${GITHUB_OUTPUT} build: - runs-on: macOS-latest - needs: [ config ] + runs-on: macOS-15 + needs: [config] strategy: fail-fast: false matrix: - target: ['macOS', 'iOS', 'tvOS', 'watchOS'] + platform: ["macOS", "iOS", "tvOS", "watchOS"] + + steps: + - uses: actions/checkout@v6 + + - name: Set up Xcode + # GitHub recommends explicitly selecting the desired Xcode version: + # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 + # This became a necessity as a result of + # https://github.com/actions/runner-images/issues/12541 and + # https://github.com/actions/runner-images/issues/12751. + run: | + sudo xcode-select --switch /Applications/Xcode_16.4.app + + - name: Set up Python + uses: actions/setup-python@v6.1.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true + + - name: Build ${{ matrix.platform }} + run: | + # Do the build for the requested platform. + make ${{ matrix.platform }} BUILD_NUMBER=${{ needs.config.outputs.BUILD_NUMBER }} + + - name: Upload build artefacts + uses: actions/upload-artifact@v6.0.0 + with: + name: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + + briefcase-testbed: + name: Briefcase testbed (${{ matrix.platform }}) + runs-on: macOS-15 + needs: [config, build] + strategy: + fail-fast: false + matrix: + platform: ["macOS", "iOS"] include: - - briefcase-run-args: - - run-tests: false + - briefcase-run-args: + + - platform: iOS + briefcase-run-args: ' -d "iPhone 16e::iOS 18.5"' + + steps: + - uses: actions/checkout@v6 + + - name: Set up Xcode + # GitHub recommends explicitly selecting the desired Xcode version: + # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 + # This became a necessity as a result of + # https://github.com/actions/runner-images/issues/12541 and + # https://github.com/actions/runner-images/issues/12751. + run: | + sudo xcode-select --switch /Applications/Xcode_16.4.app + + - name: Get build artifact + uses: actions/download-artifact@v7.0.0 + with: + pattern: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist + merge-multiple: true - - target: macOS - run-tests: true + - name: Set up Python + uses: actions/setup-python@v6.1.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true - - target: iOS - briefcase-run-args: ' -d "iPhone SE (3rd generation)"' - run-tests: true + - uses: actions/checkout@v6 + with: + repository: beeware/Python-support-testbed + path: Python-support-testbed + + - name: Install dependencies + run: | + # Use the development version of Briefcase + python -m pip install git+https://github.com/beeware/briefcase.git + + - name: Run support testbed check + timeout-minutes: 15 + working-directory: Python-support-testbed + run: briefcase run ${{ matrix.platform }} Xcode --test ${{ matrix.briefcase-run-args }} -C support_package=\'../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz\' + + cpython-testbed: + name: CPython testbed (${{ matrix.platform }}) + runs-on: macOS-15 + needs: [config, build] + strategy: + fail-fast: false + matrix: + platform: ["iOS", "tvOS"] + include: + - platform: "iOS" + testbed-args: '--simulator "iPhone 16e,arch=arm64,OS=18.5"' + + steps: + - uses: actions/checkout@v6 + + - name: Get build artifact + uses: actions/download-artifact@v7.0.0 + with: + pattern: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist + merge-multiple: true + + - name: Set up Xcode + # GitHub recommends explicitly selecting the desired Xcode version: + # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 + # This became a necessity as a result of + # https://github.com/actions/runner-images/issues/12541 and + # https://github.com/actions/runner-images/issues/12751. + run: | + sudo xcode-select --switch /Applications/Xcode_16.4.app + + - name: Set up Python + uses: actions/setup-python@v6.1.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true + + - name: Unpack support package + run: | + mkdir -p support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + cd support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + tar zxvf ../../../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + + - name: Run CPython testbed + timeout-minutes: 15 + working-directory: support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + run: | + # Run a representative subset of CPython core tests: + # - test_builtin as a test of core language tools + # - test_grammar as a test of core language features + # - test_os as a test of system library calls + # - test_bz2 as a simple test of third party libraries + # - test_ctypes as a test of FFI + python -m testbed run --verbose ${{ matrix.testbed-args }} -- test -W --timeout=-1 test_builtin test_grammar test_os test_bz2 test_ctypes + + crossenv-test: + name: Cross-platform env test (${{ matrix.multiarch }}) + runs-on: macOS-latest + needs: [config, build] + strategy: + fail-fast: false + matrix: + include: + - platform: iOS + slice: ios-arm64_x86_64-simulator + multiarch: arm64-iphonesimulator + - platform: iOS + slice: ios-arm64_x86_64-simulator + multiarch: x86_64-iphonesimulator + - platform: iOS + slice: ios-arm64 + multiarch: arm64-iphoneos steps: - - uses: actions/checkout@v4.1.7 - - - name: Set up Python - uses: actions/setup-python@v5.3.0 - with: - # Appending -dev ensures that we can always build the dev release. - # It's a no-op for versions that have been published. - python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev - - - name: Build ${{ matrix.target }} - run: | - # Do the build for the requested target. - make ${{ matrix.target }} BUILD_NUMBER=${{ needs.config.outputs.BUILD_NUMBER }} - - - name: Upload build artefacts - uses: actions/upload-artifact@v4.4.3 - with: - name: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.target }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz - path: dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.target }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz - - - uses: actions/checkout@v4.1.7 - if: matrix.run-tests - with: - repository: beeware/Python-support-testbed - path: Python-support-testbed - - - name: Install dependencies - if: matrix.run-tests - run: | - # Use the development version of Briefcase - python -m pip install git+https://github.com/beeware/briefcase.git - - - name: Run support testbed check - if: matrix.run-tests - timeout-minutes: 10 - working-directory: Python-support-testbed - run: briefcase run ${{ matrix.target }} Xcode --test ${{ matrix.briefcase-run-args }} -C support_package=\'../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.target }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz\' + - uses: actions/checkout@v6 + + - name: Get build artifact + uses: actions/download-artifact@v7.0.0 + with: + pattern: Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + path: dist + merge-multiple: true + + - name: Set up Python + uses: actions/setup-python@v6.1.0 + with: + # Appending -dev ensures that we can always build the dev release. + # It's a no-op for versions that have been published. + python-version: ${{ needs.config.outputs.PYTHON_VER }}-dev + # Ensure that we *always* use the latest build, not a cached version. + # It's an edge case, but when a new alpha is released, we need to use it ASAP. + check-latest: true + + - name: Unpack support package + run: | + mkdir -p support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + cd support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }} + tar zxvf ../../../dist/Python-${{ needs.config.outputs.PYTHON_VER }}-${{ matrix.platform }}-support.${{ needs.config.outputs.BUILD_NUMBER }}.tar.gz + + - name: Run cross-platform environment test + env: + PYTHON_CROSS_PLATFORM: ${{ matrix.platform }} + PYTHON_CROSS_SLICE: ${{ matrix.slice }} + PYTHON_CROSS_MULTIARCH: ${{ matrix.multiarch }} + run: | + # Create and activate a native virtual environment + python${{ needs.config.outputs.PYTHON_VER }} -m venv cross-venv + source cross-venv/bin/activate + + # Install pytest + python -m pip install pytest + + # Convert venv into cross-venv + python support/${{ needs.config.outputs.PYTHON_VER }}/${{ matrix.platform }}/Python.xcframework/${{ matrix.slice }}/platform-config/${{ matrix.multiarch }}/make_cross_venv.py cross-venv + + # Run the test suite + python -m pytest tests diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index a9f69ed4..a3b23c53 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -8,43 +8,43 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Set up Python environment - uses: actions/setup-python@v5.3.0 - with: - python-version: "3.X" + - name: Set up Python environment + uses: actions/setup-python@v6.1.0 + with: + python-version: "3.X" - - name: Set build variables - id: build-vars - env: - TAG_NAME: ${{ github.ref }} - run: | - TAG=$(basename $TAG_NAME) - PYTHON_VER="${TAG%-*}" - BUILD_NUMBER="${TAG#*-}" + - name: Set build variables + id: build-vars + env: + TAG_NAME: ${{ github.ref }} + run: | + TAG=$(basename $TAG_NAME) + PYTHON_VER="${TAG%-*}" + BUILD_NUMBER="${TAG#*-}" - echo "TAG=${TAG}" | tee -a ${GITHUB_OUTPUT} - echo "PYTHON_VER=${PYTHON_VER}" | tee -a ${GITHUB_OUTPUT} - echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a ${GITHUB_OUTPUT} + echo "TAG=${TAG}" | tee -a ${GITHUB_OUTPUT} + echo "PYTHON_VER=${PYTHON_VER}" | tee -a ${GITHUB_OUTPUT} + echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a ${GITHUB_OUTPUT} - - name: Update Release Asset to S3 - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - run: | - python -m pip install -U pip - python -m pip install -U setuptools - python -m pip install awscli - # macOS build - curl -o macOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-macOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - aws s3 cp macOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/macOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-macOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - # iOS build - curl -o iOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-iOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - aws s3 cp iOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/iOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-iOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - # tvOS build - curl -o tvOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-tvOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - aws s3 cp tvOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/tvOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-tvOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - # watchOS build - curl -o watchOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-watchOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz - aws s3 cp watchOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/watchOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-watchOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + - name: Update Release Asset to S3 + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: | + python -m pip install -U pip + python -m pip install -U setuptools + python -m pip install awscli + # macOS build + curl -o macOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-macOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + aws s3 cp macOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/macOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-macOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + # iOS build + curl -o iOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-iOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + aws s3 cp iOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/iOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-iOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + # tvOS build + curl -o tvOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-tvOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + aws s3 cp tvOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/tvOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-tvOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + # watchOS build + curl -o watchOS-artefact.tar.gz -L https://github.com/beeware/Python-Apple-support/releases/download/${{ steps.build-vars.outputs.TAG }}/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-watchOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz + aws s3 cp watchOS-artefact.tar.gz s3://briefcase-support/python/${{ steps.build-vars.outputs.PYTHON_VER }}/watchOS/Python-${{ steps.build-vars.outputs.PYTHON_VER }}-watchOS-support.${{ steps.build-vars.outputs.BUILD_NUMBER }}.tar.gz diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5e5ef751..a94a79d4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,7 +5,7 @@ name: Build support package on: push: tags: - - '*-b*' + - "*-b*" jobs: config: @@ -16,20 +16,20 @@ jobs: BUILD_NUMBER: ${{ steps.build-vars.outputs.BUILD_NUMBER }} steps: - - name: Set Build Variables - id: build-vars - env: - TAG_NAME: ${{ github.ref }} - run: | - export TAG=$(basename $TAG_NAME) - export BUILD_NUMBER="${TAG#*-}" + - name: Set Build Variables + id: build-vars + env: + TAG_NAME: ${{ github.ref }} + run: | + export TAG=$(basename $TAG_NAME) + export BUILD_NUMBER="${TAG#*-}" - echo "TAG=${TAG}" | tee -a ${GITHUB_OUTPUT} - echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a ${GITHUB_OUTPUT} + echo "TAG=${TAG}" | tee -a ${GITHUB_OUTPUT} + echo "BUILD_NUMBER=${BUILD_NUMBER}" | tee -a ${GITHUB_OUTPUT} ci: name: CI - needs: [ config ] + needs: [config] uses: ./.github/workflows/ci.yaml with: build-number: ${{ needs.config.outputs.BUILD_NUMBER }} @@ -37,29 +37,28 @@ jobs: make-release: name: Make Release runs-on: ubuntu-latest - needs: [ config, ci ] + needs: [config, ci] steps: - - name: Get build artifacts - uses: actions/download-artifact@v4.1.8 - with: - pattern: Python-* - path: dist - merge-multiple: true + - name: Get build artifacts + uses: actions/download-artifact@v7.0.0 + with: + pattern: Python-* + path: dist + merge-multiple: true - - name: Create Release - uses: ncipollo/release-action@v1.14.0 - with: - name: ${{ needs.ci.outputs.PYTHON_VER }}-${{ needs.config.outputs.BUILD_NUMBER }} - tag: ${{ needs.ci.outputs.PYTHON_VER }}-${{ needs.config.outputs.BUILD_NUMBER }} - draft: true - body: | - Build ${{ needs.config.outputs.BUILD_NUMBER }} of the BeeWare support package for Python ${{ needs.ci.outputs.PYTHON_VER }}. + - name: Create Release + uses: ncipollo/release-action@v1.20.0 + with: + name: ${{ needs.ci.outputs.PYTHON_VER }}-${{ needs.config.outputs.BUILD_NUMBER }} + tag: ${{ needs.ci.outputs.PYTHON_VER }}-${{ needs.config.outputs.BUILD_NUMBER }} + draft: true + body: | + Build ${{ needs.config.outputs.BUILD_NUMBER }} of the BeeWare support package for Python ${{ needs.ci.outputs.PYTHON_VER }}. - Includes: - * Python ${{ needs.ci.outputs.PYTHON_VERSION }} - * BZip2 ${{ needs.ci.outputs.BZIP2_VERSION }} - * libFFI ${{ needs.ci.outputs.LIBFFI_VERSION }} - * mpdecimal ${{ needs.ci.outputs.MPDECIMAL_VERSION }} - * OpenSSL ${{ needs.ci.outputs.OPENSSL_VERSION }} - * XZ ${{ needs.ci.outputs.XZ_VERSION }} - artifacts: "dist/*" + Includes: + * Python ${{ needs.ci.outputs.PYTHON_VERSION }} + * BZip2 ${{ needs.ci.outputs.BZIP2_VERSION }} + * libFFI ${{ needs.ci.outputs.LIBFFI_VERSION }} + * OpenSSL ${{ needs.ci.outputs.OPENSSL_VERSION }} + * XZ ${{ needs.ci.outputs.XZ_VERSION }} + artifacts: "dist/*" diff --git a/Makefile b/Makefile index 04b19588..ee938e14 100644 --- a/Makefile +++ b/Makefile @@ -18,19 +18,18 @@ BUILD_NUMBER=custom # of a release cycle, as official binaries won't be published. # PYTHON_MICRO_VERSION is the full version number, without any alpha/beta/rc suffix. (e.g., 3.10.0) # PYTHON_VER is the major/minor version (e.g., 3.10) -PYTHON_VERSION=3.14.0a2 -PYTHON_PKG_VERSION=$(PYTHON_VERSION) +PYTHON_VERSION=3.10.20 +PYTHON_PKG_VERSION=3.10.11 PYTHON_MICRO_VERSION=$(shell echo $(PYTHON_VERSION) | grep -Eo "\d+\.\d+\.\d+") PYTHON_PKG_MICRO_VERSION=$(shell echo $(PYTHON_PKG_VERSION) | grep -Eo "\d+\.\d+\.\d+") PYTHON_VER=$(basename $(PYTHON_VERSION)) # The binary releases of dependencies, published at: # https://github.com/beeware/cpython-apple-source-deps/releases -BZIP2_VERSION=1.0.8-1 -LIBFFI_VERSION=3.4.6-1 -MPDECIMAL_VERSION=4.0.0-1 -OPENSSL_VERSION=3.0.15-1 -XZ_VERSION=5.6.2-1 +BZIP2_VERSION=1.0.8-2 +LIBFFI_VERSION=3.4.7-2 +OPENSSL_VERSION=3.0.18-1 +XZ_VERSION=5.6.4-2 # Supported OS OS_LIST=macOS iOS tvOS watchOS @@ -39,18 +38,26 @@ CURL_FLAGS=--disable --fail --location --create-dirs --progress-bar # macOS targets TARGETS-macOS=macosx.x86_64 macosx.arm64 +TRIPLE_OS-macOS=macos +PLATFORM_NAME-macOS=macOS VERSION_MIN-macOS=11.0 # iOS targets TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.arm64 iphoneos.arm64 +TRIPLE_OS-iOS=ios +PLATFORM_NAME-iOS=iOS VERSION_MIN-iOS=13.0 # tvOS targets TARGETS-tvOS=appletvsimulator.x86_64 appletvsimulator.arm64 appletvos.arm64 +TRIPLE_OS-tvOS=tvos +PLATFORM_NAME-tvOS=tvOS VERSION_MIN-tvOS=12.0 # watchOS targets TARGETS-watchOS=watchsimulator.x86_64 watchsimulator.arm64 watchos.arm64_32 +TRIPLE_OS-watchOS=watchos +PLATFORM_NAME-watchOS=watchOS VERSION_MIN-watchOS=4.0 # The architecture of the machine doing the build @@ -80,13 +87,13 @@ update-patch: # comparing between the current state of the 3.X branch against the v3.X.Y # tag associated with the release being built. This allows you to # maintain a branch that contains custom patches against the default Python. - # The patch archived in this respository is based on github.com/freakboy3742/cpython + # The patch archived in this repository is based on github.com/freakboy3742/cpython # Requires patchutils (installable via `brew install patchutils`); this # also means we need to re-introduce homebrew to the path for the filterdiff # call if [ -z "$(PYTHON_REPO_DIR)" ]; then echo "\n\nPYTHON_REPO_DIR must be set to the root of your Python github checkout\n\n"; fi cd $(PYTHON_REPO_DIR) && \ - git diff -D v$(PYTHON_VERSION) $(PYTHON_VER)-patched \ + git diff --no-renames -D v$(PYTHON_VERSION) $(PYTHON_VER)-patched \ | PATH="/usr/local/bin:/opt/homebrew/bin:$(PATH)" filterdiff \ -X $(PROJECT_DIR)/patch/Python/diff.exclude -p 1 --clean \ > $(PROJECT_DIR)/patch/Python/Python.patch @@ -128,11 +135,11 @@ ARCH-$(target)=$$(subst .,,$$(suffix $(target))) ifneq ($(os),macOS) ifeq ($$(findstring simulator,$$(SDK-$(target))),) -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(OS_LOWER-$(target))$$(VERSION_MIN-$(os)) -IS_SIMULATOR-$(target)="False" +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os)) +IS_SIMULATOR-$(target)=False else -TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(OS_LOWER-$(target))$$(VERSION_MIN-$(os))-simulator -IS_SIMULATOR-$(target)="True" +TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(TRIPLE_OS-$(os))$$(VERSION_MIN-$(os))-simulator +IS_SIMULATOR-$(target)=True endif endif @@ -178,26 +185,6 @@ $$(XZ_LIB-$(target)): downloads/xz-$(XZ_VERSION)-$(target).tar.gz # Ensure the target is marked as clean. touch $$(XZ_LIB-$(target)) -########################################################################### -# Target: mpdecimal -########################################################################### - -MPDECIMAL_INSTALL-$(target)=$(PROJECT_DIR)/install/$(os)/$(target)/mpdecimal-$(MPDECIMAL_VERSION) -MPDECIMAL_LIB-$(target)=$$(MPDECIMAL_INSTALL-$(target))/lib/libmpdec.a - -downloads/mpdecimal-$(MPDECIMAL_VERSION)-$(target).tar.gz: - @echo ">>> Download mpdecimal for $(target)" - mkdir -p downloads - curl $(CURL_FLAGS) -o $$@ \ - https://github.com/beeware/cpython-apple-source-deps/releases/download/mpdecimal-$(MPDECIMAL_VERSION)/mpdecimal-$(MPDECIMAL_VERSION)-$(target).tar.gz - -$$(MPDECIMAL_LIB-$(target)): downloads/mpdecimal-$(MPDECIMAL_VERSION)-$(target).tar.gz - @echo ">>> Install mpdecimal for $(target)" - mkdir -p $$(MPDECIMAL_INSTALL-$(target)) - cd $$(MPDECIMAL_INSTALL-$(target)) && tar zxvf $(PROJECT_DIR)/downloads/mpdecimal-$(MPDECIMAL_VERSION)-$(target).tar.gz --exclude="*.dylib" - # Ensure the target is marked as clean. - touch $$(MPDECIMAL_LIB-$(target)) - ########################################################################### # Target: OpenSSL ########################################################################### @@ -261,12 +248,14 @@ PYTHON_LIB-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Python PYTHON_BIN-$(target)=$$(PYTHON_INSTALL-$(target))/bin PYTHON_INCLUDE-$(target)=$$(PYTHON_FRAMEWORK-$(target))/Headers PYTHON_STDLIB-$(target)=$$(PYTHON_INSTALL-$(target))/lib/python$(PYTHON_VER) +PYTHON_PLATFORM_CONFIG-$(target)=$$(PYTHON_INSTALL-$(target))/platform-config/$$(ARCH-$(target))-$$(SDK-$(target)) +PYTHON_PLATFORM_SITECUSTOMIZE-$(target)=$$(PYTHON_PLATFORM_CONFIG-$(target))/sitecustomize.py + $$(PYTHON_SRCDIR-$(target))/configure: \ downloads/Python-$(PYTHON_VERSION).tar.gz \ $$(BZIP2_LIB-$(target)) \ $$(LIBFFI_LIB-$(target)) \ - $$(MPDECIMAL_LIB-$(target)) \ $$(OPENSSL_SSL_LIB-$(target)) \ $$(XZ_LIB-$(target)) @echo ">>> Unpack and configure Python for $(target)" @@ -275,7 +264,7 @@ $$(PYTHON_SRCDIR-$(target))/configure: \ # Apply target Python patches cd $$(PYTHON_SRCDIR-$(target)) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch # Make sure the binary scripts are executable - chmod 755 $$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin/* + chmod 755 $$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin/* # Touch the configure script to ensure that Make identifies it as up to date. touch $$(PYTHON_SRCDIR-$(target))/configure @@ -283,59 +272,66 @@ $$(PYTHON_SRCDIR-$(target))/Makefile: \ $$(PYTHON_SRCDIR-$(target))/configure # Configure target Python cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin:$(PATH)" \ ./configure \ - LIBLZMA_CFLAGS="-I$$(XZ_INSTALL-$(target))/include" \ - LIBLZMA_LIBS="-L$$(XZ_INSTALL-$(target))/lib -llzma" \ - BZIP2_CFLAGS="-I$$(BZIP2_INSTALL-$(target))/include" \ - BZIP2_LIBS="-L$$(BZIP2_INSTALL-$(target))/lib -lbz2" \ - LIBMPDEC_CFLAGS="-I$$(MPDECIMAL_INSTALL-$(target))/include" \ - LIBMPDEC_LIBS="-L$$(MPDECIMAL_INSTALL-$(target))/lib -lmpdec" \ - LIBFFI_CFLAGS="-I$$(LIBFFI_INSTALL-$(target))/include" \ - LIBFFI_LIBS="-L$$(LIBFFI_INSTALL-$(target))/lib -lffi" \ + CFLAGS="-I$$(XZ_INSTALL-$(target))/include -I$$(BZIP2_INSTALL-$(target))/include" \ + LDFLAGS="-L$$(XZ_INSTALL-$(target))/lib -L$$(BZIP2_INSTALL-$(target))/lib" \ + LIBFFI_INCLUDEDIR="$$(LIBFFI_INSTALL-$(target))/include" \ + LIBFFI_LIBDIR="$$(LIBFFI_INSTALL-$(target))/lib" \ + LIBFFI_LIB="ffi" \ + PYTHON_FOR_REGEN="$(HOST_PYTHON)" \ --host=$$(TARGET_TRIPLE-$(target)) \ --build=$(HOST_ARCH)-apple-darwin \ - --with-build-python=$(HOST_PYTHON) \ - --enable-ipv6 \ --with-openssl="$$(OPENSSL_INSTALL-$(target))" \ --enable-framework="$$(PYTHON_INSTALL-$(target))" \ - --with-system-libmpdec \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).config.log $$(PYTHON_SRCDIR-$(target))/python.exe: $$(PYTHON_SRCDIR-$(target))/Makefile @echo ">>> Build Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ - make -j8 all \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin:$(PATH)" \ + make all \ 2>&1 | tee -a ../python-$(PYTHON_VERSION).build.log $$(PYTHON_LIB-$(target)): $$(PYTHON_SRCDIR-$(target))/python.exe @echo ">>> Install Python for $(target)" cd $$(PYTHON_SRCDIR-$(target)) && \ - PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/$(os)/Resources/bin:$(PATH)" \ + PATH="$(PROJECT_DIR)/$$(PYTHON_SRCDIR-$(target))/Apple/$(os)/Resources/bin:$(PATH)" \ make install \ - 2>&1 | tee -a ../python-$(PYTHON_VERSION).install.log + 2>&1 | tee -a ../python-$(PYTHON_VERSION).install.log # Remove any .orig files produced by the compliance patching process find $$(PYTHON_INSTALL-$(target)) -name "*.orig" -exec rm {} \; -endif - -PYTHON_SITECUSTOMIZE-$(target)=$(PROJECT_DIR)/support/$(PYTHON_VER)/$(os)/platform-site/$(target)/sitecustomize.py -$$(PYTHON_SITECUSTOMIZE-$(target)): - @echo ">>> Create cross-platform sitecustomize.py for $(target)" - mkdir -p $$(dir $$(PYTHON_SITECUSTOMIZE-$(target))) - cat $(PROJECT_DIR)/patch/Python/sitecustomize.$(os).py \ +$$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)): + @echo ">>> Create cross-platform config for $(target)" + mkdir -p $$(PYTHON_PLATFORM_CONFIG-$(target)) + # Create the cross-platform site definition + echo "import _cross_$$(ARCH-$(target))_$$(SDK-$(target)); import _cross_venv;" \ + > $$(PYTHON_PLATFORM_CONFIG-$(target))/_cross_venv.pth + cp $(PROJECT_DIR)/patch/Python/make_cross_venv.py \ + $$(PYTHON_PLATFORM_CONFIG-$(target))/make_cross_venv.py + cp $(PROJECT_DIR)/patch/Python/_cross_venv.py \ + $$(PYTHON_PLATFORM_CONFIG-$(target))/_cross_venv.py + cp $$(PYTHON_STDLIB-$(target))/_sysconfig* \ + $$(PYTHON_PLATFORM_CONFIG-$(target)) + cat $(PROJECT_DIR)/patch/Python/_cross_target.py.tmpl \ | sed -e "s/{{os}}/$(os)/g" \ + | sed -e "s/{{platform}}/$$(OS_LOWER-$(target))/g" \ | sed -e "s/{{arch}}/$$(ARCH-$(target))/g" \ + | sed -e "s/{{sdk}}/$$(SDK-$(target))/g" \ | sed -e "s/{{version_min}}/$$(VERSION_MIN-$(os))/g" \ | sed -e "s/{{is_simulator}}/$$(IS_SIMULATOR-$(target))/g" \ - | sed -e "s/{{multiarch}}/$$(ARCH-$(target))-$$(SDK-$(target))/g" \ - | sed -e "s/{{tag}}/$$(OS_LOWER-$(target))-$$(VERSION_MIN-$(os))-$$(ARCH-$(target))-$$(SDK-$(target))/g" \ - > $$(PYTHON_SITECUSTOMIZE-$(target)) + > $$(PYTHON_PLATFORM_CONFIG-$(target))/_cross_$$(ARCH-$(target))_$$(SDK-$(target)).py + cat $(PROJECT_DIR)/patch/Python/sitecustomize.py.tmpl \ + | sed -e "s/{{arch}}/$$(ARCH-$(target))/g" \ + | sed -e "s/{{sdk}}/$$(SDK-$(target))/g" \ + > $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)) -$(target): $$(PYTHON_SITECUSTOMIZE-$(target)) $$(PYTHON_LIB-$(target)) +endif + +$(target): $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target)) $$(PYTHON_LIB-$(target)) ########################################################################### # Target: Debug @@ -351,8 +347,6 @@ vars-$(target): @echo "BZIP2_LIB-$(target): $$(BZIP2_LIB-$(target))" @echo "LIBFFI_INSTALL-$(target): $$(LIBFFI_INSTALL-$(target))" @echo "LIBFFI_LIB-$(target): $$(LIBFFI_LIB-$(target))" - @echo "MPDECIMAL_INSTALL-$(target): $$(MPDECIMAL_INSTALL-$(target))" - @echo "MPDECIMAL_LIB-$(target): $$(MPDECIMAL_LIB-$(target))" @echo "OPENSSL_INSTALL-$(target): $$(OPENSSL_INSTALL-$(target))" @echo "OPENSSL_SSL_LIB-$(target): $$(OPENSSL_SSL_LIB-$(target))" @echo "XZ_INSTALL-$(target): $$(XZ_INSTALL-$(target))" @@ -364,6 +358,8 @@ vars-$(target): @echo "PYTHON_BIN-$(target): $$(PYTHON_BIN-$(target))" @echo "PYTHON_INCLUDE-$(target): $$(PYTHON_INCLUDE-$(target))" @echo "PYTHON_STDLIB-$(target): $$(PYTHON_STDLIB-$(target))" + @echo "PYTHON_PLATFORM_CONFIG-$(target): $$(PYTHON_PLATFORM_CONFIG-$(target))" + @echo "PYTHON_PLATFORM_SITECUSTOMIZE-$(target): $$(PYTHON_PLATFORM_SITECUSTOMIZE-$(target))" @echo endef # build-target @@ -381,15 +377,13 @@ define build-sdk sdk=$1 os=$2 -OS_LOWER-$(sdk)=$(shell echo $(os) | tr '[:upper:]' '[:lower:]') - SDK_TARGETS-$(sdk)=$$(filter $(sdk).%,$$(TARGETS-$(os))) SDK_ARCHES-$(sdk)=$$(sort $$(subst .,,$$(suffix $$(SDK_TARGETS-$(sdk))))) ifeq ($$(findstring simulator,$(sdk)),) -SDK_SLICE-$(sdk)=$$(OS_LOWER-$(sdk))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g") +SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g") else -SDK_SLICE-$(sdk)=$$(OS_LOWER-$(sdk))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")-simulator +SDK_SLICE-$(sdk)=$$(TRIPLE_OS-$(os))-$$(shell echo $$(SDK_ARCHES-$(sdk)) | sed "s/ /_/g")-simulator endif # Expand the build-target macro for target on this OS @@ -409,7 +403,7 @@ PYTHON_FRAMEWORK-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/Python.framework PYTHON_INSTALL_VERSION-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Versions/$(PYTHON_VER) PYTHON_LIB-$(sdk)=$$(PYTHON_INSTALL_VERSION-$(sdk))/Python PYTHON_INCLUDE-$(sdk)=$$(PYTHON_INSTALL_VERSION-$(sdk))/include/python$(PYTHON_VER) -PYTHON_STDLIB-$(sdk)=$$(PYTHON_INSTALL_VERSION-$(sdk))/lib/python$(PYTHON_VER) +PYTHON_MODULEMAP-$(sdk)=$$(PYTHON_INCLUDE-$(sdk))/module.modulemap else # Non-macOS builds need to be merged on a per-SDK basis. The merge covers: @@ -419,11 +413,12 @@ else # The non-macOS frameworks don't use the versioning structure. PYTHON_INSTALL-$(sdk)=$(PROJECT_DIR)/install/$(os)/$(sdk)/python-$(PYTHON_VERSION) +PYTHON_MODULEMAP-$(sdk)=$$(PYTHON_INCLUDE-$(sdk))/module.modulemap PYTHON_FRAMEWORK-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/Python.framework PYTHON_LIB-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Python PYTHON_BIN-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/bin PYTHON_INCLUDE-$(sdk)=$$(PYTHON_FRAMEWORK-$(sdk))/Headers -PYTHON_STDLIB-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/lib/python$(PYTHON_VER) +PYTHON_PLATFORM_CONFIG-$(sdk)=$$(PYTHON_INSTALL-$(sdk))/platform-config $$(PYTHON_LIB-$(sdk)): $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_LIB-$$(target))) @echo ">>> Build Python fat library for the $(sdk) SDK" @@ -448,6 +443,15 @@ $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) # Copy headers as-is from the first target in the $(sdk) SDK cp -r $$(PYTHON_INCLUDE-$$(firstword $$(SDK_TARGETS-$(sdk)))) $$(PYTHON_INCLUDE-$(sdk)) + # Create the modulemap file + cp -r patch/Python/module.modulemap.prefix $$(PYTHON_MODULEMAP-$(sdk)) + echo "" >> $$(PYTHON_MODULEMAP-$(sdk)) + cd $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/Include && \ + find cpython -name "*.h" | sort | sed -e 's/^/ exclude header "/' | sed 's/$$$$/"/' >> $$(PYTHON_MODULEMAP-$(sdk)) && \ + echo "" >> $$(PYTHON_MODULEMAP-$(sdk)) && \ + find internal -name "*.h" | sort | sed -e 's/^/ exclude header "/' | sed 's/$$$$/"/' >> $$(PYTHON_MODULEMAP-$(sdk)) + echo "\n}" >> $$(PYTHON_MODULEMAP-$(sdk)) + # Link the PYTHONHOME version of the headers mkdir -p $$(PYTHON_INSTALL-$(sdk))/include ln -si ../Python.framework/Headers $$(PYTHON_INSTALL-$(sdk))/include/python$(PYTHON_VER) @@ -456,30 +460,31 @@ $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_INCLUDE-$$(target))/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig-$$(ARCH-$$(target)).h; ) # Copy the cross-target header from the source folder of the first target in the $(sdk) SDK - cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/$(os)/Resources/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$(sdk))))/Apple/$(os)/Resources/pyconfig.h $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h -$$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h +$$(PYTHON_PLATFORM_CONFIG-$(sdk))/sitecustomize.py: $$(PYTHON_LIB-$(sdk)) $$(PYTHON_FRAMEWORK-$(sdk))/Info.plist $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) @echo ">>> Build Python stdlib for the $(sdk) SDK" - mkdir -p $$(PYTHON_STDLIB-$(sdk))/lib-dynload - # Copy stdlib from the first target associated with the $(sdk) SDK - cp -r $$(PYTHON_STDLIB-$$(firstword $$(SDK_TARGETS-$(sdk))))/ $$(PYTHON_STDLIB-$(sdk)) + mkdir -p $$(PYTHON_INSTALL-$(sdk))/lib - # Delete the single-SDK parts of the standard library - rm -rf \ - $$(PYTHON_STDLIB-$(sdk))/_sysconfigdata__*.py \ - $$(PYTHON_STDLIB-$(sdk))/config-* \ - $$(PYTHON_STDLIB-$(sdk))/lib-dynload/* + # Create arch-specific stdlib directories + $$(foreach target,$$(SDK_TARGETS-$(sdk)),mkdir -p $$(PYTHON_INSTALL-$(sdk))/lib-$$(ARCH-$$(target))/python$(PYTHON_VER); ) + $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_STDLIB-$$(target))/_sysconfigdata_* $$(PYTHON_INSTALL-$(sdk))/lib-$$(ARCH-$$(target))/python$(PYTHON_VER)/; ) + $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp -r $$(PYTHON_STDLIB-$$(target))/lib-dynload $$(PYTHON_INSTALL-$(sdk))/lib-$$(ARCH-$$(target))/python$(PYTHON_VER)/; ) - # Copy the individual _sysconfigdata modules into names that include the architecture - $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $$(PYTHON_STDLIB-$$(target))/_sysconfigdata_* $$(PYTHON_STDLIB-$(sdk))/; ) + # Copy in known-required xcprivacy files. + # Libraries linking OpenSSL must provide a privacy manifest. The one in this repository + # has been sourced from https://github.com/openssl/openssl/blob/openssl-3.0/os-dep/Apple/PrivacyInfo.xcprivacy + $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $(PROJECT_DIR)/patch/Python/OpenSSL.xcprivacy $$(PYTHON_STDLIB-$$(target))/lib-dynload/_hashlib.xcprivacy; ) + $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp $(PROJECT_DIR)/patch/Python/OpenSSL.xcprivacy $$(PYTHON_STDLIB-$$(target))/lib-dynload/_ssl.xcprivacy; ) - # Merge the binary modules from each target in the $(sdk) SDK into a single binary - $$(foreach module,$$(wildcard $$(PYTHON_STDLIB-$$(firstword $$(SDK_TARGETS-$(sdk))))/lib-dynload/*),lipo -create -output $$(PYTHON_STDLIB-$(sdk))/lib-dynload/$$(notdir $$(module)) $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_STDLIB-$$(target))/lib-dynload/$$(notdir $$(module))); ) + # Copy the platform site folders for each architecture + mkdir -p $$(PYTHON_PLATFORM_CONFIG-$(sdk)) + $$(foreach target,$$(SDK_TARGETS-$(sdk)),cp -r $$(PYTHON_PLATFORM_CONFIG-$$(target)) $$(PYTHON_PLATFORM_CONFIG-$(sdk)); ) endif -$(sdk): $$(PYTHON_STDLIB-$(sdk))/LICENSE.TXT +$(sdk): $$(PYTHON_PLATFORM_CONFIG-$(sdk))/sitecustomize.py ########################################################################### # SDK: Debug @@ -496,8 +501,7 @@ vars-$(sdk): @echo "PYTHON_LIB-$(sdk): $$(PYTHON_LIB-$(sdk))" @echo "PYTHON_BIN-$(sdk): $$(PYTHON_BIN-$(sdk))" @echo "PYTHON_INCLUDE-$(sdk): $$(PYTHON_INCLUDE-$(sdk))" - @echo "PYTHON_STDLIB-$(sdk): $$(PYTHON_STDLIB-$(sdk))" - + @echo "PYTHON_PLATFORM_CONFIG-$(sdk): $$(PYTHON_PLATFORM_CONFIG-$(sdk))" @echo endef # build-sdk @@ -550,7 +554,7 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ tar zxf build/macOS/macosx/python-$(PYTHON_VERSION)/Python_Framework.pkgPython_Framework.pkg/PayloadPython_Framework.pkgPython_Framework.pkg/PayloadPython_Framework.pkgPython_Framework.pkg/Payload -C $$(PYTHON_FRAMEWORK-macosx) -X patch/Python/release.macOS.exclude # Apply the App Store compliance patch - patch --strip 2 --directory $$(PYTHON_INSTALL_VERSION-macosx)/lib/python$(PYTHON_VER) --input $(PROJECT_DIR)/patch/Python/app-store-compliance.patch + # patch --strip 2 --directory $$(PYTHON_INSTALL_VERSION-macosx)/lib/python$(PYTHON_VER) --input $(PROJECT_DIR)/patch/Python/app-store-compliance.patch # Remove any .orig files produced by the patching process find $$(PYTHON_INSTALL_VERSION-macosx) -name "*.orig" -exec rm {} \; @@ -558,6 +562,15 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ # Rewrite the framework to make it standalone patch/make-relocatable.sh $$(PYTHON_INSTALL_VERSION-macosx) 2>&1 > /dev/null + # Create the modulemap file + cp -r patch/Python/module.modulemap.prefix $$(PYTHON_MODULEMAP-macosx) + echo "" >> $$(PYTHON_MODULEMAP-macosx) + cd $$(PYTHON_INCLUDE-macosx) && \ + find cpython -name "*.h" | sort | sed -e 's/^/ exclude header "/' | sed 's/$$$$/"/' >> $$(PYTHON_MODULEMAP-macosx) && \ + echo "" >> $$(PYTHON_MODULEMAP-macosx) && \ + find internal -name "*.h" | sort | sed -e 's/^/ exclude header "/' | sed 's/$$$$/"/' >> $$(PYTHON_MODULEMAP-macosx) + echo "\n}" >> $$(PYTHON_MODULEMAP-macosx) + # Re-apply the signature on the binaries. codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f $$(PYTHON_LIB-macosx) \ 2>&1 | tee $$(PYTHON_INSTALL-macosx)/python-$(os).codesign.log @@ -581,7 +594,7 @@ support/$(PYTHON_VER)/macOS/VERSIONS: dist/Python-$(PYTHON_VER)-macOS-support.$(BUILD_NUMBER).tar.gz: \ $$(PYTHON_XCFRAMEWORK-macOS)/Info.plist \ support/$(PYTHON_VER)/macOS/VERSIONS \ - $$(foreach target,$$(TARGETS-macOS), $$(PYTHON_SITECUSTOMIZE-$$(target))) + $$(foreach target,$$(TARGETS-macOS), $$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) @echo ">>> Create final distribution artefact for macOS" mkdir -p dist @@ -593,24 +606,40 @@ dist/Python-$(PYTHON_VER)-macOS-support.$(BUILD_NUMBER).tar.gz: \ else $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ - $$(foreach sdk,$$(SDKS-$(os)),$$(PYTHON_STDLIB-$$(sdk))/LICENSE.TXT) + $$(foreach sdk,$$(SDKS-$(os)),$$(PYTHON_PLATFORM_CONFIG-$$(sdk))/sitecustomize.py) @echo ">>> Create Python.XCFramework on $(os)" mkdir -p $$(dir $$(PYTHON_XCFRAMEWORK-$(os))) xcodebuild -create-xcframework \ -output $$(PYTHON_XCFRAMEWORK-$(os)) $$(foreach sdk,$$(SDKS-$(os)),-framework $$(PYTHON_FRAMEWORK-$$(sdk))) \ 2>&1 | tee -a support/$(PYTHON_VER)/python-$(os).xcframework.log + @echo ">>> Install build tools for $(os)" + mkdir $$(PYTHON_XCFRAMEWORK-$(os))/build + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/Apple/testbed/Python.xcframework/build/utils.sh $$(PYTHON_XCFRAMEWORK-$(os))/build + cp $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/Apple/testbed/Python.xcframework/build/$$(PLATFORM_NAME-$(os))-dylib-Info-template.plist $$(PYTHON_XCFRAMEWORK-$(os))/build + + @echo ">>> Install stdlib for $(os)" + mkdir -p $$(PYTHON_XCFRAMEWORK-$(os))/lib + cp -r $$(PYTHON_STDLIB-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/ $$(PYTHON_XCFRAMEWORK-$(os))/lib/python$(PYTHON_VER) + + # Delete the single-SDK parts of the standard library + rm -rf \ + $$(PYTHON_XCFRAMEWORK-$(os))/lib/python$(PYTHON_VER)/_sysconfigdata__*.py \ + $$(PYTHON_XCFRAMEWORK-$(os))/lib/python$(PYTHON_VER)/config-* \ + $$(PYTHON_XCFRAMEWORK-$(os))/lib/python$(PYTHON_VER)/lib-dynload + @echo ">>> Install PYTHONHOME for $(os)" $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/include $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/bin $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) - $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/lib $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) + $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/lib* $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) + $$(foreach sdk,$$(SDKS-$(os)),cp -r $$(PYTHON_INSTALL-$$(sdk))/platform-config $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk)); ) - @echo ">>> Create helper links in XCframework for $(os)" - $$(foreach sdk,$$(SDKS-$(os)),ln -si $$(SDK_SLICE-$$(sdk)) $$(PYTHON_XCFRAMEWORK-$(os))/$$(sdk); ) + # Create symlink for dylib + $$(foreach sdk,$$(SDKS-$(os)),ln -si ../Python.framework/Python $$(PYTHON_XCFRAMEWORK-$(os))/$$(SDK_SLICE-$$(sdk))/lib/libpython$(PYTHON_VER).dylib; ) -ifeq ($(os),iOS) +ifeq ($(filter $(os),iOS tvOS),$(os)) @echo ">>> Clone testbed project for $(os)" - $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/iOS/testbed clone --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed + $(HOST_PYTHON) $$(PYTHON_SRCDIR-$$(firstword $$(SDK_TARGETS-$$(firstword $$(SDKS-$(os))))))/Apple/testbed clone --platform $(os) --framework $$(PYTHON_XCFRAMEWORK-$(os)) support/$(PYTHON_VER)/$(os)/testbed endif @echo ">>> Create VERSIONS file for $(os)" @@ -620,13 +649,12 @@ endif echo "---------------------" >> support/$(PYTHON_VER)/$(os)/VERSIONS echo "BZip2: $(BZIP2_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS echo "libFFI: $(LIBFFI_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS - echo "mpdecimal: $(MPDECIMAL_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS echo "OpenSSL: $(OPENSSL_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS echo "XZ: $(XZ_VERSION)" >> support/$(PYTHON_VER)/$(os)/VERSIONS dist/Python-$(PYTHON_VER)-$(os)-support.$(BUILD_NUMBER).tar.gz: \ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist \ - $$(foreach target,$$(TARGETS-$(os)), $$(PYTHON_SITECUSTOMIZE-$$(target))) + $$(foreach target,$$(TARGETS-$(os)), $$(PYTHON_PLATFORM_SITECUSTOMIZE-$$(target))) @echo ">>> Create final distribution artefact for $(os)" mkdir -p dist @@ -688,7 +716,6 @@ config: @echo "BUILD_NUMBER=$(BUILD_NUMBER)" @echo "BZIP2_VERSION=$(BZIP2_VERSION)" @echo "LIBFFI_VERSION=$(LIBFFI_VERSION)" - @echo "MPDECIMAL_VERSION=$(MPDECIMAL_VERSION)" @echo "OPENSSL_VERSION=$(OPENSSL_VERSION)" @echo "XZ_VERSION=$(XZ_VERSION)" diff --git a/README.rst b/README.rst index 94c0ae94..aca2d07f 100644 --- a/README.rst +++ b/README.rst @@ -4,15 +4,15 @@ Python Apple Support This is a meta-package for building a version of Python that can be embedded into a macOS, iOS, tvOS or watchOS project. -**This branch builds a packaged version of Python 3.14**. +**This branch builds a packaged version of Python 3.10**. Other Python versions are available by cloning other branches of the main repository: * `Python 3.9 `__ -* `Python 3.10 `__ * `Python 3.11 `__ * `Python 3.12 `__ * `Python 3.13 `__ +* `Python 3.14 `__ It works by downloading, patching, and building a fat binary of Python and selected pre-requisites, and packaging them as frameworks that can be @@ -83,15 +83,6 @@ Each support package contains: * ``VERSIONS``, a text file describing the specific versions of code used to build the support package; -* ``platform-site``, a folder that contains site customization scripts that can be used - to make your local Python install look like it is an on-device install for each of the - underlying target architectures supported by the platform. This is needed because when - you run ``pip`` you'll be on a macOS machine with a specific architecture; if ``pip`` - tries to install a binary package, it will install a macOS binary wheel (which won't - work on iOS/tvOS/watchOS). However, if you add the ``platform-site`` folder to your - ``PYTHONPATH`` when invoking pip, the site customization will make your Python install - return ``platform`` and ``sysconfig`` responses consistent with on-device behavior, - which will cause ``pip`` to install platform-appropriate packages. * ``Python.xcframework``, a multi-architecture build of the Python runtime library On iOS/tvOS/watchOS, the ``Python.xcframework`` contains a @@ -105,6 +96,32 @@ needed to build packages. This is required because Xcode uses the ``xcrun`` alias to dynamically generate the name of binaries, but a lot of C tooling expects that ``CC`` will not contain spaces. +Each slice of an iOS/tvOS/watchOS XCframework also contains a +``platform-config`` folder with a subfolder for each supported architecture in +that slice. These subfolders can be used to make a macOS Python environment +behave as if it were on an iOS/tvOS/watchOS device. This works in one of two +ways: + +1. **A sitecustomize.py script**. If the ``platform-config`` subfolder is on + your ``PYTHONPATH`` when a Python interpreter is started, a site + customization will be applied that patches methods in ``sys``, ``sysconfig`` + and ``platform`` that are used to identify the system. + +2. **A make_cross_venv.py script**. If you call ``make_cross_venv.py``, + providing the location of a virtual environment, the script will add some + files to the ``site-packages`` folder of that environment that will + automatically apply the same set of patches as the ``sitecustomize.py`` + script whenever the environment is activated, without any need to modify + ``PYTHONPATH``. If you use ``build`` to create an isolated PEP 517 + environment to build a wheel, these patches will also be applied to the + isolated build environment that is created. + +iOS distributions also contain a copy of the iOS ``testbed`` project - an Xcode +project that can be used to run test suites of Python code. See the `CPython +documentation on testing packages +`__ for +details on how to use this testbed. + For a detailed instructions on using the support package in your own project, see the `usage guide <./USAGE.md>`__ diff --git a/USAGE.md b/USAGE.md index 12bc1dc7..096f71b0 100644 --- a/USAGE.md +++ b/USAGE.md @@ -20,71 +20,110 @@ what Briefcase is doing). The steps required are documented in the CPython usage guides: * [macOS](https://docs.python.org/3/using/mac.html) -* [iOS](https://docs.python.org/3.14/using/ios.html) +* [iOS](https://docs.python.org/3/using/ios.html#adding-python-to-an-ios-project) For tvOS and watchOS, you should be able to broadly follow the instructions in the iOS guide. +### Using Objective C + +Once you've added the Python XCframework to your project, you'll need to +initialize the Python runtime in your Objective C code (This is step 10 of the +iOS guide linked above). This initialization should generally be done as early +as possible in the application's lifecycle, but definitely needs to be done +before you invoke Python code. + +As a *bare minimum*, you can do the following: + +1. Import the Python C API headers: + ```objc + #include + ``` + +2. Initialize the Python interpreter: + ```objc + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + NSString *pythonHome = [NSString stringWithFormat:@"%@/python", resourcePath, nil]; + NSString *pythonPath = [NSString stringWithFormat:@"%@/lib/python3.13", python_home, nil]; + NSString *libDynloadPath = [NSString stringWithFormat:@"%@/lib/python3.13/lib-dynload", python_home, nil]; + NSString *appPath = [NSString stringWithFormat:@"%@/app", resourcePath, nil]; + + setenv("PYTHONHOME", pythonHome, 1); + setenv("PYTHONPATH", [NSString stringWithFormat:@"%@:%@:%@", pythonpath, libDynloadPath, appPath, nil]); + + Py_Initialize(); + + // we now have a Python interpreter ready to be used + ``` + References to a specific Python version should reflect the version of + Python you are using. + +Again - this is the *bare minimum* initialization. In practice, you will likely +need to configure other aspects of the Python interpreter using the +`PyPreConfig` and `PyConfig` mechanisms. Consult the [Python documentation on +interpreter configuration](https://docs.python.org/3/c-api/init_config.html) for +more details on the configuration options that are available. You may find the +[bootstrap mainline code used by +Briefcase](https://github.com/beeware/briefcase-iOS-Xcode-template/blob/main/%7B%7B%20cookiecutter.format%20%7D%7D/%7B%7B%20cookiecutter.class_name%20%7D%7D/main.m) +a helpful point of comparison. + +### Using Swift + +If you want to use Swift instead of Objective C, the bare minimum initialization +code will look something like this: + +1. Import the Python framework: + ```swift + import Python + ``` + +2. Initialize the Python interpreter: + ```swift + guard let pythonHome = Bundle.main.path(forResource: "python", ofType: nil) else { return } + guard let pythonPath = Bundle.main.path(forResource: "python/lib/python3.13", ofType: nil) else { return } + guard let libDynloadPath = Bundle.main.path(forResource: "python/lib/python3.13/lib-dynload", ofType: nil) else { return } + let appPath = Bundle.main.path(forResource: "app", ofType: nil) + + setenv("PYTHONHOME", pythonHome, 1) + setenv("PYTHONPATH", [pythonPath, libDynloadPath, appPath].compactMap { $0 }.joined(separator: ":"), 1) + Py_Initialize() + // we now have a Python interpreter ready to be used + ``` + + Again, references to a specific Python version should reflect the version of + Python you are using; and you will likely need to use `PyPreConfig` and + `PreConfig` APIs. + ## Accessing the Python runtime There are 2 ways to access the Python runtime in your project code. -### Embedded C API. +### Embedded C API You can use the [Python Embedded C -API](https://docs.python.org/3/extending/embedding.html) to instantiate a Python -interpreter. This is the approach taken by Briefcase; you may find the bootstrap -mainline code generated by Briefcase a helpful guide to what is needed to start -an interpreter and run Python code. +API](https://docs.python.org/3/extending/embedding.html) to invoke Python code +and interact with Python objects. This is a raw C API that is accesible to both +Objective C and Swift. ### PythonKit -An alternate approach is to use +If you're using Swift, an alternate approach is to use [PythonKit](https://github.com/pvieito/PythonKit). PythonKit is a package that provides a Swift API to running Python code. -To use PythonKit in your project: - -1. Add PythonKit to your project using the Swift Package manager. See the - PythonKit documentation for details. - -2. Create a file called `module.modulemap` inside - `Python.xcframework/macos-arm64_x86_64/Headers/`, containing the following - code: -``` -module Python { - umbrella header "Python.h" - export * - link "Python" -} -``` +To use PythonKit in your project, add the Python Apple Support package to your +project and instantiate a Python interpreter as described above; then add +PythonKit to your project using the Swift Package manager (see the [PythonKit +documentation](https://github.com/pvieito/PythonKit) for details). -3. In your Swift code, initialize the Python runtime. This should generally be - done as early as possible in the application's lifecycle, but definitely - needs to be done before you invoke Python code: +Once you've done this, you can import PythonKit: ```swift -import Python - -guard let stdLibPath = Bundle.main.path(forResource: "python-stdlib", ofType: nil) else { return } -guard let libDynloadPath = Bundle.main.path(forResource: "python-stdlib/lib-dynload", ofType: nil) else { return } -setenv("PYTHONHOME", stdLibPath, 1) -setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath)", 1) -Py_Initialize() -// we now have a Python interpreter ready to be used +import PythonKit ``` - -5. Invoke Python code in your app. For example: +and use the PythonKit Swift API to interact with Python code: ```swift -import PythonKit - let sys = Python.import("sys") print("Python Version: \(sys.version_info.major).\(sys.version_info.minor)") print("Python Encoding: \(sys.getdefaultencoding().upper())") print("Python Path: \(sys.path)") - -_ = Python.import("math") // verifies `lib-dynload` is found and signed successfully ``` - -To integrate 3rd party python code and dependencies, you will need to make sure -`PYTHONPATH` contains their paths; once this has been done, you can run -`Python.import("")`. to import that module from inside swift. diff --git a/patch/Python/OpenSSL.xcprivacy b/patch/Python/OpenSSL.xcprivacy new file mode 100644 index 00000000..95780a09 --- /dev/null +++ b/patch/Python/OpenSSL.xcprivacy @@ -0,0 +1,23 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTrackingDomains + + NSPrivacyTracking + + + diff --git a/patch/Python/Python.patch b/patch/Python/Python.patch index 36d93a03..def71232 100644 --- a/patch/Python/Python.patch +++ b/patch/Python/Python.patch @@ -1,2242 +1,2549 @@ -diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst -index 6194d7446c7..55a9dd1f25f 100644 ---- a/Doc/c-api/init_config.rst -+++ b/Doc/c-api/init_config.rst -@@ -1279,6 +1279,17 @@ - - Default: ``1`` in Python config and ``0`` in isolated config. - -+ .. c:member:: int use_system_logger +diff --git a/.ruff.toml b/.ruff.toml +new file mode 100644 +index 00000000000..1c015fa8841 +--- /dev/null ++++ b/.ruff.toml +@@ -0,0 +1,12 @@ ++# Default settings for Ruff in CPython ++ ++# PYTHON_FOR_REGEN ++target-version = "py310" ++ ++# PEP 8 ++line-length = 79 ++ ++# Enable automatic fixes by default. ++# To override this, use ``fix = false`` in a subdirectory's config file ++# or ``--no-fix`` on the command line. ++fix = true +diff --git a/Apple/.ruff.toml b/Apple/.ruff.toml +new file mode 100644 +index 00000000000..f9098e0f5ce +--- /dev/null ++++ b/Apple/.ruff.toml +@@ -0,0 +1,22 @@ ++extend = "../.ruff.toml" # Inherit the project-wide settings ++ ++[format] ++preview = true ++docstring-code-format = true ++ ++[lint] ++select = [ ++ "C4", # flake8-comprehensions ++ "E", # pycodestyle ++ "F", # pyflakes ++ "I", # isort ++ # "ISC", # flake8-implicit-str-concat ++ "LOG", # flake8-logging ++ "PGH", # pygrep-hooks ++ "PT", # flake8-pytest-style ++ "PYI", # flake8-pyi ++ "RUF100", # Ban unused `# noqa` comments ++ # "UP", # pyupgrade ++ "W", # pycodestyle ++ "YTT", # flake8-2020 ++] +diff --git a/Apple/__main__.py b/Apple/__main__.py +new file mode 100644 +index 00000000000..9fcb464a273 +--- /dev/null ++++ b/Apple/__main__.py +@@ -0,0 +1,1147 @@ ++#!/usr/bin/env python3 ++########################################################################## ++# Apple XCframework build script ++# ++# This script simplifies the process of configuring, compiling and packaging an ++# XCframework for an Apple platform. ++# ++# At present, it supports iOS, tvOS, visionOS and watchOS, but it has been ++# constructed so that it could be used on any Apple platform. ++# ++# The simplest entry point is: ++# ++# $ python Apple ci iOS ++# ++# (replace iOS with tvOS, visionOS or watchOS as required.) ++# ++# which will: ++# * Clean any pre-existing build artefacts ++# * Configure and make a Python that can be used for the build ++# * Configure and make a Python for each supported iOS/tvOS/watchOS/visionOS ++# architecture and ABI ++# * Combine the outputs of the builds from the previous step into a single ++# XCframework, merging binaries into a "fat" binary if necessary ++# * Clone a copy of the testbed, configured to use the XCframework ++# * Construct a tarball containing the release artefacts ++# * Run the test suite using the generated XCframework. ++# ++# This is the complete sequence that would be needed in CI to build and test ++# a candidate release artefact. ++# ++# Each individual step can be invoked individually - there are commands to ++# clean, configure-build, make-build, configure-host, make-host, package, and ++# test. ++# ++# There is also a build command that can be used to combine the configure and ++# make steps for the build Python, an individual host, all hosts, or all ++# builds. ++########################################################################## ++from __future__ import annotations + -+ If non-zero, ``stdout`` and ``stderr`` will be redirected to the system -+ log. ++import argparse ++import os ++import platform ++import re ++import shlex ++import shutil ++import signal ++import subprocess ++import sys ++import sysconfig ++import time ++from collections.abc import Callable, Sequence ++from contextlib import contextmanager ++from datetime import datetime, timezone ++from os.path import basename, relpath ++from pathlib import Path ++from subprocess import CalledProcessError ++ ++EnvironmentT = dict[str, str] ++ArgsT = Sequence[str | Path] ++ ++SCRIPT_NAME = Path(__file__).name ++PYTHON_DIR = Path(__file__).resolve().parent.parent ++ ++CROSS_BUILD_DIR = PYTHON_DIR / "cross-build" ++ ++HOSTS: dict[str, dict[str, dict[str, str]]] = { ++ # Structure of this data: ++ # * Platform identifier ++ # * an XCframework slice that must exist for that platform ++ # * a host triple: the multiarch spec for that host ++ "iOS": { ++ "ios-arm64": { ++ "arm64-apple-ios": "arm64-iphoneos", ++ }, ++ "ios-arm64_x86_64-simulator": { ++ "arm64-apple-ios-simulator": "arm64-iphonesimulator", ++ "x86_64-apple-ios-simulator": "x86_64-iphonesimulator", ++ }, ++ }, ++ "tvOS": { ++ "tvos-arm64": { ++ "arm64-apple-tvos": "arm64-appletvos", ++ }, ++ "tvos-arm64_x86_64-simulator": { ++ "arm64-apple-tvos-simulator": "arm64-appletvsimulator", ++ "x86_64-apple-tvos-simulator": "x86_64-appletvsimulator", ++ }, ++ }, ++ "visionOS": { ++ "xros-arm64": { ++ "arm64-apple-xros": "arm64-xros", ++ }, ++ "xros-arm64-simulator": { ++ "arm64-apple-xros-simulator": "arm64-xrsimulator", ++ }, ++ }, ++ "watchOS": { ++ "watchos-arm64_32": { ++ "arm64_32-apple-watchos": "arm64_32-watchos", ++ }, ++ "watchos-arm64_x86_64-simulator": { ++ "arm64-apple-watchos-simulator": "arm64-watchsimulator", ++ "x86_64-apple-watchos-simulator": "x86_64-watchsimulator", ++ }, ++ }, ++} + -+ Only available on macOS 10.12 and later, and on iOS. + -+ Default: ``0`` (don't use system log). ++def subdir(name: str, create: bool = False) -> Path: ++ """Ensure that a cross-build directory for the given name exists.""" ++ path = CROSS_BUILD_DIR / name ++ if not path.exists(): ++ if not create: ++ sys.exit( ++ f"{path} does not exist. Create it by running the appropriate " ++ f"`configure` subcommand of {SCRIPT_NAME}." ++ ) ++ else: ++ path.mkdir(parents=True) ++ return path + -+ .. versionadded:: 3.13.2 + - .. c:member:: int user_site_directory - - If non-zero, add the user site directory to :data:`sys.path`. -diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst -index 4d4eb2031ee..aa43f75ec35 100644 ---- a/Doc/using/ios.rst -+++ b/Doc/using/ios.rst -@@ -292,10 +292,12 @@ - 10. Add Objective C code to initialize and use a Python interpreter in embedded - mode. You should ensure that: - -- * :c:member:`UTF-8 mode ` is *enabled*; -- * :c:member:`Buffered stdio ` is *disabled*; -- * :c:member:`Writing bytecode ` is *disabled*; -- * :c:member:`Signal handlers ` are *enabled*; -+ * UTF-8 mode (:c:member:`PyPreConfig.utf8_mode`) is *enabled*; -+ * Buffered stdio (:c:member:`PyConfig.buffered_stdio`) is *disabled*; -+ * Writing bytecode (:c:member:`PyConfig.write_bytecode`) is *disabled*; -+ * Signal handlers (:c:member:`PyConfig.install_signal_handlers`) are *enabled*; -+ * System logging (:c:member:`PyConfig.use_system_logger`) is *enabled* -+ (optional, but strongly recommended); - * ``PYTHONHOME`` for the interpreter is configured to point at the - ``python`` subfolder of your app's bundle; and - * The ``PYTHONPATH`` for the interpreter includes: -@@ -324,6 +326,49 @@ - * If you're using a separate folder for third-party packages, ensure that folder - is included as part of the ``PYTHONPATH`` configuration in step 10. - -+Testing a Python package -+------------------------ ++def run( ++ command: ArgsT, ++ *, ++ host: str | None = None, ++ env: EnvironmentT | None = None, ++ log: bool | None = True, ++ **kwargs, ++) -> subprocess.CompletedProcess: ++ """Run a command in an Apple development environment. + -+The CPython source tree contains :source:`a testbed project ` that -+is used to run the CPython test suite on the iOS simulator. This testbed can also -+be used as a testbed project for running your Python library's test suite on iOS. ++ Optionally logs the executed command to the console. ++ """ ++ kwargs.setdefault("check", True) ++ if env is None: ++ env = os.environ.copy() + -+After building or obtaining an iOS XCFramework (See :source:`iOS/README.rst` -+for details), create a clone of the Python iOS testbed project by running: ++ if host: ++ host_env = apple_env(host) ++ print_env(host_env) ++ env.update(host_env) + -+.. code-block:: bash ++ if log: ++ print(">", join_command(command)) ++ return subprocess.run(command, env=env, **kwargs) + -+ $ python iOS/testbed clone --framework --app --app app-testbed + -+You will need to modify the ``iOS/testbed`` reference to point to that -+directory in the CPython source tree; any folders specified with the ``--app`` -+flag will be copied into the cloned testbed project. The resulting testbed will -+be created in the ``app-testbed`` folder. In this example, the ``module1`` and -+``module2`` would be importable modules at runtime. If your project has -+additional dependencies, they can be installed into the -+``app-testbed/iOSTestbed/app_packages`` folder (using ``pip install --target -+app-testbed/iOSTestbed/app_packages`` or similar). ++def join_command(args: str | Path | ArgsT) -> str: ++ """Format a command so it can be copied into a shell. + -+You can then use the ``app-testbed`` folder to run the test suite for your app, -+For example, if ``module1.tests`` was the entry point to your test suite, you -+could run: ++ Similar to `shlex.join`, but also accepts arguments which are Paths, or a ++ single string/Path outside of a list. ++ """ ++ if isinstance(args, (str, Path)): ++ return str(args) ++ else: ++ return shlex.join(map(str, args)) ++ ++ ++def print_env(env: EnvironmentT) -> None: ++ """Format the environment so it can be pasted into a shell.""" ++ for key, value in sorted(env.items()): ++ print(f"export {key}={shlex.quote(value)}") ++ ++ ++def platform_for_host(host): ++ """Determine the platform for a given host triple.""" ++ for plat, slices in HOSTS.items(): ++ for _, candidates in slices.items(): ++ for candidate in candidates: ++ if candidate == host: ++ return plat ++ raise KeyError(host) ++ ++ ++def apple_env(host: str) -> EnvironmentT: ++ """Construct an Apple development environment for the given host.""" ++ env = { ++ "PATH": ":".join([ ++ str(PYTHON_DIR / f"Apple/{platform_for_host(host)}/Resources/bin"), ++ str(subdir(host) / "prefix"), ++ "/usr/bin", ++ "/bin", ++ "/usr/sbin", ++ "/sbin", ++ "/Library/Apple/usr/bin", ++ ]), ++ } + -+.. code-block:: bash ++ return env + -+ $ python app-testbed run -- module1.tests + -+This is the equivalent of running ``python -m module1.tests`` on a desktop -+Python build. Any arguments after the ``--`` will be passed to the testbed as -+if they were arguments to ``python -m`` on a desktop machine. ++def delete_path(name: str) -> None: ++ """Delete the named cross-build directory, if it exists.""" ++ path = CROSS_BUILD_DIR / name ++ if path.exists(): ++ print(f"Deleting {path} ...") ++ shutil.rmtree(path) + -+You can also open the testbed project in Xcode by running: + -+.. code-block:: bash ++def all_host_triples(platform: str) -> list[str]: ++ """Return all host triples for the given platform. + -+ $ open app-testbed/iOSTestbed.xcodeproj ++ The host triples are the platform definitions used as input to configure ++ (e.g., "arm64-apple-ios-simulator"). ++ """ ++ triples = [] ++ for slice_name, slice_parts in HOSTS[platform].items(): ++ triples.extend(list(slice_parts)) ++ return triples ++ ++ ++def clean(context: argparse.Namespace, target: str | None = None) -> None: ++ """The implementation of the "clean" command.""" ++ if target is None: ++ target = context.host ++ ++ # If we're explicitly targeting the build, there's no platform or ++ # distribution artefacts. If we're cleaning tests, we keep all built ++ # artefacts. Otherwise, the built artefacts must be dirty, so we remove ++ # them. ++ if target not in {"build", "test"}: ++ paths = ["dist", context.platform] + list(HOSTS[context.platform]) ++ else: ++ paths = [] ++ ++ if target in {"all", "build"}: ++ paths.append("build") ++ ++ if target in {"all", "hosts"}: ++ paths.extend(all_host_triples(context.platform)) ++ elif target not in {"build", "test", "package"}: ++ paths.append(target) ++ ++ if target in {"all", "hosts", "test"}: ++ paths.extend([ ++ path.name ++ for path in CROSS_BUILD_DIR.glob(f"{context.platform}-testbed.*") ++ ]) ++ ++ for path in paths: ++ delete_path(path) ++ ++ ++def build_python_path() -> Path: ++ """The path to the build Python binary.""" ++ build_dir = subdir("build") ++ binary = build_dir / "python" ++ if not binary.is_file(): ++ binary = binary.with_suffix(".exe") ++ if not binary.is_file(): ++ raise FileNotFoundError( ++ f"Unable to find `python(.exe)` in {build_dir}" ++ ) + -+This will allow you to use the full Xcode suite of tools for debugging. ++ return binary + - App Store Compliance - ==================== - -diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst -index 3eabf22e499..b509f2a0607 100644 ---- a/Doc/whatsnew/3.14.rst -+++ b/Doc/whatsnew/3.14.rst -@@ -205,6 +205,13 @@ - making it a :term:`generic type`. - (Contributed by Brian Schubert in :gh:`126012`.) - -+* iOS and macOS apps can now be configured to redirect ``stdout`` and -+ ``stderr`` content to the system log. (Contributed by Russell Keith-Magee in -+ :gh:`127592`.) -+ -+* The iOS testbed is now able to stream test output while the test is running. -+ The testbed can also be used to run the test suite of projects other than -+ CPython itself. (Contributed by Russell Keith-Magee in :gh:`127592`.) - - New modules - =========== -diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h -index f69c586a4f9..8ef19f67706 100644 ---- a/Include/cpython/initconfig.h -+++ b/Include/cpython/initconfig.h -@@ -179,6 +179,9 @@ - int use_frozen_modules; - int safe_path; - int int_max_str_digits; -+#ifdef __APPLE__ -+ int use_system_logger; -+#endif - - int cpu_count; - #ifdef Py_GIL_DISABLED ---- /dev/null -+++ b/Lib/_apple_support.py -@@ -0,0 +1,66 @@ -+import io -+import sys + ++@contextmanager ++def group(text: str): ++ """A context manager that outputs a log marker around a section of a build. + -+def init_streams(log_write, stdout_level, stderr_level): -+ # Redirect stdout and stderr to the Apple system log. This method is -+ # invoked by init_apple_streams() (initconfig.c) if config->use_system_logger -+ # is enabled. -+ sys.stdout = SystemLog(log_write, stdout_level, errors=sys.stderr.errors) -+ sys.stderr = SystemLog(log_write, stderr_level, errors=sys.stderr.errors) ++ If running in a GitHub Actions environment, the GitHub syntax for ++ collapsible log sections is used. ++ """ ++ if "GITHUB_ACTIONS" in os.environ: ++ print(f"::group::{text}") ++ else: ++ print(f"===== {text} " + "=" * (70 - len(text))) + ++ yield + -+class SystemLog(io.TextIOWrapper): -+ def __init__(self, log_write, level, **kwargs): -+ kwargs.setdefault("encoding", "UTF-8") -+ kwargs.setdefault("line_buffering", True) -+ super().__init__(LogStream(log_write, level), **kwargs) ++ if "GITHUB_ACTIONS" in os.environ: ++ print("::endgroup::") ++ else: ++ print() + -+ def __repr__(self): -+ return f"" + -+ def write(self, s): -+ if not isinstance(s, str): -+ raise TypeError( -+ f"write() argument must be str, not {type(s).__name__}") ++@contextmanager ++def cwd(subdir: Path): ++ """A context manager that sets the current working directory.""" ++ orig = os.getcwd() ++ os.chdir(subdir) ++ yield ++ os.chdir(orig) + -+ # In case `s` is a str subclass that writes itself to stdout or stderr -+ # when we call its methods, convert it to an actual str. -+ s = str.__str__(s) + -+ # We want to emit one log message per line, so split -+ # the string before sending it to the superclass. -+ for line in s.splitlines(keepends=True): -+ super().write(line) ++def configure_build_python(context: argparse.Namespace) -> None: ++ """The implementation of the "configure-build" command.""" ++ if context.clean: ++ clean(context, "build") + -+ return len(s) ++ with ( ++ group("Configuring build Python"), ++ cwd(subdir("build", create=True)), ++ ): ++ command = [relpath(PYTHON_DIR / "configure")] ++ if context.args: ++ command.extend(context.args) ++ run(command) + + -+class LogStream(io.RawIOBase): -+ def __init__(self, log_write, level): -+ self.log_write = log_write -+ self.level = level ++def make_build_python(context: argparse.Namespace) -> None: ++ """The implementation of the "make-build" command.""" ++ with ( ++ group("Compiling build Python"), ++ cwd(subdir("build")), ++ ): ++ run(["make", "-j", str(os.cpu_count())]) + -+ def __repr__(self): -+ return f"" + -+ def writable(self): -+ return True ++def apple_target(host: str) -> str: ++ """Return the Apple platform identifier for a given host triple.""" ++ for _, platform_slices in HOSTS.items(): ++ for slice_name, slice_parts in platform_slices.items(): ++ for host_triple, multiarch in slice_parts.items(): ++ if host == host_triple: ++ return ".".join(multiarch.split("-")[::-1]) + -+ def write(self, b): -+ if type(b) is not bytes: -+ try: -+ b = bytes(memoryview(b)) -+ except TypeError: -+ raise TypeError( -+ f"write() argument must be bytes-like, not {type(b).__name__}" -+ ) from None ++ raise KeyError(host) + -+ # Writing an empty string to the stream should have no effect. -+ if b: -+ # Encode null bytes using "modified UTF-8" to avoid truncating the -+ # message. This should not affect the return value, as the caller -+ # may be expecting it to match the length of the input. -+ self.log_write(self.level, b.replace(b"\x00", b"\xc0\x80")) + -+ return len(b) -diff --git a/Lib/platform.py b/Lib/platform.py -index 239e660cd16..8e007c3c3b5 100644 ---- a/Lib/platform.py -+++ b/Lib/platform.py -@@ -520,6 +520,54 @@ - return IOSVersionInfo(system, release, model, is_simulator) - - -+# A namedtuple for tvOS version information. -+TVOSVersionInfo = collections.namedtuple( -+ "TVOSVersionInfo", -+ ["system", "release", "model", "is_simulator"] -+) ++def apple_multiarch(host: str) -> str: ++ """Return the multiarch descriptor for a given host triple.""" ++ for _, platform_slices in HOSTS.items(): ++ for slice_name, slice_parts in platform_slices.items(): ++ for host_triple, multiarch in slice_parts.items(): ++ if host == host_triple: ++ return multiarch + ++ raise KeyError(host) + -+def tvos_ver(system="", release="", model="", is_simulator=False): -+ """Get tvOS version information, and return it as a namedtuple: -+ (system, release, model, is_simulator). + -+ If values can't be determined, they are set to values provided as -+ parameters. -+ """ -+ if sys.platform == "tvos": -+ # TODO: Can the iOS implementation be used here? -+ import _ios_support -+ result = _ios_support.get_platform_ios() -+ if result is not None: -+ return TVOSVersionInfo(*result) ++def unpack_deps( ++ platform: str, ++ host: str, ++ prefix_dir: Path, ++ cache_dir: Path, ++) -> None: ++ """Unpack binary dependencies into a provided directory. + -+ return TVOSVersionInfo(system, release, model, is_simulator) ++ Downloads binaries if they aren't already present. Downloads will be stored ++ in provided cache directory. + ++ On non-macOS platforms, as a safety mechanism, any dynamic libraries will ++ be purged from the unpacked dependencies. ++ """ ++ # To create new builds of these dependencies, usually all that's necessary ++ # is to push a tag to the cpython-apple-source-deps repository, and GitHub ++ # Actions will do the rest. ++ # ++ # If you're a member of the Python core team, and you'd like to be able to ++ # push these tags yourself, please contact Malcolm Smith or Russell ++ # Keith-Magee. ++ deps_url = "https://github.com/beeware/cpython-apple-source-deps/releases/download" ++ for name_ver in [ ++ "BZip2-1.0.8-2", ++ "libFFI-3.4.7-2", ++ "OpenSSL-3.0.19-1", ++ "XZ-5.6.4-2", ++ "mpdecimal-4.0.0-2", ++ "zstd-1.5.7-1", ++ ]: ++ filename = f"{name_ver.lower()}-{apple_target(host)}.tar.gz" ++ archive_path = download( ++ f"{deps_url}/{name_ver}/{filename}", ++ target_dir=cache_dir, ++ ) ++ shutil.unpack_archive(archive_path, prefix_dir) + -+# A namedtuple for watchOS version information. -+WatchOSVersionInfo = collections.namedtuple( -+ "WatchOSVersionInfo", -+ ["system", "release", "model", "is_simulator"] -+) ++ # Dynamic libraries will be preferentially linked over static; ++ # On iOS, ensure that no dylibs are available in the prefix folder. ++ if platform == "iOS": ++ for dylib in prefix_dir.glob("**/*.dylib"): ++ dylib.unlink() + + -+def watchos_ver(system="", release="", model="", is_simulator=False): -+ """Get watchOS version information, and return it as a namedtuple: -+ (system, release, model, is_simulator). ++def download(url: str, target_dir: Path) -> Path: ++ """Download the specified URL into the given directory. + -+ If values can't be determined, they are set to values provided as -+ parameters. ++ :return: The path to the downloaded archive. + """ -+ if sys.platform == "watchos": -+ # TODO: Can the iOS implementation be used here? -+ import _ios_support -+ result = _ios_support.get_platform_ios() -+ if result is not None: -+ return WatchOSVersionInfo(*result) ++ target_path = Path(target_dir).resolve() ++ target_path.mkdir(exist_ok=True, parents=True) ++ ++ out_path = target_path / basename(url) ++ if not Path(out_path).is_file(): ++ run([ ++ "curl", ++ "-Lf", ++ "--retry", ++ "5", ++ "--retry-all-errors", ++ "-o", ++ out_path, ++ url, ++ ]) ++ else: ++ print(f"Using cached version of {basename(url)}") ++ return out_path + -+ return WatchOSVersionInfo(system, release, model, is_simulator) + ++def configure_host_python( ++ context: argparse.Namespace, ++ host: str | None = None, ++) -> None: ++ """The implementation of the "configure-host" command.""" ++ if host is None: ++ host = context.host ++ ++ if context.clean: ++ clean(context, host) ++ ++ host_dir = subdir(host, create=True) ++ prefix_dir = host_dir / "prefix" ++ ++ with group(f"Downloading dependencies ({host})"): ++ if not prefix_dir.exists(): ++ prefix_dir.mkdir() ++ cache_dir = ( ++ Path(context.cache_dir).resolve() ++ if context.cache_dir ++ else CROSS_BUILD_DIR / "downloads" ++ ) ++ unpack_deps(context.platform, host, prefix_dir, cache_dir) ++ else: ++ print("Dependencies already installed") ++ ++ with ( ++ group(f"Configuring host Python ({host})"), ++ cwd(host_dir), ++ ): ++ command = [ ++ # Basic cross-compiling configuration ++ relpath(PYTHON_DIR / "configure"), ++ f"--host={host}", ++ f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}", ++ "--enable-framework", ++ "PYTHON_FOR_REGEN=../build/python.exe", ++ # Dependent libraries. ++ f"--with-openssl={prefix_dir}", ++ f"CFLAGS=-I{prefix_dir}/include", ++ f"LDFLAGS=-L{prefix_dir}/lib", ++ f"LIBFFI_INCLUDEDIR={prefix_dir}/include", ++ f"LIBFFI_LIBDIR={prefix_dir}/lib", ++ "LIBFFI_LIB=ffi", ++ ] ++ ++ if context.args: ++ command.extend(context.args) ++ run(command, host=host) ++ ++ ++def make_host_python( ++ context: argparse.Namespace, ++ host: str | None = None, ++) -> None: ++ """The implementation of the "make-host" command.""" ++ if host is None: ++ host = context.host + - def _java_getprop(name, default): - """This private helper is deprecated in 3.13 and will be removed in 3.15""" - from java.lang import System -@@ -883,14 +931,25 @@ - csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0) - return 'Alpha' if cpu_number >= 128 else 'VAX' - -- # On the iOS simulator, os.uname returns the architecture as uname.machine. -- # On device it returns the model name for some reason; but there's only one -- # CPU architecture for iOS devices, so we know the right answer. -+ # On the iOS/tvOS/watchOS simulator, os.uname returns the architecture as -+ # uname.machine. On device it returns the model name for some reason; but -+ # there's only one CPU architecture for devices, so we know the right -+ # answer. - def get_ios(): - if sys.implementation._multiarch.endswith("simulator"): - return os.uname().machine - return 'arm64' - -+ def get_tvos(): -+ if sys.implementation._multiarch.endswith("simulator"): -+ return os.uname().machine -+ return 'arm64' ++ with ( ++ group(f"Compiling host Python ({host})"), ++ cwd(subdir(host)), ++ ): ++ run(["make"], host=host) ++ run(["make", "install"], host=host, env={"DESTDIR": f"{Path.cwd()}/"}) + -+ def get_watchos(): -+ if sys.implementation._multiarch.endswith("simulator"): -+ return os.uname().machine -+ return 'arm64_32' + - def from_subprocess(): - """ - Fall back to `uname -p` -@@ -1050,9 +1109,13 @@ - system = 'Android' - release = android_ver().release - -- # Normalize responses on iOS -+ # Normalize responses on Apple mobile platforms - if sys.platform == 'ios': - system, release, _, _ = ios_ver() -+ if sys.platform == 'tvos': -+ system, release, _, _ = tvos_ver() -+ if sys.platform == 'watchos': -+ system, release, _, _ = watchos_ver() - - vals = system, node, release, version, machine - # Replace 'unknown' values with the more portable '' -@@ -1342,6 +1405,10 @@ - # macOS and iOS both report as a "Darwin" kernel - if sys.platform == "ios": - system, release, _, _ = ios_ver() -+ elif sys.platform == "tvos": -+ system, release, _, _ = tvos_ver() -+ elif sys.platform == "watchos": -+ system, release, _, _ = watchos_ver() - else: - macos_release = mac_ver()[0] - if macos_release: -diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py -index 67a071963d8..eefcac66cb5 100644 ---- a/Lib/sysconfig/__init__.py -+++ b/Lib/sysconfig/__init__.py -@@ -669,6 +669,14 @@ - release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "13.0") - osname = sys.platform - machine = sys.implementation._multiarch -+ elif sys.platform == "tvos": -+ release = get_config_vars().get("TVOS_DEPLOYMENT_TARGET", "9.0") -+ osname = sys.platform -+ machine = sys.implementation._multiarch -+ elif sys.platform == "watchos": -+ release = get_config_vars().get("WATCHOS_DEPLOYMENT_TARGET", "4.0") -+ osname = sys.platform -+ machine = sys.implementation._multiarch - else: - import _osx_support - osname, release, machine = _osx_support.get_platform_osx( ---- /dev/null -+++ b/Lib/test/test_apple.py -@@ -0,0 +1,155 @@ -+import unittest -+from _apple_support import SystemLog -+from test.support import is_apple -+from unittest.mock import Mock, call ++def framework_path(host_triple: str, multiarch: str) -> Path: ++ """The path to a built single-architecture framework product. + -+if not is_apple: -+ raise unittest.SkipTest("Apple-specific") ++ :param host_triple: The host triple (e.g., arm64-apple-ios-simulator) ++ :param multiarch: The multiarch identifier (e.g., arm64-simulator) ++ """ ++ return ( ++ CROSS_BUILD_DIR ++ / f"{host_triple}/Apple/{platform_for_host(host_triple)}" ++ / f"Frameworks/{multiarch}" ++ ) + + -+# Test redirection of stdout and stderr to the Apple system log. -+class TestAppleSystemLogOutput(unittest.TestCase): -+ maxDiff = None ++def package_version(prefix_path: Path) -> str: ++ """Extract the Python version being built from patchlevel.h.""" ++ for path in prefix_path.glob("**/patchlevel.h"): ++ text = path.read_text(encoding="utf-8") ++ if match := re.search( ++ r'\n\s*#define\s+PY_VERSION\s+"(.+)"\s*\n', text ++ ): ++ version = match[1] ++ # If not building against a tagged commit, add a timestamp to the ++ # version. Follow the PyPA version number rules, as this will make ++ # it easier to process with other tools. The version will have a ++ # `+` suffix once any official release has been made; a freshly ++ # forked main branch will have a version of 3.X.0a0. ++ if version.endswith("a0"): ++ version += "+" ++ if version.endswith("+"): ++ version += datetime.now(timezone.utc).strftime("%Y%m%d.%H%M%S") ++ ++ return version ++ ++ sys.exit("Unable to determine Python version being packaged.") ++ ++ ++def lib_platform_files(dirname, names): ++ """A file filter that ignores platform-specific files in lib.""" ++ path = Path(dirname) ++ if ( ++ path.parts[-3] == "lib" ++ and path.parts[-2].startswith("python") ++ and path.parts[-1] == "lib-dynload" ++ ): ++ return names ++ elif path.parts[-2] == "lib" and path.parts[-1].startswith("python"): ++ ignored_names = { ++ name ++ for name in names ++ if ( ++ name.startswith("_sysconfigdata_") ++ or name.startswith("_sysconfig_vars_") ++ or name == "build-details.json" ++ ) ++ } ++ elif path.parts[-1] == "lib": ++ ignored_names = { ++ name ++ for name in names ++ if name.startswith("libpython") and name.endswith(".dylib") ++ } ++ else: ++ ignored_names = set() + -+ def assert_writes(self, output): -+ self.assertEqual( -+ self.log_write.mock_calls, -+ [ -+ call(self.log_level, line) -+ for line in output -+ ] -+ ) ++ return ignored_names + -+ self.log_write.reset_mock() + -+ def setUp(self): -+ self.log_write = Mock() -+ self.log_level = 42 -+ self.log = SystemLog(self.log_write, self.log_level, errors="replace") ++def lib_non_platform_files(dirname, names): ++ """A file filter that ignores anything *except* platform-specific files ++ in the lib directory. ++ """ ++ path = Path(dirname) ++ if path.parts[-2] == "lib" and path.parts[-1].startswith("python"): ++ return ( ++ set(names) - lib_platform_files(dirname, names) - {"lib-dynload"} ++ ) ++ else: ++ return set() + -+ def test_repr(self): -+ self.assertEqual(repr(self.log), "") -+ self.assertEqual(repr(self.log.buffer), "") + -+ def test_log_config(self): -+ self.assertIs(self.log.writable(), True) -+ self.assertIs(self.log.readable(), False) ++def create_xcframework(platform: str) -> str: ++ """Build an XCframework from the component parts for the platform. + -+ self.assertEqual("UTF-8", self.log.encoding) -+ self.assertEqual("replace", self.log.errors) ++ :return: The version number of the Python version that was packaged. ++ """ ++ package_path = CROSS_BUILD_DIR / platform ++ try: ++ package_path.mkdir() ++ except FileExistsError: ++ raise RuntimeError( ++ f"{platform} XCframework already exists; do you need to run " ++ "with --clean?" ++ ) from None ++ ++ frameworks = [] ++ # Merge Frameworks for each component SDK. If there's only one architecture ++ # for the SDK, we can use the compiled Python.framework as-is. However, if ++ # there's more than architecture, we need to merge the individual built ++ # frameworks into a merged "fat" framework. ++ for slice_name, slice_parts in HOSTS[platform].items(): ++ # Some parts are the same across all slices, so we use can any of the ++ # host frameworks as the source for the merged version. Use the first ++ # one on the list, as it's as representative as any other. ++ first_host_triple, first_multiarch = next(iter(slice_parts.items())) ++ first_framework = ( ++ framework_path(first_host_triple, first_multiarch) ++ / "Python.framework" ++ ) + -+ self.assertIs(self.log.line_buffering, True) -+ self.assertIs(self.log.write_through, False) ++ if len(slice_parts) == 1: ++ # The first framework is the only framework, so copy it. ++ print(f"Copying framework for {slice_name}...") ++ frameworks.append(first_framework) ++ else: ++ print(f"Merging framework for {slice_name}...") ++ slice_path = CROSS_BUILD_DIR / slice_name ++ slice_framework = slice_path / "Python.framework" ++ slice_framework.mkdir(exist_ok=True, parents=True) ++ ++ # Copy the Info.plist ++ shutil.copy( ++ first_framework / "Info.plist", ++ slice_framework / "Info.plist", ++ ) + -+ def test_empty_str(self): -+ self.log.write("") -+ self.log.flush() ++ # Copy the headers ++ shutil.copytree( ++ first_framework / "Headers", ++ slice_framework / "Headers", ++ ) + -+ self.assert_writes([]) ++ # Create the "fat" library binary for the slice ++ run( ++ ["lipo", "-create", "-output", slice_framework / "Python"] ++ + [ ++ ( ++ framework_path(host_triple, multiarch) ++ / "Python.framework/Python" ++ ) ++ for host_triple, multiarch in slice_parts.items() ++ ] ++ ) + -+ def test_simple_str(self): -+ self.log.write("hello world\n") ++ # Add this merged slice to the list to be added to the XCframework ++ frameworks.append(slice_framework) + -+ self.assert_writes([b"hello world\n"]) ++ print() ++ print("Build XCframework...") ++ cmd = [ ++ "xcodebuild", ++ "-create-xcframework", ++ "-output", ++ package_path / "Python.xcframework", ++ ] ++ for framework in frameworks: ++ cmd.extend(["-framework", framework]) ++ ++ run(cmd) ++ ++ # Extract the package version from the merged framework ++ version = package_version(package_path / "Python.xcframework") ++ version_tag = ".".join(version.split(".")[:2]) ++ ++ # On non-macOS platforms, each framework in XCframework only contains the ++ # headers, libPython, plus an Info.plist. Other resources like the standard ++ # library and binary shims aren't allowed to live in framework; they need ++ # to be copied in separately. ++ print() ++ print("Copy additional resources...") ++ has_common_stdlib = False ++ for slice_name, slice_parts in HOSTS[platform].items(): ++ # Some parts are the same across all slices, so we can any of the ++ # host frameworks as the source for the merged version. ++ first_host_triple, first_multiarch = next(iter(slice_parts.items())) ++ first_path = framework_path(first_host_triple, first_multiarch) ++ first_framework = first_path / "Python.framework" ++ ++ slice_path = package_path / f"Python.xcframework/{slice_name}" ++ slice_framework = slice_path / "Python.framework" ++ ++ # Copy the binary helpers ++ print(f" - {slice_name} binaries") ++ shutil.copytree(first_path / "bin", slice_path / "bin") ++ ++ # Copy the include path (a symlink to the framework headers) ++ print(f" - {slice_name} include files") ++ shutil.copytree( ++ first_path / "include", ++ slice_path / "include", ++ symlinks=True, ++ ) + -+ def test_buffered_str(self): -+ self.log.write("h") -+ self.log.write("ello") -+ self.log.write(" ") -+ self.log.write("world\n") -+ self.log.write("goodbye.") -+ self.log.flush() ++ # Copy in the cross-architecture pyconfig.h ++ shutil.copy( ++ PYTHON_DIR / f"Apple/{platform}/Resources/pyconfig.h", ++ slice_framework / "Headers/pyconfig.h", ++ ) + -+ self.assert_writes([b"hello world\n", b"goodbye."]) ++ print(f" - {slice_name} shared library") ++ # Create a simlink for the fat library ++ shared_lib = slice_path / f"lib/libpython{version_tag}.dylib" ++ shared_lib.parent.mkdir() ++ shared_lib.symlink_to("../Python.framework/Python") ++ ++ print(f" - {slice_name} architecture-specific files") ++ for host_triple, multiarch in slice_parts.items(): ++ print(f" - {multiarch} standard library") ++ arch, _ = multiarch.split("-", 1) ++ ++ if not has_common_stdlib: ++ print(" - using this architecture as the common stdlib") ++ shutil.copytree( ++ framework_path(host_triple, multiarch) / "lib", ++ package_path / "Python.xcframework/lib", ++ ignore=lib_platform_files, ++ symlinks=True, ++ ) ++ has_common_stdlib = True + -+ def test_manual_flush(self): -+ self.log.write("Hello") ++ shutil.copytree( ++ framework_path(host_triple, multiarch) / "lib", ++ slice_path / f"lib-{arch}", ++ ignore=lib_non_platform_files, ++ symlinks=True, ++ ) + -+ self.assert_writes([]) ++ # Copy the host's pyconfig.h to an architecture-specific name. ++ arch = multiarch.split("-")[0] ++ host_path = ( ++ CROSS_BUILD_DIR ++ / host_triple ++ / f"Apple/{platform}/Frameworks" ++ / multiarch ++ ) ++ host_framework = host_path / "Python.framework" ++ shutil.copy( ++ host_framework / "Headers/pyconfig.h", ++ slice_framework / f"Headers/pyconfig-{arch}.h", ++ ) + -+ self.log.write(" world\nHere for a while...\nGoodbye") -+ self.assert_writes([b"Hello world\n", b"Here for a while...\n"]) ++ # Apple identifies certain libraries as "security risks"; if you ++ # statically link those libraries into a Framework, you become ++ # responsible for providing a privacy manifest for that framework. ++ xcprivacy_file = { ++ "OpenSSL": subdir(host_triple) ++ / "prefix/share/OpenSSL.xcprivacy" ++ } ++ print(f" - {multiarch} xcprivacy files") ++ for module, lib in [ ++ ("_hashlib", "OpenSSL"), ++ ("_ssl", "OpenSSL"), ++ ]: ++ shutil.copy( ++ xcprivacy_file[lib], ++ slice_path ++ / f"lib-{arch}/python{version_tag}" ++ / f"lib-dynload/{module}.xcprivacy", ++ ) + -+ self.log.write(" world\nHello again") -+ self.assert_writes([b"Goodbye world\n"]) ++ print(" - build tools") ++ shutil.copytree( ++ PYTHON_DIR / "Apple/testbed/Python.xcframework/build", ++ package_path / "Python.xcframework/build", ++ ) + -+ self.log.flush() -+ self.assert_writes([b"Hello again"]) ++ return version + -+ def test_non_ascii(self): -+ # Spanish -+ self.log.write("ol\u00e9\n") -+ self.assert_writes([b"ol\xc3\xa9\n"]) + -+ # Chinese -+ self.log.write("\u4e2d\u6587\n") -+ self.assert_writes([b"\xe4\xb8\xad\xe6\x96\x87\n"]) ++def package(context: argparse.Namespace) -> None: ++ """The implementation of the "package" command.""" ++ if context.clean: ++ clean(context, "package") + -+ # Printing Non-BMP emoji -+ self.log.write("\U0001f600\n") -+ self.assert_writes([b"\xf0\x9f\x98\x80\n"]) ++ with group("Building package"): ++ # Create an XCframework ++ version = create_xcframework(context.platform) + -+ # Non-encodable surrogates are replaced -+ self.log.write("\ud800\udc00\n") -+ self.assert_writes([b"??\n"]) ++ # watchOS doesn't have a testbed (yet!) ++ if context.platform != "watchOS": ++ # Clone testbed ++ print() ++ run([ ++ sys.executable, ++ "Apple/testbed", ++ "clone", ++ "--platform", ++ context.platform, ++ "--framework", ++ CROSS_BUILD_DIR / context.platform / "Python.xcframework", ++ CROSS_BUILD_DIR / context.platform / "testbed", ++ ]) ++ ++ # Build the final archive ++ archive_name = ( ++ CROSS_BUILD_DIR ++ / "dist" ++ / f"python-{version}-{context.platform}-XCframework" ++ ) + -+ def test_modified_null(self): -+ # Null characters are logged using "modified UTF-8". -+ self.log.write("\u0000\n") -+ self.assert_writes([b"\xc0\x80\n"]) -+ self.log.write("a\u0000\n") -+ self.assert_writes([b"a\xc0\x80\n"]) -+ self.log.write("\u0000b\n") -+ self.assert_writes([b"\xc0\x80b\n"]) -+ self.log.write("a\u0000b\n") -+ self.assert_writes([b"a\xc0\x80b\n"]) ++ print() ++ print("Create package archive...") ++ shutil.make_archive( ++ str(CROSS_BUILD_DIR / archive_name), ++ format="gztar", ++ root_dir=CROSS_BUILD_DIR / context.platform, ++ base_dir=".", ++ ) ++ print() ++ print(f"{archive_name.relative_to(PYTHON_DIR)}.tar.gz created.") + -+ def test_nonstandard_str(self): -+ # String subclasses are accepted, but they should be converted -+ # to a standard str without calling any of their methods. -+ class CustomStr(str): -+ def splitlines(self, *args, **kwargs): -+ raise AssertionError() + -+ def __len__(self): -+ raise AssertionError() ++def build(context: argparse.Namespace, host: str | None = None) -> None: ++ """The implementation of the "build" command.""" ++ if host is None: ++ host = context.host + -+ def __str__(self): -+ raise AssertionError() ++ if context.clean: ++ clean(context, host) + -+ self.log.write(CustomStr("custom\n")) -+ self.assert_writes([b"custom\n"]) ++ if host in {"all", "build"}: ++ for step in [ ++ configure_build_python, ++ make_build_python, ++ ]: ++ step(context) + -+ def test_non_str(self): -+ # Non-string classes are not accepted. -+ for obj in [b"", b"hello", None, 42]: -+ with self.subTest(obj=obj): -+ with self.assertRaisesRegex( -+ TypeError, -+ fr"write\(\) argument must be str, not " -+ fr"{type(obj).__name__}" -+ ): -+ self.log.write(obj) ++ if host == "build": ++ hosts = [] ++ elif host in {"all", "hosts"}: ++ hosts = all_host_triples(context.platform) ++ else: ++ hosts = [host] + -+ def test_byteslike_in_buffer(self): -+ # The underlying buffer *can* accept bytes-like objects -+ self.log.buffer.write(bytearray(b"hello")) -+ self.log.flush() ++ for step_host in hosts: ++ for step in [ ++ configure_host_python, ++ make_host_python, ++ ]: ++ step(context, host=step_host) + -+ self.log.buffer.write(b"") -+ self.log.flush() ++ if host == "all": ++ package(context) + -+ self.log.buffer.write(b"goodbye") -+ self.log.flush() + -+ self.assert_writes([b"hello", b"goodbye"]) ++def test(context: argparse.Namespace, host: str | None = None) -> None: ++ """The implementation of the "test" command.""" ++ if host is None: ++ host = context.host + -+ def test_non_byteslike_in_buffer(self): -+ for obj in ["hello", None, 42]: -+ with self.subTest(obj=obj): -+ with self.assertRaisesRegex( -+ TypeError, -+ fr"write\(\) argument must be bytes-like, not " -+ fr"{type(obj).__name__}" -+ ): -+ self.log.buffer.write(obj) -diff --git a/Lib/test/test_capi/test_config.py b/Lib/test/test_capi/test_config.py -index 77730ad2f32..a3179efe4a8 100644 ---- a/Lib/test/test_capi/test_config.py -+++ b/Lib/test/test_capi/test_config.py -@@ -110,6 +110,10 @@ - options.extend(( - ("_pystats", bool, None), - )) -+ if support.is_apple: -+ options.extend(( -+ ("use_system_logger", bool, None), -+ )) - - for name, option_type, sys_attr in options: - with self.subTest(name=name, option_type=option_type, -diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py -index bf861ef06ee..468f821370e 100644 ---- a/Lib/test/test_embed.py -+++ b/Lib/test/test_embed.py -@@ -649,6 +649,8 @@ - CONFIG_COMPAT.update({ - 'legacy_windows_stdio': False, - }) -+ if support.is_apple: -+ CONFIG_COMPAT['use_system_logger'] = False - - CONFIG_PYTHON = dict(CONFIG_COMPAT, - _config_init=API_PYTHON, -diff --git a/Makefile.pre.in b/Makefile.pre.in -index 8d94ba361fd..6c1c95d4dd9 100644 ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -2132,7 +2132,6 @@ - # This must be run *after* a `make install` has completed the build. The - # `--with-framework-name` argument *cannot* be used when configuring the build. - XCFOLDER:=iOSTestbed.$(MULTIARCH).$(shell date +%s) --XCRESULT=$(XCFOLDER)/$(MULTIARCH).xcresult - .PHONY: testios - testios: - @if test "$(MACHDEP)" != "ios"; then \ -@@ -2151,29 +2150,12 @@ - echo "Cannot find a finalized iOS Python.framework. Have you run 'make install' to finalize the framework build?"; \ - exit 1;\ - fi -- # Copy the testbed project into the build folder -- cp -r $(srcdir)/iOS/testbed $(XCFOLDER) -- # Copy the framework from the install location to the testbed project. -- cp -r $(PYTHONFRAMEWORKPREFIX)/* $(XCFOLDER)/Python.xcframework/ios-arm64_x86_64-simulator -- -- # Run the test suite for the Xcode project, targeting the iOS simulator. -- # If the suite fails, touch a file in the test folder as a marker -- if ! xcodebuild test -project $(XCFOLDER)/iOSTestbed.xcodeproj -scheme "iOSTestbed" -destination "platform=iOS Simulator,name=iPhone SE (3rd Generation)" -resultBundlePath $(XCRESULT) -derivedDataPath $(XCFOLDER)/DerivedData ; then \ -- touch $(XCFOLDER)/failed; \ -- fi - -- # Regardless of success or failure, extract and print the test output -- xcrun xcresulttool get --path $(XCRESULT) \ -- --id $$( \ -- xcrun xcresulttool get --path $(XCRESULT) --format json | \ -- $(PYTHON_FOR_BUILD) -c "import sys, json; result = json.load(sys.stdin); print(result['actions']['_values'][0]['actionResult']['logRef']['id']['_value'])" \ -- ) \ -- --format json | \ -- $(PYTHON_FOR_BUILD) -c "import sys, json; result = json.load(sys.stdin); print(result['subsections']['_values'][1]['subsections']['_values'][0]['emittedOutput']['_value'])" -+ # Clone the testbed project into the XCFOLDER -+ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" - -- @if test -e $(XCFOLDER)/failed ; then \ -- exit 1; \ -- fi -+ # Run the testbed project -+ $(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W - - # Like test, but using --slow-ci which enables all test resources and use - # longer timeout. Run an optional pybuildbot.identify script to include -diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c -index ec0857a4a99..2350e9dc821 100644 ---- a/Misc/platform_triplet.c -+++ b/Misc/platform_triplet.c -@@ -257,6 +257,26 @@ - # else - PLATFORM_TRIPLET=arm64-iphoneos - # endif -+# elif defined(TARGET_OS_TV) && TARGET_OS_TV -+# if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR -+# if __x86_64__ -+PLATFORM_TRIPLET=x86_64-appletvsimulator -+# else -+PLATFORM_TRIPLET=arm64-appletvsimulator -+# endif -+# else -+PLATFORM_TRIPLET=arm64-appletvos -+# endif -+# elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH -+# if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR -+# if __x86_64__ -+PLATFORM_TRIPLET=x86_64-watchsimulator -+# else -+PLATFORM_TRIPLET=arm64-watchsimulator -+# endif -+# else -+PLATFORM_TRIPLET=arm64_32-watchos -+# endif - // Older macOS SDKs do not define TARGET_OS_OSX - # elif !defined(TARGET_OS_OSX) || TARGET_OS_OSX - PLATFORM_TRIPLET=darwin -diff --git a/Python/initconfig.c b/Python/initconfig.c -index 438f8a5c1cf..7851b86db1f 100644 ---- a/Python/initconfig.c -+++ b/Python/initconfig.c -@@ -168,6 +168,9 @@ - SPEC(tracemalloc, UINT, READ_ONLY, NO_SYS), - SPEC(use_frozen_modules, BOOL, READ_ONLY, NO_SYS), - SPEC(use_hash_seed, BOOL, READ_ONLY, NO_SYS), -+#ifdef __APPLE__ -+ SPEC(use_system_logger, BOOL, PUBLIC, NO_SYS), -+#endif - SPEC(user_site_directory, BOOL, READ_ONLY, NO_SYS), // sys.flags.no_user_site - SPEC(warn_default_encoding, BOOL, READ_ONLY, NO_SYS), - -@@ -884,6 +887,9 @@ - assert(config->cpu_count != 0); - // config->use_frozen_modules is initialized later - // by _PyConfig_InitImportConfig(). -+#ifdef __APPLE__ -+ assert(config->use_system_logger >= 0); -+#endif - #ifdef Py_STATS - assert(config->_pystats >= 0); - #endif -@@ -986,6 +992,9 @@ - config->_is_python_build = 0; - config->code_debug_ranges = 1; - config->cpu_count = -1; -+#ifdef __APPLE__ -+ config->use_system_logger = 0; -+#endif - #ifdef Py_GIL_DISABLED - config->enable_gil = _PyConfig_GIL_DEFAULT; - config->tlbc_enabled = 1; -@@ -1015,6 +1024,9 @@ - #ifdef MS_WINDOWS - config->legacy_windows_stdio = 0; - #endif -+#ifdef __APPLE__ -+ config->use_system_logger = 0; -+#endif - } - - -@@ -1049,6 +1061,9 @@ - #ifdef MS_WINDOWS - config->legacy_windows_stdio = 0; - #endif -+#ifdef __APPLE__ -+ config->use_system_logger = 0; -+#endif - } - - -diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c -index 23882d08384..64985527606 100644 ---- a/Python/pylifecycle.c -+++ b/Python/pylifecycle.c -@@ -45,7 +45,9 @@ - #endif - - #if defined(__APPLE__) -+# include - # include -+# include - #endif - - #ifdef HAVE_SIGNAL_H -@@ -75,6 +77,9 @@ - #ifdef __ANDROID__ - static PyStatus init_android_streams(PyThreadState *tstate); - #endif -+#if defined(__APPLE__) -+static PyStatus init_apple_streams(PyThreadState *tstate); -+#endif - static void wait_for_thread_shutdown(PyThreadState *tstate); - static void finalize_subinterpreters(void); - static void call_ll_exitfuncs(_PyRuntimeState *runtime); -@@ -1257,6 +1262,14 @@ - return status; - } - #endif -+#if defined(__APPLE__) -+ if (config->use_system_logger) { -+ status = init_apple_streams(tstate); -+ if (_PyStatus_EXCEPTION(status)) { -+ return status; -+ } -+ } -+#endif - - #ifdef Py_DEBUG - run_presite(tstate); -@@ -2931,6 +2944,75 @@ - - #endif // __ANDROID__ - -+#if defined(__APPLE__) ++ if context.clean: ++ clean(context, "test") + -+static PyObject * -+apple_log_write_impl(PyObject *self, PyObject *args) -+{ -+ int logtype = 0; -+ const char *text = NULL; -+ if (!PyArg_ParseTuple(args, "iy", &logtype, &text)) { -+ return NULL; -+ } ++ with group(f"Test {'XCframework' if host in {'all', 'hosts'} else host}"): ++ timestamp = str(time.time_ns())[:-6] ++ testbed_dir = ( ++ CROSS_BUILD_DIR / f"{context.platform}-testbed.{timestamp}" ++ ) ++ if host in {"all", "hosts"}: ++ framework_path = ( ++ CROSS_BUILD_DIR / context.platform / "Python.xcframework" ++ ) ++ else: ++ build_arch = platform.machine() ++ host_arch = host.split("-")[0] + -+ // Call the underlying Apple logging API. The os_log unified logging APIs -+ // were introduced in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0; -+ // this call is a no-op on older versions. -+ #if TARGET_OS_IPHONE || (TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) -+ // Pass the user-provided text through explicit %s formatting -+ // to avoid % literals being interpreted as a formatting directive. -+ os_log_with_type(OS_LOG_DEFAULT, logtype, "%s", text); -+ #endif -+ Py_RETURN_NONE; -+} ++ if not host.endswith("-simulator"): ++ print("Skipping test suite non-simulator build.") ++ return ++ elif build_arch != host_arch: ++ print( ++ f"Skipping test suite for an {host_arch} build " ++ f"on an {build_arch} machine." ++ ) ++ return ++ else: ++ framework_path = ( ++ CROSS_BUILD_DIR ++ / host ++ / f"Apple/{context.platform}" ++ / f"Frameworks/{apple_multiarch(host)}" ++ ) + ++ run([ ++ sys.executable, ++ "Apple/testbed", ++ "clone", ++ "--platform", ++ context.platform, ++ "--framework", ++ framework_path, ++ testbed_dir, ++ ]) ++ ++ run( ++ [ ++ sys.executable, ++ testbed_dir, ++ "run", ++ "--verbose", ++ ] ++ + ( ++ ["--simulator", str(context.simulator)] ++ if context.simulator ++ else [] ++ ) ++ + [ ++ "--", ++ "test", ++ # f"--{context.ci_mode}-ci", ++ "-uall", ++ # "--rerun", ++ # "--single-process", ++ "-W", ++ # Timeout handling requires subprocesses; explicitly setting ++ # the timeout to -1 disables the faulthandler. ++ "--timeout=-1", ++ # Adding Python options requires the use of a subprocess to ++ # start a new Python interpreter. ++ # "--dont-add-python-opts", ++ ] ++ ) + -+static PyMethodDef apple_log_write_method = { -+ "apple_log_write", apple_log_write_impl, METH_VARARGS -+}; + ++def apple_sim_host(platform_name: str) -> str: ++ """Determine the native simulator target for this platform.""" ++ for _, slice_parts in HOSTS[platform_name].items(): ++ for host_triple in slice_parts: ++ parts = host_triple.split("-") ++ if parts[0] == platform.machine() and parts[-1] == "simulator": ++ return host_triple + -+static PyStatus -+init_apple_streams(PyThreadState *tstate) -+{ -+ PyStatus status = _PyStatus_OK(); -+ PyObject *_apple_support = NULL; -+ PyObject *apple_log_write = NULL; -+ PyObject *result = NULL; ++ raise KeyError(platform_name) + -+ _apple_support = PyImport_ImportModule("_apple_support"); -+ if (_apple_support == NULL) { -+ goto error; -+ } + -+ apple_log_write = PyCFunction_New(&apple_log_write_method, NULL); -+ if (apple_log_write == NULL) { -+ goto error; -+ } ++def ci(context: argparse.Namespace) -> None: ++ """The implementation of the "ci" command. + -+ // Initialize the logging streams, sending stdout -> Default; stderr -> Error -+ result = PyObject_CallMethod( -+ _apple_support, "init_streams", "Oii", -+ apple_log_write, OS_LOG_TYPE_DEFAULT, OS_LOG_TYPE_ERROR); -+ if (result == NULL) { -+ goto error; -+ } ++ In "Fast" mode, this compiles the build python, and the simulator for the ++ build machine's architecture; and runs the test suite with `--fast-ci` ++ configuration. + -+ goto done; ++ In "Slow" mode, it compiles the build python, plus all candidate ++ architectures (both device and simulator); then runs the test suite with ++ `--slow-ci` configuration. ++ """ ++ clean(context, "all") ++ if context.ci_mode == "slow": ++ # In slow mode, build and test the full XCframework ++ build(context, host="all") ++ test(context, host="all") ++ else: ++ # In fast mode, just build the simulator platform. ++ sim_host = apple_sim_host(context.platform) ++ build(context, host="build") ++ build(context, host=sim_host) ++ test(context, host=sim_host) + -+error: -+ _PyErr_Print(tstate); -+ status = _PyStatus_ERR("failed to initialize Apple log streams"); + -+done: -+ Py_XDECREF(result); -+ Py_XDECREF(apple_log_write); -+ Py_XDECREF(_apple_support); -+ return status; -+} ++def parse_args() -> argparse.Namespace: ++ parser = argparse.ArgumentParser( ++ description=( ++ "A tool for managing the build, package and test process of " ++ "CPython on Apple platforms." ++ ), ++ ) ++ parser.suggest_on_error = True ++ subcommands = parser.add_subparsers(dest="subcommand", required=True) + -+#endif // __APPLE__ ++ clean = subcommands.add_parser( ++ "clean", ++ help="Delete all build directories", ++ ) + - - static void - _Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp, -diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h -index c8cdb933bb1..584b050fc4b 100644 ---- a/Python/stdlib_module_names.h -+++ b/Python/stdlib_module_names.h -@@ -6,6 +6,7 @@ - "_abc", - "_aix_support", - "_android_support", -+"_apple_support", - "_ast", - "_asyncio", - "_bisect", -diff --git a/configure b/configure -index 5b44a3d6992..83803f12853 100755 ---- a/configure -+++ b/configure -@@ -979,6 +979,8 @@ - CFLAGS - CC - HAS_XCRUN -+WATCHOS_DEPLOYMENT_TARGET -+TVOS_DEPLOYMENT_TARGET - IPHONEOS_DEPLOYMENT_TARGET - EXPORT_MACOSX_DEPLOYMENT_TARGET - CONFIGURE_MACOSX_DEPLOYMENT_TARGET -@@ -4053,6 +4055,12 @@ - *-apple-ios*) - ac_sys_system=iOS - ;; -+ *-apple-tvos*) -+ ac_sys_system=tvOS -+ ;; -+ *-apple-watchos*) -+ ac_sys_system=watchOS -+ ;; - *-*-vxworks*) - ac_sys_system=VxWorks - ;; -@@ -4130,7 +4138,7 @@ - # On cross-compile builds, configure will look for a host-specific compiler by - # prepending the user-provided host triple to the required binary name. - # --# On iOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", -+# On iOS/tvOS/watchOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", - # which isn't a binary that exists, and isn't very convenient, as it contains the - # iOS version. As the default cross-compiler name won't exist, configure falls - # back to gcc, which *definitely* won't work. We're providing wrapper scripts for -@@ -4145,6 +4153,14 @@ - aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;; - aarch64-apple-ios*) AR=arm64-apple-ios-ar ;; - x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; ++ configure_build = subcommands.add_parser( ++ "configure-build", help="Run `configure` for the build Python" ++ ) ++ make_build = subcommands.add_parser( ++ "make-build", help="Run `make` for the build Python" ++ ) ++ configure_host = subcommands.add_parser( ++ "configure-host", ++ help="Run `configure` for a specific platform and target", ++ ) ++ make_host = subcommands.add_parser( ++ "make-host", ++ help="Run `make` for a specific platform and target", ++ ) ++ package = subcommands.add_parser( ++ "package", ++ help="Create a release package for the platform", ++ ) ++ build = subcommands.add_parser( ++ "build", ++ help="Build all platform targets and create the XCframework", ++ ) ++ test = subcommands.add_parser( ++ "test", ++ help="Run the testbed for a specific platform", ++ ) ++ ci = subcommands.add_parser( ++ "ci", ++ help="Run build, package, and test", ++ ) + -+ aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;; -+ aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;; -+ x86_64-apple-tvos*-simulator) AR=x86_64-apple-tvos-simulator-ar ;; ++ # platform argument ++ for cmd in [clean, configure_host, make_host, package, build, test, ci]: ++ cmd.add_argument( ++ "platform", ++ choices=HOSTS.keys(), ++ help="The target platform to build", ++ ) + -+ aarch64-apple-watchos*-simulator) AR=arm64-apple-watchos-simulator-ar ;; -+ aarch64-apple-watchos*) AR=arm64_32-apple-watchos-ar ;; -+ x86_64-apple-watchos*-simulator) AR=x86_64-apple-watchos-simulator-ar ;; - *) - esac - fi -@@ -4153,6 +4169,14 @@ - aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;; - aarch64-apple-ios*) CC=arm64-apple-ios-clang ;; - x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; ++ # host triple argument ++ for cmd in [configure_host, make_host]: ++ cmd.add_argument( ++ "host", ++ help="The host triple to build (e.g., arm64-apple-ios-simulator)", ++ ) ++ # optional host triple argument ++ for cmd in [clean, build, test]: ++ cmd.add_argument( ++ "host", ++ nargs="?", ++ default="all", ++ help=( ++ "The host triple to build (e.g., arm64-apple-ios-simulator), " ++ "or 'build' for just the build platform, or 'hosts' for all " ++ "host platforms, or 'all' for the build platform and all " ++ "hosts. Defaults to 'all'" ++ ), ++ ) + -+ aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;; -+ aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;; -+ x86_64-apple-tvos*-simulator) CC=x86_64-apple-tvos-simulator-clang ;; ++ # --cross-build-dir argument ++ for cmd in [ ++ clean, ++ configure_build, ++ make_build, ++ configure_host, ++ make_host, ++ build, ++ package, ++ test, ++ ci, ++ ]: ++ cmd.add_argument( ++ "--cross-build-dir", ++ action="store", ++ default=os.environ.get("CROSS_BUILD_DIR"), ++ dest="cross_build_dir", ++ type=Path, ++ help=( ++ "Path to the cross-build directory " ++ f"(default: {CROSS_BUILD_DIR}). Can also be set " ++ "with the CROSS_BUILD_DIR environment variable." ++ ), ++ ) + -+ aarch64-apple-watchos*-simulator) CC=arm64-apple-watchos-simulator-clang ;; -+ aarch64-apple-watchos*) CC=arm64_32-apple-watchos-clang ;; -+ x86_64-apple-watchos*-simulator) CC=x86_64-apple-watchos-simulator-clang ;; - *) - esac - fi -@@ -4161,6 +4185,14 @@ - aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;; - aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;; - x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; ++ # --clean option ++ for cmd in [configure_build, configure_host, build, package, test, ci]: ++ cmd.add_argument( ++ "--clean", ++ action="store_true", ++ default=False, ++ dest="clean", ++ help="Delete the relevant build directories first", ++ ) + -+ aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;; -+ aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;; -+ x86_64-apple-tvos*-simulator) CPP=x86_64-apple-tvos-simulator-cpp ;; ++ # --cache-dir option ++ for cmd in [configure_host, build, ci]: ++ cmd.add_argument( ++ "--cache-dir", ++ default=os.environ.get("CACHE_DIR"), ++ help="The directory to store cached downloads.", ++ ) + -+ aarch64-apple-watchos*-simulator) CPP=arm64-apple-watchos-simulator-cpp ;; -+ aarch64-apple-watchos*) CPP=arm64_32-apple-watchos-cpp ;; -+ x86_64-apple-watchos*-simulator) CPP=x86_64-apple-watchos-simulator-cpp ;; - *) - esac - fi -@@ -4169,6 +4201,14 @@ - aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;; - aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;; - x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; ++ # --simulator option ++ for cmd in [test, ci]: ++ cmd.add_argument( ++ "--simulator", ++ help=( ++ "The name of the simulator to use (eg: 'iPhone 16e'). " ++ "Defaults to the most recently released 'entry level' " ++ "iPhone device. Device architecture and OS version can also " ++ "be specified; e.g., " ++ "`--simulator 'iPhone 16 Pro,arch=arm64,OS=26.0'` would " ++ "run on an ARM64 iPhone 16 Pro simulator running iOS 26.0." ++ ), ++ ) ++ group = cmd.add_mutually_exclusive_group() ++ group.add_argument( ++ "--fast-ci", ++ action="store_const", ++ dest="ci_mode", ++ const="fast", ++ help="Add test arguments for GitHub Actions", ++ ) ++ group.add_argument( ++ "--slow-ci", ++ action="store_const", ++ dest="ci_mode", ++ const="slow", ++ help="Add test arguments for buildbots", ++ ) + -+ aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;; -+ aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;; -+ x86_64-apple-tvos*-simulator) CXX=x86_64-apple-tvos-simulator-clang++ ;; ++ for subcommand in [configure_build, configure_host, build, ci]: ++ subcommand.add_argument( ++ "args", nargs="*", help="Extra arguments to pass to `configure`" ++ ) + -+ aarch64-apple-watchos*-simulator) CXX=arm64-apple-watchos-simulator-clang++ ;; -+ aarch64-apple-watchos*) CXX=arm64_32-apple-watchos-clang++ ;; -+ x86_64-apple-watchos*-simulator) CXX=x86_64-apple-watchos-simulator-clang++ ;; - *) - esac - fi -@@ -4289,8 +4329,10 @@ - case $enableval in - yes) - case $ac_sys_system in -- Darwin) enableval=/Library/Frameworks ;; -- iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ Darwin) enableval=/Library/Frameworks ;; -+ iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ tvOS) enableval=tvOS/Frameworks/\$\(MULTIARCH\) ;; -+ watchOS) enableval=watchOS/Frameworks/\$\(MULTIARCH\) ;; - *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 - esac - esac -@@ -4299,6 +4341,8 @@ - no) - case $ac_sys_system in - iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; -+ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; -+ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -4405,6 +4449,36 @@ - - ac_config_files="$ac_config_files iOS/Resources/Info.plist" - -+ ;; -+ tvOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ return parser.parse_args() + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=tvOS/Resources + -+ ac_config_files="$ac_config_files tvOS/Resources/Info.plist" ++def print_called_process_error(e: subprocess.CalledProcessError) -> None: ++ for stream_name in ["stdout", "stderr"]: ++ content = getattr(e, stream_name) ++ stream = getattr(sys, stream_name) ++ if content: ++ stream.write(content) ++ if not content.endswith("\n"): ++ stream.write("\n") + -+ ;; -+ watchOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ # shlex uses single quotes, so we surround the command with double quotes. ++ print( ++ f'Command "{join_command(e.cmd)}" returned exit status {e.returncode}' ++ ) + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=watchOS/Resources + -+ ac_config_files="$ac_config_files watchOS/Resources/Info.plist" ++def main() -> None: ++ # Handle SIGTERM the same way as SIGINT. This ensures that if we're ++ # terminated by the buildbot worker, we'll make an attempt to clean up our ++ # subprocesses. ++ def signal_handler(*args): ++ os.kill(os.getpid(), signal.SIGINT) ++ ++ signal.signal(signal.SIGTERM, signal_handler) ++ ++ # Process command line arguments ++ context = parse_args() ++ ++ # Set the CROSS_BUILD_DIR if an argument was provided ++ if context.cross_build_dir: ++ global CROSS_BUILD_DIR ++ CROSS_BUILD_DIR = context.cross_build_dir.resolve() ++ ++ dispatch: dict[str, Callable] = { ++ "clean": clean, ++ "configure-build": configure_build_python, ++ "make-build": make_build_python, ++ "configure-host": configure_host_python, ++ "make-host": make_host_python, ++ "package": package, ++ "build": build, ++ "test": test, ++ "ci": ci, ++ } + - ;; - *) - as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 -@@ -4416,6 +4490,8 @@ - - case $ac_sys_system in - iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; -+ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; -+ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -4469,8 +4545,8 @@ - case "$withval" in - yes) - case $ac_sys_system in -- Darwin|iOS) -- # iOS is able to share the macOS patch -+ Darwin|iOS|tvOS|watchOS) -+ # iOS/tvOS/watchOS is able to share the macOS patch - APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - ;; - *) as_fn_error $? "no default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; -@@ -4488,8 +4564,8 @@ - else $as_nop - - case $ac_sys_system in -- iOS) -- # Always apply the compliance patch on iOS; we can use the macOS patch -+ iOS|tvOS|watchOS) -+ # Always apply the compliance patch on iOS/tvOS/watchOS; we can use the macOS patch - APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 - printf "%s\n" "applying default app store compliance patch" >&6; } -@@ -4543,6 +4619,50 @@ - ;; - esac - ;; -+ *-apple-tvos*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++ try: ++ dispatch[context.subcommand](context) ++ except CalledProcessError as e: ++ print() ++ print_called_process_error(e) ++ sys.exit(1) ++ except RuntimeError as e: ++ print() ++ print(e) ++ sys.exit(2) + -+ # TVOS_DEPLOYMENT_TARGET is the minimum supported tvOS version -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking tvOS deployment target" >&5 -+printf %s "checking tvOS deployment target... " >&6; } -+ TVOS_DEPLOYMENT_TARGET=${_host_os:4} -+ TVOS_DEPLOYMENT_TARGET=${TVOS_DEPLOYMENT_TARGET:=12.0} -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TVOS_DEPLOYMENT_TARGET" >&5 -+printf "%s\n" "$TVOS_DEPLOYMENT_TARGET" >&6; } + -+ case "$host_cpu" in -+ aarch64) -+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-arm64-appletv${_host_device} -+ ;; -+ *) -+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-$host_cpu-appletv${_host_device} -+ ;; -+ esac -+ ;; -+ *-apple-watchos*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++if __name__ == "__main__": ++ # Under the buildbot, stdout is not a TTY, but we must still flush after ++ # every line to make sure our output appears in the correct order relative ++ # to the output of our subprocesses. ++ for stream in [sys.stdout, sys.stderr]: ++ stream.reconfigure(line_buffering=True) + -+ # WATCHOS_DEPLOYMENT_TARGET is the minimum supported watchOS version -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking watchOS deployment target" >&5 -+printf %s "checking watchOS deployment target... " >&6; } -+ WATCHOS_DEPLOYMENT_TARGET=${_host_os:7} -+ WATCHOS_DEPLOYMENT_TARGET=${WATCHOS_DEPLOYMENT_TARGET:=4.0} -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WATCHOS_DEPLOYMENT_TARGET" >&5 -+printf "%s\n" "$WATCHOS_DEPLOYMENT_TARGET" >&6; } ++ main() +diff --git a/Apple/iOS/README.md b/Apple/iOS/README.md +new file mode 100644 +index 00000000000..7ee257b5d64 +--- /dev/null ++++ b/Apple/iOS/README.md +@@ -0,0 +1,339 @@ ++# Python on iOS README + -+ case "$host_cpu" in -+ aarch64) -+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-arm64-watch${_host_device} -+ ;; -+ *) -+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-$host_cpu-watch${_host_device} -+ ;; -+ esac -+ ;; - *-*-vxworks*) - _host_ident=$host_cpu - ;; -@@ -4621,9 +4741,13 @@ - define_xopen_source=no;; - Darwin/[12][0-9].*) - define_xopen_source=no;; -- # On iOS, defining _POSIX_C_SOURCE also disables platform specific features. -+ # On iOS/tvOS/watchOS, defining _POSIX_C_SOURCE also disables platform specific features. - iOS/*) - define_xopen_source=no;; -+ tvOS/*) -+ define_xopen_source=no;; -+ watchOS/*) -+ define_xopen_source=no;; - # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from - # defining NI_NUMERICHOST. - QNX/6.3.2) -@@ -4686,7 +4810,10 @@ - CONFIGURE_MACOSX_DEPLOYMENT_TARGET= - EXPORT_MACOSX_DEPLOYMENT_TARGET='#' - --# Record the value of IPHONEOS_DEPLOYMENT_TARGET enforced by the selected host triple. -+# Record the value of IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET / -+# WATCHOS_DEPLOYMENT_TARGET enforced by the selected host triple. ++**iOS support is [tier 3](https://peps.python.org/pep-0011/#tier-3).** + ++This document provides a quick overview of some iOS specific features in the ++Python distribution. + - - - # checks for alternative programs -@@ -4727,6 +4854,16 @@ - as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" - as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" - ;; #( -+ tvOS) : ++These instructions are only needed if you're planning to compile Python for iOS ++yourself. Most users should *not* need to do this. If you're looking to ++experiment with writing an iOS app in Python, tools such as [BeeWare's ++Briefcase](https://briefcase.readthedocs.io) and [Kivy's ++Buildozer](https://buildozer.readthedocs.io) will provide a much more ++approachable user experience. + -+ as_fn_append CFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" -+ as_fn_append LDFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" -+ ;; #( -+ watchOS) : ++## Compilers for building on iOS + -+ as_fn_append CFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" -+ as_fn_append LDFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" -+ ;; #( - *) : - ;; - esac -@@ -7031,6 +7168,10 @@ - MULTIARCH="" ;; #( - iOS) : - MULTIARCH="" ;; #( -+ tvOS) : -+ MULTIARCH="" ;; #( -+ watchOS) : -+ MULTIARCH="" ;; #( - FreeBSD*) : - MULTIARCH="" ;; #( - *) : -@@ -7051,7 +7192,7 @@ - printf "%s\n" "$MULTIARCH" >&6; } - - case $ac_sys_system in #( -- iOS) : -+ iOS|tvOS|watchOS) : - SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2` ;; #( - *) : - SOABI_PLATFORM=$PLATFORM_TRIPLET -@@ -7102,6 +7243,14 @@ - PY_SUPPORT_TIER=3 ;; #( - aarch64-apple-ios*/clang) : - PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-tvos*-simulator/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-tvos*/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ aarch64-apple-watchos*-simulator/clang) : -+ PY_SUPPORT_TIER=3 ;; #( -+ arm64_32-apple-watchos*/clang) : -+ PY_SUPPORT_TIER=3 ;; #( - aarch64-*-linux-android/clang) : - PY_SUPPORT_TIER=3 ;; #( - x86_64-*-linux-android/clang) : -@@ -7531,7 +7680,7 @@ - case $ac_sys_system in - Darwin) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; -- iOS) -+ iOS|tvOS|watchOS) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; - *) - as_fn_error $? "Unknown platform for framework build" "$LINENO" 5;; -@@ -7597,7 +7746,7 @@ - BLDLIBRARY='-L. -lpython$(LDVERSION)' - RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} - ;; -- iOS) -+ iOS|tvOS|watchOS) - LDLIBRARY='libpython$(LDVERSION).dylib' - ;; - AIX*) -@@ -13150,7 +13299,7 @@ - BLDSHARED="$LDSHARED" - fi - ;; -- iOS/*) -+ iOS/*|tvOS/*|watchOS/*) - LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - BLDSHARED="$LDSHARED" -@@ -13283,7 +13432,7 @@ - Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; - Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; - # -u libsys_s pulls in all symbols in libsys -- Darwin/*|iOS/*) -+ Darwin/*|iOS/*|tvOS/*|watchOS/*) - LINKFORSHARED="$extra_undefs -framework CoreFoundation" - - # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -13307,7 +13456,7 @@ - LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' - fi - LINKFORSHARED="$LINKFORSHARED" -- elif test $ac_sys_system = "iOS"; then -+ elif test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS"; then - LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' - fi - ;; -@@ -14759,7 +14908,7 @@ - - ctypes_malloc_closure=yes - ;; #( -- iOS) : -+ iOS|tvOS|watchOS) : - - ctypes_malloc_closure=yes - ;; #( -@@ -18262,12 +18411,6 @@ - then : - printf "%s\n" "#define HAVE_DUP3 1" >>confdefs.h - --fi --ac_fn_c_check_func "$LINENO" "execv" "ac_cv_func_execv" --if test "x$ac_cv_func_execv" = xyes --then : -- printf "%s\n" "#define HAVE_EXECV 1" >>confdefs.h -- - fi - ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero" - if test "x$ac_cv_func_explicit_bzero" = xyes -@@ -18328,18 +18471,6 @@ - then : - printf "%s\n" "#define HAVE_FEXECVE 1" >>confdefs.h - --fi --ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork" --if test "x$ac_cv_func_fork" = xyes --then : -- printf "%s\n" "#define HAVE_FORK 1" >>confdefs.h -- --fi --ac_fn_c_check_func "$LINENO" "fork1" "ac_cv_func_fork1" --if test "x$ac_cv_func_fork1" = xyes --then : -- printf "%s\n" "#define HAVE_FORK1 1" >>confdefs.h -- - fi - ac_fn_c_check_func "$LINENO" "fpathconf" "ac_cv_func_fpathconf" - if test "x$ac_cv_func_fpathconf" = xyes -@@ -18766,24 +18897,6 @@ - then : - printf "%s\n" "#define HAVE_POSIX_OPENPT 1" >>confdefs.h - --fi --ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn" --if test "x$ac_cv_func_posix_spawn" = xyes --then : -- printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h -- --fi --ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp" --if test "x$ac_cv_func_posix_spawnp" = xyes --then : -- printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h -- --fi --ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_addclosefrom_np" "ac_cv_func_posix_spawn_file_actions_addclosefrom_np" --if test "x$ac_cv_func_posix_spawn_file_actions_addclosefrom_np" = xyes --then : -- printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP 1" >>confdefs.h -- - fi - ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread" - if test "x$ac_cv_func_pread" = xyes -@@ -19072,12 +19185,6 @@ - then : - printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h - --fi --ac_fn_c_check_func "$LINENO" "sigaltstack" "ac_cv_func_sigaltstack" --if test "x$ac_cv_func_sigaltstack" = xyes --then : -- printf "%s\n" "#define HAVE_SIGALTSTACK 1" >>confdefs.h -- - fi - ac_fn_c_check_func "$LINENO" "sigfillset" "ac_cv_func_sigfillset" - if test "x$ac_cv_func_sigfillset" = xyes -@@ -19346,11 +19453,11 @@ - - fi - --# iOS defines some system methods that can be linked (so they are -+# iOS/tvOS/watchOS define some system methods that can be linked (so they are - # found by configure), but either raise a compilation error (because the - # header definition prevents usage - autoconf doesn't use the headers), or - # raise an error if used at runtime. Force these symbols off. --if test "$ac_sys_system" != "iOS" ; then -+if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then - ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" - if test "x$ac_cv_func_getentropy" = xyes - then : -@@ -19372,6 +19479,53 @@ - - fi - -+# tvOS/watchOS have some additional methods that can be found, but not used. -+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then -+ ac_fn_c_check_func "$LINENO" "execv" "ac_cv_func_execv" -+if test "x$ac_cv_func_execv" = xyes -+then : -+ printf "%s\n" "#define HAVE_EXECV 1" >>confdefs.h ++Building for iOS requires the use of Apple's Xcode tooling. It is strongly ++recommended that you use the most recent stable release of Xcode. This will ++require the use of the most (or second-most) recently released macOS version, ++as Apple does not maintain Xcode for older macOS versions. The Xcode Command ++Line Tools are not sufficient for iOS development; you need a *full* Xcode ++install. + -+fi -+ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork" -+if test "x$ac_cv_func_fork" = xyes -+then : -+ printf "%s\n" "#define HAVE_FORK 1" >>confdefs.h ++If you want to run your code on the iOS simulator, you'll also need to install ++an iOS Simulator Platform. You should be prompted to select an iOS Simulator ++Platform when you first run Xcode. Alternatively, you can add an iOS Simulator ++Platform by selecting an open the Platforms tab of the Xcode Settings panel. + -+fi -+ac_fn_c_check_func "$LINENO" "fork1" "ac_cv_func_fork1" -+if test "x$ac_cv_func_fork1" = xyes -+then : -+ printf "%s\n" "#define HAVE_FORK1 1" >>confdefs.h ++## Building Python on iOS + -+fi -+ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn" -+if test "x$ac_cv_func_posix_spawn" = xyes -+then : -+ printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h ++### ABIs and Architectures + -+fi -+ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp" -+if test "x$ac_cv_func_posix_spawnp" = xyes -+then : -+ printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h ++iOS apps can be deployed on physical devices, and on the iOS simulator. Although ++the API used on these devices is identical, the ABI is different - you need to ++link against different libraries for an iOS device build (`iphoneos`) or an ++iOS simulator build (`iphonesimulator`). + -+fi -+ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_addclosefrom_np" "ac_cv_func_posix_spawn_file_actions_addclosefrom_np" -+if test "x$ac_cv_func_posix_spawn_file_actions_addclosefrom_np" = xyes -+then : -+ printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP 1" >>confdefs.h ++Apple uses the `XCframework` format to allow specifying a single dependency ++that supports multiple ABIs. An `XCframework` is a wrapper around multiple ++ABI-specific frameworks that share a common API. + -+fi -+ac_fn_c_check_func "$LINENO" "sigaltstack" "ac_cv_func_sigaltstack" -+if test "x$ac_cv_func_sigaltstack" = xyes -+then : -+ printf "%s\n" "#define HAVE_SIGALTSTACK 1" >>confdefs.h ++iOS can also support different CPU architectures within each ABI. At present, ++there is only a single supported architecture on physical devices - ARM64. ++However, the *simulator* supports 2 architectures - ARM64 (for running on Apple ++Silicon machines), and x86_64 (for running on older Intel-based machines). + -+fi ++To support multiple CPU architectures on a single platform, Apple uses a "fat ++binary" format - a single physical file that contains support for multiple ++architectures. It is possible to compile and use a "thin" single architecture ++version of a binary for testing purposes; however, the "thin" binary will not be ++portable to machines using other architectures. ++ ++### Building a multi-architecture iOS XCframework ++ ++The `Apple` subfolder of the Python repository acts as a build script that ++can be used to coordinate the compilation of a complete iOS XCframework. To use ++it, run:: ++ ++ python Apple build iOS ++ ++This will: ++ ++* Configure and compile a version of Python to run on the build machine ++* Download pre-compiled binary dependencies for each platform ++* Configure and build a `Python.framework` for each required architecture and ++ iOS SDK ++* Merge the multiple `Python.framework` folders into a single `Python.xcframework` ++* Produce a `.tar.gz` archive in the `cross-build/dist` folder containing ++ the `Python.xcframework`, plus a copy of the Testbed app pre-configured to ++ use the XCframework. ++ ++The `Apple` build script has other entry points that will perform the ++individual parts of the overall `build` target, plus targets to test the ++build, clean the `cross-build` folder of iOS build products, and perform a ++complete "build and test" CI run. The `--clean` flag can also be used on ++individual commands to ensure that a stale build product are removed before ++building. ++ ++### Building a single-architecture framework ++ ++If you're using the `Apple` build script, you won't need to build ++individual frameworks. However, if you do need to manually configure an iOS ++Python build for a single framework, the following options are available. ++ ++#### iOS specific arguments to configure ++ ++* `--enable-framework[=DIR]` ++ ++ This argument specifies the location where the Python.framework will be ++ installed. If `DIR` is not specified, the framework will be installed into ++ a subdirectory of the `iOS/Frameworks` folder. ++ ++ This argument *must* be provided when configuring iOS builds. iOS does not ++ support non-framework builds. ++ ++* `--with-framework-name=NAME` ++ ++ Specify the name for the Python framework; defaults to `Python`. ++ ++ > [!NOTE] ++ > Unless you know what you're doing, changing the name of the Python ++ > framework on iOS is not advised. If you use this option, you won't be able ++ > to run the `Apple` build script without making significant manual ++ > alterations, and you won't be able to use any binary packages unless you ++ > compile them yourself using your own framework name. ++ ++#### Building Python for iOS ++ ++The Python build system will create a `Python.framework` that supports a ++*single* ABI with a *single* architecture. Unlike macOS, iOS does not allow a ++framework to contain non-library content, so the iOS build will produce a ++`bin` and `lib` folder in the same output folder as `Python.framework`. ++The `lib` folder will be needed at runtime to support the Python library. ++ ++If you want to use Python in a real iOS project, you need to produce multiple ++`Python.framework` builds, one for each ABI and architecture. iOS builds of ++Python *must* be constructed as framework builds. To support this, you must ++provide the `--enable-framework` flag when configuring the build. The build ++also requires the use of cross-compilation. The minimal commands for building ++Python for the ARM64 iOS simulator will look something like: ++``` ++export PATH="$(pwd)/Apple/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin" ++./configure \ ++ --enable-framework \ ++ --host=arm64-apple-ios-simulator \ ++ --build=arm64-apple-darwin \ ++ --with-build-python=/path/to/python.exe ++make ++make install ++``` + -+fi ++In this invocation: + - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 - printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } - if test ${ac_cv_c_undeclared_builtin_options+y} -@@ -22247,7 +22401,8 @@ - - - # check for openpty, login_tty, and forkpty -- -+# tvOS/watchOS have functions for tty, but can't use them -+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then - - for ac_func in openpty - do : -@@ -22343,7 +22498,7 @@ - fi - - done --{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing login_tty" >&5 -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing login_tty" >&5 - printf %s "checking for library containing login_tty... " >&6; } - if test ${ac_cv_search_login_tty+y} - then : -@@ -22500,6 +22655,7 @@ - fi - - done -+fi - - # check for long file support functions - ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" -@@ -22746,10 +22902,10 @@ - - done - --# On Android and iOS, clock_settime can be linked (so it is found by -+# On Android, iOS, tvOS and watchOS, clock_settime can be linked (so it is found by - # configure), but when used in an unprivileged process, it crashes rather than - # returning an error. Force the symbol off. --if test "$ac_sys_system" != "Linux-android" && test "$ac_sys_system" != "iOS" -+if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" - then - - for ac_func in clock_settime -@@ -24977,8 +25133,8 @@ - LIBPYTHON="\$(BLDLIBRARY)" - fi - --# On iOS the shared libraries must be linked with the Python framework --if test "$ac_sys_system" = "iOS"; then -+# On iOS/tvOS/watchOS the shared libraries must be linked with the Python framework -+if test "$ac_sys_system" = "iOS" -o $ac_sys_system = "tvOS" -o $ac_sys_system = "watchOS"; then - MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" - fi - -@@ -27730,7 +27886,7 @@ - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for device files" >&5 - printf "%s\n" "$as_me: checking for device files" >&6;} - --if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS"; then -+if test "$ac_sys_system" = "Linux-android" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS" ; then - ac_cv_file__dev_ptmx=no - ac_cv_file__dev_ptc=no - else -@@ -28162,7 +28318,7 @@ - with_ensurepip=no ;; #( - WASI) : - with_ensurepip=no ;; #( -- iOS) : -+ iOS|tvOS|watchOS) : - with_ensurepip=no ;; #( - *) : - with_ensurepip=upgrade -@@ -29091,7 +29247,7 @@ - ;; #( - Darwin) : - ;; #( -- iOS) : -+ iOS|tvOS|watchOS) : - - - -@@ -32989,6 +33145,8 @@ - "Mac/Resources/framework/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/framework/Info.plist" ;; - "Mac/Resources/app/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/app/Info.plist" ;; - "iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES iOS/Resources/Info.plist" ;; -+ "tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES tvOS/Resources/Info.plist" ;; -+ "watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES watchOS/Resources/Info.plist" ;; - "Makefile.pre") CONFIG_FILES="$CONFIG_FILES Makefile.pre" ;; - "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; - "Misc/python-embed.pc") CONFIG_FILES="$CONFIG_FILES Misc/python-embed.pc" ;; -diff --git a/configure.ac b/configure.ac -index 7904f8990c4..f2367cd47d3 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -330,6 +330,12 @@ - *-apple-ios*) - ac_sys_system=iOS - ;; -+ *-apple-tvos*) -+ ac_sys_system=tvOS -+ ;; -+ *-apple-watchos*) -+ ac_sys_system=watchOS -+ ;; - *-*-vxworks*) - ac_sys_system=VxWorks - ;; -@@ -401,7 +407,7 @@ - # On cross-compile builds, configure will look for a host-specific compiler by - # prepending the user-provided host triple to the required binary name. - # --# On iOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", -+# On iOS/tvOS/watchOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", - # which isn't a binary that exists, and isn't very convenient, as it contains the - # iOS version. As the default cross-compiler name won't exist, configure falls - # back to gcc, which *definitely* won't work. We're providing wrapper scripts for -@@ -416,6 +422,14 @@ - aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;; - aarch64-apple-ios*) AR=arm64-apple-ios-ar ;; - x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; -+ -+ aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;; -+ aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;; -+ x86_64-apple-tvos*-simulator) AR=x86_64-apple-tvos-simulator-ar ;; ++* `Apple/iOS/Resources/bin` has been added to the path, providing some shims for the ++ compilers and linkers needed by the build. Xcode requires the use of `xcrun` ++ to invoke compiler tooling. However, if `xcrun` is pre-evaluated and the ++ result passed to `configure`, these results can embed user- and ++ version-specific paths into the sysconfig data, which limits the portability ++ of the compiled Python. Alternatively, if `xcrun` is used *as* the compiler, ++ it requires that compiler variables like `CC` include spaces, which can ++ cause significant problems with many C configuration systems which assume that ++ `CC` will be a single executable. ++ ++ To work around this problem, the `Apple/iOS/Resources/bin` folder contains some ++ wrapper scripts that present as simple compilers and linkers, but wrap ++ underlying calls to `xcrun`. This allows configure to use a `CC` ++ definition without spaces, and without user- or version-specific paths, while ++ retaining the ability to adapt to the local Xcode install. These scripts are ++ included in the `bin` directory of an iOS install. ++ ++ These scripts will, by default, use the currently active Xcode installation. ++ If you want to use a different Xcode installation, you can use ++ `xcode-select` to set a new default Xcode globally, or you can use the ++ `DEVELOPER_DIR` environment variable to specify an Xcode install. The ++ scripts will use the default `iphoneos`/`iphonesimulator` SDK version for ++ the select Xcode install; if you want to use a different SDK, you can set the ++ `IOS_SDK_VERSION` environment variable. (e.g, setting ++ `IOS_SDK_VERSION=17.1` would cause the scripts to use the `iphoneos17.1` ++ and `iphonesimulator17.1` SDKs, regardless of the Xcode default.) ++ ++ The path has also been cleared of any user customizations. A common source of ++ bugs is for tools like Homebrew to accidentally leak macOS binaries into an iOS ++ build. Resetting the path to a known "bare bones" value is the easiest way to ++ avoid these problems. ++ ++* `--host` is the architecture and ABI that you want to build, in GNU compiler ++ triple format. This will be one of: + -+ aarch64-apple-watchos*-simulator) AR=arm64-apple-watchos-simulator-ar ;; -+ aarch64-apple-watchos*) AR=arm64_32-apple-watchos-ar ;; -+ x86_64-apple-watchos*-simulator) AR=x86_64-apple-watchos-simulator-ar ;; - *) - esac - fi -@@ -424,6 +438,14 @@ - aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;; - aarch64-apple-ios*) CC=arm64-apple-ios-clang ;; - x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; ++ - `arm64-apple-ios` for ARM64 iOS devices. ++ - `arm64-apple-ios-simulator` for the iOS simulator running on Apple ++ Silicon devices. ++ - `x86_64-apple-ios-simulator` for the iOS simulator running on Intel ++ devices. + -+ aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;; -+ aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;; -+ x86_64-apple-tvos*-simulator) CC=x86_64-apple-tvos-simulator-clang ;; ++* `--build` is the GNU compiler triple for the machine that will be running ++ the compiler. This is one of: + -+ aarch64-apple-watchos*-simulator) CC=arm64-apple-watchos-simulator-clang ;; -+ aarch64-apple-watchos*) CC=arm64_32-apple-watchos-clang ;; -+ x86_64-apple-watchos*-simulator) CC=x86_64-apple-watchos-simulator-clang ;; - *) - esac - fi -@@ -432,6 +454,14 @@ - aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;; - aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;; - x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; ++ - `arm64-apple-darwin` for Apple Silicon devices. ++ - `x86_64-apple-darwin` for Intel devices. + -+ aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;; -+ aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;; -+ x86_64-apple-tvos*-simulator) CPP=x86_64-apple-tvos-simulator-cpp ;; ++* `/path/to/python.exe` is the path to a Python binary on the machine that ++ will be running the compiler. This is needed because the Python compilation ++ process involves running some Python code. On a normal desktop build of ++ Python, you can compile a python interpreter and then use that interpreter to ++ run Python code. However, the binaries produced for iOS won't run on macOS, so ++ you need to provide an external Python interpreter. This interpreter must be ++ the same version as the Python that is being compiled. To be completely safe, ++ this should be the *exact* same commit hash. However, the longer a Python ++ release has been stable, the more likely it is that this constraint can be ++ relaxed - the same micro version will often be sufficient. ++ ++* The `install` target for iOS builds is slightly different to other ++ platforms. On most platforms, `make install` will install the build into ++ the final runtime location. This won't be the case for iOS, as the final ++ runtime location will be on a physical device. ++ ++ However, you still need to run the `install` target for iOS builds, as it ++ performs some final framework assembly steps. The location specified with ++ `--enable-framework` will be the location where `make install` will ++ assemble the complete iOS framework. This completed framework can then ++ be copied and relocated as required. ++ ++For a full CPython build, you also need to specify the paths to iOS builds of ++the binary libraries that CPython depends on (such as XZ, LibFFI and OpenSSL). ++This can be done by defining library specific environment variables (such as ++`LIBLZMA_CFLAGS`, `LIBLZMA_LIBS`), and the `--with-openssl` configure ++option. Versions of these libraries pre-compiled for iOS can be found in [this ++repository](https://github.com/beeware/cpython-apple-source-deps/releases). ++LibFFI is especially important, as many parts of the standard library ++(including the `platform`, `sysconfig` and `webbrowser` modules) require ++the use of the `ctypes` module at runtime. ++ ++By default, Python will be compiled with an iOS deployment target (i.e., the ++minimum supported iOS version) of 13.0. To specify a different deployment ++target, provide the version number as part of the `--host` argument - for ++example, `--host=arm64-apple-ios15.4-simulator` would compile an ARM64 ++simulator build with a deployment target of 15.4. ++ ++## Testing Python on iOS ++ ++### Testing a multi-architecture framework ++ ++Once you have a built an XCframework, you can test that framework by running: ++ ++ $ python Apple test iOS ++ ++This test will attempt to find an "SE-class" simulator (i.e., an iPhone SE, or ++iPhone 16e, or similar), and run the test suite on the most recent version of ++iOS that is available. You can specify a simulator using the `--simulator` ++command line argument, providing the name of the simulator (e.g., `--simulator ++'iPhone 16 Pro'`). You can also use this argument to control the OS version used ++for testing; `--simulator 'iPhone 16 Pro,OS=18.2'` would attempt to run the ++tests on an iPhone 16 Pro running iOS 18.2. ++ ++If the test runner is executed on GitHub Actions, the `GITHUB_ACTIONS` ++environment variable will be exposed to the iOS process at runtime. ++ ++### Testing a single-architecture framework ++ ++The `Apple/testbed` folder that contains an Xcode project that is able to run ++the Python test suite on Apple platforms. This project converts the Python test ++suite into a single test case in Xcode's XCTest framework. The single XCTest ++passes if the test suite passes. ++ ++To run the test suite, configure a Python build for an iOS simulator (i.e., ++`--host=arm64-apple-ios-simulator` or `--host=x86_64-apple-ios-simulator` ++), specifying a framework build (i.e. `--enable-framework`). Ensure that your ++`PATH` has been configured to include the `Apple/iOS/Resources/bin` folder and ++exclude any non-iOS tools, then run: ++``` ++make all ++make install ++make testios ++``` ++ ++This will: ++ ++* Build an iOS framework for your chosen architecture; ++* Finalize the single-platform framework; ++* Make a clean copy of the testbed project; ++* Install the Python iOS framework into the copy of the testbed project; and ++* Run the test suite on an "entry-level device" simulator (i.e., an iPhone SE, ++ iPhone 16e, or a similar). ++ ++On success, the test suite will exit and report successful completion of the ++test suite. On a 2022 M1 MacBook Pro, the test suite takes approximately 15 ++minutes to run; a couple of extra minutes is required to compile the testbed ++project, and then boot and prepare the iOS simulator. + -+ aarch64-apple-watchos*-simulator) CPP=arm64-apple-watchos-simulator-cpp ;; -+ aarch64-apple-watchos*) CPP=arm64_32-apple-watchos-cpp ;; -+ x86_64-apple-watchos*-simulator) CPP=x86_64-apple-watchos-simulator-cpp ;; - *) - esac - fi -@@ -440,6 +470,14 @@ - aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;; - aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;; - x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; ++### Debugging test failures + -+ aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;; -+ aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;; -+ x86_64-apple-tvos*-simulator) CXX=x86_64-apple-tvos-simulator-clang++ ;; ++Running `python Apple test iOS` generates a standalone version of the ++`Apple/testbed` project, and runs the full test suite. It does this using ++`Apple/testbed` itself - the folder is an executable module that can be used ++to create and run a clone of the testbed project. The standalone version of the ++testbed will be created in a directory named ++`cross-build/iOS-testbed.`. + -+ aarch64-apple-watchos*-simulator) CXX=arm64-apple-watchos-simulator-clang++ ;; -+ aarch64-apple-watchos*) CXX=arm64_32-apple-watchos-clang++ ;; -+ x86_64-apple-watchos*-simulator) CXX=x86_64-apple-watchos-simulator-clang++ ;; - *) - esac - fi -@@ -554,8 +592,10 @@ - case $enableval in - yes) - case $ac_sys_system in -- Darwin) enableval=/Library/Frameworks ;; -- iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ Darwin) enableval=/Library/Frameworks ;; -+ iOS) enableval=iOS/Frameworks/\$\(MULTIARCH\) ;; -+ tvOS) enableval=tvOS/Frameworks/\$\(MULTIARCH\) ;; -+ watchOS) enableval=watchOS/Frameworks/\$\(MULTIARCH\) ;; - *) AC_MSG_ERROR([Unknown platform for framework build]) - esac - esac -@@ -564,6 +604,8 @@ - no) - case $ac_sys_system in - iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; -+ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; -+ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -666,6 +708,34 @@ - - AC_CONFIG_FILES([iOS/Resources/Info.plist]) - ;; -+ tvOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++You can generate your own standalone testbed instance by running: ++``` ++python cross-build/iOS/testbed clone my-testbed ++``` + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=tvOS/Resources ++In this invocation, `my-testbed` is the name of the folder for the new ++testbed clone. + -+ AC_CONFIG_FILES([tvOS/Resources/Info.plist]) -+ ;; -+ watchOS) : -+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" -+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " -+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" -+ FRAMEWORKPYTHONW= -+ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++If you've built your own XCframework, or you only want to test a single architecture, ++you can construct a standalone testbed instance by running: ++``` ++python Apple/testbed clone --platform iOS --framework my-testbed ++``` + -+ prefix=$PYTHONFRAMEWORKPREFIX -+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" -+ RESSRCDIR=watchOS/Resources ++The framework path can be the path path to a `Python.xcframework`, or the ++path to a folder that contains a single-platform `Python.framework`. + -+ AC_CONFIG_FILES([watchOS/Resources/Info.plist]) -+ ;; - *) - AC_MSG_ERROR([Unknown platform for framework build]) - ;; -@@ -674,6 +744,8 @@ - ],[ - case $ac_sys_system in - iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; -+ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; -+ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; - *) - PYTHONFRAMEWORK= - PYTHONFRAMEWORKDIR=no-framework -@@ -726,8 +798,8 @@ - case "$withval" in - yes) - case $ac_sys_system in -- Darwin|iOS) -- # iOS is able to share the macOS patch -+ Darwin|iOS|tvOS|watchOS) -+ # iOS/tvOS/watchOS is able to share the macOS patch - APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - ;; - *) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;; -@@ -741,8 +813,8 @@ - esac - ],[ - case $ac_sys_system in -- iOS) -- # Always apply the compliance patch on iOS; we can use the macOS patch -+ iOS|tvOS|watchOS) -+ # Always apply the compliance patch on iOS/tvOS/watchOS; we can use the macOS patch - APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" - AC_MSG_RESULT([applying default app store compliance patch]) - ;; -@@ -790,6 +862,46 @@ - ;; - esac - ;; -+ *-apple-tvos*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++You can then use the `my-testbed` folder to run the Python test suite, ++passing in any command line arguments you may require. For example, if you're ++trying to diagnose a failure in the `os` module, you might run: ++``` ++python my-testbed run -- test -W test_os ++``` + -+ # TVOS_DEPLOYMENT_TARGET is the minimum supported tvOS version -+ AC_MSG_CHECKING([tvOS deployment target]) -+ TVOS_DEPLOYMENT_TARGET=${_host_os:4} -+ TVOS_DEPLOYMENT_TARGET=${TVOS_DEPLOYMENT_TARGET:=12.0} -+ AC_MSG_RESULT([$TVOS_DEPLOYMENT_TARGET]) ++This is the equivalent of running `python -m test -W test_os` on a desktop ++Python build. Any arguments after the `--` will be passed to testbed as if ++they were arguments to `python -m` on a desktop machine. + -+ case "$host_cpu" in -+ aarch64) -+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-arm64-appletv${_host_device} -+ ;; -+ *) -+ _host_ident=${TVOS_DEPLOYMENT_TARGET}-$host_cpu-appletv${_host_device} -+ ;; -+ esac -+ ;; -+ *-apple-watchos*) -+ _host_os=`echo $host | cut -d '-' -f3` -+ _host_device=`echo $host | cut -d '-' -f4` -+ _host_device=${_host_device:=os} ++### Testing in Xcode + -+ # WATCHOS_DEPLOYMENT_TARGET is the minimum supported watchOS version -+ AC_MSG_CHECKING([watchOS deployment target]) -+ WATCHOS_DEPLOYMENT_TARGET=${_host_os:7} -+ WATCHOS_DEPLOYMENT_TARGET=${WATCHOS_DEPLOYMENT_TARGET:=4.0} -+ AC_MSG_RESULT([$WATCHOS_DEPLOYMENT_TARGET]) ++You can also open the testbed project in Xcode by running: ++``` ++open my-testbed/iOSTestbed.xcodeproj ++``` + -+ case "$host_cpu" in -+ aarch64) -+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-arm64-watch${_host_device} -+ ;; -+ *) -+ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-$host_cpu-watch${_host_device} -+ ;; -+ esac -+ ;; - *-*-vxworks*) - _host_ident=$host_cpu - ;; -@@ -867,9 +979,13 @@ - define_xopen_source=no;; - Darwin/@<:@[12]@:>@@<:@0-9@:>@.*) - define_xopen_source=no;; -- # On iOS, defining _POSIX_C_SOURCE also disables platform specific features. -+ # On iOS/tvOS/watchOS, defining _POSIX_C_SOURCE also disables platform specific features. - iOS/*) - define_xopen_source=no;; -+ tvOS/*) -+ define_xopen_source=no;; -+ watchOS/*) -+ define_xopen_source=no;; - # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from - # defining NI_NUMERICHOST. - QNX/6.3.2) -@@ -928,8 +1044,11 @@ - CONFIGURE_MACOSX_DEPLOYMENT_TARGET= - EXPORT_MACOSX_DEPLOYMENT_TARGET='#' - --# Record the value of IPHONEOS_DEPLOYMENT_TARGET enforced by the selected host triple. -+# Record the value of IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET / -+# WATCHOS_DEPLOYMENT_TARGET enforced by the selected host triple. - AC_SUBST([IPHONEOS_DEPLOYMENT_TARGET]) -+AC_SUBST([TVOS_DEPLOYMENT_TARGET]) -+AC_SUBST([WATCHOS_DEPLOYMENT_TARGET]) - - # checks for alternative programs - -@@ -963,11 +1082,17 @@ - ], - ) - --dnl Add the compiler flag for the iOS minimum supported OS version. -+dnl Add the compiler flag for the iOS/tvOS/watchOS minimum supported OS version. - AS_CASE([$ac_sys_system], - [iOS], [ - AS_VAR_APPEND([CFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) - AS_VAR_APPEND([LDFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) -+ ],[tvOS], [ -+ AS_VAR_APPEND([CFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) -+ AS_VAR_APPEND([LDFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) -+ ],[watchOS], [ -+ AS_VAR_APPEND([CFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) -+ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) - ], - ) - -@@ -1156,6 +1281,8 @@ - AS_CASE([$ac_sys_system], - [Darwin*], [MULTIARCH=""], - [iOS], [MULTIARCH=""], -+ [tvOS], [MULTIARCH=""], -+ [watchOS], [MULTIARCH=""], - [FreeBSD*], [MULTIARCH=""], - [MULTIARCH=$($CC --print-multiarch 2>/dev/null)] - ) -@@ -1177,7 +1304,7 @@ - dnl use a single "fat" binary at runtime. SOABI_PLATFORM is the component of - dnl the PLATFORM_TRIPLET that will be used in binary module extensions. - AS_CASE([$ac_sys_system], -- [iOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`], -+ [iOS|tvOS|watchOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`], - [SOABI_PLATFORM=$PLATFORM_TRIPLET] - ) - -@@ -1211,6 +1338,10 @@ - [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 - [aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64 - [aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64 -+ [aarch64-apple-tvos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl tvOS Simulator on arm64 -+ [aarch64-apple-tvos*/clang], [PY_SUPPORT_TIER=3], dnl tvOS on ARM64 -+ [aarch64-apple-watchos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl watchOS Simulator on arm64 -+ [arm64_32-apple-watchos*/clang], [PY_SUPPORT_TIER=3], dnl watchOS on ARM64 - [aarch64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on ARM64 - [x86_64-*-linux-android/clang], [PY_SUPPORT_TIER=3], dnl Android on AMD64 - -@@ -1520,7 +1651,7 @@ - case $ac_sys_system in - Darwin) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; -- iOS) -+ iOS|tvOS|watchOS) - LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; - *) - AC_MSG_ERROR([Unknown platform for framework build]);; -@@ -1585,7 +1716,7 @@ - BLDLIBRARY='-L. -lpython$(LDVERSION)' - RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} - ;; -- iOS) -+ iOS|tvOS|watchOS) - LDLIBRARY='libpython$(LDVERSION).dylib' - ;; - AIX*) -@@ -3407,7 +3538,7 @@ - BLDSHARED="$LDSHARED" - fi - ;; -- iOS/*) -+ iOS/*|tvOS/*|watchOS/*) - LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - BLDSHARED="$LDSHARED" -@@ -3531,7 +3662,7 @@ - Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; - Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; - # -u libsys_s pulls in all symbols in libsys -- Darwin/*|iOS/*) -+ Darwin/*|iOS/*|tvOS/*|watchOS/*) - LINKFORSHARED="$extra_undefs -framework CoreFoundation" - - # Issue #18075: the default maximum stack size (8MBytes) is too -@@ -3555,7 +3686,7 @@ - LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' - fi - LINKFORSHARED="$LINKFORSHARED" -- elif test $ac_sys_system = "iOS"; then -+ elif test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS"; then - LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' - fi - ;; -@@ -3975,7 +4106,7 @@ - dnl when do we need USING_APPLE_OS_LIBFFI? - ctypes_malloc_closure=yes - ], -- [iOS], [ -+ [iOS|tvOS|watchOS], [ - ctypes_malloc_closure=yes - ], - [sunos5], [AS_VAR_APPEND([LIBFFI_LIBS], [" -mimpure-text"])] -@@ -5093,9 +5224,9 @@ - # checks for library functions - AC_CHECK_FUNCS([ \ - accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \ -- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \ -+ copy_file_range ctermid dup dup3 explicit_bzero explicit_memset \ - faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ -- fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ -+ fpathconf fstatat ftime ftruncate futimens futimes futimesat \ - gai_strerror getegid geteuid getgid getgrent getgrgid getgrgid_r \ - getgrnam_r getgrouplist gethostname getitimer getloadavg getlogin \ - getpeername getpgid getpid getppid getpriority _getpty \ -@@ -5103,15 +5234,14 @@ - getspnam getuid getwd grantpt if_nameindex initgroups kill killpg lchown linkat \ - lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ - mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ -- pipe2 plock poll posix_fadvise posix_fallocate posix_openpt posix_spawn posix_spawnp \ -- posix_spawn_file_actions_addclosefrom_np \ -+ pipe2 plock poll posix_fadvise posix_fallocate posix_openpt \ - pread preadv preadv2 process_vm_readv pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_init \ - pthread_kill ptsname ptsname_r pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ - rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \ - sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ - sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ - setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ -- setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \ -+ setresuid setreuid setsid setuid setvbuf shutdown sigaction \ - sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \ - sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ - sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ -@@ -5126,12 +5256,20 @@ - AC_CHECK_FUNCS([lchmod]) - fi - --# iOS defines some system methods that can be linked (so they are -+# iOS/tvOS/watchOS define some system methods that can be linked (so they are - # found by configure), but either raise a compilation error (because the - # header definition prevents usage - autoconf doesn't use the headers), or - # raise an error if used at runtime. Force these symbols off. --if test "$ac_sys_system" != "iOS" ; then -- AC_CHECK_FUNCS([getentropy getgroups system]) -+if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then -+ AC_CHECK_FUNCS([ getentropy getgroups system ]) -+fi ++This will allow you to use the full Xcode suite of tools for debugging. + -+# tvOS/watchOS have some additional methods that can be found, but not used. -+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then -+ AC_CHECK_FUNCS([ \ -+ execv fork fork1 posix_spawn posix_spawnp posix_spawn_file_actions_addclosefrom_np \ -+ sigaltstack \ -+ ]) - fi - - AC_CHECK_DECL([dirfd], -@@ -5385,20 +5523,22 @@ - ]) - - # check for openpty, login_tty, and forkpty -- --AC_CHECK_FUNCS([openpty], [], -- [AC_CHECK_LIB([util], [openpty], -- [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lutil"], -- [AC_CHECK_LIB([bsd], [openpty], -- [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lbsd"])])]) --AC_SEARCH_LIBS([login_tty], [util], -- [AC_DEFINE([HAVE_LOGIN_TTY], [1], [Define to 1 if you have the `login_tty' function.])] --) --AC_CHECK_FUNCS([forkpty], [], -- [AC_CHECK_LIB([util], [forkpty], -- [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lutil"], -- [AC_CHECK_LIB([bsd], [forkpty], -- [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lbsd"])])]) -+# tvOS/watchOS have functions for tty, but can't use them -+if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then -+ AC_CHECK_FUNCS([openpty], [], -+ [AC_CHECK_LIB([util], [openpty], -+ [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lutil"], -+ [AC_CHECK_LIB([bsd], [openpty], -+ [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lbsd"])])]) -+ AC_SEARCH_LIBS([login_tty], [util], -+ [AC_DEFINE([HAVE_LOGIN_TTY], [1], [Define to 1 if you have the `login_tty' function.])] -+ ) -+ AC_CHECK_FUNCS([forkpty], [], -+ [AC_CHECK_LIB([util], [forkpty], -+ [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lutil"], -+ [AC_CHECK_LIB([bsd], [forkpty], -+ [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lbsd"])])]) -+fi - - # check for long file support functions - AC_CHECK_FUNCS([fseek64 fseeko fstatvfs ftell64 ftello statvfs]) -@@ -5437,10 +5577,10 @@ - ]) - ]) - --# On Android and iOS, clock_settime can be linked (so it is found by -+# On Android, iOS, tvOS and watchOS, clock_settime can be linked (so it is found by - # configure), but when used in an unprivileged process, it crashes rather than - # returning an error. Force the symbol off. --if test "$ac_sys_system" != "Linux-android" && test "$ac_sys_system" != "iOS" -+if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" - then - AC_CHECK_FUNCS([clock_settime], [], [ - AC_CHECK_LIB([rt], [clock_settime], [ -@@ -6191,8 +6331,8 @@ - LIBPYTHON="\$(BLDLIBRARY)" - fi - --# On iOS the shared libraries must be linked with the Python framework --if test "$ac_sys_system" = "iOS"; then -+# On iOS/tvOS/watchOS the shared libraries must be linked with the Python framework -+if test "$ac_sys_system" = "iOS" -o $ac_sys_system = "tvOS" -o $ac_sys_system = "watchOS"; then - MODULE_DEPS_SHARED="$MODULE_DEPS_SHARED \$(PYTHONFRAMEWORKDIR)/\$(PYTHONFRAMEWORK)" - fi - -@@ -6856,7 +6996,7 @@ - dnl NOTE: Inform user how to proceed with files when cross compiling. - dnl Some cross-compile builds are predictable; they won't ever - dnl have /dev/ptmx or /dev/ptc, so we can set them explicitly. --if test "$ac_sys_system" = "Linux-android" || test "$ac_sys_system" = "iOS"; then -+if test "$ac_sys_system" = "Linux-android" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS" ; then - ac_cv_file__dev_ptmx=no - ac_cv_file__dev_ptc=no - else -@@ -7112,7 +7252,7 @@ - AS_CASE([$ac_sys_system], - [Emscripten], [with_ensurepip=no], - [WASI], [with_ensurepip=no], -- [iOS], [with_ensurepip=no], -+ [iOS|tvOS|watchOS], [with_ensurepip=no], - [with_ensurepip=upgrade] - ) - ]) -@@ -7506,7 +7646,7 @@ - [VxWorks*], [PY_STDLIB_MOD_SET_NA([_scproxy], [termios], [grp])], - dnl The _scproxy module is available on macOS - [Darwin], [], -- [iOS], [ -+ [iOS|tvOS|watchOS], [ - dnl subprocess and multiprocessing are not supported (no fork syscall). - dnl curses and tkinter user interface are not available. - dnl gdbm and nis aren't available -diff --git a/iOS/README.rst b/iOS/README.rst -index e33455eef8f..13b88514493 100644 ---- a/iOS/README.rst -+++ b/iOS/README.rst -@@ -285,52 +285,42 @@ - * Install the Python iOS framework into the copy of the testbed project; and - * Run the test suite on an "iPhone SE (3rd generation)" simulator. - --While the test suite is running, Xcode does not display any console output. --After showing some Xcode build commands, the console output will print ``Testing --started``, and then appear to stop. It will remain in this state until the test --suite completes. On a 2022 M1 MacBook Pro, the test suite takes approximately 12 --minutes to run; a couple of extra minutes is required to boot and prepare the --iOS simulator. -- - On success, the test suite will exit and report successful completion of the --test suite. No output of the Python test suite will be displayed. -- --On failure, the output of the Python test suite *will* be displayed. This will --show the details of the tests that failed. -+test suite. On a 2022 M1 MacBook Pro, the test suite takes approximately 15 -+minutes to run; a couple of extra minutes is required to compile the testbed -+project, and then boot and prepare the iOS simulator. - - Debugging test failures - ----------------------- - --The easiest way to diagnose a single test failure is to open the testbed project --in Xcode and run the tests from there using the "Product > Test" menu item. -- --To test in Xcode, you must ensure the testbed project has a copy of a compiled --framework. If you've configured your build with the default install location of --``iOS/Frameworks``, you can copy from that location into the test project. To --test on an ARM64 simulator, run:: -- -- $ rm -rf iOS/testbed/Python.xcframework/ios-arm64_x86_64-simulator/* -- $ cp -r iOS/Frameworks/arm64-iphonesimulator/* iOS/testbed/Python.xcframework/ios-arm64_x86_64-simulator -+Running ``make test`` generates a standalone version of the ``iOS/testbed`` -+project, and runs the full test suite. It does this using ``iOS/testbed`` -+itself - the folder is an executable module that can be used to create and run -+a clone of the testbed project. - --To test on an x86-64 simulator, run:: -+You can generate your own standalone testbed instance by running:: - -- $ rm -rf iOS/testbed/Python.xcframework/ios-arm64_x86_64-simulator/* -- $ cp -r iOS/Frameworks/x86_64-iphonesimulator/* iOS/testbed/Python.xcframework/ios-arm64_x86_64-simulator -+ $ python iOS/testbed clone --framework iOS/Frameworks/arm64-iphonesimulator my-testbed - --To test on a physical device:: -+This invocation assumes that ``iOS/Frameworks/arm64-iphonesimulator`` is the -+path to the iOS simulator framework for your platform (ARM64 in this case); -+``my-testbed`` is the name of the folder for the new testbed clone. - -- $ rm -rf iOS/testbed/Python.xcframework/ios-arm64/* -- $ cp -r iOS/Frameworks/arm64-iphoneos/* iOS/testbed/Python.xcframework/ios-arm64 -+You can then use the ``my-testbed`` folder to run the Python test suite, -+passing in any command line arguments you may require. For example, if you're -+trying to diagnose a failure in the ``os`` module, you might run:: - --Alternatively, you can configure your build to install directly into the --testbed project. For a simulator, use:: -+ $ python my-testbed run -- test -W test_os - -- --enable-framework=$(pwd)/iOS/testbed/Python.xcframework/ios-arm64_x86_64-simulator -+This is the equivalent of running ``python -m test -W test_os`` on a desktop -+Python build. Any arguments after the ``--`` will be passed to testbed as if -+they were arguments to ``python -m`` on a desktop machine. - --For a physical device, use:: -+You can also open the testbed project in Xcode by running:: - -- --enable-framework=$(pwd)/iOS/testbed/Python.xcframework/ios-arm64 -+ $ open my-testbed/iOSTestbed.xcodeproj - -+This will allow you to use the full Xcode suite of tools for debugging. - - Testing on an iOS device - ^^^^^^^^^^^^^^^^^^^^^^^^ -diff --git a/iOS/Resources/Info.plist.in b/iOS/Resources/Info.plist.in -index c3e261ecd9e..26ef7a95de4 100644 ---- a/iOS/Resources/Info.plist.in -+++ b/iOS/Resources/Info.plist.in -@@ -17,13 +17,13 @@ - CFBundlePackageType - FMWK - CFBundleShortVersionString -- @VERSION@ ++The arguments used to run the test suite are defined as part of the test plan. ++To modify the test plan, select the test plan node of the project tree (it ++should be the first child of the root node), and select the "Configurations" ++tab. Modify the "Arguments Passed On Launch" value to change the testing ++arguments. ++ ++The test plan also disables parallel testing, and specifies the use of the ++`Testbed.lldbinit` file for providing configuration of the debugger. The ++default debugger configuration disables automatic breakpoints on the ++`SIGINT`, `SIGUSR1`, `SIGUSR2`, and `SIGXFSZ` signals. ++ ++### Testing on an iOS device ++ ++To test on an iOS device, the app needs to be signed with known developer ++credentials. To obtain these credentials, you must have an iOS Developer ++account, and your Xcode install will need to be logged into your account (see ++the Accounts tab of the Preferences dialog). ++ ++Once the project is open, and you're signed into your Apple Developer account, ++select the root node of the project tree (labeled "iOSTestbed"), then the ++"Signing & Capabilities" tab in the details page. Select a development team ++(this will likely be your own name), and plug in a physical device to your ++macOS machine with a USB cable. You should then be able to select your physical ++device from the list of targets in the pulldown in the Xcode titlebar. +diff --git a/Apple/iOS/Resources/Info.plist.in b/Apple/iOS/Resources/Info.plist.in +new file mode 100644 +index 00000000000..26ef7a95de4 +--- /dev/null ++++ b/Apple/iOS/Resources/Info.plist.in +@@ -0,0 +1,34 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleExecutable ++ Python ++ CFBundleGetInfoString ++ Python Runtime and Library ++ CFBundleIdentifier ++ @PYTHONFRAMEWORKIDENTIFIER@ ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundleName ++ Python ++ CFBundlePackageType ++ FMWK ++ CFBundleShortVersionString + %VERSION% - CFBundleLongVersionString - %VERSION%, (c) 2001-2024 Python Software Foundation. - CFBundleSignature - ???? - CFBundleVersion -- 1 ++ CFBundleLongVersionString ++ %VERSION%, (c) 2001-2024 Python Software Foundation. ++ CFBundleSignature ++ ???? ++ CFBundleVersion + %VERSION% - CFBundleSupportedPlatforms - - iPhoneOS -diff --git a/iOS/Resources/bin/arm64-apple-ios-ar b/iOS/Resources/bin/arm64-apple-ios-ar -index 8122332b9c1..3cf3eb21874 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-ar -+++ b/iOS/Resources/bin/arm64-apple-ios-ar -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphoneos${IOS_SDK_VERSION} ar $@ ++ CFBundleSupportedPlatforms ++ ++ iPhoneOS ++ ++ MinimumOSVersion ++ @IPHONEOS_DEPLOYMENT_TARGET@ ++ ++ +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-ar b/Apple/iOS/Resources/bin/arm64-apple-ios-ar +new file mode 100755 +index 00000000000..3cf3eb21874 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-ar +@@ -0,0 +1,2 @@ ++#!/bin/sh +xcrun --sdk iphoneos${IOS_SDK_VERSION} ar "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-clang b/iOS/Resources/bin/arm64-apple-ios-clang -index 4d525751eba..c39519cd1f8 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-clang -+++ b/iOS/Resources/bin/arm64-apple-ios-clang -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios $@ -+xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-clang++ b/iOS/Resources/bin/arm64-apple-ios-clang++ -index f24bec11268..d9b12925f38 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-clang++ -+++ b/iOS/Resources/bin/arm64-apple-ios-clang++ -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphoneos${IOS_SDK_VERSION} clang++ -target arm64-apple-ios $@ -+xcrun --sdk iphoneos${IOS_SDK_VERSION} clang++ -target arm64-apple-ios "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-cpp b/iOS/Resources/bin/arm64-apple-ios-cpp -index 891bb25bb43..24da23d3448 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-cpp -+++ b/iOS/Resources/bin/arm64-apple-ios-cpp -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios -E $@ -+xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios -E "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/iOS/Resources/bin/arm64-apple-ios-simulator-ar -index 74ed3bc6df1..b836b6db902 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-simulator-ar -+++ b/iOS/Resources/bin/arm64-apple-ios-simulator-ar -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar $@ +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-clang b/Apple/iOS/Resources/bin/arm64-apple-ios-clang +new file mode 100755 +index 00000000000..f50d5b5142f +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-clang +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-clang++ b/Apple/iOS/Resources/bin/arm64-apple-ios-clang++ +new file mode 100755 +index 00000000000..0794731d7dc +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-cpp b/Apple/iOS/Resources/bin/arm64-apple-ios-cpp +new file mode 100755 +index 00000000000..24fa1506bab +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-cpp +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} -E "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar +new file mode 100755 +index 00000000000..b836b6db902 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/sh +xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/iOS/Resources/bin/arm64-apple-ios-simulator-clang -index 32574cad284..92e8d853d6e 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-simulator-clang -+++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios-simulator $@ -+xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios-simulator "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ -index ef37d05b512..076469cc70c 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ -+++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target arm64-apple-ios-simulator $@ -+xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target arm64-apple-ios-simulator "$@" -diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp -index 6aaf6fbe188..c57f28cee5b 100755 ---- a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp -+++ b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios-simulator -E $@ -+xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios-simulator -E "$@" -diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar -index 74ed3bc6df1..b836b6db902 100755 ---- a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar -+++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar $@ +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang +new file mode 100755 +index 00000000000..4891a00876e +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ +new file mode 100755 +index 00000000000..58b2a5f6f18 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp +new file mode 100755 +index 00000000000..c9df94e8b7c +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip +new file mode 100755 +index 00000000000..fd59d309b73 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/Apple/iOS/Resources/bin/arm64-apple-ios-strip b/Apple/iOS/Resources/bin/arm64-apple-ios-strip +new file mode 100755 +index 00000000000..75e823a3d02 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/arm64-apple-ios-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar +new file mode 100755 +index 00000000000..b836b6db902 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/sh +xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar "$@" -diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang -index bcbe91f6061..17cbe0c8a1e 100755 ---- a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang -+++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios-simulator $@ -+xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios-simulator "$@" -diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ -index 86f03ea32bc..565d47b24c2 100755 ---- a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ -+++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target x86_64-apple-ios-simulator $@ -+xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target x86_64-apple-ios-simulator "$@" -diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp -index e6a42d9b85d..63fc8e8de2d 100755 ---- a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp -+++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp -@@ -1,2 +1,2 @@ - #!/bin/sh --xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios-simulator -E $@ -+xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios-simulator -E "$@" +diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang +new file mode 100755 +index 00000000000..f4739a7b945 --- /dev/null -+++ b/iOS/testbed/__main__.py -@@ -0,0 +1,395 @@ -+import argparse -+import asyncio -+import json -+import plistlib -+import shutil -+import subprocess -+import sys -+from contextlib import asynccontextmanager -+from datetime import datetime -+from pathlib import Path -+ ++++ b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ +new file mode 100755 +index 00000000000..c348ae4c103 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp +new file mode 100755 +index 00000000000..6d7f8084c9f +--- /dev/null ++++ b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip +new file mode 100755 +index 00000000000..c5cfb289291 +--- /dev/null ++++ b/Apple/iOS/Resources/bin/x86_64-apple-ios-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} strip -arch x86_64 "$@" +diff --git a/Apple/iOS/Resources/pyconfig.h b/Apple/iOS/Resources/pyconfig.h +new file mode 100644 +index 00000000000..4acff2c6051 +--- /dev/null ++++ b/Apple/iOS/Resources/pyconfig.h +@@ -0,0 +1,7 @@ ++#ifdef __arm64__ ++#include "pyconfig-arm64.h" ++#endif + -+DECODE_ARGS = ("UTF-8", "backslashreplace") ++#ifdef __x86_64__ ++#include "pyconfig-x86_64.h" ++#endif +diff --git a/Apple/testbed/Python.xcframework/Info.plist b/Apple/testbed/Python.xcframework/Info.plist +new file mode 100644 +index 00000000000..f90105a6d70 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/Info.plist +@@ -0,0 +1,106 @@ ++ ++ ++ ++ ++ AvailableLibraries ++ ++ ++ BinaryPath ++ Python.framework/Python ++ LibraryIdentifier ++ ios-arm64 ++ LibraryPath ++ Python.framework ++ SupportedArchitectures ++ ++ arm64 ++ ++ SupportedPlatform ++ ios ++ ++ ++ BinaryPath ++ Python.framework/Python ++ LibraryIdentifier ++ ios-arm64_x86_64-simulator ++ LibraryPath ++ Python.framework ++ SupportedArchitectures ++ ++ arm64 ++ x86_64 ++ ++ SupportedPlatform ++ ios ++ SupportedPlatformVariant ++ simulator ++ ++ ++ BinaryPath ++ Python.framework/Python ++ LibraryIdentifier ++ tvos-arm64 ++ LibraryPath ++ Python.framework ++ SupportedArchitectures ++ ++ arm64 ++ ++ SupportedPlatform ++ tvos ++ ++ ++ BinaryPath ++ Python.framework/Python ++ LibraryIdentifier ++ tvos-arm64_x86_64-simulator ++ LibraryPath ++ Python.framework ++ SupportedArchitectures ++ ++ arm64 ++ x86_64 ++ ++ SupportedPlatform ++ tvos ++ SupportedPlatformVariant ++ simulator ++ ++ ++ BinaryPath ++ Python.framework/Python ++ LibraryIdentifier ++ watchos-arm64_x86_64-simulator ++ LibraryPath ++ Python.framework ++ SupportedArchitectures ++ ++ arm64 ++ x86_64 ++ ++ SupportedPlatform ++ watchos ++ SupportedPlatformVariant ++ simulator ++ ++ ++ BinaryPath ++ Python.framework/Python ++ LibraryIdentifier ++ watchos-arm64_32 ++ LibraryPath ++ Python.framework ++ SupportedArchitectures ++ ++ arm64_32 ++ ++ SupportedPlatform ++ watchos ++ ++ ++ CFBundlePackageType ++ XFWK ++ XCFrameworkFormatVersion ++ 1.0 ++ ++ +diff --git a/Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist b/Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist +new file mode 100644 +index 00000000000..d6caa01c1e4 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/build/iOS-dylib-Info-template.plist +@@ -0,0 +1,26 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleExecutable ++ ++ CFBundleIdentifier ++ ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundlePackageType ++ APPL ++ CFBundleShortVersionString ++ 1.0 ++ CFBundleSupportedPlatforms ++ ++ iPhoneOS ++ ++ MinimumOSVersion ++ 13.0 ++ CFBundleVersion ++ 1 ++ ++ +diff --git a/Apple/testbed/Python.xcframework/build/tvOS-dylib-Info-template.plist b/Apple/testbed/Python.xcframework/build/tvOS-dylib-Info-template.plist +new file mode 100644 +index 00000000000..a20d476fa7b +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/build/tvOS-dylib-Info-template.plist +@@ -0,0 +1,26 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleExecutable ++ ++ CFBundleIdentifier ++ ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundlePackageType ++ APPL ++ CFBundleShortVersionString ++ 1.0 ++ CFBundleSupportedPlatforms ++ ++ tvOS ++ ++ MinimumOSVersion ++ 9.0 ++ CFBundleVersion ++ 1 ++ ++ +diff --git a/Apple/testbed/Python.xcframework/build/utils.sh b/Apple/testbed/Python.xcframework/build/utils.sh +new file mode 100755 +index 00000000000..2c3c8008512 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/build/utils.sh +@@ -0,0 +1,174 @@ ++# Utility methods for use in an Xcode project. ++# ++# An iOS XCframework cannot include any content other than the library binary ++# and relevant metadata. However, Python requires a standard library at runtime. ++# Therefore, it is necessary to add a build step to an Xcode app target that ++# processes the standard library and puts the content into the final app. ++# ++# In general, these tools will be invoked after bundle resources have been ++# copied into the app, but before framework embedding (and signing). ++# ++# The following is an example script, assuming that: ++# * Python.xcframework is in the root of the project ++# * There is an `app` folder that contains the app code ++# * There is an `app_packages` folder that contains installed Python packages. ++# ----- ++# set -e ++# source $PROJECT_DIR/Python.xcframework/build/build_utils.sh ++# install_python Python.xcframework app app_packages ++# ----- ++ ++# Copy the standard library from the XCframework into the app bundle. ++# ++# Accepts one argument: ++# 1. The path, relative to the root of the Xcode project, where the Python ++# XCframework can be found. ++install_stdlib() { ++ PYTHON_XCFRAMEWORK_PATH=$1 ++ ++ mkdir -p "$CODESIGNING_FOLDER_PATH/python/lib" ++ if [ "$EFFECTIVE_PLATFORM_NAME" = "-iphonesimulator" ]; then ++ echo "Installing Python modules for iOS Simulator" ++ if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/ios-arm64-simulator" ]; then ++ SLICE_FOLDER="ios-arm64-simulator" ++ else ++ SLICE_FOLDER="ios-arm64_x86_64-simulator" ++ fi ++ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-iphoneos" ]; then ++ echo "Installing Python modules for iOS Device" ++ SLICE_FOLDER="ios-arm64" ++ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-appletvsimulator" ]; then ++ echo "Installing Python modules for tvOS Simulator" ++ if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/tvos-arm64-simulator" ]; then ++ SLICE_FOLDER="tvos-arm64-simulator" ++ else ++ SLICE_FOLDER="tvos-arm64_x86_64-simulator" ++ fi ++ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-appletvos" ]; then ++ echo "Installing Python modules for tvOS Device" ++ SLICE_FOLDER="tvos-arm64" ++ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-watchsimulator" ]; then ++ echo "Installing Python modules for watchOS Simulator" ++ if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/watchos-arm64-simulator" ]; then ++ SLICE_FOLDER="watchos-arm64-simulator" ++ else ++ SLICE_FOLDER="watchos-arm64_x86_64-simulator" ++ fi ++ elif [ "$EFFECTIVE_PLATFORM_NAME" = "-watchos" ]; then ++ echo "Installing Python modules for watchOS Device" ++ SLICE_FOLDER="watchos-arm64" ++ else ++ echo "Unsupported platform name $EFFECTIVE_PLATFORM_NAME" ++ exit 1 ++ fi ++ ++ # If the XCframework has a shared lib folder, then it's a full framework. ++ # Copy both the common and slice-specific part of the lib directory. ++ # Otherwise, it's a single-arch framework; use the "full" lib folder. ++ # Don't include any libpython symlink; that can't be included at runtime ++ if [ -d "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/lib" ]; then ++ rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib' ++ rsync -au "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib-$ARCHS/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib' ++ else ++ rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib' ++ fi ++} + ++# Convert a single .so library into a framework that iOS can load. ++# ++# Accepts three arguments: ++# 1. The path, relative to the root of the Xcode project, where the Python ++# XCframework can be found. ++# 2. The base path, relative to the installed location in the app bundle, that ++# needs to be processed. Any .so file found in this path (or a subdirectory ++# of it) will be processed. ++# 2. The full path to a single .so file to process. This path should include ++# the base path. ++install_dylib () { ++ PYTHON_XCFRAMEWORK_PATH=$1 ++ INSTALL_BASE=$2 ++ FULL_EXT=$3 ++ ++ # The name of the extension file ++ EXT=$(basename "$FULL_EXT") ++ # The name and location of the module ++ MODULE_PATH=$(dirname "$FULL_EXT") ++ MODULE_NAME=$(echo $EXT | cut -d "." -f 1) ++ # The location of the extension file, relative to the bundle ++ RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} ++ # The path to the extension file, relative to the install base ++ PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/} ++ # The full dotted name of the extension module, constructed from the file path. ++ FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d "." -f 1 | tr "/" "."); ++ # A bundle identifier; not actually used, but required by Xcode framework packaging ++ FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr "_" "-") ++ # The name of the framework folder. ++ FRAMEWORK_FOLDER="Frameworks/$FULL_MODULE_NAME.framework" ++ ++ # If the framework folder doesn't exist, create it. ++ if [ ! -d "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" ]; then ++ echo "Creating framework for $RELATIVE_EXT" ++ mkdir -p "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" ++ cp "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/build/$PLATFORM_FAMILY_NAME-dylib-Info-template.plist" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist" ++ plutil -replace CFBundleExecutable -string "$FULL_MODULE_NAME" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist" ++ plutil -replace CFBundleIdentifier -string "$FRAMEWORK_BUNDLE_ID" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist" ++ fi ++ ++ echo "Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME" ++ mv "$FULL_EXT" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME" ++ # Create a placeholder .fwork file where the .so was ++ echo "$FRAMEWORK_FOLDER/$FULL_MODULE_NAME" > ${FULL_EXT%.so}.fwork ++ # Create a back reference to the .so file location in the framework ++ echo "${RELATIVE_EXT%.so}.fwork" > "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin" ++ ++ # If the framework provides an xcprivacy file, install it. ++ if [ -e "$MODULE_PATH/$MODULE_NAME.xcprivacy" ]; then ++ echo "Installing XCPrivacy file for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME" ++ XCPRIVACY_FILE="$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/PrivacyInfo.xcprivacy" ++ if [ -e "$XCPRIVACY_FILE" ]; then ++ rm -rf "$XCPRIVACY_FILE" ++ fi ++ mv "$MODULE_PATH/$MODULE_NAME.xcprivacy" "$XCPRIVACY_FILE" ++ fi ++ ++ echo "Signing framework as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)..." ++ /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" ++} + -+# Work around a bug involving sys.exit and TaskGroups -+# (https://github.com/python/cpython/issues/101515). -+def exit(*args): -+ raise MySystemExit(*args) ++# Process all the dynamic libraries in a path into Framework format. ++# ++# Accepts two arguments: ++# 1. The path, relative to the root of the Xcode project, where the Python ++# XCframework can be found. ++# 2. The base path, relative to the installed location in the app bundle, that ++# needs to be processed. Any .so file found in this path (or a subdirectory ++# of it) will be processed. ++process_dylibs () { ++ PYTHON_XCFRAMEWORK_PATH=$1 ++ LIB_PATH=$2 ++ find "$CODESIGNING_FOLDER_PATH/$LIB_PATH" -name "*.so" | while read FULL_EXT; do ++ install_dylib $PYTHON_XCFRAMEWORK_PATH "$LIB_PATH/" "$FULL_EXT" ++ done ++} + ++# The entry point for post-processing a Python XCframework. ++# ++# Accepts 1 or more arguments: ++# 1. The path, relative to the root of the Xcode project, where the Python ++# XCframework can be found. If the XCframework is in the root of the project, ++# 2+. The path of a package, relative to the root of the packaged app, that contains ++# library content that should be processed for binary libraries. ++install_python() { ++ PYTHON_XCFRAMEWORK_PATH=$1 ++ shift ++ ++ install_stdlib $PYTHON_XCFRAMEWORK_PATH ++ PYTHON_VER=$(ls -1 "$CODESIGNING_FOLDER_PATH/python/lib" | grep -E "^python3\.\d+$") ++ echo "Install Python $PYTHON_VER standard library extension modules..." ++ process_dylibs $PYTHON_XCFRAMEWORK_PATH python/lib/$PYTHON_VER/lib-dynload ++ ++ for package_path in $@; do ++ echo "Installing $package_path extension modules ..." ++ process_dylibs $PYTHON_XCFRAMEWORK_PATH $package_path ++ done ++} +diff --git a/Apple/testbed/Python.xcframework/build/watchOS-dylib-Info-template.plist b/Apple/testbed/Python.xcframework/build/watchOS-dylib-Info-template.plist +new file mode 100644 +index 00000000000..6f8c0bc2095 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/build/watchOS-dylib-Info-template.plist +@@ -0,0 +1,26 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleExecutable ++ ++ CFBundleIdentifier ++ ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundlePackageType ++ APPL ++ CFBundleShortVersionString ++ 1.0 ++ CFBundleSupportedPlatforms ++ ++ watchOS ++ ++ MinimumOSVersion ++ 4.0 ++ CFBundleVersion ++ 1 ++ ++ +diff --git a/Apple/testbed/Python.xcframework/ios-arm64/README b/Apple/testbed/Python.xcframework/ios-arm64/README +new file mode 100644 +index 00000000000..c1b076d12cd +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/ios-arm64/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling an iOS on-device ++build for testing purposes. +diff --git a/Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README b/Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README +new file mode 100644 +index 00000000000..ae334e5d769 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/ios-arm64_x86_64-simulator/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling an iOS simulator ++build for testing purposes (either x86_64 or ARM64). +diff --git a/Apple/testbed/Python.xcframework/tvos-arm64/README b/Apple/testbed/Python.xcframework/tvos-arm64/README +new file mode 100644 +index 00000000000..ebd648d04bd +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/tvos-arm64/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling a tvOS ++on-device build for testing purposes. +diff --git a/Apple/testbed/Python.xcframework/tvos-arm64_x86_64-simulator/README b/Apple/testbed/Python.xcframework/tvos-arm64_x86_64-simulator/README +new file mode 100644 +index 00000000000..f8163468d8c +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/tvos-arm64_x86_64-simulator/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling a tvOS ++simulator build for testing purposes (either x86_64 or ARM64). +diff --git a/Apple/testbed/Python.xcframework/watchos-arm64_32/README b/Apple/testbed/Python.xcframework/watchos-arm64_32/README +new file mode 100644 +index 00000000000..696af231df3 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/watchos-arm64_32/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling a watchOS on-device ++build for testing purposes. +diff --git a/Apple/testbed/Python.xcframework/watchos-arm64_x86_64-simulator/README b/Apple/testbed/Python.xcframework/watchos-arm64_x86_64-simulator/README +new file mode 100644 +index 00000000000..d38e1e98276 +--- /dev/null ++++ b/Apple/testbed/Python.xcframework/watchos-arm64_x86_64-simulator/README +@@ -0,0 +1,4 @@ ++This directory is intentionally empty. ++ ++It should be used as a target for `--enable-framework` when compiling a watchOS ++simulator build for testing purposes (either x86_64 or ARM64). +diff --git a/Apple/testbed/Testbed.lldbinit b/Apple/testbed/Testbed.lldbinit +new file mode 100644 +index 00000000000..4cf00dd0f9d +--- /dev/null ++++ b/Apple/testbed/Testbed.lldbinit +@@ -0,0 +1,4 @@ ++process handle SIGINT -n true -p true -s false ++process handle SIGUSR1 -n true -p true -s false ++process handle SIGUSR2 -n true -p true -s false ++process handle SIGXFSZ -n true -p true -s false +diff --git a/Apple/testbed/TestbedTests/TestbedTests.m b/Apple/testbed/TestbedTests/TestbedTests.m +new file mode 100644 +index 00000000000..cc0d9224042 +--- /dev/null ++++ b/Apple/testbed/TestbedTests/TestbedTests.m +@@ -0,0 +1,198 @@ ++#import ++#import ++ ++@interface TestbedTests : XCTestCase ++ ++@end ++ ++@implementation TestbedTests ++ ++ ++- (void)testPython { ++ const char **argv; ++ int exit_code; ++ int failed; ++ PyStatus status; ++ PyPreConfig preconfig; ++ PyConfig config; ++ PyObject *app_packages_path; ++ PyObject *method_args; ++ PyObject *result; ++ PyObject *site_module; ++ PyObject *site_addsitedir_attr; ++ PyObject *sys_module; ++ PyObject *sys_path_attr; ++ NSArray *test_args; ++ NSString *python_home; ++ NSString *path; ++ wchar_t *wtmp_str; ++ ++ NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + -+class MySystemExit(Exception): -+ pass ++ // Set some other common environment indicators to disable color, as the ++ // Xcode log can't display color. Stdout will report that it is *not* a ++ // TTY. ++ setenv("NO_COLOR", "1", true); ++ setenv("PYTHON_COLORS", "0", true); + ++ if (getenv("GITHUB_ACTIONS")) { ++ NSLog(@"Running in a GitHub Actions environment"); ++ } ++ // Arguments to pass into the test suite runner. ++ // argv[0] must identify the process; any subsequent arg ++ // will be handled as if it were an argument to `python -m test` ++ // The processInfo arguments contain the binary that is running, ++ // followed by the arguments defined in the test plan. This means: ++ // run_module = test_args[1] ++ // argv = ["Testbed"] + test_args[2:] ++ test_args = [[NSProcessInfo processInfo] arguments]; ++ if (test_args == NULL) { ++ NSLog(@"Unable to identify test arguments."); ++ } ++ NSLog(@"Test arguments: %@", test_args); ++ argv = malloc(sizeof(char *) * ([test_args count] - 1)); ++ argv[0] = "Testbed"; ++ for (int i = 1; i < [test_args count] - 1; i++) { ++ argv[i] = [[test_args objectAtIndex:i+1] UTF8String]; ++ } + -+# All subprocesses are executed through this context manager so that no matter -+# what happens, they can always be cancelled from another task, and they will -+# always be cleaned up on exit. -+@asynccontextmanager -+async def async_process(*args, **kwargs): -+ process = await asyncio.create_subprocess_exec(*args, **kwargs) -+ try: -+ yield process -+ finally: -+ if process.returncode is None: -+ # Allow a reasonably long time for Xcode to clean itself up, -+ # because we don't want stale emulators left behind. -+ timeout = 10 -+ process.terminate() -+ try: -+ await asyncio.wait_for(process.wait(), timeout) -+ except TimeoutError: -+ print( -+ f"Command {args} did not terminate after {timeout} seconds " -+ f" - sending SIGKILL" -+ ) -+ process.kill() ++ // Generate an isolated Python configuration. ++ NSLog(@"Configuring isolated Python..."); ++ PyPreConfig_InitIsolatedConfig(&preconfig); ++ PyConfig_InitIsolatedConfig(&config); ++ ++ // Configure the Python interpreter: ++ // Enforce UTF-8 encoding for stderr, stdout, file-system encoding and locale. ++ // See https://docs.python.org/3/library/os.html#python-utf-8-mode. ++ preconfig.utf8_mode = 1; ++ // Don't buffer stdio. We want output to appears in the log immediately ++ config.buffered_stdio = 0; ++ // Don't write bytecode; we can't modify the app bundle ++ // after it has been signed. ++ config.write_bytecode = 0; ++ // Ensure that signal handlers are installed ++ config.install_signal_handlers = 1; ++ // Run the test module. ++ config.run_module = Py_DecodeLocale([[test_args objectAtIndex:1] UTF8String], NULL); ++ // For debugging - enable verbose mode. ++ // config.verbose = 1; ++ ++ NSLog(@"Pre-initializing Python runtime..."); ++ status = Py_PreInitialize(&preconfig); ++ if (PyStatus_Exception(status)) { ++ XCTFail(@"Unable to pre-initialize Python interpreter: %s", status.err_msg); ++ PyConfig_Clear(&config); ++ return; ++ } + -+ # Even after killing the process we must still wait for it, -+ # otherwise we'll get the warning "Exception ignored in __del__". -+ await asyncio.wait_for(process.wait(), timeout=1) ++ // Set the home for the Python interpreter ++ python_home = [NSString stringWithFormat:@"%@/python", resourcePath, nil]; ++ NSLog(@"PythonHome: %@", python_home); ++ wtmp_str = Py_DecodeLocale([python_home UTF8String], NULL); ++ status = PyConfig_SetString(&config, &config.home, wtmp_str); ++ if (PyStatus_Exception(status)) { ++ XCTFail(@"Unable to set PYTHONHOME: %s", status.err_msg); ++ PyConfig_Clear(&config); ++ return; ++ } ++ PyMem_RawFree(wtmp_str); ++ ++ // Read the site config ++ status = PyConfig_Read(&config); ++ if (PyStatus_Exception(status)) { ++ XCTFail(@"Unable to read site config: %s", status.err_msg); ++ PyConfig_Clear(&config); ++ return; ++ } + ++ NSLog(@"Configure argc/argv..."); ++ status = PyConfig_SetBytesArgv(&config, [test_args count] - 1, (char**) argv); ++ if (PyStatus_Exception(status)) { ++ XCTFail(@"Unable to configure argc/argv: %s", status.err_msg); ++ PyConfig_Clear(&config); ++ return; ++ } + -+async def async_check_output(*args, **kwargs): -+ async with async_process( -+ *args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs -+ ) as process: -+ stdout, stderr = await process.communicate() -+ if process.returncode == 0: -+ return stdout.decode(*DECODE_ARGS) -+ else: -+ raise subprocess.CalledProcessError( -+ process.returncode, -+ args, -+ stdout.decode(*DECODE_ARGS), -+ stderr.decode(*DECODE_ARGS), -+ ) ++ NSLog(@"Initializing Python runtime..."); ++ status = Py_InitializeFromConfig(&config); ++ if (PyStatus_Exception(status)) { ++ XCTFail(@"Unable to initialize Python interpreter: %s", status.err_msg); ++ PyConfig_Clear(&config); ++ return; ++ } + ++ // Add app_packages as a site directory. This both adds to sys.path, ++ // and ensures that any .pth files in that directory will be executed. ++ site_module = PyImport_ImportModule("site"); ++ if (site_module == NULL) { ++ XCTFail(@"Could not import site module"); ++ return; ++ } + -+# Return a list of UDIDs associated with booted simulators -+async def list_devices(): -+ # List the testing simulators, in JSON format -+ raw_json = await async_check_output( -+ "xcrun", "simctl", "--set", "testing", "list", "-j" -+ ) -+ json_data = json.loads(raw_json) ++ site_addsitedir_attr = PyObject_GetAttrString(site_module, "addsitedir"); ++ if (site_addsitedir_attr == NULL || !PyCallable_Check(site_addsitedir_attr)) { ++ XCTFail(@"Could not access site.addsitedir"); ++ return; ++ } + -+ # Filter out the booted iOS simulators -+ return [ -+ simulator["udid"] -+ for runtime, simulators in json_data["devices"].items() -+ for simulator in simulators -+ if runtime.split(".")[-1].startswith("iOS") and simulator["state"] == "Booted" -+ ] ++ path = [NSString stringWithFormat:@"%@/app_packages", resourcePath, nil]; ++ NSLog(@"App packages path: %@", path); ++ wtmp_str = Py_DecodeLocale([path UTF8String], NULL); ++ app_packages_path = PyUnicode_FromWideChar(wtmp_str, wcslen(wtmp_str)); ++ if (app_packages_path == NULL) { ++ XCTFail(@"Could not convert app_packages path to unicode"); ++ return; ++ } ++ PyMem_RawFree(wtmp_str); + ++ method_args = Py_BuildValue("(O)", app_packages_path); ++ if (method_args == NULL) { ++ XCTFail(@"Could not create arguments for site.addsitedir"); ++ return; ++ } + -+async def find_device(initial_devices): -+ while True: -+ new_devices = set(await list_devices()).difference(initial_devices) -+ if len(new_devices) == 0: -+ await asyncio.sleep(1) -+ elif len(new_devices) == 1: -+ udid = new_devices.pop() -+ print(f"{datetime.now():%Y-%m-%d %H:%M:%S}: New test simulator detected") -+ print(f"UDID: {udid}") -+ return udid -+ else: -+ exit(f"Found more than one new device: {new_devices}") ++ result = PyObject_CallObject(site_addsitedir_attr, method_args); ++ if (result == NULL) { ++ XCTFail(@"Could not add app_packages directory using site.addsitedir"); ++ return; ++ } + ++ // Add test code to sys.path ++ sys_module = PyImport_ImportModule("sys"); ++ if (sys_module == NULL) { ++ XCTFail(@"Could not import sys module"); ++ return; ++ } + -+async def log_stream_task(initial_devices): -+ # Wait up to 5 minutes for the build to complete and the simulator to boot. -+ udid = await asyncio.wait_for(find_device(initial_devices), 5 * 60) ++ sys_path_attr = PyObject_GetAttrString(sys_module, "path"); ++ if (sys_path_attr == NULL) { ++ XCTFail(@"Could not access sys.path"); ++ return; ++ } + -+ # Stream the iOS device's logs, filtering out messages that come from the -+ # XCTest test suite (catching NSLog messages from the test method), or -+ # Python itself (catching stdout/stderr content routed to the system log -+ # with config->use_system_logger). -+ args = [ -+ "xcrun", -+ "simctl", -+ "--set", -+ "testing", -+ "spawn", -+ udid, -+ "log", -+ "stream", -+ "--style", -+ "compact", -+ "--predicate", -+ ( -+ 'senderImagePath ENDSWITH "/iOSTestbedTests.xctest/iOSTestbedTests"' -+ ' OR senderImagePath ENDSWITH "/Python.framework/Python"' -+ ), -+ ] ++ path = [NSString stringWithFormat:@"%@/app", resourcePath, nil]; ++ NSLog(@"App path: %@", path); ++ wtmp_str = Py_DecodeLocale([path UTF8String], NULL); ++ failed = PyList_Insert(sys_path_attr, 0, PyUnicode_FromString([path UTF8String])); ++ if (failed) { ++ XCTFail(@"Unable to add app to sys.path"); ++ return; ++ } ++ PyMem_RawFree(wtmp_str); ++ ++ // Ensure the working directory is the app folder. ++ chdir([path UTF8String]); ++ ++ // Start the test suite. Print a separator to differentiate Python startup logs from app logs ++ NSLog(@"---------------------------------------------------------------------------"); ++ ++ exit_code = Py_RunMain(); ++ XCTAssertEqual(exit_code, 0, @"Test suite did not pass"); ++ ++ NSLog(@"---------------------------------------------------------------------------"); ++ ++ Py_Finalize(); ++} + -+ async with async_process( -+ *args, -+ stdout=subprocess.PIPE, -+ stderr=subprocess.STDOUT, -+ ) as process: -+ suppress_dupes = False -+ while line := (await process.stdout.readline()).decode(*DECODE_ARGS): -+ # The iOS log streamer can sometimes lag; when it does, it outputs -+ # a warning about messages being dropped... often multiple times. -+ # Only print the first of these duplicated warnings. -+ if line.startswith("=== Messages dropped "): -+ if not suppress_dupes: -+ suppress_dupes = True -+ sys.stdout.write(line) -+ else: -+ suppress_dupes = False -+ sys.stdout.write(line) -+ sys.stdout.flush() + ++@end +diff --git a/Apple/testbed/__main__.py b/Apple/testbed/__main__.py +new file mode 100644 +index 00000000000..7872ecba271 +--- /dev/null ++++ b/Apple/testbed/__main__.py +@@ -0,0 +1,472 @@ ++import argparse ++import json ++import os ++import re ++import shlex ++import shutil ++import subprocess ++import sys ++from itertools import chain ++from pathlib import Path ++ ++TEST_SLICES = { ++ "iOS": "ios-arm64_x86_64-simulator", ++ "tvOS": "tvos-arm64_x86_64-simulator", ++ "visionOS": "xros-arm64-simulator", ++ "watchOS": "watchos-arm64_x86_64-simulator", ++} ++ ++DECODE_ARGS = ("UTF-8", "backslashreplace") ++ ++# The system log prefixes each line: ++# 2025-01-17 16:14:29.093742+0800 iOSTestbed[23987:1fd393b4] ... ++# 2025-01-17 16:14:29.093742+0800 iOSTestbed[23987:1fd393b4] ... ++ ++LOG_PREFIX_REGEX = re.compile( ++ r"^\d{4}-\d{2}-\d{2}" # YYYY-MM-DD ++ r"\s+\d+:\d{2}:\d{2}\.\d+\+\d{4}" # HH:MM:SS.ssssss+ZZZZ ++ r"\s+.*Testbed\[\d+:\w+\] " # Process/thread ID ++) ++ ++ ++# Select a simulator device to use. ++def select_simulator_device(platform): ++ # List the testing simulators, in JSON format ++ raw_json = subprocess.check_output(["xcrun", "simctl", "list", "-j"]) ++ json_data = json.loads(raw_json) ++ ++ if platform == "iOS": ++ # Any iOS device will do; we'll look for "SE" devices - but the name ++ # isn't consistent over time. Older Xcode versions will use "iPhone SE ++ # (Nth generation)"; As of 2025, they've started using "iPhone 16e". ++ # ++ # When Xcode is updated after a new release, new devices will be ++ # available and old ones will be dropped from the set available on the ++ # latest iOS version. Select the one with the highest minimum runtime ++ # version - this is an indicator of the "newest" released device, which ++ # should always be supported on the "most recent" iOS version. ++ se_simulators = sorted( ++ (devicetype["minRuntimeVersion"], devicetype["name"]) ++ for devicetype in json_data["devicetypes"] ++ if devicetype["productFamily"] == "iPhone" ++ and ( ++ ( ++ "iPhone " in devicetype["name"] ++ and devicetype["name"].endswith("e") ++ ) ++ or "iPhone SE " in devicetype["name"] ++ ) ++ ) ++ simulator = se_simulators[-1][1] ++ elif platform == "tvOS": ++ # Find the most recent tvOS release. ++ simulators = sorted( ++ (devicetype["minRuntimeVersion"], devicetype["name"]) ++ for devicetype in json_data["devicetypes"] ++ if devicetype["productFamily"] == "Apple TV" ++ ) ++ simulator = simulators[-1][1] ++ elif platform == "visionOS": ++ # Find the most recent visionOS release. ++ simulators = sorted( ++ (devicetype["minRuntimeVersion"], devicetype["name"]) ++ for devicetype in json_data["devicetypes"] ++ if devicetype["productFamily"] == "Apple Vision" ++ ) ++ simulator = simulators[-1][1] ++ elif platform == "watchOS": ++ raise NotImplementedError("Don't know how to launch watchOS (yet)") ++ else: ++ raise ValueError(f"Unknown platform {platform}") ++ ++ return simulator ++ ++ ++# A backport of Path.relative_to(*, walk_up=True) ++def relative_to(target, other): ++ for step, path in enumerate(chain([other], other.parents)): ++ if path == target or path in target.parents: ++ break ++ else: ++ raise ValueError( ++ f"{str(target)!r} and {str(other)!r} have different anchors" ++ ) ++ parts = [".."] * step + list(target.parts[len(path.parts) :]) ++ return Path("/".join(parts)) + -+async def xcode_test(location, simulator, verbose): -+ # Run the test suite on the named simulator -+ print("Starting xcodebuild...") ++ ++def xcode_test(location: Path, platform: str, simulator: str, verbose: bool): ++ # Build and run the test suite on the named simulator. + args = [ -+ "xcodebuild", -+ "test", + "-project", -+ str(location / "iOSTestbed.xcodeproj"), ++ str(location / f"{platform}Testbed.xcodeproj"), + "-scheme", -+ "iOSTestbed", ++ f"{platform}Testbed", + "-destination", -+ f"platform=iOS Simulator,name={simulator}", -+ "-resultBundlePath", -+ str(location / f"{datetime.now():%Y%m%d-%H%M%S}.xcresult"), ++ f"platform={platform} Simulator,name={simulator}", + "-derivedDataPath", + str(location / "DerivedData"), + ] -+ if not verbose: -+ args += ["-quiet"] ++ verbosity_args = [] if verbose else ["-quiet"] ++ ++ print("Building test project...") ++ subprocess.run( ++ ["xcodebuild", "build-for-testing"] + args + verbosity_args, ++ check=True, ++ ) + -+ async with async_process( -+ *args, ++ # Any environment variable prefixed with TEST_RUNNER_ is exposed into the ++ # test runner environment. There are some variables (like those identifying ++ # CI platforms) that can be useful to have access to. ++ test_env = os.environ.copy() ++ if "GITHUB_ACTIONS" in os.environ: ++ test_env["TEST_RUNNER_GITHUB_ACTIONS"] = os.environ["GITHUB_ACTIONS"] ++ ++ print("Running test project...") ++ # Test execution *can't* be run -quiet; verbose mode ++ # is how we see the output of the test output. ++ process = subprocess.Popen( ++ ["xcodebuild", "test-without-building"] + args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, -+ ) as process: -+ while line := (await process.stdout.readline()).decode(*DECODE_ARGS): -+ sys.stdout.write(line) -+ sys.stdout.flush() ++ env=test_env, ++ ) ++ while line := (process.stdout.readline()).decode(*DECODE_ARGS): ++ # Strip the timestamp/process prefix from each log line ++ line = LOG_PREFIX_REGEX.sub("", line) ++ sys.stdout.write(line) ++ sys.stdout.flush() + -+ status = await asyncio.wait_for(process.wait(), timeout=1) -+ exit(status) ++ status = process.wait(timeout=5) ++ exit(status) ++ ++ ++def copy(src, tgt): ++ """An all-purpose copy. ++ ++ If src is a file, it is copied. If src is a symlink, it is copied *as a ++ symlink*. If src is a directory, the full tree is duplicated, with symlinks ++ being preserved. ++ """ ++ if src.is_file() or src.is_symlink(): ++ shutil.copyfile(src, tgt, follow_symlinks=False) ++ else: ++ shutil.copytree(src, tgt, symlinks=True) + + +def clone_testbed( + source: Path, + target: Path, + framework: Path, ++ platform: str, + apps: list[Path], +) -> None: + if target.exists(): @@ -2245,11 +2552,11 @@ index e6a42d9b85d..63fc8e8de2d 100755 + + if framework is None: + if not ( -+ source / "Python.xcframework/ios-arm64_x86_64-simulator/bin" ++ source / "Python.xcframework" / TEST_SLICES[platform] / "bin" + ).is_dir(): + print( + f"The testbed being cloned ({source}) does not contain " -+ f"a simulator framework. Re-run with --framework" ++ "a framework with slices. Re-run with --framework" + ) + sys.exit(11) + else: @@ -2267,41 +2574,92 @@ index e6a42d9b85d..63fc8e8de2d 100755 + sys.exit(13) + + print("Cloning testbed project:") -+ print(f" Cloning {source}...", end="", flush=True) -+ shutil.copytree(source, target, symlinks=True) ++ print(f" Cloning {source}...", end="") ++ # Only copy the files for the platform being cloned plus the files common ++ # to all platforms. The XCframework will be copied later, if needed. ++ target.mkdir(parents=True) ++ ++ for name in [ ++ "__main__.py", ++ "TestbedTests", ++ "Testbed.lldbinit", ++ f"{platform}Testbed", ++ f"{platform}Testbed.xcodeproj", ++ f"{platform}Testbed.xctestplan", ++ ]: ++ copy(source / name, target / name) ++ + print(" done") + ++ orig_xc_framework_path = source / "Python.xcframework" ++ xc_framework_path = target / "Python.xcframework" ++ test_framework_path = xc_framework_path / TEST_SLICES[platform] + if framework is not None: + if framework.suffix == ".xcframework": -+ print(" Installing XCFramework...", end="", flush=True) -+ xc_framework_path = (target / "Python.xcframework").resolve() -+ if xc_framework_path.is_dir(): -+ shutil.rmtree(xc_framework_path) -+ else: -+ xc_framework_path.unlink() ++ print(" Installing XCFramework...", end="") + xc_framework_path.symlink_to( -+ framework.relative_to(xc_framework_path.parent, walk_up=True) ++ relative_to(framework, xc_framework_path.parent) + ) + print(" done") + else: -+ print(" Installing simulator framework...", end="", flush=True) -+ sim_framework_path = ( -+ target / "Python.xcframework" / "ios-arm64_x86_64-simulator" -+ ).resolve() -+ if sim_framework_path.is_dir(): -+ shutil.rmtree(sim_framework_path) ++ print(" Installing simulator framework...", end="") ++ # We're only installing a slice of a framework; we need ++ # to do a full tree copy to make sure we don't damage ++ # symlinked content. ++ shutil.copytree(orig_xc_framework_path, xc_framework_path) ++ if test_framework_path.is_dir(): ++ shutil.rmtree(test_framework_path) + else: -+ sim_framework_path.unlink() -+ sim_framework_path.symlink_to( -+ framework.relative_to(sim_framework_path.parent, walk_up=True) ++ test_framework_path.unlink(missing_ok=True) ++ test_framework_path.symlink_to( ++ relative_to(framework, test_framework_path.parent) + ) + print(" done") + else: -+ print(" Using pre-existing iOS framework.") ++ copy(orig_xc_framework_path, xc_framework_path) ++ ++ if ( ++ xc_framework_path.is_symlink() ++ and not xc_framework_path.readlink().is_absolute() ++ ): ++ # XCFramework is a relative symlink. Rewrite the symlink relative ++ # to the new location. ++ print(" Rewriting symlink to XCframework...", end="") ++ resolved_xc_framework_path = ( ++ source / xc_framework_path.readlink() ++ ).resolve() ++ xc_framework_path.unlink() ++ xc_framework_path.symlink_to( ++ relative_to( ++ resolved_xc_framework_path, ++ xc_framework_path.parent, ++ ) ++ ) ++ print(" done") ++ elif ( ++ test_framework_path.is_symlink() ++ and not test_framework_path.readlink().is_absolute() ++ ): ++ print(" Rewriting symlink to simulator framework...", end="") ++ # Simulator framework is a relative symlink. Rewrite the symlink ++ # relative to the new location. ++ orig_test_framework_path = ( ++ source / "Python.XCframework" / test_framework_path.readlink() ++ ).resolve() ++ test_framework_path.unlink() ++ test_framework_path.symlink_to( ++ relative_to( ++ orig_test_framework_path, ++ test_framework_path.parent, ++ ) ++ ) ++ print(" done") ++ else: ++ print(" Using pre-existing Python framework.") + + for app_src in apps: -+ print(f" Installing app {app_src.name!r}...", end="", flush=True) -+ app_target = target / f"iOSTestbed/app/{app_src.name}" ++ print(f" Installing app {app_src.name!r}...", end="") ++ app_target = target / f"Testbed/app/{app_src.name}" + if app_target.is_dir(): + shutil.rmtree(app_target) + shutil.copytree(app_src, app_target) @@ -2310,53 +2668,65 @@ index e6a42d9b85d..63fc8e8de2d 100755 + print(f"Successfully cloned testbed: {target.resolve()}") + + -+def update_plist(testbed_path, args): -+ # Add the test runner arguments to the testbed's Info.plist file. -+ info_plist = testbed_path / "iOSTestbed" / "iOSTestbed-Info.plist" -+ with info_plist.open("rb") as f: -+ info = plistlib.load(f) ++def update_test_plan(testbed_path, platform, args): ++ # Modify the test plan to use the requested test arguments. ++ test_plan_path = testbed_path / f"{platform}Testbed.xctestplan" ++ with test_plan_path.open("r", encoding="utf-8") as f: ++ test_plan = json.load(f) + -+ info["TestArgs"] = args ++ test_plan["defaultOptions"]["commandLineArgumentEntries"] = [ ++ {"argument": shlex.quote(arg)} for arg in args ++ ] + -+ with info_plist.open("wb") as f: -+ plistlib.dump(info, f) ++ with test_plan_path.open("w", encoding="utf-8") as f: ++ json.dump(test_plan, f, indent=2) + + -+async def run_testbed(simulator: str, args: list[str], verbose: bool=False): ++def run_testbed( ++ platform: str, ++ simulator: str | None, ++ args: list[str], ++ verbose: bool = False, ++): + location = Path(__file__).parent -+ print("Updating plist...", end="", flush=True) -+ update_plist(location, args) ++ print("Updating test plan...", end="") ++ update_test_plan(location, platform, args) + print(" done.") + -+ # Get the list of devices that are booted at the start of the test run. -+ # The simulator started by the test suite will be detected as the new -+ # entry that appears on the device list. -+ initial_devices = await list_devices() ++ if simulator is None: ++ simulator = select_simulator_device(platform) ++ print(f"Running test on {simulator}") + -+ try: -+ async with asyncio.TaskGroup() as tg: -+ tg.create_task(log_stream_task(initial_devices)) -+ tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose)) -+ except* MySystemExit as e: -+ raise SystemExit(*e.exceptions[0].args) from None -+ except* subprocess.CalledProcessError as e: -+ # Extract it from the ExceptionGroup so it can be handled by `main`. -+ raise e.exceptions[0] ++ xcode_test( ++ location, ++ platform=platform, ++ simulator=simulator, ++ verbose=verbose, ++ ) + + +def main(): ++ # Look for directories like `iOSTestbed` as an indicator of the platforms ++ # that the testbed folder supports. The original source testbed can support ++ # many platforms, but when cloned, only one platform is preserved. ++ available_platforms = [ ++ platform ++ for platform in ["iOS", "tvOS", "visionOS", "watchOS"] ++ if (Path(__file__).parent / f"{platform}Testbed").is_dir() ++ ] ++ + parser = argparse.ArgumentParser( + description=( -+ "Manages the process of testing a Python project in the iOS simulator." ++ "Manages the process of testing an Apple Python project " ++ "through Xcode." + ), + ) + + subcommands = parser.add_subparsers(dest="subcommand") -+ + clone = subcommands.add_parser( + "clone", + description=( -+ "Clone the testbed project, copying in an iOS Python framework and" ++ "Clone the testbed project, copying in a Python framework and" + "any specified application code." + ), + help="Clone a testbed project to a new location.", @@ -2369,6 +2739,13 @@ index e6a42d9b85d..63fc8e8de2d 100755 + ), + ) + clone.add_argument( ++ "--platform", ++ dest="platform", ++ choices=available_platforms, ++ default=available_platforms[0], ++ help=f"The platform to target (default: {available_platforms[0]})", ++ ) ++ clone.add_argument( + "--app", + dest="apps", + action="append", @@ -2382,21 +2759,37 @@ index e6a42d9b85d..63fc8e8de2d 100755 + + run = subcommands.add_parser( + "run", -+ usage="%(prog)s [-h] [--simulator SIMULATOR] -- [ ...]", ++ usage=( ++ "%(prog)s [-h] [--simulator SIMULATOR] -- " ++ " [ ...]" ++ ), + description=( + "Run a testbed project. The arguments provided after `--` will be " -+ "passed to the running iOS process as if they were arguments to " ++ "passed to the running test process as if they were arguments to " + "`python -m`." + ), + help="Run a testbed project", + ) + run.add_argument( ++ "--platform", ++ dest="platform", ++ choices=available_platforms, ++ default=available_platforms[0], ++ help=f"The platform to target (default: {available_platforms[0]})", ++ ) ++ run.add_argument( + "--simulator", -+ default="iPhone SE (3rd Generation)", -+ help="The name of the simulator to use (default: 'iPhone SE (3rd Generation)')", ++ help=( ++ "The name of the simulator to use (eg: 'iPhone 16e'). Defaults to " ++ "the most recently released 'entry level' iPhone device. Device " ++ "architecture and OS version can also be specified; e.g., " ++ "`--simulator 'iPhone 16 Pro,arch=arm64,OS=26.0'` would run on " ++ "an ARM64 iPhone 16 Pro simulator running iOS 26.0." ++ ), + ) + run.add_argument( -+ "-v", "--verbose", ++ "-v", ++ "--verbose", + action="store_true", + help="Enable verbose output", + ) @@ -2413,32 +2806,40 @@ index e6a42d9b85d..63fc8e8de2d 100755 + + if context.subcommand == "clone": + clone_testbed( -+ source=Path(__file__).parent, -+ target=Path(context.location), -+ framework=Path(context.framework).resolve() if context.framework else None, ++ source=Path(__file__).parent.resolve(), ++ target=Path(context.location).resolve(), ++ framework=Path(context.framework).resolve() ++ if context.framework ++ else None, ++ platform=context.platform, + apps=[Path(app) for app in context.apps], + ) + elif context.subcommand == "run": + if test_args: + if not ( -+ Path(__file__).parent / "Python.xcframework/ios-arm64_x86_64-simulator/bin" ++ Path(__file__).parent ++ / "Python.xcframework" ++ / TEST_SLICES[context.platform] ++ / "bin" + ).is_dir(): + print( -+ f"Testbed does not contain a compiled iOS framework. Use " -+ f"`python {sys.argv[0]} clone ...` to create a runnable " -+ f"clone of this testbed." ++ "Testbed does not contain a compiled Python framework. " ++ f"Use `python {sys.argv[0]} clone ...` to create a " ++ "runnable clone of this testbed." + ) + sys.exit(20) + -+ asyncio.run( -+ run_testbed( -+ simulator=context.simulator, -+ verbose=context.verbose, -+ args=test_args, -+ ) ++ run_testbed( ++ platform=context.platform, ++ simulator=context.simulator, ++ verbose=context.verbose, ++ args=test_args, + ) + else: -+ print(f"Must specify test arguments (e.g., {sys.argv[0]} run -- test)") ++ print( ++ "Must specify test arguments " ++ f"(e.g., {sys.argv[0]} run -- test)" ++ ) + print() + parser.print_help(sys.stderr) + sys.exit(21) @@ -2448,55 +2849,1792 @@ index e6a42d9b85d..63fc8e8de2d 100755 + + +if __name__ == "__main__": ++ # Under the buildbot, stdout is not a TTY, but we must still flush after ++ # every line to make sure our output appears in the correct order relative ++ # to the output of our subprocesses. ++ for stream in [sys.stdout, sys.stderr]: ++ stream.reconfigure(line_buffering=True) + main() -diff --git a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj -index 6819ac0eeed..c7d63909ee2 100644 ---- a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj -+++ b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj -@@ -263,6 +263,7 @@ - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "set -e\n\nmkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelse\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nfi\n"; +diff --git a/Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj b/Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj +new file mode 100644 +index 00000000000..f8835a3bc58 +--- /dev/null ++++ b/Apple/testbed/iOSTestbed.xcodeproj/project.pbxproj +@@ -0,0 +1,557 @@ ++// !$*UTF8*$! ++{ ++ archiveVersion = 1; ++ classes = { ++ }; ++ objectVersion = 56; ++ objects = { ++ ++/* Begin PBXBuildFile section */ ++ 607A66172B0EFA380010BFC8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66162B0EFA380010BFC8 /* AppDelegate.m */; }; ++ 607A66222B0EFA390010BFC8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607A66212B0EFA390010BFC8 /* Assets.xcassets */; }; ++ 607A66252B0EFA390010BFC8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607A66232B0EFA390010BFC8 /* LaunchScreen.storyboard */; }; ++ 607A66282B0EFA390010BFC8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66272B0EFA390010BFC8 /* main.m */; }; ++ 607A66322B0EFA3A0010BFC8 /* TestbedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 607A66312B0EFA3A0010BFC8 /* TestbedTests.m */; }; ++ 607A664C2B0EFC080010BFC8 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 607A664A2B0EFB310010BFC8 /* Python.xcframework */; }; ++ 607A664D2B0EFC080010BFC8 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 607A664A2B0EFB310010BFC8 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; ++ 607A66502B0EFFE00010BFC8 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 607A664A2B0EFB310010BFC8 /* Python.xcframework */; }; ++ 607A66512B0EFFE00010BFC8 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 607A664A2B0EFB310010BFC8 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; ++ 608619542CB77BA900F46182 /* app_packages in Resources */ = {isa = PBXBuildFile; fileRef = 608619532CB77BA900F46182 /* app_packages */; }; ++ 608619562CB7819B00F46182 /* app in Resources */ = {isa = PBXBuildFile; fileRef = 608619552CB7819B00F46182 /* app */; }; ++/* End PBXBuildFile section */ ++ ++/* Begin PBXContainerItemProxy section */ ++ 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 607A660A2B0EFA380010BFC8 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = 607A66112B0EFA380010BFC8; ++ remoteInfo = iOSTestbed; ++ }; ++/* End PBXContainerItemProxy section */ ++ ++/* Begin PBXCopyFilesBuildPhase section */ ++ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ 607A664D2B0EFC080010BFC8 /* Python.xcframework in Embed Frameworks */, ++ ); ++ name = "Embed Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ 607A66512B0EFFE00010BFC8 /* Python.xcframework in Embed Frameworks */, ++ ); ++ name = "Embed Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXCopyFilesBuildPhase section */ ++ ++/* Begin PBXFileReference section */ ++ 607A66122B0EFA380010BFC8 /* iOSTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; }; ++ 607A66152B0EFA380010BFC8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; ++ 607A66162B0EFA380010BFC8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; ++ 607A66212B0EFA390010BFC8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; ++ 607A66242B0EFA390010BFC8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; ++ 607A66272B0EFA390010BFC8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; ++ 607A662D2B0EFA3A0010BFC8 /* iOSTestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSTestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; ++ 607A66312B0EFA3A0010BFC8 /* TestbedTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestbedTests.m; sourceTree = ""; }; ++ 607A664A2B0EFB310010BFC8 /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = ""; }; ++ 607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "iOSTestbed-Info.plist"; sourceTree = ""; }; ++ 608619532CB77BA900F46182 /* app_packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app_packages; sourceTree = ""; }; ++ 608619552CB7819B00F46182 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = ""; }; ++ 60FE0EFB2E56BB6D00524F87 /* iOSTestbed.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = iOSTestbed.xctestplan; sourceTree = ""; }; ++/* End PBXFileReference section */ ++ ++/* Begin PBXFrameworksBuildPhase section */ ++ 607A660F2B0EFA380010BFC8 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A664C2B0EFC080010BFC8 /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A662A2B0EFA3A0010BFC8 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A66502B0EFFE00010BFC8 /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXFrameworksBuildPhase section */ ++ ++/* Begin PBXGroup section */ ++ 607A66092B0EFA380010BFC8 = { ++ isa = PBXGroup; ++ children = ( ++ 60FE0EFB2E56BB6D00524F87 /* iOSTestbed.xctestplan */, ++ 607A664A2B0EFB310010BFC8 /* Python.xcframework */, ++ 607A66142B0EFA380010BFC8 /* iOSTestbed */, ++ 607A66302B0EFA3A0010BFC8 /* TestbedTests */, ++ 607A66132B0EFA380010BFC8 /* Products */, ++ 607A664F2B0EFFE00010BFC8 /* Frameworks */, ++ ); ++ sourceTree = ""; ++ }; ++ 607A66132B0EFA380010BFC8 /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ 607A66122B0EFA380010BFC8 /* iOSTestbed.app */, ++ 607A662D2B0EFA3A0010BFC8 /* iOSTestbedTests.xctest */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++ 607A66142B0EFA380010BFC8 /* iOSTestbed */ = { ++ isa = PBXGroup; ++ children = ( ++ 608619552CB7819B00F46182 /* app */, ++ 608619532CB77BA900F46182 /* app_packages */, ++ 607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */, ++ 607A66152B0EFA380010BFC8 /* AppDelegate.h */, ++ 607A66162B0EFA380010BFC8 /* AppDelegate.m */, ++ 607A66212B0EFA390010BFC8 /* Assets.xcassets */, ++ 607A66232B0EFA390010BFC8 /* LaunchScreen.storyboard */, ++ 607A66272B0EFA390010BFC8 /* main.m */, ++ ); ++ path = iOSTestbed; ++ sourceTree = ""; ++ }; ++ 607A66302B0EFA3A0010BFC8 /* TestbedTests */ = { ++ isa = PBXGroup; ++ children = ( ++ 607A66312B0EFA3A0010BFC8 /* TestbedTests.m */, ++ ); ++ path = TestbedTests; ++ sourceTree = ""; ++ }; ++ 607A664F2B0EFFE00010BFC8 /* Frameworks */ = { ++ isa = PBXGroup; ++ children = ( ++ ); ++ name = Frameworks; ++ sourceTree = ""; ++ }; ++/* End PBXGroup section */ ++ ++/* Begin PBXNativeTarget section */ ++ 607A66112B0EFA380010BFC8 /* iOSTestbed */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = 607A66412B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "iOSTestbed" */; ++ buildPhases = ( ++ 607A660E2B0EFA380010BFC8 /* Sources */, ++ 607A660F2B0EFA380010BFC8 /* Frameworks */, ++ 607A66102B0EFA380010BFC8 /* Resources */, ++ 607A66552B0F061D0010BFC8 /* Process Python libraries */, ++ 607A664E2B0EFC080010BFC8 /* Embed Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ name = iOSTestbed; ++ productName = iOSTestbed; ++ productReference = 607A66122B0EFA380010BFC8 /* iOSTestbed.app */; ++ productType = "com.apple.product-type.application"; ++ }; ++ 607A662C2B0EFA3A0010BFC8 /* iOSTestbedTests */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = 607A66442B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "iOSTestbedTests" */; ++ buildPhases = ( ++ 607A66292B0EFA3A0010BFC8 /* Sources */, ++ 607A662A2B0EFA3A0010BFC8 /* Frameworks */, ++ 607A662B2B0EFA3A0010BFC8 /* Resources */, ++ 607A66522B0EFFE00010BFC8 /* Embed Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ 607A662F2B0EFA3A0010BFC8 /* PBXTargetDependency */, ++ ); ++ name = iOSTestbedTests; ++ productName = iOSTestbedTests; ++ productReference = 607A662D2B0EFA3A0010BFC8 /* iOSTestbedTests.xctest */; ++ productType = "com.apple.product-type.bundle.unit-test"; ++ }; ++/* End PBXNativeTarget section */ ++ ++/* Begin PBXProject section */ ++ 607A660A2B0EFA380010BFC8 /* Project object */ = { ++ isa = PBXProject; ++ attributes = { ++ BuildIndependentTargetsInParallel = 1; ++ LastUpgradeCheck = 1500; ++ TargetAttributes = { ++ 607A66112B0EFA380010BFC8 = { ++ CreatedOnToolsVersion = 15.0.1; ++ }; ++ 607A662C2B0EFA3A0010BFC8 = { ++ CreatedOnToolsVersion = 15.0.1; ++ TestTargetID = 607A66112B0EFA380010BFC8; ++ }; ++ }; ++ }; ++ buildConfigurationList = 607A660D2B0EFA380010BFC8 /* Build configuration list for PBXProject "iOSTestbed" */; ++ compatibilityVersion = "Xcode 14.0"; ++ developmentRegion = en; ++ hasScannedForEncodings = 0; ++ knownRegions = ( ++ en, ++ Base, ++ ); ++ mainGroup = 607A66092B0EFA380010BFC8; ++ productRefGroup = 607A66132B0EFA380010BFC8 /* Products */; ++ projectDirPath = ""; ++ projectRoot = ""; ++ targets = ( ++ 607A66112B0EFA380010BFC8 /* iOSTestbed */, ++ 607A662C2B0EFA3A0010BFC8 /* iOSTestbedTests */, ++ ); ++ }; ++/* End PBXProject section */ ++ ++/* Begin PBXResourcesBuildPhase section */ ++ 607A66102B0EFA380010BFC8 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A66252B0EFA390010BFC8 /* LaunchScreen.storyboard in Resources */, ++ 608619562CB7819B00F46182 /* app in Resources */, ++ 607A66222B0EFA390010BFC8 /* Assets.xcassets in Resources */, ++ 608619542CB77BA900F46182 /* app_packages in Resources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A662B2B0EFA3A0010BFC8 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXResourcesBuildPhase section */ ++ ++/* Begin PBXShellScriptBuildPhase section */ ++ 607A66552B0F061D0010BFC8 /* Process Python libraries */ = { ++ isa = PBXShellScriptBuildPhase; ++ alwaysOutOfDate = 1; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ inputFileListPaths = ( ++ ); ++ inputPaths = ( ++ ); ++ name = "Process Python libraries"; ++ outputFileListPaths = ( ++ ); ++ outputPaths = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ shellPath = /bin/sh; ++ shellScript = "set -e\nsource $PROJECT_DIR/Python.xcframework/build/utils.sh\ninstall_python Python.xcframework app app_packages\n"; + showEnvVarsInLog = 0; - }; - 607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */ = { - isa = PBXShellScriptBuildPhase; -@@ -282,6 +283,7 @@ - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nPYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\necho \"Install Python $PYTHON_VER standard library extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\ndone\necho \"Install app package extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\ndone\necho \"Install app extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\ndone\n\n# Clean up dylib template \nrm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\necho \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\nfind \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \n"; ++ }; ++/* End PBXShellScriptBuildPhase section */ ++ ++/* Begin PBXSourcesBuildPhase section */ ++ 607A660E2B0EFA380010BFC8 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A66172B0EFA380010BFC8 /* AppDelegate.m in Sources */, ++ 607A66282B0EFA390010BFC8 /* main.m in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ 607A66292B0EFA3A0010BFC8 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ 607A66322B0EFA3A0010BFC8 /* TestbedTests.m in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXSourcesBuildPhase section */ ++ ++/* Begin PBXTargetDependency section */ ++ 607A662F2B0EFA3A0010BFC8 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = 607A66112B0EFA380010BFC8 /* iOSTestbed */; ++ targetProxy = 607A662E2B0EFA3A0010BFC8 /* PBXContainerItemProxy */; ++ }; ++/* End PBXTargetDependency section */ ++ ++/* Begin PBXVariantGroup section */ ++ 607A66232B0EFA390010BFC8 /* LaunchScreen.storyboard */ = { ++ isa = PBXVariantGroup; ++ children = ( ++ 607A66242B0EFA390010BFC8 /* Base */, ++ ); ++ name = LaunchScreen.storyboard; ++ sourceTree = ""; ++ }; ++/* End PBXVariantGroup section */ ++ ++/* Begin XCBuildConfiguration section */ ++ 607A663F2B0EFA3A0010BFC8 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ++ CLANG_ANALYZER_NONNULL = YES; ++ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; ++ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; ++ CLANG_ENABLE_MODULES = YES; ++ CLANG_ENABLE_OBJC_ARC = YES; ++ CLANG_ENABLE_OBJC_WEAK = YES; ++ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; ++ CLANG_WARN_BOOL_CONVERSION = YES; ++ CLANG_WARN_COMMA = YES; ++ CLANG_WARN_CONSTANT_CONVERSION = YES; ++ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; ++ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; ++ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; ++ CLANG_WARN_EMPTY_BODY = YES; ++ CLANG_WARN_ENUM_CONVERSION = YES; ++ CLANG_WARN_INFINITE_RECURSION = YES; ++ CLANG_WARN_INT_CONVERSION = YES; ++ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; ++ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; ++ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; ++ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; ++ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; ++ CLANG_WARN_STRICT_PROTOTYPES = YES; ++ CLANG_WARN_SUSPICIOUS_MOVE = YES; ++ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; ++ CLANG_WARN_UNREACHABLE_CODE = YES; ++ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ++ COPY_PHASE_STRIP = NO; ++ DEBUG_INFORMATION_FORMAT = dwarf; ++ ENABLE_STRICT_OBJC_MSGSEND = YES; ++ ENABLE_TESTABILITY = YES; ++ ENABLE_USER_SCRIPT_SANDBOXING = YES; ++ GCC_C_LANGUAGE_STANDARD = gnu17; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_NO_COMMON_BLOCKS = YES; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PREPROCESSOR_DEFINITIONS = ( ++ "DEBUG=1", ++ "$(inherited)", ++ ); ++ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; ++ GCC_WARN_UNDECLARED_SELECTOR = YES; ++ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; ++ GCC_WARN_UNUSED_FUNCTION = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ IPHONEOS_DEPLOYMENT_TARGET = 13.0; ++ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; ++ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; ++ MTL_FAST_MATH = YES; ++ ONLY_ACTIVE_ARCH = YES; ++ SDKROOT = iphoneos; ++ }; ++ name = Debug; ++ }; ++ 607A66402B0EFA3A0010BFC8 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ++ CLANG_ANALYZER_NONNULL = YES; ++ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; ++ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; ++ CLANG_ENABLE_MODULES = YES; ++ CLANG_ENABLE_OBJC_ARC = YES; ++ CLANG_ENABLE_OBJC_WEAK = YES; ++ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; ++ CLANG_WARN_BOOL_CONVERSION = YES; ++ CLANG_WARN_COMMA = YES; ++ CLANG_WARN_CONSTANT_CONVERSION = YES; ++ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; ++ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; ++ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; ++ CLANG_WARN_EMPTY_BODY = YES; ++ CLANG_WARN_ENUM_CONVERSION = YES; ++ CLANG_WARN_INFINITE_RECURSION = YES; ++ CLANG_WARN_INT_CONVERSION = YES; ++ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; ++ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; ++ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; ++ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; ++ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; ++ CLANG_WARN_STRICT_PROTOTYPES = YES; ++ CLANG_WARN_SUSPICIOUS_MOVE = YES; ++ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; ++ CLANG_WARN_UNREACHABLE_CODE = YES; ++ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ++ COPY_PHASE_STRIP = NO; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ ENABLE_NS_ASSERTIONS = NO; ++ ENABLE_STRICT_OBJC_MSGSEND = YES; ++ ENABLE_USER_SCRIPT_SANDBOXING = YES; ++ GCC_C_LANGUAGE_STANDARD = gnu17; ++ GCC_NO_COMMON_BLOCKS = YES; ++ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; ++ GCC_WARN_UNDECLARED_SELECTOR = YES; ++ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; ++ GCC_WARN_UNUSED_FUNCTION = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ IPHONEOS_DEPLOYMENT_TARGET = 13.0; ++ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; ++ MTL_ENABLE_DEBUG_INFO = NO; ++ MTL_FAST_MATH = YES; ++ SDKROOT = iphoneos; ++ VALIDATE_PRODUCT = YES; ++ }; ++ name = Release; ++ }; ++ 607A66422B0EFA3A0010BFC8 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ++ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ DEVELOPMENT_TEAM = ""; ++ ENABLE_USER_SCRIPT_SANDBOXING = NO; ++ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; ++ INFOPLIST_FILE = "iOSTestbed/iOSTestbed-Info.plist"; ++ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; ++ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; ++ INFOPLIST_KEY_UIMainStoryboardFile = Main; ++ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; ++ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; ++ IPHONEOS_DEPLOYMENT_TARGET = 13.0; ++ LD_RUNPATH_SEARCH_PATHS = ( ++ "$(inherited)", ++ "@executable_path/Frameworks", ++ ); ++ MARKETING_VERSION = 3.13.0a1; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbed; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = YES; ++ TARGETED_DEVICE_FAMILY = "1,2"; ++ }; ++ name = Debug; ++ }; ++ 607A66432B0EFA3A0010BFC8 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ++ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ DEVELOPMENT_TEAM = ""; ++ ENABLE_TESTABILITY = YES; ++ ENABLE_USER_SCRIPT_SANDBOXING = NO; ++ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; ++ INFOPLIST_FILE = "iOSTestbed/iOSTestbed-Info.plist"; ++ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; ++ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; ++ INFOPLIST_KEY_UIMainStoryboardFile = Main; ++ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; ++ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; ++ IPHONEOS_DEPLOYMENT_TARGET = 13.0; ++ LD_RUNPATH_SEARCH_PATHS = ( ++ "$(inherited)", ++ "@executable_path/Frameworks", ++ ); ++ MARKETING_VERSION = 3.13.0a1; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbed; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = YES; ++ TARGETED_DEVICE_FAMILY = "1,2"; ++ }; ++ name = Release; ++ }; ++ 607A66452B0EFA3A0010BFC8 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ BUNDLE_LOADER = "$(TEST_HOST)"; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ DEVELOPMENT_TEAM = 3HEZE76D99; ++ GENERATE_INFOPLIST_FILE = YES; ++ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; ++ IPHONEOS_DEPLOYMENT_TARGET = 13.0; ++ MARKETING_VERSION = 1.0; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbedTests; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = NO; ++ TARGETED_DEVICE_FAMILY = "1,2"; ++ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/iOSTestbed"; ++ }; ++ name = Debug; ++ }; ++ 607A66462B0EFA3A0010BFC8 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ BUNDLE_LOADER = "$(TEST_HOST)"; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ DEVELOPMENT_TEAM = 3HEZE76D99; ++ GENERATE_INFOPLIST_FILE = YES; ++ HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\""; ++ IPHONEOS_DEPLOYMENT_TARGET = 13.0; ++ MARKETING_VERSION = 1.0; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbedTests; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = NO; ++ TARGETED_DEVICE_FAMILY = "1,2"; ++ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/iOSTestbed"; ++ }; ++ name = Release; ++ }; ++/* End XCBuildConfiguration section */ ++ ++/* Begin XCConfigurationList section */ ++ 607A660D2B0EFA380010BFC8 /* Build configuration list for PBXProject "iOSTestbed" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ 607A663F2B0EFA3A0010BFC8 /* Debug */, ++ 607A66402B0EFA3A0010BFC8 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ 607A66412B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "iOSTestbed" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ 607A66422B0EFA3A0010BFC8 /* Debug */, ++ 607A66432B0EFA3A0010BFC8 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ 607A66442B0EFA3A0010BFC8 /* Build configuration list for PBXNativeTarget "iOSTestbedTests" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ 607A66452B0EFA3A0010BFC8 /* Debug */, ++ 607A66462B0EFA3A0010BFC8 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++/* End XCConfigurationList section */ ++ }; ++ rootObject = 607A660A2B0EFA380010BFC8 /* Project object */; ++} +diff --git a/Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme b/Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme +new file mode 100644 +index 00000000000..3c330a4152b +--- /dev/null ++++ b/Apple/testbed/iOSTestbed.xcodeproj/xcshareddata/xcschemes/iOSTestbed.xcscheme +@@ -0,0 +1,97 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/Apple/testbed/iOSTestbed.xctestplan b/Apple/testbed/iOSTestbed.xctestplan +new file mode 100644 +index 00000000000..0c4ab9eb2ba +--- /dev/null ++++ b/Apple/testbed/iOSTestbed.xctestplan +@@ -0,0 +1,46 @@ ++{ ++ "configurations" : [ ++ { ++ "id" : "F5A95CE4-1ADE-4A6E-A0E1-CDBAE26DF0C5", ++ "name" : "Test Scheme Action", ++ "options" : { ++ ++ } ++ } ++ ], ++ "defaultOptions" : { ++ "commandLineArgumentEntries" : [ ++ { ++ "argument" : "test" ++ }, ++ { ++ "argument" : "-uall" ++ }, ++ { ++ "argument" : "--single-process" ++ }, ++ { ++ "argument" : "--rerun" ++ }, ++ { ++ "argument" : "-W" ++ } ++ ], ++ "targetForVariableExpansion" : { ++ "containerPath" : "container:iOSTestbed.xcodeproj", ++ "identifier" : "607A66112B0EFA380010BFC8", ++ "name" : "iOSTestbed" ++ } ++ }, ++ "testTargets" : [ ++ { ++ "parallelizable" : false, ++ "target" : { ++ "containerPath" : "container:iOSTestbed.xcodeproj", ++ "identifier" : "607A662C2B0EFA3A0010BFC8", ++ "name" : "iOSTestbedTests" ++ } ++ } ++ ], ++ "version" : 1 ++} +diff --git a/Apple/testbed/iOSTestbed/AppDelegate.h b/Apple/testbed/iOSTestbed/AppDelegate.h +new file mode 100644 +index 00000000000..f695b3b5efc +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/AppDelegate.h +@@ -0,0 +1,11 @@ ++// ++// AppDelegate.h ++// iOSTestbed ++// ++ ++#import ++ ++@interface AppDelegate : UIResponder ++ ++ ++@end +diff --git a/Apple/testbed/iOSTestbed/AppDelegate.m b/Apple/testbed/iOSTestbed/AppDelegate.m +new file mode 100644 +index 00000000000..e5085399d0c +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/AppDelegate.m +@@ -0,0 +1,19 @@ ++// ++// AppDelegate.m ++// iOSTestbed ++// ++ ++#import "AppDelegate.h" ++ ++@interface AppDelegate () ++ ++@end ++ ++@implementation AppDelegate ++ ++ ++- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ++ return YES; ++} ++ ++@end +diff --git a/Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json b/Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json +new file mode 100644 +index 00000000000..eb878970081 +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/Assets.xcassets/AccentColor.colorset/Contents.json +@@ -0,0 +1,11 @@ ++{ ++ "colors" : [ ++ { ++ "idiom" : "universal" ++ } ++ ], ++ "info" : { ++ "author" : "xcode", ++ "version" : 1 ++ } ++} +diff --git a/Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json b/Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json +new file mode 100644 +index 00000000000..13613e3ee1a +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/Assets.xcassets/AppIcon.appiconset/Contents.json +@@ -0,0 +1,13 @@ ++{ ++ "images" : [ ++ { ++ "idiom" : "universal", ++ "platform" : "ios", ++ "size" : "1024x1024" ++ } ++ ], ++ "info" : { ++ "author" : "xcode", ++ "version" : 1 ++ } ++} +diff --git a/Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json b/Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json +new file mode 100644 +index 00000000000..73c00596a7f +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/Assets.xcassets/Contents.json +@@ -0,0 +1,6 @@ ++{ ++ "info" : { ++ "author" : "xcode", ++ "version" : 1 ++ } ++} +diff --git a/Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard b/Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard +new file mode 100644 +index 00000000000..5daafe73a86 +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/Base.lproj/LaunchScreen.storyboard +@@ -0,0 +1,9 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/Apple/testbed/iOSTestbed/app/README b/Apple/testbed/iOSTestbed/app/README +new file mode 100644 +index 00000000000..46c0e8e2a29 +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/app/README +@@ -0,0 +1,7 @@ ++This folder can contain any Python application code. ++ ++During the build, any binary modules found in this folder will be processed into ++Framework form. ++ ++When the test suite runs, this folder will be on the PYTHONPATH, and will be the ++working directory for the test suite. +diff --git a/Apple/testbed/iOSTestbed/app_packages/README b/Apple/testbed/iOSTestbed/app_packages/README +new file mode 100644 +index 00000000000..02c2beccfbd +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/app_packages/README +@@ -0,0 +1,7 @@ ++This folder can be a target for installing any Python dependencies needed by the ++test suite. ++ ++During the build, any binary modules found in this folder will be processed into ++Framework form. ++ ++When the test suite runs, this folder will be on the PYTHONPATH. +diff --git a/Apple/testbed/iOSTestbed/iOSTestbed-Info.plist b/Apple/testbed/iOSTestbed/iOSTestbed-Info.plist +new file mode 100644 +index 00000000000..fea45e1fad6 +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/iOSTestbed-Info.plist +@@ -0,0 +1,52 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleDisplayName ++ ${PRODUCT_NAME} ++ CFBundleExecutable ++ ${EXECUTABLE_NAME} ++ CFBundleIdentifier ++ org.python.iOSTestbed ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundleName ++ ${PRODUCT_NAME} ++ CFBundlePackageType ++ APPL ++ CFBundleShortVersionString ++ 1.0 ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ 1 ++ LSRequiresIPhoneOS ++ ++ UIRequiresFullScreen ++ ++ UILaunchStoryboardName ++ Launch Screen ++ UISupportedInterfaceOrientations ++ ++ UIInterfaceOrientationPortrait ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ ++ UISupportedInterfaceOrientations~ipad ++ ++ UIInterfaceOrientationPortrait ++ UIInterfaceOrientationPortraitUpsideDown ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ ++ UIApplicationSceneManifest ++ ++ UIApplicationSupportsMultipleScenes ++ ++ UISceneConfigurations ++ ++ ++ ++ +diff --git a/Apple/testbed/iOSTestbed/main.m b/Apple/testbed/iOSTestbed/main.m +new file mode 100644 +index 00000000000..e32bd78c9b4 +--- /dev/null ++++ b/Apple/testbed/iOSTestbed/main.m +@@ -0,0 +1,16 @@ ++// ++// main.m ++// iOSTestbed ++// ++ ++#import ++#import "AppDelegate.h" ++ ++int main(int argc, char * argv[]) { ++ NSString * appDelegateClassName; ++ @autoreleasepool { ++ appDelegateClassName = NSStringFromClass([AppDelegate class]); ++ ++ return UIApplicationMain(argc, argv, nil, appDelegateClassName); ++ } ++} +diff --git a/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj b/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj +new file mode 100644 +index 00000000000..85e7047dfb7 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed.xcodeproj/project.pbxproj +@@ -0,0 +1,506 @@ ++// !$*UTF8*$! ++{ ++ archiveVersion = 1; ++ classes = { ++ }; ++ objectVersion = 77; ++ objects = { ++ ++/* Begin PBXBuildFile section */ ++ EE7C8A1E2DCD6FF3003206DB /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */; }; ++ EE7C8A1F2DCD70CD003206DB /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */; }; ++ EE7C8A202DCD70CD003206DB /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; ++/* End PBXBuildFile section */ ++ ++/* Begin PBXContainerItemProxy section */ ++ EE989E662DCD6E7A0036B268 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = EE989E462DCD6E780036B268 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = EE989E4D2DCD6E780036B268; ++ remoteInfo = tvOSTestbed; ++ }; ++/* End PBXContainerItemProxy section */ ++ ++/* Begin PBXCopyFilesBuildPhase section */ ++ EE7C8A212DCD70CD003206DB /* Embed Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ EE7C8A202DCD70CD003206DB /* Python.xcframework in Embed Frameworks */, ++ ); ++ name = "Embed Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXCopyFilesBuildPhase section */ ++ ++/* Begin PBXFileReference section */ ++ 6077B3802E82A4BE00E3D6A3 /* tvOSTestbed.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = tvOSTestbed.xctestplan; sourceTree = ""; }; ++ EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = ""; }; ++ EE989E4E2DCD6E780036B268 /* tvOSTestbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tvOSTestbed.app; sourceTree = BUILT_PRODUCTS_DIR; }; ++ EE989E652DCD6E7A0036B268 /* TestbedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestbedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; ++/* End PBXFileReference section */ ++ ++/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ ++ 6077B37F2E81892A00E3D6A3 /* Exceptions for "tvOSTestbed" folder in "tvOSTestbed" target */ = { ++ isa = PBXFileSystemSynchronizedBuildFileExceptionSet; ++ membershipExceptions = ( ++ "tvOSTestbed-Info.plist", ++ ); ++ target = EE989E4D2DCD6E780036B268 /* tvOSTestbed */; ++ }; ++/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ ++ ++/* Begin PBXFileSystemSynchronizedRootGroup section */ ++ EE989E502DCD6E780036B268 /* tvOSTestbed */ = { ++ isa = PBXFileSystemSynchronizedRootGroup; ++ exceptions = ( ++ 6077B37F2E81892A00E3D6A3 /* Exceptions for "tvOSTestbed" folder in "tvOSTestbed" target */, ++ ); ++ explicitFolders = ( ++ app, ++ app_packages, ++ ); ++ path = tvOSTestbed; ++ sourceTree = ""; ++ }; ++ EE989E682DCD6E7A0036B268 /* TestbedTests */ = { ++ isa = PBXFileSystemSynchronizedRootGroup; ++ path = TestbedTests; ++ sourceTree = ""; ++ }; ++/* End PBXFileSystemSynchronizedRootGroup section */ ++ ++/* Begin PBXFrameworksBuildPhase section */ ++ EE989E4B2DCD6E780036B268 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ EE7C8A1F2DCD70CD003206DB /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ EE989E622DCD6E7A0036B268 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ EE7C8A1E2DCD6FF3003206DB /* Python.xcframework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXFrameworksBuildPhase section */ ++ ++/* Begin PBXGroup section */ ++ EE989E452DCD6E780036B268 = { ++ isa = PBXGroup; ++ children = ( ++ 6077B3802E82A4BE00E3D6A3 /* tvOSTestbed.xctestplan */, ++ EE7C8A1C2DCD6FF3003206DB /* Python.xcframework */, ++ EE989E502DCD6E780036B268 /* tvOSTestbed */, ++ EE989E682DCD6E7A0036B268 /* TestbedTests */, ++ EE989E4F2DCD6E780036B268 /* Products */, ++ ); ++ sourceTree = ""; ++ }; ++ EE989E4F2DCD6E780036B268 /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ EE989E4E2DCD6E780036B268 /* tvOSTestbed.app */, ++ EE989E652DCD6E7A0036B268 /* TestbedTests.xctest */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++/* End PBXGroup section */ ++ ++/* Begin PBXNativeTarget section */ ++ EE989E4D2DCD6E780036B268 /* tvOSTestbed */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = EE989E792DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "tvOSTestbed" */; ++ buildPhases = ( ++ EE989E4A2DCD6E780036B268 /* Sources */, ++ EE989E4B2DCD6E780036B268 /* Frameworks */, ++ EE989E4C2DCD6E780036B268 /* Resources */, ++ EE7C8A222DCD70F4003206DB /* Process Python libraries */, ++ EE7C8A212DCD70CD003206DB /* Embed Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ fileSystemSynchronizedGroups = ( ++ EE989E502DCD6E780036B268 /* tvOSTestbed */, ++ ); ++ name = tvOSTestbed; ++ packageProductDependencies = ( ++ ); ++ productName = tvOSTestbed; ++ productReference = EE989E4E2DCD6E780036B268 /* tvOSTestbed.app */; ++ productType = "com.apple.product-type.application"; ++ }; ++ EE989E642DCD6E7A0036B268 /* TestbedTests */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = EE989E7C2DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "TestbedTests" */; ++ buildPhases = ( ++ EE989E612DCD6E7A0036B268 /* Sources */, ++ EE989E622DCD6E7A0036B268 /* Frameworks */, ++ EE989E632DCD6E7A0036B268 /* Resources */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ EE989E672DCD6E7A0036B268 /* PBXTargetDependency */, ++ ); ++ fileSystemSynchronizedGroups = ( ++ EE989E682DCD6E7A0036B268 /* TestbedTests */, ++ ); ++ name = TestbedTests; ++ packageProductDependencies = ( ++ ); ++ productName = TestbedTests; ++ productReference = EE989E652DCD6E7A0036B268 /* TestbedTests.xctest */; ++ productType = "com.apple.product-type.bundle.unit-test"; ++ }; ++/* End PBXNativeTarget section */ ++ ++/* Begin PBXProject section */ ++ EE989E462DCD6E780036B268 /* Project object */ = { ++ isa = PBXProject; ++ attributes = { ++ BuildIndependentTargetsInParallel = 1; ++ LastUpgradeCheck = 1620; ++ TargetAttributes = { ++ EE989E4D2DCD6E780036B268 = { ++ CreatedOnToolsVersion = 16.2; ++ }; ++ EE989E642DCD6E7A0036B268 = { ++ CreatedOnToolsVersion = 16.2; ++ TestTargetID = EE989E4D2DCD6E780036B268; ++ }; ++ }; ++ }; ++ buildConfigurationList = EE989E492DCD6E780036B268 /* Build configuration list for PBXProject "tvOSTestbed" */; ++ developmentRegion = en; ++ hasScannedForEncodings = 0; ++ knownRegions = ( ++ en, ++ Base, ++ ); ++ mainGroup = EE989E452DCD6E780036B268; ++ minimizedProjectReferenceProxies = 1; ++ preferredProjectObjectVersion = 77; ++ productRefGroup = EE989E4F2DCD6E780036B268 /* Products */; ++ projectDirPath = ""; ++ projectRoot = ""; ++ targets = ( ++ EE989E4D2DCD6E780036B268 /* tvOSTestbed */, ++ EE989E642DCD6E7A0036B268 /* TestbedTests */, ++ ); ++ }; ++/* End PBXProject section */ ++ ++/* Begin PBXResourcesBuildPhase section */ ++ EE989E4C2DCD6E780036B268 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ EE989E632DCD6E7A0036B268 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXResourcesBuildPhase section */ ++ ++/* Begin PBXShellScriptBuildPhase section */ ++ EE7C8A222DCD70F4003206DB /* Process Python libraries */ = { ++ isa = PBXShellScriptBuildPhase; ++ alwaysOutOfDate = 1; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ inputFileListPaths = ( ++ ); ++ inputPaths = ( ++ ); ++ name = "Process Python libraries"; ++ outputFileListPaths = ( ++ ); ++ outputPaths = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ shellPath = /bin/sh; ++ shellScript = "set -e\n\nsource $PROJECT_DIR/Python.xcframework/build/utils.sh\n\ninstall_python Python.xcframework app app_packages\n"; + showEnvVarsInLog = 0; - }; - /* End PBXShellScriptBuildPhase section */ - -diff --git a/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m b/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m -index db00d43da85..6db38253396 100644 ---- a/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m -+++ b/iOS/testbed/iOSTestbedTests/iOSTestbedTests.m -@@ -24,8 +24,11 @@ - - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - -- // Disable all color, as the Xcode log can't display color -+ // Set some other common environment indicators to disable color, as the -+ // Xcode log can't display color. Stdout will report that it is *not* a -+ // TTY. - setenv("NO_COLOR", "1", true); -+ setenv("PY_COLORS", "0", true); - - // Arguments to pass into the test suite runner. - // argv[0] must identify the process; any subsequent arg -@@ -50,6 +53,8 @@ - // Enforce UTF-8 encoding for stderr, stdout, file-system encoding and locale. - // See https://docs.python.org/3/library/os.html#python-utf-8-mode. - preconfig.utf8_mode = 1; -+ // Use the system logger for stdout/err -+ config.use_system_logger = 1; - // Don't buffer stdio. We want output to appears in the log immediately - config.buffered_stdio = 0; - // Don't write bytecode; we can't modify the app bundle ---- /dev/null -+++ b/tvOS/README.rst ++ }; ++/* End PBXShellScriptBuildPhase section */ ++ ++/* Begin PBXSourcesBuildPhase section */ ++ EE989E4A2DCD6E780036B268 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ EE989E612DCD6E7A0036B268 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXSourcesBuildPhase section */ ++ ++/* Begin PBXTargetDependency section */ ++ EE989E672DCD6E7A0036B268 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = EE989E4D2DCD6E780036B268 /* tvOSTestbed */; ++ targetProxy = EE989E662DCD6E7A0036B268 /* PBXContainerItemProxy */; ++ }; ++/* End PBXTargetDependency section */ ++ ++/* Begin XCBuildConfiguration section */ ++ EE989E772DCD6E7A0036B268 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ++ CLANG_ANALYZER_NONNULL = YES; ++ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; ++ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; ++ CLANG_ENABLE_MODULES = YES; ++ CLANG_ENABLE_OBJC_ARC = YES; ++ CLANG_ENABLE_OBJC_WEAK = YES; ++ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; ++ CLANG_WARN_BOOL_CONVERSION = YES; ++ CLANG_WARN_COMMA = YES; ++ CLANG_WARN_CONSTANT_CONVERSION = YES; ++ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; ++ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; ++ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; ++ CLANG_WARN_EMPTY_BODY = YES; ++ CLANG_WARN_ENUM_CONVERSION = YES; ++ CLANG_WARN_INFINITE_RECURSION = YES; ++ CLANG_WARN_INT_CONVERSION = YES; ++ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; ++ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; ++ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; ++ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; ++ CLANG_WARN_STRICT_PROTOTYPES = YES; ++ CLANG_WARN_SUSPICIOUS_MOVE = YES; ++ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; ++ CLANG_WARN_UNREACHABLE_CODE = YES; ++ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ++ COPY_PHASE_STRIP = NO; ++ DEBUG_INFORMATION_FORMAT = dwarf; ++ ENABLE_STRICT_OBJC_MSGSEND = YES; ++ ENABLE_TESTABILITY = YES; ++ ENABLE_USER_SCRIPT_SANDBOXING = NO; ++ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)"; ++ GCC_C_LANGUAGE_STANDARD = gnu17; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_NO_COMMON_BLOCKS = YES; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PREPROCESSOR_DEFINITIONS = ( ++ "DEBUG=1", ++ "$(inherited)", ++ ); ++ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; ++ GCC_WARN_UNDECLARED_SELECTOR = YES; ++ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; ++ GCC_WARN_UNUSED_FUNCTION = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/Python.framework/Headers"; ++ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; ++ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; ++ MTL_FAST_MATH = YES; ++ ONLY_ACTIVE_ARCH = YES; ++ SDKROOT = appletvos; ++ TVOS_DEPLOYMENT_TARGET = 18.2; ++ }; ++ name = Debug; ++ }; ++ EE989E782DCD6E7A0036B268 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ++ CLANG_ANALYZER_NONNULL = YES; ++ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; ++ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; ++ CLANG_ENABLE_MODULES = YES; ++ CLANG_ENABLE_OBJC_ARC = YES; ++ CLANG_ENABLE_OBJC_WEAK = YES; ++ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; ++ CLANG_WARN_BOOL_CONVERSION = YES; ++ CLANG_WARN_COMMA = YES; ++ CLANG_WARN_CONSTANT_CONVERSION = YES; ++ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; ++ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; ++ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; ++ CLANG_WARN_EMPTY_BODY = YES; ++ CLANG_WARN_ENUM_CONVERSION = YES; ++ CLANG_WARN_INFINITE_RECURSION = YES; ++ CLANG_WARN_INT_CONVERSION = YES; ++ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; ++ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; ++ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; ++ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; ++ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; ++ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; ++ CLANG_WARN_STRICT_PROTOTYPES = YES; ++ CLANG_WARN_SUSPICIOUS_MOVE = YES; ++ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; ++ CLANG_WARN_UNREACHABLE_CODE = YES; ++ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ++ COPY_PHASE_STRIP = NO; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ ENABLE_NS_ASSERTIONS = NO; ++ ENABLE_STRICT_OBJC_MSGSEND = YES; ++ ENABLE_TESTABILITY = YES; ++ ENABLE_USER_SCRIPT_SANDBOXING = NO; ++ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)"; ++ GCC_C_LANGUAGE_STANDARD = gnu17; ++ GCC_NO_COMMON_BLOCKS = YES; ++ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; ++ GCC_WARN_UNDECLARED_SELECTOR = YES; ++ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; ++ GCC_WARN_UNUSED_FUNCTION = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/Python.framework/Headers"; ++ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; ++ MTL_ENABLE_DEBUG_INFO = NO; ++ MTL_FAST_MATH = YES; ++ SDKROOT = appletvos; ++ TVOS_DEPLOYMENT_TARGET = 18.2; ++ VALIDATE_PRODUCT = YES; ++ }; ++ name = Release; ++ }; ++ EE989E7A2DCD6E7A0036B268 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ++ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ GENERATE_INFOPLIST_FILE = NO; ++ INFOPLIST_FILE = "tvOSTestbed/tvOSTestbed-Info.plist"; ++ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; ++ INFOPLIST_KEY_UIMainStoryboardFile = Main; ++ INFOPLIST_KEY_UIUserInterfaceStyle = Automatic; ++ LD_RUNPATH_SEARCH_PATHS = ( ++ "$(inherited)", ++ "@executable_path/Frameworks", ++ ); ++ MARKETING_VERSION = 1.0; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.tvOSTestbed; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = YES; ++ TARGETED_DEVICE_FAMILY = 3; ++ }; ++ name = Debug; ++ }; ++ EE989E7B2DCD6E7A0036B268 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; ++ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ GENERATE_INFOPLIST_FILE = NO; ++ INFOPLIST_FILE = "tvOSTestbed/tvOSTestbed-Info.plist"; ++ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; ++ INFOPLIST_KEY_UIMainStoryboardFile = Main; ++ INFOPLIST_KEY_UIUserInterfaceStyle = Automatic; ++ LD_RUNPATH_SEARCH_PATHS = ( ++ "$(inherited)", ++ "@executable_path/Frameworks", ++ ); ++ MARKETING_VERSION = 1.0; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.tvOSTestbed; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = YES; ++ TARGETED_DEVICE_FAMILY = 3; ++ }; ++ name = Release; ++ }; ++ EE989E7D2DCD6E7A0036B268 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ BUNDLE_LOADER = "$(TEST_HOST)"; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ GENERATE_INFOPLIST_FILE = YES; ++ MARKETING_VERSION = 1.0; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = NO; ++ TARGETED_DEVICE_FAMILY = 3; ++ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/tvOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/tvOSTestbed"; ++ TVOS_DEPLOYMENT_TARGET = 18.2; ++ }; ++ name = Debug; ++ }; ++ EE989E7E2DCD6E7A0036B268 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ BUNDLE_LOADER = "$(TEST_HOST)"; ++ CODE_SIGN_STYLE = Automatic; ++ CURRENT_PROJECT_VERSION = 1; ++ GENERATE_INFOPLIST_FILE = YES; ++ MARKETING_VERSION = 1.0; ++ PRODUCT_BUNDLE_IDENTIFIER = org.python.TestbedTests; ++ PRODUCT_NAME = "$(TARGET_NAME)"; ++ SWIFT_EMIT_LOC_STRINGS = NO; ++ TARGETED_DEVICE_FAMILY = 3; ++ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/tvOSTestbed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/tvOSTestbed"; ++ TVOS_DEPLOYMENT_TARGET = 18.2; ++ }; ++ name = Release; ++ }; ++/* End XCBuildConfiguration section */ ++ ++/* Begin XCConfigurationList section */ ++ EE989E492DCD6E780036B268 /* Build configuration list for PBXProject "tvOSTestbed" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ EE989E772DCD6E7A0036B268 /* Debug */, ++ EE989E782DCD6E7A0036B268 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ EE989E792DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "tvOSTestbed" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ EE989E7A2DCD6E7A0036B268 /* Debug */, ++ EE989E7B2DCD6E7A0036B268 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ EE989E7C2DCD6E7A0036B268 /* Build configuration list for PBXNativeTarget "TestbedTests" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ EE989E7D2DCD6E7A0036B268 /* Debug */, ++ EE989E7E2DCD6E7A0036B268 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++/* End XCConfigurationList section */ ++ }; ++ rootObject = EE989E462DCD6E780036B268 /* Project object */; ++} +diff --git a/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme b/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme +new file mode 100644 +index 00000000000..c3f3f894a1f +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed.xcodeproj/xcshareddata/xcschemes/tvOSTestbed.xcscheme +@@ -0,0 +1,97 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/Apple/testbed/tvOSTestbed.xctestplan b/Apple/testbed/tvOSTestbed.xctestplan +new file mode 100644 +index 00000000000..f996facc178 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed.xctestplan +@@ -0,0 +1,46 @@ ++{ ++ "configurations" : [ ++ { ++ "id" : "F5A95CE4-1ADE-4A6E-A0E1-CDBAE26DF0C5", ++ "name" : "Test Scheme Action", ++ "options" : { ++ ++ } ++ } ++ ], ++ "defaultOptions" : { ++ "commandLineArgumentEntries" : [ ++ { ++ "argument" : "test" ++ }, ++ { ++ "argument" : "-uall" ++ }, ++ { ++ "argument" : "--single-process" ++ }, ++ { ++ "argument" : "--rerun" ++ }, ++ { ++ "argument" : "-W" ++ } ++ ], ++ "targetForVariableExpansion" : { ++ "containerPath" : "container:tvOSTestbed.xcodeproj", ++ "identifier" : "607A66112B0EFA380010BFC8", ++ "name" : "tvOSTestbed" ++ } ++ }, ++ "testTargets" : [ ++ { ++ "parallelizable" : false, ++ "target" : { ++ "containerPath" : "container:tvOSTestbed.xcodeproj", ++ "identifier" : "EE989E642DCD6E7A0036B268", ++ "name" : "TestbedTests" ++ } ++ } ++ ], ++ "version" : 1 ++} +\ No newline at end of file +diff --git a/Apple/testbed/tvOSTestbed/AppDelegate.h b/Apple/testbed/tvOSTestbed/AppDelegate.h +new file mode 100644 +index 00000000000..112c9ed64b8 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/AppDelegate.h +@@ -0,0 +1,11 @@ ++// ++// AppDelegate.h ++// tvOSTestbed ++// ++ ++#import ++ ++@interface AppDelegate : UIResponder ++ ++ ++@end +diff --git a/Apple/testbed/tvOSTestbed/AppDelegate.m b/Apple/testbed/tvOSTestbed/AppDelegate.m +new file mode 100644 +index 00000000000..bd91fb2d7d6 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/AppDelegate.m +@@ -0,0 +1,19 @@ ++// ++// AppDelegate.m ++// tvOSTestbed ++// ++ ++#import "AppDelegate.h" ++ ++@interface AppDelegate () ++ ++@end ++ ++@implementation AppDelegate ++ ++ ++- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ++ return YES; ++} ++ ++@end +diff --git a/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard b/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard +new file mode 100644 +index 00000000000..660ba53de4f +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/Base.lproj/LaunchScreen.storyboard +@@ -0,0 +1,24 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/Apple/testbed/tvOSTestbed/app/README b/Apple/testbed/tvOSTestbed/app/README +new file mode 100644 +index 00000000000..46c0e8e2a29 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/app/README +@@ -0,0 +1,7 @@ ++This folder can contain any Python application code. ++ ++During the build, any binary modules found in this folder will be processed into ++Framework form. ++ ++When the test suite runs, this folder will be on the PYTHONPATH, and will be the ++working directory for the test suite. +diff --git a/Apple/testbed/tvOSTestbed/app_packages/README b/Apple/testbed/tvOSTestbed/app_packages/README +new file mode 100644 +index 00000000000..02c2beccfbd +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/app_packages/README +@@ -0,0 +1,7 @@ ++This folder can be a target for installing any Python dependencies needed by the ++test suite. ++ ++During the build, any binary modules found in this folder will be processed into ++Framework form. ++ ++When the test suite runs, this folder will be on the PYTHONPATH. +diff --git a/Apple/testbed/tvOSTestbed/main.m b/Apple/testbed/tvOSTestbed/main.m +new file mode 100644 +index 00000000000..d5808fbb933 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/main.m +@@ -0,0 +1,16 @@ ++// ++// main.m ++// tvOSTestbed ++// ++ ++#import ++#import "AppDelegate.h" ++ ++int main(int argc, char * argv[]) { ++ NSString * appDelegateClassName; ++ @autoreleasepool { ++ appDelegateClassName = NSStringFromClass([AppDelegate class]); ++ ++ return UIApplicationMain(argc, argv, nil, appDelegateClassName); ++ } ++} +diff --git a/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist b/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist +new file mode 100644 +index 00000000000..f08f6098999 +--- /dev/null ++++ b/Apple/testbed/tvOSTestbed/tvOSTestbed-Info.plist +@@ -0,0 +1,52 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ en ++ CFBundleDisplayName ++ ${PRODUCT_NAME} ++ CFBundleExecutable ++ ${EXECUTABLE_NAME} ++ CFBundleIdentifier ++ org.python.tvOSTestbed ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundleName ++ ${PRODUCT_NAME} ++ CFBundlePackageType ++ APPL ++ CFBundleShortVersionString ++ 1.0 ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ 1 ++ LSRequiresIPhoneOS ++ ++ UIRequiresFullScreen ++ ++ UILaunchStoryboardName ++ Launch Screen ++ UISupportedInterfaceOrientations ++ ++ UIInterfaceOrientationPortrait ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ ++ UISupportedInterfaceOrientations~ipad ++ ++ UIInterfaceOrientationPortrait ++ UIInterfaceOrientationPortraitUpsideDown ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ ++ UIApplicationSceneManifest ++ ++ UIApplicationSupportsMultipleScenes ++ ++ UISceneConfigurations ++ ++ ++ ++ +diff --git a/Apple/tvOS/README.rst b/Apple/tvOS/README.rst +new file mode 100644 +index 00000000000..1f793252caf +--- /dev/null ++++ b/Apple/tvOS/README.rst @@ -0,0 +1,108 @@ +===================== +Python on tvOS README @@ -2606,8 +4744,11 @@ index db00d43da85..6db38253396 100644 + +Using a framework-based Python on tvOS +====================================== +diff --git a/Apple/tvOS/Resources/Info.plist.in b/Apple/tvOS/Resources/Info.plist.in +new file mode 100644 +index 00000000000..ab3050804b8 --- /dev/null -+++ b/tvOS/Resources/Info.plist.in ++++ b/Apple/tvOS/Resources/Info.plist.in @@ -0,0 +1,34 @@ + + @@ -2643,353 +4784,15949 @@ index db00d43da85..6db38253396 100644 + @TVOS_DEPLOYMENT_TARGET@ + + +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar b/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar +new file mode 100755 +index 00000000000..e302748a13c --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-ar ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-ar @@ -0,0 +1,2 @@ +#!/bin/bash +xcrun --sdk appletvos${TVOS_SDK_VERSION} ar "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang b/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang +new file mode 100755 +index 00000000000..7fb6d3d901c --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-clang ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos "$@" ++xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++ +new file mode 100755 +index 00000000000..33bfb1367c3 --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-clang++ ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos "$@" ++xcrun --sdk appletvos${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp b/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp +new file mode 100755 +index 00000000000..641c1bc8d18 --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-cpp ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos -E "$@" ++xcrun --sdk appletvos${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET} -E "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar +new file mode 100755 +index 00000000000..87ef5015aae --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-ar @@ -0,0 +1,2 @@ +#!/bin/bash +xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} ar "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang +new file mode 100755 +index 00000000000..c8719cb0318 --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ +new file mode 100755 +index 00000000000..e3f0e720f7f --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp +new file mode 100755 +index 00000000000..f9a37b72a61 --- /dev/null -+++ b/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos-simulator -E "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target arm64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip +new file mode 100755 +index 00000000000..a8cce95233e --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-simulator-strip @@ -0,0 +1,2 @@ -+#!/bin/bash ++#!/bin/sh ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip b/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip +new file mode 100755 +index 00000000000..ee1d2b95ff1 +--- /dev/null ++++ b/Apple/tvOS/Resources/bin/arm64-apple-tvos-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${TVOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar +new file mode 100755 +index 00000000000..87ef5015aae +--- /dev/null ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash +xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} ar "$@" +diff --git a/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang +new file mode 100755 +index 00000000000..ea0cc26cbd9 --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ +new file mode 100755 +index 00000000000..f18f3603169 --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-clang++ @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target x86_64-apple-tvos-simulator "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang++ -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp +new file mode 100755 +index 00000000000..b98054d1ce2 --- /dev/null -+++ b/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-cpp @@ -0,0 +1,2 @@ +#!/bin/bash -+xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos-simulator -E "$@" ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} clang -target x86_64-apple-tvos${TVOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-strip b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-strip +new file mode 100755 +index 00000000000..f6a884b4aef --- /dev/null -+++ b/tvOS/Resources/dylib-Info-template.plist -@@ -0,0 +1,26 @@ ++++ b/Apple/tvOS/Resources/bin/x86_64-apple-tvos-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk appletvsimulator${TVOS_SDK_VERSION} strip -arch x86_64 "$@" +diff --git a/Apple/tvOS/Resources/pyconfig.h b/Apple/tvOS/Resources/pyconfig.h +new file mode 100644 +index 00000000000..4acff2c6051 +--- /dev/null ++++ b/Apple/tvOS/Resources/pyconfig.h +@@ -0,0 +1,7 @@ ++#ifdef __arm64__ ++#include "pyconfig-arm64.h" ++#endif ++ ++#ifdef __x86_64__ ++#include "pyconfig-x86_64.h" ++#endif +diff --git a/Apple/watchOS/README.rst b/Apple/watchOS/README.rst +new file mode 100644 +index 00000000000..35221478452 +--- /dev/null ++++ b/Apple/watchOS/README.rst +@@ -0,0 +1,108 @@ ++======================== ++Python on watchOS README ++======================== ++ ++:Authors: ++ Russell Keith-Magee (2023-11) ++ ++This document provides a quick overview of some watchOS specific features in the ++Python distribution. ++ ++Compilers for building on watchOS ++================================= ++ ++Building for watchOS requires the use of Apple's Xcode tooling. It is strongly ++recommended that you use the most recent stable release of Xcode, on the ++most recently released macOS. ++ ++watchOS specific arguments to configure ++======================================= ++ ++* ``--enable-framework[=DIR]`` ++ ++ This argument specifies the location where the Python.framework will ++ be installed. ++ ++* ``--with-framework-name=NAME`` ++ ++ Specify the name for the python framework, defaults to ``Python``. ++ ++ ++Building and using Python on watchOS ++==================================== ++ ++ABIs and Architectures ++---------------------- ++ ++watchOS apps can be deployed on physical devices, and on the watchOS simulator. ++Although the API used on these devices is identical, the ABI is different - you ++need to link against different libraries for an watchOS device build ++(``watchos``) or an watchOS simulator build (``watchsimulator``). Apple uses the ++XCframework format to allow specifying a single dependency that supports ++multiple ABIs. An XCframework is a wrapper around multiple ABI-specific ++frameworks. ++ ++watchOS can also support different CPU architectures within each ABI. At present, ++there is only a single support ed architecture on physical devices - ARM64. ++However, the *simulator* supports 2 architectures - ARM64 (for running on Apple ++Silicon machines), and x86_64 (for running on older Intel-based machines.) ++ ++To support multiple CPU architectures on a single platform, Apple uses a "fat ++binary" format - a single physical file that contains support for multiple ++architectures. ++ ++How do I build Python for watchOS? ++------------------------------- ++ ++The Python build system will build a ``Python.framework`` that supports a ++*single* ABI with a *single* architecture. If you want to use Python in an watchOS ++project, you need to: ++ ++1. Produce multiple ``Python.framework`` builds, one for each ABI and architecture; ++2. Merge the binaries for each architecture on a given ABI into a single "fat" binary; ++3. Merge the "fat" frameworks for each ABI into a single XCframework. ++ ++watchOS builds of Python *must* be constructed as framework builds. To support this, ++you must provide the ``--enable-framework`` flag when configuring the build. ++ ++The build also requires the use of cross-compilation. The commands for building ++Python for watchOS will look somethign like:: ++ ++ $ ./configure \ ++ --enable-framework=/path/to/install \ ++ --host=aarch64-apple-watchos \ ++ --build=aarch64-apple-darwin \ ++ --with-build-python=/path/to/python.exe ++ $ make ++ $ make install ++ ++In this invocation: ++ ++* ``/path/to/install`` is the location where the final Python.framework will be ++ output. ++ ++* ``--host`` is the architecture and ABI that you want to build, in GNU compiler ++ triple format. This will be one of: ++ ++ - ``arm64_32-apple-watchos`` for ARM64-32 watchOS devices. ++ - ``aarch64-apple-watchos-simulator`` for the watchOS simulator running on Apple ++ Silicon devices. ++ - ``x86_64-apple-watchos-simulator`` for the watchOS simulator running on Intel ++ devices. ++ ++* ``--build`` is the GNU compiler triple for the machine that will be running ++ the compiler. This is one of: ++ ++ - ``aarch64-apple-darwin`` for Apple Silicon devices. ++ - ``x86_64-apple-darwin`` for Intel devices. ++ ++* ``/path/to/python.exe`` is the path to a Python binary on the machine that ++ will be running the compiler. This is needed because the Python compilation ++ process involves running some Python code. On a normal desktop build of ++ Python, you can compile a python interpreter and then use that interpreter to ++ run Python code. However, the binaries produced for watchOS won't run on macOS, so ++ you need to provide an external Python interpreter. This interpreter must be ++ the version as the Python that is being compiled. ++ ++Using a framework-based Python on watchOS ++====================================== +diff --git a/Apple/watchOS/Resources/Info.plist.in b/Apple/watchOS/Resources/Info.plist.in +new file mode 100644 +index 00000000000..e83ddfd2a43 +--- /dev/null ++++ b/Apple/watchOS/Resources/Info.plist.in +@@ -0,0 +1,34 @@ + -+ -+ ++ ++ + + CFBundleDevelopmentRegion + en + CFBundleExecutable -+ ++ Python ++ CFBundleGetInfoString ++ Python Runtime and Library + CFBundleIdentifier -+ ++ @PYTHONFRAMEWORKIDENTIFIER@ + CFBundleInfoDictionaryVersion + 6.0 ++ CFBundleName ++ Python + CFBundlePackageType -+ APPL ++ FMWK + CFBundleShortVersionString -+ 1.0 ++ %VERSION% ++ CFBundleLongVersionString ++ %VERSION%, (c) 2001-2023 Python Software Foundation. ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ %VERSION% + CFBundleSupportedPlatforms + -+ tvOS ++ watchOS + + MinimumOSVersion -+ 9.0 -+ CFBundleVersion -+ 1 ++ @WATCHOS_DEPLOYMENT_TARGET@ + + +diff --git a/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar +new file mode 100755 +index 00000000000..dda2b211bd5 --- /dev/null -+++ b/tvOS/Resources/pyconfig.h -@@ -0,0 +1,7 @@ ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang +new file mode 100755 +index 00000000000..fe834d3efe4 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ +new file mode 100755 +index 00000000000..757f3a26d8f +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp +new file mode 100755 +index 00000000000..fdb57d9e010 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator clang -target arm64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip +new file mode 100755 +index 00000000000..e28e3f7597a +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip b/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip +new file mode 100755 +index 00000000000..efe5a1260ad +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64-apple-watchos-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar +new file mode 100755 +index 00000000000..029f9a32073 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} ar "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang +new file mode 100755 +index 00000000000..285036d4010 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ +new file mode 100755 +index 00000000000..c8f60ebec51 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang++ -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} "$@" +diff --git a/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp +new file mode 100755 +index 00000000000..b411fc25aa4 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/arm64_32-apple-watchos-cpp +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos${WATCHOS_DEPLOYMENT_TARGET} -E "$@" +diff --git a/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar +new file mode 100755 +index 00000000000..dda2b211bd5 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" +diff --git a/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang +new file mode 100755 +index 00000000000..4776b9b5348 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ +new file mode 100755 +index 00000000000..e9b0c5f4b87 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp +new file mode 100755 +index 00000000000..d3b821c5f7f +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/bash ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos${WATCHOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-strip b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-strip +new file mode 100755 +index 00000000000..105c78281f9 +--- /dev/null ++++ b/Apple/watchOS/Resources/bin/x86_64-apple-watchos-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} strip -arch x86_64 "$@" +diff --git a/Apple/watchOS/Resources/pyconfig.h b/Apple/watchOS/Resources/pyconfig.h +new file mode 100644 +index 00000000000..f842b987b2e +--- /dev/null ++++ b/Apple/watchOS/Resources/pyconfig.h +@@ -0,0 +1,11 @@ +#ifdef __arm64__ ++# ifdef __LP64__ +#include "pyconfig-arm64.h" ++# else ++#include "pyconfig-arm64_32.h" ++# endif +#endif + +#ifdef __x86_64__ +#include "pyconfig-x86_64.h" +#endif ---- /dev/null -+++ b/watchOS/README.rst -@@ -0,0 +1,108 @@ -+======================== -+Python on watchOS README -+======================== +diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst +index 21c19903464..61baa722359 100644 +--- a/Doc/library/importlib.rst ++++ b/Doc/library/importlib.rst +@@ -1466,6 +1466,69 @@ + Boolean indicating whether or not the module's "origin" + attribute refers to a loadable location. + ++.. class:: AppleFrameworkLoader(name, path) ++ ++ A specialization of :class:`importlib.machinery.ExtensionFileLoader` that ++ is able to load extension modules in Framework format. ++ ++ For compatibility with the iOS App Store, *all* binary modules in an iOS app ++ must be dynamic libraries, contained in a framework with appropriate ++ metadata, stored in the ``Frameworks`` folder of the packaged app. There can ++ be only a single binary per framework, and there can be no executable binary ++ material outside the Frameworks folder. ++ ++ To accomodate this requirement, when running on iOS, extension module ++ binaries are *not* packaged as ``.so`` files on ``sys.path``, but as ++ individual standalone frameworks. To discover those frameworks, this loader ++ is be registered against the ``.fwork`` file extension, with a ``.fwork`` ++ file acting as a placeholder in the original location of the binary on ++ ``sys.path``. The ``.fwork`` file contains the path of the actual binary in ++ the ``Frameworks`` folder, relative to the app bundle. To allow for ++ resolving a framework-packaged binary back to the original location, the ++ framework is expected to contain a ``.origin`` file that contains the ++ location of the ``.fwork`` file, relative to the app bundle. ++ ++ For example, consider the case of an import ``from foo.bar import _whiz``, ++ where ``_whiz`` is implemented with the binary module ++ ``sources/foo/bar/_whiz.abi3.so``, with ``sources`` being the location ++ registered on ``sys.path``, relative to the application bundle. This module ++ *must* be distributed as ++ ``Frameworks/foo.bar._whiz.framework/foo.bar._whiz`` (creating the framework ++ name from the full import path of the module), with an ``Info.plist`` file ++ in the ``.framework`` directory identifying the binary as a framework. The ++ ``foo.bar._whiz`` module would be represented in the original location with ++ a ``sources/foo/bar/_whiz.abi3.fwork`` marker file, containing the path ++ ``Frameworks/foo.bar._whiz/foo.bar._whiz``. The framework would also contain ++ ``Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin``, containing the ++ path to the ``.fwork`` file. ++ ++ When a module is loaded with this loader, the ``__file__`` for the module ++ will report as the location of the ``.fwork`` file. This allows code to use ++ the ``__file__`` of a module as an anchor for file system traveral. ++ However, the spec origin will reference the location of the *actual* binary ++ in the ``.framework`` folder. ++ ++ The Xcode project building the app is responsible for converting any ``.so`` ++ files from wherever they exist in the ``PYTHONPATH`` into frameworks in the ++ ``Frameworks`` folder (including stripping extensions from the module file, ++ the addition of framework metadata, and signing the resulting framework), ++ and creating the ``.fwork`` and ``.origin`` files. This will usually be done ++ with a build step in the Xcode project; see the iOS documentation for ++ details on how to construct this build step. ++ ++ .. versionadded:: 3.13 ++ ++ .. availability:: iOS. ++ ++ .. attribute:: name ++ ++ Name of the module the loader supports. ++ ++ .. attribute:: path ++ ++ Path to the ``.fwork`` file for the extension module. ++ ++ + :mod:`importlib.util` -- Utility code for importers + --------------------------------------------------- + +diff --git a/Doc/library/os.rst b/Doc/library/os.rst +index 8405fb1917e..79db1891a1a 100644 +--- a/Doc/library/os.rst ++++ b/Doc/library/os.rst +@@ -710,6 +710,11 @@ + :func:`socket.gethostname` or even + ``socket.gethostbyaddr(socket.gethostname())``. + ++ On macOS, iOS and Android, this returns the *kernel* name and version (i.e., ++ ``'Darwin'`` on macOS and iOS; ``'Linux'`` on Android). :func:`platform.uname()` ++ can be used to get the user-facing operating system name and version on iOS and ++ Android. + -+:Authors: -+ Russell Keith-Magee (2023-11) + .. availability:: recent flavors of Unix. + + .. versionchanged:: 3.3 +diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst +index dc2d871b47d..57dc421bb6c 100644 +--- a/Doc/library/platform.rst ++++ b/Doc/library/platform.rst +@@ -148,6 +148,9 @@ + Returns the system/OS name, such as ``'Linux'``, ``'Darwin'``, ``'Java'``, + ``'Windows'``. An empty string is returned if the value cannot be determined. + ++ On iOS and Android, this returns the user-facing OS name (i.e, ``'iOS``, ++ ``'iPadOS'`` or ``'Android'``). To obtain the kernel name (``'Darwin'`` or ++ ``'Linux'``), use :func:`os.uname()`. + + .. function:: system_alias(system, release, version) + +@@ -161,6 +164,8 @@ + Returns the system's release version, e.g. ``'#3 on degas'``. An empty string is + returned if the value cannot be determined. + ++ On iOS and Android, this is the user-facing OS version. To obtain the ++ Darwin or Linux kernel version, use :func:`os.uname()`. + + .. function:: uname() + +@@ -230,7 +235,6 @@ + macOS Platform + -------------- + +- + .. function:: mac_ver(release='', versioninfo=('','',''), machine='') + + Get macOS version information and return it as tuple ``(release, versioninfo, +@@ -240,6 +244,24 @@ + Entries which cannot be determined are set to ``''``. All tuple entries are + strings. + ++iOS Platform ++------------ + -+This document provides a quick overview of some watchOS specific features in the -+Python distribution. ++.. function:: ios_ver(system='', release='', model='', is_simulator=False) + -+Compilers for building on watchOS -+================================= ++ Get iOS version information and return it as a ++ :func:`~collections.namedtuple` with the following attributes: + -+Building for watchOS requires the use of Apple's Xcode tooling. It is strongly -+recommended that you use the most recent stable release of Xcode, on the -+most recently released macOS. ++ * ``system`` is the OS name; either ``'iOS'`` or ``'iPadOS'``. ++ * ``release`` is the iOS version number as a string (e.g., ``'17.2'``). ++ * ``model`` is the device model identifier; this will be a string like ++ ``'iPhone13,2'`` for a physical device, or ``'iPhone'`` on a simulator. ++ * ``is_simulator`` is a boolean describing if the app is running on a ++ simulator or a physical device. ++ ++ Entries which cannot be determined are set to the defaults given as ++ parameters. ++ + + Unix Platforms + -------------- +diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst +index 1e85602951c..8f5af980dee 100644 +--- a/Doc/library/urllib.parse.rst ++++ b/Doc/library/urllib.parse.rst +@@ -27,6 +27,14 @@ + ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``, ``telnet``, + ``wais``, ``ws``, ``wss``. + ++.. impl-detail:: ++ ++ The inclusion of the ``itms-services`` URL scheme can prevent an app from ++ passing Apple's App Store review process for the macOS and iOS App Stores. ++ Handling for the ``itms-services`` scheme is always removed on iOS; on ++ macOS, it *may* be removed if CPython has been built with the ++ :option:`--with-app-store-compliance` option. ++ + The :mod:`urllib.parse` module defines functions that fall into two broad + categories: URL parsing and URL quoting. These are covered in detail in + the following sections. +diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst +index c0990882e58..e5cc007d2b8 100644 +--- a/Doc/library/webbrowser.rst ++++ b/Doc/library/webbrowser.rst +@@ -33,6 +33,13 @@ + browsers are not available on Unix, the controlling process will launch a new + browser and wait. + ++On iOS, the :envvar:`BROWSER` environment variable, as well as any arguments ++controlling autoraise, browser preference, and new tab/window creation will be ++ignored. Web pages will *always* be opened in the user's preferred browser, in ++a new tab, with the browser being brought to the foreground. The use of the ++:mod:`webbrowser` module on iOS requires the :mod:`ctypes` module. If ++:mod:`ctypes` isn't available, calls to :func:`.open` will fail. ++ + The script :program:`webbrowser` can be used as a command-line interface for the + module. It accepts a URL as the argument. It accepts the following optional + parameters: ``-n`` opens the URL in a new browser window, if possible; +@@ -155,6 +162,8 @@ + +------------------------+-----------------------------------------+-------+ + | ``'chromium-browser'`` | :class:`Chromium('chromium-browser')` | | + +------------------------+-----------------------------------------+-------+ ++| ``'iosbrowser'`` | ``IOSBrowser`` | \(4) | +++------------------------+-----------------------------------------+-------+ + + Notes: + +@@ -169,11 +178,18 @@ + Only on Windows platforms. + + (3) +- Only on macOS platform. ++ Only on macOS. ++ ++(4) ++ Only on iOS. ++ + + .. versionadded:: 3.3 + Support for Chrome/Chromium has been added. + ++.. versionchanged:: 3.13 ++ Support for iOS has been added. ++ + Here are some simple examples:: + + url = 'https://docs.python.org/' +diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst +index ab33e0a06f5..6fe63e9ce2d 100644 +--- a/Doc/using/configure.rst ++++ b/Doc/using/configure.rst +@@ -506,6 +506,75 @@ + Specify the name for the python framework on macOS only valid when + :option:`--enable-framework` is set (default: ``Python``). + ++.. option:: --with-app-store-compliance ++.. option:: --with-app-store-compliance=PATCH-FILE ++ ++ The Python standard library contains strings that are known to trigger ++ automated inspection tool errors when submitted for distribution by ++ the macOS and iOS App Stores. If enabled, this option will apply the list of ++ patches that are known to correct app store compliance. A custom patch ++ file can also be specified. This option is disabled by default. ++ ++ .. versionadded:: 3.13 ++ ++iOS Options ++----------- ++ ++See :source:`iOS/README.rst`. ++ ++.. option:: --enable-framework=INSTALLDIR ++ ++ Create a Python.framework. Unlike macOS, the *INSTALLDIR* argument ++ specifying the installation path is mandatory. ++ ++.. option:: --with-framework-name=FRAMEWORK ++ ++ Specify the name for the framework (default: ``Python``). ++ ++ ++Cross Compiling Options ++----------------------- ++ ++Cross compiling, also known as cross building, can be used to build Python ++for another CPU architecture or platform. Cross compiling requires a Python ++interpreter for the build platform. The version of the build Python must match ++the version of the cross compiled host Python. ++ ++.. option:: --build=BUILD ++ ++ configure for building on BUILD, usually guessed by :program:`config.guess`. ++ ++.. option:: --host=HOST ++ ++ cross-compile to build programs to run on HOST (target platform) ++ ++.. option:: --with-build-python=path/to/python ++ ++ path to build ``python`` binary for cross compiling ++ ++ .. versionadded:: 3.11 ++ ++.. option:: CONFIG_SITE=file ++ ++ An environment variable that points to a file with configure overrides. ++ ++ Example *config.site* file: ++ ++ .. code-block:: ini ++ ++ # config.site-aarch64 ++ ac_cv_buggy_getaddrinfo=no ++ ac_cv_file__dev_ptmx=yes ++ ac_cv_file__dev_ptc=no ++ ++ ++Cross compiling example:: ++ ++ CONFIG_SITE=config.site-aarch64 ../configure \ ++ --build=x86_64-pc-linux-gnu \ ++ --host=aarch64-unknown-linux-gnu \ ++ --with-build-python=../x86_64/python ++ + + Python Build System + =================== +diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst +index 9ae0270eaee..2bb14d88dc9 100644 +--- a/Doc/using/mac.rst ++++ b/Doc/using/mac.rst +@@ -164,6 +164,28 @@ + at https://pypi.org/project/py2app/. + + ++App Store Compliance ++-------------------- ++ ++Apps submitted for distribution through the macOS App Store must pass Apple's ++app review process. This process includes a set of automated validation rules ++that inspect the submitted application bundle for problematic code. ++ ++The Python standard library contains some code that is known to violate these ++automated rules. While these violations appear to be false positives, Apple's ++review rules cannot be challenged. Therefore, it is necessary to modify the ++Python standard library for an app to pass App Store review. ++ ++The Python source tree contains ++:source:`a patch file ` that will remove ++all code that is known to cause issues with the App Store review process. This ++patch is applied automatically when CPython is configured with the ++:option:`--with-app-store-compliance` option. ++ ++This patch is not normally required to use CPython on a Mac; nor is it required ++if you are distributing an app *outside* the macOS App Store. It is *only* ++required if you are using the macOS App Store as a distribution channel. ++ + Other Resources + =============== + +diff --git a/Lib/_apple_support.py b/Lib/_apple_support.py +new file mode 100644 +index 00000000000..92febdcf587 +--- /dev/null ++++ b/Lib/_apple_support.py +@@ -0,0 +1,66 @@ ++import io ++import sys ++ ++ ++def init_streams(log_write, stdout_level, stderr_level): ++ # Redirect stdout and stderr to the Apple system log. This method is ++ # invoked by init_apple_streams() (initconfig.c) if config->use_system_logger ++ # is enabled. ++ sys.stdout = SystemLog(log_write, stdout_level, errors=sys.stderr.errors) ++ sys.stderr = SystemLog(log_write, stderr_level, errors=sys.stderr.errors) ++ ++ ++class SystemLog(io.TextIOWrapper): ++ def __init__(self, log_write, level, **kwargs): ++ kwargs.setdefault("encoding", "UTF-8") ++ kwargs.setdefault("line_buffering", True) ++ super().__init__(LogStream(log_write, level), **kwargs) ++ ++ def __repr__(self): ++ return f"" ++ ++ def write(self, s): ++ if not isinstance(s, str): ++ raise TypeError( ++ f"write() argument must be str, not {type(s).__name__}") ++ ++ # In case `s` is a str subclass that writes itself to stdout or stderr ++ # when we call its methods, convert it to an actual str. ++ s = str.__str__(s) ++ ++ # We want to emit one log message per line, so split ++ # the string before sending it to the superclass. ++ for line in s.splitlines(keepends=True): ++ super().write(line) ++ ++ return len(s) ++ ++ ++class LogStream(io.RawIOBase): ++ def __init__(self, log_write, level): ++ self.log_write = log_write ++ self.level = level ++ ++ def __repr__(self): ++ return f"" ++ ++ def writable(self): ++ return True ++ ++ def write(self, b): ++ if type(b) is not bytes: ++ try: ++ b = bytes(memoryview(b)) ++ except TypeError: ++ raise TypeError( ++ f"write() argument must be bytes-like, not {type(b).__name__}" ++ ) from None ++ ++ # Writing an empty string to the stream should have no effect. ++ if b: ++ # Encode null bytes using "modified UTF-8" to avoid truncating the ++ # message. This should not affect the return value, as the caller ++ # may be expecting it to match the length of the input. ++ self.log_write(self.level, b.replace(b"\x00", b"\xc0\x80")) ++ ++ return len(b) +diff --git a/Lib/_ios_support.py b/Lib/_ios_support.py +new file mode 100644 +index 00000000000..db3fe23e45b +--- /dev/null ++++ b/Lib/_ios_support.py +@@ -0,0 +1,71 @@ ++import sys ++try: ++ from ctypes import cdll, c_void_p, c_char_p, util ++except ImportError: ++ # ctypes is an optional module. If it's not present, we're limited in what ++ # we can tell about the system, but we don't want to prevent the module ++ # from working. ++ print("ctypes isn't available; iOS system calls will not be available") ++ objc = None ++else: ++ # ctypes is available. Load the ObjC library, and wrap the objc_getClass, ++ # sel_registerName methods ++ lib = util.find_library("objc") ++ if lib is None: ++ # Failed to load the objc library ++ raise RuntimeError("ObjC runtime library couldn't be loaded") ++ ++ objc = cdll.LoadLibrary(lib) ++ objc.objc_getClass.restype = c_void_p ++ objc.objc_getClass.argtypes = [c_char_p] ++ objc.sel_registerName.restype = c_void_p ++ objc.sel_registerName.argtypes = [c_char_p] ++ ++ ++def get_platform_ios(): ++ # Determine if this is a simulator using the multiarch value ++ is_simulator = sys.implementation._multiarch.endswith("simulator") ++ ++ # We can't use ctypes; abort ++ if not objc: ++ return None ++ ++ # Most of the methods return ObjC objects ++ objc.objc_msgSend.restype = c_void_p ++ # All the methods used have no arguments. ++ objc.objc_msgSend.argtypes = [c_void_p, c_void_p] ++ ++ # Equivalent of: ++ # device = [UIDevice currentDevice] ++ UIDevice = objc.objc_getClass(b"UIDevice") ++ SEL_currentDevice = objc.sel_registerName(b"currentDevice") ++ device = objc.objc_msgSend(UIDevice, SEL_currentDevice) ++ ++ # Equivalent of: ++ # device_systemVersion = [device systemVersion] ++ SEL_systemVersion = objc.sel_registerName(b"systemVersion") ++ device_systemVersion = objc.objc_msgSend(device, SEL_systemVersion) ++ ++ # Equivalent of: ++ # device_systemName = [device systemName] ++ SEL_systemName = objc.sel_registerName(b"systemName") ++ device_systemName = objc.objc_msgSend(device, SEL_systemName) ++ ++ # Equivalent of: ++ # device_model = [device model] ++ SEL_model = objc.sel_registerName(b"model") ++ device_model = objc.objc_msgSend(device, SEL_model) ++ ++ # UTF8String returns a const char*; ++ SEL_UTF8String = objc.sel_registerName(b"UTF8String") ++ objc.objc_msgSend.restype = c_char_p ++ ++ # Equivalent of: ++ # system = [device_systemName UTF8String] ++ # release = [device_systemVersion UTF8String] ++ # model = [device_model UTF8String] ++ system = objc.objc_msgSend(device_systemName, SEL_UTF8String).decode() ++ release = objc.objc_msgSend(device_systemVersion, SEL_UTF8String).decode() ++ model = objc.objc_msgSend(device_model, SEL_UTF8String).decode() ++ ++ return system, release, model, is_simulator +diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py +index 4afa4ebd422..dca2081bea4 100644 +--- a/Lib/ctypes/__init__.py ++++ b/Lib/ctypes/__init__.py +@@ -341,6 +341,19 @@ + use_errno=False, + use_last_error=False, + winmode=None): ++ if name: ++ name = _os.fspath(name) ++ ++ # If the filename that has been provided is an iOS/tvOS/watchOS ++ # .fwork file, dereference the location to the true origin of the ++ # binary. ++ if name.endswith(".fwork"): ++ with open(name) as f: ++ name = _os.path.join( ++ _os.path.dirname(_sys.executable), ++ f.read().strip() ++ ) ++ + self._name = name + flags = self._func_flags_ + if use_errno: +diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py +index 0c2510e1619..438f2713563 100644 +--- a/Lib/ctypes/util.py ++++ b/Lib/ctypes/util.py +@@ -67,7 +67,7 @@ + return fname + return None + +-elif os.name == "posix" and sys.platform == "darwin": ++elif os.name == "posix" and sys.platform in {"darwin", "ios", "tvos", "watchos"}: + from ctypes.macholib.dyld import dyld_find as _dyld_find + def find_library(name): + possible = ['lib%s.dylib' % name, +diff --git a/Lib/distutils/tests/test_cygwinccompiler.py b/Lib/distutils/tests/test_cygwinccompiler.py +index 9dc869de4c8..646b24faa86 100644 +--- a/Lib/distutils/tests/test_cygwinccompiler.py ++++ b/Lib/distutils/tests/test_cygwinccompiler.py +@@ -5,6 +5,9 @@ + from io import BytesIO + from test.support import run_unittest + ++if sys.platform != 'win32': ++ raise unittest.SkipTest("Cygwin tests only needed on Windows") ++ + from distutils import cygwinccompiler + from distutils.cygwinccompiler import (check_config_h, + CONFIG_H_OK, CONFIG_H_NOTOK, +diff --git a/Lib/distutils/tests/test_sysconfig.py b/Lib/distutils/tests/test_sysconfig.py +index 59676b0e0b0..ba7bb5b7693 100644 +--- a/Lib/distutils/tests/test_sysconfig.py ++++ b/Lib/distutils/tests/test_sysconfig.py +@@ -10,7 +10,7 @@ + from distutils import sysconfig + from distutils.ccompiler import get_default_compiler + from distutils.tests import support +-from test.support import run_unittest, swap_item ++from test.support import is_apple_mobile, requires_subprocess, run_unittest, swap_item + from test.support.os_helper import TESTFN + from test.support.warnings_helper import check_warnings + +@@ -32,6 +32,7 @@ + elif os.path.isdir(TESTFN): + shutil.rmtree(TESTFN) + ++ @unittest.skipIf(is_apple_mobile, "Header files not distributed with Apple mobile") + def test_get_config_h_filename(self): + config_h = sysconfig.get_config_h_filename() + self.assertTrue(os.path.isfile(config_h), config_h) +@@ -48,6 +49,7 @@ + self.assertIsInstance(cvars, dict) + self.assertTrue(cvars) + ++ @unittest.skipIf(is_apple_mobile, "Header files not distributed with Apple mobile") + def test_srcdir(self): + # See Issues #15322, #15364. + srcdir = sysconfig.get_config_var('srcdir') +@@ -247,6 +249,7 @@ + self.assertIsNotNone(vars['SO']) + self.assertEqual(vars['SO'], vars['EXT_SUFFIX']) + ++ @requires_subprocess() + def test_customize_compiler_before_get_config_vars(self): + # Issue #21923: test that a Distribution compiler + # instance can be called without an explicit call to +diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py +index d00c48981eb..5d12b4779db 100644 +--- a/Lib/distutils/unixccompiler.py ++++ b/Lib/distutils/unixccompiler.py +@@ -270,9 +270,9 @@ + static_f = self.library_filename(lib, lib_type='static') + + if sys.platform == 'darwin': +- # On OSX users can specify an alternate SDK using +- # '-isysroot', calculate the SDK root if it is specified +- # (and use it further on) ++ # On macOS users can specify an alternate SDK using ++ # '-isysroot ' or --sysroot=, calculate the SDK root ++ # if it is specified (and use it further on) + # + # Note that, as of Xcode 7, Apple SDKs may contain textual stub + # libraries with .tbd extensions rather than the normal .dylib +@@ -291,12 +291,14 @@ + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s*(\S+)', cflags) + if m is None: +- sysroot = _osx_support._default_sysroot(sysconfig.get_config_var('CC')) ++ m = re.search(r'--sysroot=(\S+)', cflags) ++ if m is None: ++ sysroot = _osx_support._default_sysroot(sysconfig.get_config_var('CC')) ++ else: ++ sysroot = m.group(1) + else: + sysroot = m.group(1) + +- +- + for dir in dirs: + shared = os.path.join(dir, shared_f) + dylib = os.path.join(dir, dylib_f) +diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py +index 2ce5c5b64d6..e927f4af938 100644 +--- a/Lib/distutils/util.py ++++ b/Lib/distutils/util.py +@@ -89,10 +89,25 @@ + if m: + release = m.group() + elif osname[:6] == "darwin": +- import _osx_support, distutils.sysconfig +- osname, release, machine = _osx_support.get_platform_osx( +- distutils.sysconfig.get_config_vars(), +- osname, release, machine) ++ import distutils.sysconfig ++ config_vars = distutils.sysconfig.get_config_vars() ++ if sys.platform == "ios": ++ release = config_vars.get("IPHONEOS_DEPLOYMENT_TARGET", "13.0") ++ osname = sys.platform ++ machine = sys.implementation._multiarch ++ elif sys.platform == "tvos": ++ release = config_vars.get("TVOS_DEPLOYMENT_TARGET", "9.0") ++ osname = sys.platform ++ machine = sys.implementation._multiarch ++ elif sys.platform == "watchos": ++ release = config_vars.get("WATCHOS_DEPLOYMENT_TARGET", "4.0") ++ osname = sys.platform ++ machine = sys.implementation._multiarch ++ else: ++ import _osx_support ++ osname, release, machine = _osx_support.get_platform_osx( ++ config_vars, ++ osname, release, machine) + + return "%s-%s-%s" % (osname, release, machine) + +@@ -170,7 +185,7 @@ + if _environ_checked: + return + +- if os.name == 'posix' and 'HOME' not in os.environ: ++ if os.name == 'posix' and 'HOME' not in os.environ and sys.platform not in {"ios", "tvos", "watchos"}: + try: + import pwd + os.environ['HOME'] = pwd.getpwuid(os.getuid())[5] +diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py +index 49bcaea78d7..94052fc72e4 100644 +--- a/Lib/importlib/_bootstrap_external.py ++++ b/Lib/importlib/_bootstrap_external.py +@@ -52,7 +52,7 @@ + + # Bootstrap-related code ###################################################### + _CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win', +-_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin' ++_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'watchos' + _CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY + + _CASE_INSENSITIVE_PLATFORMS_STR_KEY) + +@@ -1637,6 +1637,46 @@ + return 'FileFinder({!r})'.format(self.path) + + ++class AppleFrameworkLoader(ExtensionFileLoader): ++ """A loader for modules that have been packaged as frameworks for ++ compatibility with Apple's iOS App Store policies. ++ """ ++ def create_module(self, spec): ++ # If the ModuleSpec has been created by the FileFinder, it will have ++ # been created with an origin pointing to the .fwork file. We need to ++ # redirect this to the location in the Frameworks folder, using the ++ # content of the .fwork file. ++ if spec.origin.endswith(".fwork"): ++ with _io.FileIO(spec.origin, 'r') as file: ++ framework_binary = file.read().decode().strip() ++ bundle_path = _path_split(sys.executable)[0] ++ spec.origin = _path_join(bundle_path, framework_binary) ++ ++ # If the loader is created based on the spec for a loaded module, the ++ # path will be pointing at the Framework location. If this occurs, ++ # get the original .fwork location to use as the module's __file__. ++ if self.path.endswith(".fwork"): ++ path = self.path ++ else: ++ with _io.FileIO(self.path + ".origin", 'r') as file: ++ origin = file.read().decode().strip() ++ bundle_path = _path_split(sys.executable)[0] ++ path = _path_join(bundle_path, origin) ++ ++ module = _bootstrap._call_with_frames_removed(_imp.create_dynamic, spec) ++ ++ _bootstrap._verbose_message( ++ "Apple framework extension module {!r} loaded from {!r} (path {!r})", ++ spec.name, ++ spec.origin, ++ path, ++ ) ++ ++ # Ensure that the __file__ points at the .fwork location ++ module.__file__ = path ++ ++ return module ++ + # Import setup ############################################################### + + def _fix_up_module(ns, name, pathname, cpathname=None): +@@ -1667,10 +1707,17 @@ + + Each item is a tuple (loader, suffixes). + """ +- extensions = ExtensionFileLoader, _imp.extension_suffixes() ++ if sys.platform in {"ios", "tvos", "watchos"}: ++ extension_loaders = [(AppleFrameworkLoader, [ ++ suffix.replace(".so", ".fwork") ++ for suffix in _imp.extension_suffixes() ++ ])] ++ else: ++ extension_loaders = [] ++ extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes())) + source = SourceFileLoader, SOURCE_SUFFIXES + bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES +- return [extensions, source, bytecode] ++ return extension_loaders + [source, bytecode] + + + def _set_bootstrap_module(_bootstrap_module): +diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py +index 0b4a3f80717..5c97d45d2fc 100644 +--- a/Lib/importlib/abc.py ++++ b/Lib/importlib/abc.py +@@ -250,7 +250,11 @@ + else: + return self.source_to_code(source, path) + +-_register(ExecutionLoader, machinery.ExtensionFileLoader) ++_register( ++ ExecutionLoader, ++ machinery.ExtensionFileLoader, ++ machinery.AppleFrameworkLoader, ++) + + + class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader): +diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py +index 9a7757fb6e4..cdf6385ea98 100644 +--- a/Lib/importlib/machinery.py ++++ b/Lib/importlib/machinery.py +@@ -12,7 +12,11 @@ + from ._bootstrap_external import SourceFileLoader + from ._bootstrap_external import SourcelessFileLoader + from ._bootstrap_external import ExtensionFileLoader +- ++try: ++ # For cross-build purposes, allow this import to fail ++ from ._bootstrap_external import AppleFrameworkLoader ++except ImportError: ++ pass + + def all_suffixes(): + """Returns a list of all recognized module suffixes for this process""" +diff --git a/Lib/inspect.py b/Lib/inspect.py +index 2999a6019e0..d28a98539d5 100644 +--- a/Lib/inspect.py ++++ b/Lib/inspect.py +@@ -853,6 +853,7 @@ + return object + if hasattr(object, '__module__'): + return sys.modules.get(object.__module__) ++ + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) +@@ -946,7 +947,7 @@ + # Allow filenames in form of "" to pass through. + # `doctest` monkeypatches `linecache` module to enable + # inspection, so let `linecache.getlines` to be called. +- if not (file.startswith('<') and file.endswith('>')): ++ if (not (file.startswith('<') and file.endswith('>'))) or file.endswith('.fwork'): + raise OSError('source code not available') + + module = getmodule(object, file) +diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py +index 90a1b34b5ff..2e07663de43 100644 +--- a/Lib/lib2to3/tests/test_parser.py ++++ b/Lib/lib2to3/tests/test_parser.py +@@ -62,6 +62,7 @@ + shutil.rmtree(tmpdir) + + @unittest.skipIf(sys.executable is None, 'sys.executable required') ++ @test.support.requires_subprocess() + def test_load_grammar_from_subprocess(self): + tmpdir = tempfile.mkdtemp() + tmpsubdir = os.path.join(tmpdir, 'subdir') +diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py +index cb455f40c4d..55a4c78e768 100644 +--- a/Lib/modulefinder.py ++++ b/Lib/modulefinder.py +@@ -80,7 +80,12 @@ + if isinstance(spec.loader, importlib.machinery.SourceFileLoader): + kind = _PY_SOURCE + +- elif isinstance(spec.loader, importlib.machinery.ExtensionFileLoader): ++ elif isinstance( ++ spec.loader, ( ++ importlib.machinery.ExtensionFileLoader, ++ importlib.machinery.AppleFrameworkLoader, ++ ) ++ ): + kind = _C_EXTENSION + + elif isinstance(spec.loader, importlib.machinery.SourcelessFileLoader): +diff --git a/Lib/platform.py b/Lib/platform.py +index 6a820c90a1a..28bd77fcf3d 100755 +--- a/Lib/platform.py ++++ b/Lib/platform.py +@@ -449,6 +449,78 @@ + # If that also doesn't work return the default values + return release, versioninfo, machine + ++ ++# A namedtuple for iOS version information. ++IOSVersionInfo = collections.namedtuple( ++ "IOSVersionInfo", ++ ["system", "release", "model", "is_simulator"] ++) ++ ++ ++def ios_ver(system="", release="", model="", is_simulator=False): ++ """Get iOS version information, and return it as a namedtuple: ++ (system, release, model, is_simulator). ++ ++ If values can't be determined, they are set to values provided as ++ parameters. ++ """ ++ if sys.platform == "ios": ++ import _ios_support ++ result = _ios_support.get_platform_ios() ++ if result is not None: ++ return IOSVersionInfo(*result) ++ ++ return IOSVersionInfo(system, release, model, is_simulator) ++ ++ ++# A namedtuple for tvOS version information. ++TVOSVersionInfo = collections.namedtuple( ++ "TVOSVersionInfo", ++ ["system", "release", "model", "is_simulator"] ++) ++ ++ ++def tvos_ver(system="", release="", model="", is_simulator=False): ++ """Get tvOS version information, and return it as a namedtuple: ++ (system, release, model, is_simulator). ++ ++ If values can't be determined, they are set to values provided as ++ parameters. ++ """ ++ if sys.platform == "tvos": ++ # TODO: Can the iOS implementation be used here? ++ import _ios_support ++ result = _ios_support.get_platform_ios() ++ if result is not None: ++ return TVOSVersionInfo(*result) ++ ++ return TVOSVersionInfo(system, release, model, is_simulator) ++ ++ ++# A namedtuple for watchOS version information. ++WatchOSVersionInfo = collections.namedtuple( ++ "WatchOSVersionInfo", ++ ["system", "release", "model", "is_simulator"] ++) ++ ++ ++def watchos_ver(system="", release="", model="", is_simulator=False): ++ """Get watchOS version information, and return it as a namedtuple: ++ (system, release, model, is_simulator). ++ ++ If values can't be determined, they are set to values provided as ++ parameters. ++ """ ++ if sys.platform == "watchos": ++ # TODO: Can the iOS implementation be used here? ++ import _ios_support ++ result = _ios_support.get_platform_ios() ++ if result is not None: ++ return WatchOSVersionInfo(*result) ++ ++ return WatchOSVersionInfo(system, release, model, is_simulator) ++ ++ + def _java_getprop(name, default): + + from java.lang import System +@@ -564,7 +636,7 @@ + if cleaned == platform: + break + platform = cleaned +- while platform[-1] == '-': ++ while platform and platform[-1] == '-': + platform = platform[:-1] + + return platform +@@ -605,7 +677,7 @@ + default in case the command should fail. + + """ +- if sys.platform in ('dos', 'win32', 'win16'): ++ if sys.platform in {'dos', 'win32', 'win16', 'ios', 'tvos', 'watchos'}: + # XXX Others too ? + return default + +@@ -744,6 +816,25 @@ + csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0) + return 'Alpha' if cpu_number >= 128 else 'VAX' + ++ # On the iOS/tvOS/watchOS simulator, os.uname returns the architecture as ++ # uname.machine. On device it returns the model name for some reason; but ++ # there's only one CPU architecture for devices, so we know the right ++ # answer. ++ def get_ios(): ++ if sys.implementation._multiarch.endswith("simulator"): ++ return os.uname().machine ++ return 'arm64' ++ ++ def get_tvos(): ++ if sys.implementation._multiarch.endswith("simulator"): ++ return os.uname().machine ++ return 'arm64' ++ ++ def get_watchos(): ++ if sys.implementation._multiarch.endswith("simulator"): ++ return os.uname().machine ++ return 'arm64_32' ++ + def from_subprocess(): + """ + Fall back to `uname -p` +@@ -893,6 +984,14 @@ + system = 'Windows' + release = 'Vista' + ++ # Normalize responses on Apple mobile platforms ++ if sys.platform == 'ios': ++ system, release, _, _ = ios_ver() ++ if sys.platform == 'tvos': ++ system, release, _, _ = tvos_ver() ++ if sys.platform == 'watchos': ++ system, release, _, _ = watchos_ver() ++ + vals = system, node, release, version, machine + # Replace 'unknown' values with the more portable '' + _uname_cache = uname_result(*map(_unknown_as_blank, vals)) +@@ -1205,11 +1304,18 @@ + system, release, version = system_alias(system, release, version) + + if system == 'Darwin': +- # macOS (darwin kernel) +- macos_release = mac_ver()[0] +- if macos_release: +- system = 'macOS' +- release = macos_release ++ # macOS and iOS both report as a "Darwin" kernel ++ if sys.platform == "ios": ++ system, release, _, _ = ios_ver() ++ elif sys.platform == "tvos": ++ system, release, _, _ = tvos_ver() ++ elif sys.platform == "watchos": ++ system, release, _, _ = watchos_ver() ++ else: ++ macos_release = mac_ver()[0] ++ if macos_release: ++ system = 'macOS' ++ release = macos_release + + if system == 'Windows': + # MS platforms +diff --git a/Lib/site.py b/Lib/site.py +index 5302037e0bf..35bf9b03d35 100644 +--- a/Lib/site.py ++++ b/Lib/site.py +@@ -276,8 +276,8 @@ + if env_base: + return env_base + +- # VxWorks has no home directories +- if sys.platform == "vxworks": ++ # iOS, tvOS, VxWorks and watchOS have no home directories ++ if sys.platform in {"ios", "tvos", "vxworks", "watchos"}: + return None + + def joinuser(*args): +diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py +index a764c82b0d3..8b23cd3f733 100644 +--- a/Lib/sqlite3/test/dbapi.py ++++ b/Lib/sqlite3/test/dbapi.py +@@ -26,7 +26,7 @@ + import sqlite3 as sqlite + import sys + +-from test.support import check_disallow_instantiation, SHORT_TIMEOUT ++from test.support import check_disallow_instantiation, SHORT_TIMEOUT, is_apple, requires_subprocess + from test.support.os_helper import TESTFN, unlink + + +@@ -87,7 +87,7 @@ + + # sqlite3_enable_shared_cache() is deprecated on macOS and calling it may raise + # OperationalError on some buildbots. +- @unittest.skipIf(sys.platform == "darwin", "shared cache is deprecated on macOS") ++ @unittest.skipIf(is_apple, "shared cache is deprecated on Apple platforms") + def test_shared_cache_deprecated(self): + for enable in (True, False): + with self.assertWarns(DeprecationWarning) as cm: +@@ -976,6 +976,7 @@ + def tearDown(self): + unlink(TESTFN) + ++ @requires_subprocess() + def test_ctx_mgr_rollback_if_commit_failed(self): + # bpo-27334: ctx manager does not rollback if commit fails + SCRIPT = f"""if 1: +diff --git a/Lib/subprocess.py b/Lib/subprocess.py +index f1e3d64dfe0..bd82a633158 100644 +--- a/Lib/subprocess.py ++++ b/Lib/subprocess.py +@@ -65,16 +65,19 @@ + # NOTE: We intentionally exclude list2cmdline as it is + # considered an internal implementation detail. issue10838. + ++# use presence of msvcrt to detect Windows-like platforms (see bpo-8110) + try: + import msvcrt +- import _winapi +- _mswindows = True + except ModuleNotFoundError: + _mswindows = False +- import _posixsubprocess +- import select +- import selectors + else: ++ _mswindows = True ++ ++# some platforms do not support subprocesses ++_can_fork_exec = sys.platform not in {"ios", "tvos", "watchos"} ++ ++if _mswindows: ++ import _winapi + from _winapi import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP, + STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, + STD_ERROR_HANDLE, SW_HIDE, +@@ -95,6 +98,12 @@ + "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS", + "CREATE_NO_WINDOW", "DETACHED_PROCESS", + "CREATE_DEFAULT_ERROR_MODE", "CREATE_BREAKAWAY_FROM_JOB"]) ++else: ++ if _can_fork_exec: ++ import _posixsubprocess ++ ++ import select ++ import selectors + + + # Exception classes used by this module. +@@ -764,6 +773,11 @@ + pass_fds=(), *, user=None, group=None, extra_groups=None, + encoding=None, errors=None, text=None, umask=-1, pipesize=-1): + """Create new Popen instance.""" ++ if not _can_fork_exec: ++ raise OSError( ++ errno.ENOTSUP, f"{sys.platform} does not support processes." ++ ) ++ + _cleanup() + # Held while anything is calling waitpid before returncode has been + # updated to prevent clobbering returncode if wait() or poll() are +diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py +index daf9f000060..5ddead7bbc6 100644 +--- a/Lib/sysconfig.py ++++ b/Lib/sysconfig.py +@@ -20,6 +20,7 @@ + + # Keys for get_config_var() that are never converted to Python integers. + _ALWAYS_STR = { ++ 'IPHONEOS_DEPLOYMENT_TARGET', + 'MACOSX_DEPLOYMENT_TARGET', + } + +@@ -56,6 +57,46 @@ + 'scripts': '{base}/Scripts', + 'data': '{base}', + }, ++ ++ # Downstream distributors can overwrite the default install scheme. ++ # This is done to support downstream modifications where distributors change ++ # the installation layout (eg. different site-packages directory). ++ # So, distributors will change the default scheme to one that correctly ++ # represents their layout. ++ # This presents an issue for projects/people that need to bootstrap virtual ++ # environments, like virtualenv. As distributors might now be customizing ++ # the default install scheme, there is no guarantee that the information ++ # returned by sysconfig.get_default_scheme/get_paths is correct for ++ # a virtual environment, the only guarantee we have is that it is correct ++ # for the *current* environment. When bootstrapping a virtual environment, ++ # we need to know its layout, so that we can place the files in the ++ # correct locations. ++ # The "*_venv" install scheme is a scheme to bootstrap virtual environments, ++ # essentially identical to the default posix_prefix/nt schemes. ++ # Downstream distributors who patch posix_prefix/nt scheme are encouraged to ++ # leave the following schemes unchanged ++ 'posix_venv': { ++ 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}', ++ 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}', ++ 'purelib': '{base}/lib/python{py_version_short}/site-packages', ++ 'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages', ++ 'include': ++ '{installed_base}/include/python{py_version_short}{abiflags}', ++ 'platinclude': ++ '{installed_platbase}/include/python{py_version_short}{abiflags}', ++ 'scripts': '{base}/bin', ++ 'data': '{base}', ++ }, ++ 'nt_venv': { ++ 'stdlib': '{installed_base}/Lib', ++ 'platstdlib': '{base}/Lib', ++ 'purelib': '{base}/Lib/site-packages', ++ 'platlib': '{base}/Lib/site-packages', ++ 'include': '{installed_base}/Include', ++ 'platinclude': '{installed_base}/Include', ++ 'scripts': '{base}/Scripts', ++ 'data': '{base}', ++ }, + } + + +@@ -66,8 +107,8 @@ + if env_base: + return env_base + +- # VxWorks has no home directories +- if sys.platform == "vxworks": ++ # iOS, tvOS, VxWorks and watchOS have no home directories ++ if sys.platform in {"ios", "tvos", "vxworks", "watchos"}: + return None + + def joinuser(*args): +@@ -237,6 +278,7 @@ + 'home': 'posix_home', + 'user': 'osx_framework_user', + } ++ + return { + 'prefix': 'posix_prefix', + 'home': 'posix_home', +@@ -740,10 +782,23 @@ + if m: + release = m.group() + elif osname[:6] == "darwin": +- import _osx_support +- osname, release, machine = _osx_support.get_platform_osx( +- get_config_vars(), +- osname, release, machine) ++ if sys.platform == "ios": ++ release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "13.0") ++ osname = sys.platform ++ machine = sys.implementation._multiarch ++ elif sys.platform == "tvos": ++ release = get_config_vars().get("TVOS_DEPLOYMENT_TARGET", "9.0") ++ osname = sys.platform ++ machine = sys.implementation._multiarch ++ elif sys.platform == "watchos": ++ release = get_config_vars().get("WATCHOS_DEPLOYMENT_TARGET", "4.0") ++ osname = sys.platform ++ machine = sys.implementation._multiarch ++ else: ++ import _osx_support ++ osname, release, machine = _osx_support.get_platform_osx( ++ get_config_vars(), ++ osname, release, machine) + + return f"{osname}-{release}-{machine}" + +diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py +index f474a756b33..21e792a8642 100644 +--- a/Lib/test/datetimetester.py ++++ b/Lib/test/datetimetester.py +@@ -5908,6 +5908,8 @@ + ldt = tz.fromutc(udt.replace(tzinfo=tz)) + self.assertEqual(ldt.fold, 0) + ++ @unittest.skipIf(support.is_apple_mobile, ++ "FIXME: Edge case in timezone handling") + def test_system_transitions(self): + if ('Riyadh8' in self.zonename or + # From tzdata NEWS file: +diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py +index 400a3db5de4..049afff1a75 100644 +--- a/Lib/test/libregrtest/main.py ++++ b/Lib/test/libregrtest/main.py +@@ -676,7 +676,8 @@ + except SystemExit as exc: + # bpo-38203: Python can hang at exit in Py_Finalize(), especially + # on threading._shutdown() call: put a timeout +- faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True) ++ if self.ns.timeout is not None: ++ faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True) + + sys.exit(exc.code) + +diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py +index eef34f08121..22115948788 100644 +--- a/Lib/test/pythoninfo.py ++++ b/Lib/test/pythoninfo.py +@@ -267,6 +267,7 @@ + "HOMEDRIVE", + "HOMEPATH", + "IDLESTARTUP", ++ "IPHONEOS_DEPLOYMENT_TARGET", + "LANG", + "LDFLAGS", + "LDSHARED", +diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py +index d0492fe1914..632bc9c3f4d 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -43,7 +43,7 @@ + "check__all__", "skip_if_buggy_ucrt_strfptime", + "check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer", + # sys +- "is_jython", "is_android", "check_impl_detail", "unix_shell", ++ "is_jython", "is_android", "is_apple_mobile", "check_impl_detail", "unix_shell", + "setswitchinterval", + # network + "open_urlresource", +@@ -55,6 +55,7 @@ + "run_with_tz", "PGO", "missing_compiler_executable", + "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST", + "LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT", ++ "on_github_actions" + ] + + +@@ -479,11 +480,27 @@ + + is_android = hasattr(sys, 'getandroidapilevel') + +-if sys.platform not in ('win32', 'vxworks'): ++if sys.platform not in {"win32", "vxworks", "ios", "tvos", "watchos"}: + unix_shell = '/system/bin/sh' if is_android else '/bin/sh' + else: + unix_shell = None + ++# Apple mobile platforms (iOS/tvOS/watchOS) are POSIX-like but do not ++# have subprocess or fork support. ++is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"} ++is_apple = is_apple_mobile or sys.platform == "darwin" ++ ++has_fork_support = hasattr(os, "fork") and not is_apple_mobile ++ ++def requires_fork(): ++ return unittest.skipUnless(has_fork_support, "requires working os.fork()") ++ ++has_subprocess_support = not is_apple_mobile ++ ++def requires_subprocess(): ++ """Used for subprocess, os.spawn calls, fd inheritance""" ++ return unittest.skipUnless(has_subprocess_support, "requires subprocess support") ++ + # Define the URL of a dedicated HTTP server for the network tests. + # The URL must use clear-text HTTP: no redirection to encrypted HTTPS. + TEST_HTTP_URL = "http://www.pythontest.net" +@@ -1033,6 +1050,9 @@ + return no_tracing(cpython_only(test)) + + ++on_github_actions = "GITHUB_ACTIONS" in os.environ ++ ++ + def _filter_suite(suite, pred): + """Recursively filter test cases in a suite based on a predicate.""" + newtests = [] +@@ -1463,6 +1483,7 @@ + if verbose: + print("failed to clean up {}: {}".format(link, ex)) + ++ @requires_subprocess() + def _call(self, python, args, env, returncode): + import subprocess + cmd = [python, *args] +diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py +index 82a6de789c8..78b61e13dd1 100644 +--- a/Lib/test/support/os_helper.py ++++ b/Lib/test/support/os_helper.py +@@ -9,6 +9,8 @@ + import unittest + import warnings + ++from test import support ++ + + # Filename used for testing + if os.name == 'java': +@@ -23,8 +25,8 @@ + + # TESTFN_UNICODE is a non-ascii filename + TESTFN_UNICODE = TESTFN_ASCII + "-\xe0\xf2\u0258\u0141\u011f" +-if sys.platform == 'darwin': +- # In Mac OS X's VFS API file names are, by definition, canonically ++if support.is_apple: ++ # On Apple's VFS API file names are, by definition, canonically + # decomposed Unicode, encoded using UTF-8. See QA1173: + # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html + import unicodedata +@@ -49,8 +51,8 @@ + 'encoding (%s). Unicode filename tests may not be effective' + % (TESTFN_UNENCODABLE, sys.getfilesystemencoding())) + TESTFN_UNENCODABLE = None +-# Mac OS X denies unencodable filenames (invalid utf-8) +-elif sys.platform != 'darwin': ++# Apple denies unencodable filenames (invalid utf-8) ++elif not support.is_apple: + try: + # ascii and utf-8 cannot encode the byte 0xff + b'\xff'.decode(sys.getfilesystemencoding()) +@@ -515,7 +517,8 @@ + if hasattr(os, 'sysconf'): + try: + MAXFD = os.sysconf("SC_OPEN_MAX") +- except OSError: ++ except (OSError, ValueError): ++ # gh-118201: ValueError is raised intermittently on iOS + pass + + old_modes = None +diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py +index 6d699c8486c..f8bc838020d 100644 +--- a/Lib/test/support/script_helper.py ++++ b/Lib/test/support/script_helper.py +@@ -19,6 +19,7 @@ + __cached_interp_requires_environment = None + + ++@support.requires_subprocess() + def interpreter_requires_environment(): + """ + Returns True if our sys.executable interpreter requires environment +@@ -87,6 +88,7 @@ + + + # Executing the interpreter in a subprocess ++@support.requires_subprocess() + def run_python_until_end(*args, **env_vars): + env_required = interpreter_requires_environment() + cwd = env_vars.pop('__cwd', None) +@@ -146,6 +148,7 @@ + return res + + ++@support.requires_subprocess() + def assert_python_ok(*args, **env_vars): + """ + Assert that running the interpreter with `args` and optional environment +@@ -160,6 +163,7 @@ + return _assert_python(True, *args, **env_vars) + + ++@support.requires_subprocess() + def assert_python_failure(*args, **env_vars): + """ + Assert that running the interpreter with `args` and optional environment +@@ -171,6 +175,7 @@ + return _assert_python(False, *args, **env_vars) + + ++@support.requires_subprocess() + def spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): + """Run a Python subprocess with the given arguments. + +@@ -273,6 +278,7 @@ + return zip_name, os.path.join(zip_name, script_name_in_zip) + + ++@support.requires_subprocess() + def run_test_script(script): + # use -u to try to get the full output if the test hangs or crash + if support.verbose: +diff --git a/Lib/test/support/socket_helper.py b/Lib/test/support/socket_helper.py +index 38c499bf722..8de55306053 100644 +--- a/Lib/test/support/socket_helper.py ++++ b/Lib/test/support/socket_helper.py +@@ -1,8 +1,10 @@ + import contextlib + import errno ++import os.path + import socket +-import unittest ++import tempfile + import sys ++import unittest + + from .. import support + +@@ -267,3 +269,14 @@ + # __cause__ or __context__? + finally: + socket.setdefaulttimeout(old_timeout) ++ ++ ++def create_unix_domain_name(): ++ """ ++ Create a UNIX domain name: socket.bind() argument of a AF_UNIX socket. ++ ++ Return a path relative to the current directory to get a short path ++ (around 27 ASCII characters). ++ """ ++ return tempfile.mktemp(prefix="test_python_", suffix='.sock', ++ dir=os.path.curdir) +diff --git a/Lib/test/test_apple.py b/Lib/test/test_apple.py +new file mode 100644 +index 00000000000..f14db75e2f2 +--- /dev/null ++++ b/Lib/test/test_apple.py +@@ -0,0 +1,155 @@ ++import unittest ++from _apple_support import SystemLog ++from test.support import is_apple_mobile ++from unittest.mock import Mock, call ++ ++if not is_apple_mobile: ++ raise unittest.SkipTest("iOS-specific") ++ ++ ++# Test redirection of stdout and stderr to the Apple system log. ++class TestAppleSystemLogOutput(unittest.TestCase): ++ maxDiff = None ++ ++ def assert_writes(self, output): ++ self.assertEqual( ++ self.log_write.mock_calls, ++ [ ++ call(self.log_level, line) ++ for line in output ++ ] ++ ) ++ ++ self.log_write.reset_mock() ++ ++ def setUp(self): ++ self.log_write = Mock() ++ self.log_level = 42 ++ self.log = SystemLog(self.log_write, self.log_level, errors="replace") ++ ++ def test_repr(self): ++ self.assertEqual(repr(self.log), "") ++ self.assertEqual(repr(self.log.buffer), "") ++ ++ def test_log_config(self): ++ self.assertIs(self.log.writable(), True) ++ self.assertIs(self.log.readable(), False) ++ ++ self.assertEqual("UTF-8", self.log.encoding) ++ self.assertEqual("replace", self.log.errors) ++ ++ self.assertIs(self.log.line_buffering, True) ++ self.assertIs(self.log.write_through, False) ++ ++ def test_empty_str(self): ++ self.log.write("") ++ self.log.flush() ++ ++ self.assert_writes([]) ++ ++ def test_simple_str(self): ++ self.log.write("hello world\n") ++ ++ self.assert_writes([b"hello world\n"]) ++ ++ def test_buffered_str(self): ++ self.log.write("h") ++ self.log.write("ello") ++ self.log.write(" ") ++ self.log.write("world\n") ++ self.log.write("goodbye.") ++ self.log.flush() ++ ++ self.assert_writes([b"hello world\n", b"goodbye."]) ++ ++ def test_manual_flush(self): ++ self.log.write("Hello") ++ ++ self.assert_writes([]) ++ ++ self.log.write(" world\nHere for a while...\nGoodbye") ++ self.assert_writes([b"Hello world\n", b"Here for a while...\n"]) ++ ++ self.log.write(" world\nHello again") ++ self.assert_writes([b"Goodbye world\n"]) ++ ++ self.log.flush() ++ self.assert_writes([b"Hello again"]) ++ ++ def test_non_ascii(self): ++ # Spanish ++ self.log.write("ol\u00e9\n") ++ self.assert_writes([b"ol\xc3\xa9\n"]) ++ ++ # Chinese ++ self.log.write("\u4e2d\u6587\n") ++ self.assert_writes([b"\xe4\xb8\xad\xe6\x96\x87\n"]) ++ ++ # Printing Non-BMP emoji ++ self.log.write("\U0001f600\n") ++ self.assert_writes([b"\xf0\x9f\x98\x80\n"]) ++ ++ # Non-encodable surrogates are replaced ++ self.log.write("\ud800\udc00\n") ++ self.assert_writes([b"??\n"]) ++ ++ def test_modified_null(self): ++ # Null characters are logged using "modified UTF-8". ++ self.log.write("\u0000\n") ++ self.assert_writes([b"\xc0\x80\n"]) ++ self.log.write("a\u0000\n") ++ self.assert_writes([b"a\xc0\x80\n"]) ++ self.log.write("\u0000b\n") ++ self.assert_writes([b"\xc0\x80b\n"]) ++ self.log.write("a\u0000b\n") ++ self.assert_writes([b"a\xc0\x80b\n"]) ++ ++ def test_nonstandard_str(self): ++ # String subclasses are accepted, but they should be converted ++ # to a standard str without calling any of their methods. ++ class CustomStr(str): ++ def splitlines(self, *args, **kwargs): ++ raise AssertionError() ++ ++ def __len__(self): ++ raise AssertionError() ++ ++ def __str__(self): ++ raise AssertionError() ++ ++ self.log.write(CustomStr("custom\n")) ++ self.assert_writes([b"custom\n"]) ++ ++ def test_non_str(self): ++ # Non-string classes are not accepted. ++ for obj in [b"", b"hello", None, 42]: ++ with self.subTest(obj=obj): ++ with self.assertRaisesRegex( ++ TypeError, ++ fr"write\(\) argument must be str, not " ++ fr"{type(obj).__name__}" ++ ): ++ self.log.write(obj) ++ ++ def test_byteslike_in_buffer(self): ++ # The underlying buffer *can* accept bytes-like objects ++ self.log.buffer.write(bytearray(b"hello")) ++ self.log.flush() ++ ++ self.log.buffer.write(b"") ++ self.log.flush() ++ ++ self.log.buffer.write(b"goodbye") ++ self.log.flush() ++ ++ self.assert_writes([b"hello", b"goodbye"]) ++ ++ def test_non_byteslike_in_buffer(self): ++ for obj in ["hello", None, 42]: ++ with self.subTest(obj=obj): ++ with self.assertRaisesRegex( ++ TypeError, ++ fr"write\(\) argument must be bytes-like, not " ++ fr"{type(obj).__name__}" ++ ): ++ self.log.buffer.write(obj) +diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py +index 253a6c119c9..1640193c798 100644 +--- a/Lib/test/test_asyncio/test_events.py ++++ b/Lib/test/test_asyncio/test_events.py +@@ -1799,6 +1799,7 @@ + else: + self.assertEqual(-signal.SIGKILL, returncode) + ++ @support.requires_subprocess() + def test_subprocess_exec(self): + prog = os.path.join(os.path.dirname(__file__), 'echo.py') + +@@ -1820,6 +1821,7 @@ + self.check_killed(proto.returncode) + self.assertEqual(b'Python The Winner', proto.data[1]) + ++ @support.requires_subprocess() + def test_subprocess_interactive(self): + prog = os.path.join(os.path.dirname(__file__), 'echo.py') + +@@ -1847,6 +1849,7 @@ + self.loop.run_until_complete(proto.completed) + self.check_killed(proto.returncode) + ++ @support.requires_subprocess() + def test_subprocess_shell(self): + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), +@@ -1863,6 +1866,7 @@ + self.assertEqual(proto.data[2], b'') + transp.close() + ++ @support.requires_subprocess() + def test_subprocess_exitcode(self): + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), +@@ -1874,6 +1878,7 @@ + self.assertEqual(7, proto.returncode) + transp.close() + ++ @support.requires_subprocess() + def test_subprocess_close_after_finish(self): + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), +@@ -1888,6 +1893,7 @@ + self.assertEqual(7, proto.returncode) + self.assertIsNone(transp.close()) + ++ @support.requires_subprocess() + def test_subprocess_kill(self): + prog = os.path.join(os.path.dirname(__file__), 'echo.py') + +@@ -1904,6 +1910,7 @@ + self.check_killed(proto.returncode) + transp.close() + ++ @support.requires_subprocess() + def test_subprocess_terminate(self): + prog = os.path.join(os.path.dirname(__file__), 'echo.py') + +@@ -1921,6 +1928,7 @@ + transp.close() + + @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") ++ @support.requires_subprocess() + def test_subprocess_send_signal(self): + # bpo-31034: Make sure that we get the default signal handler (killing + # the process). The parent process may have decided to ignore SIGHUP, +@@ -1945,6 +1953,7 @@ + finally: + signal.signal(signal.SIGHUP, old_handler) + ++ @support.requires_subprocess() + def test_subprocess_stderr(self): + prog = os.path.join(os.path.dirname(__file__), 'echo2.py') + +@@ -1966,6 +1975,7 @@ + self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2]) + self.assertEqual(0, proto.returncode) + ++ @support.requires_subprocess() + def test_subprocess_stderr_redirect_to_stdout(self): + prog = os.path.join(os.path.dirname(__file__), 'echo2.py') + +@@ -1991,6 +2001,7 @@ + transp.close() + self.assertEqual(0, proto.returncode) + ++ @support.requires_subprocess() + def test_subprocess_close_client_stream(self): + prog = os.path.join(os.path.dirname(__file__), 'echo3.py') + +@@ -2025,6 +2036,7 @@ + self.loop.run_until_complete(proto.completed) + self.check_killed(proto.returncode) + ++ @support.requires_subprocess() + def test_subprocess_wait_no_same_group(self): + # start the new process in a new session + connect = self.loop.subprocess_shell( +@@ -2037,6 +2049,7 @@ + self.assertEqual(7, proto.returncode) + transp.close() + ++ @support.requires_subprocess() + def test_subprocess_exec_invalid_args(self): + async def connect(**kwds): + await self.loop.subprocess_exec( +@@ -2050,6 +2063,7 @@ + with self.assertRaises(ValueError): + self.loop.run_until_complete(connect(shell=True)) + ++ @support.requires_subprocess() + def test_subprocess_shell_invalid_args(self): + + async def connect(cmd=None, **kwds): +diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py +index 994041c10f0..e2bc1a2617d 100644 +--- a/Lib/test/test_asyncio/test_streams.py ++++ b/Lib/test/test_asyncio/test_streams.py +@@ -9,7 +9,7 @@ + import threading + import unittest + from unittest import mock +-from test.support import socket_helper ++from test.support import requires_subprocess, socket_helper + try: + import ssl + except ImportError: +@@ -707,6 +707,7 @@ + self.assertEqual(messages, []) + + @unittest.skipIf(sys.platform == 'win32', "Don't have pipes") ++ @requires_subprocess() + def test_read_all_from_pipe_reader(self): + # See asyncio issue 168. This test is derived from the example + # subprocess_attach_read_pipe.py, but we configure the +diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py +index 7cd80fd68e3..8c7bf67d94e 100644 +--- a/Lib/test/test_asyncio/test_subprocess.py ++++ b/Lib/test/test_asyncio/test_subprocess.py +@@ -39,6 +39,7 @@ + self._proc.pid = -1 + + ++@support.requires_subprocess() + class SubprocessTransportTests(test_utils.TestCase): + def setUp(self): + super().setUp() +@@ -104,6 +105,7 @@ + transport.close() + + ++@support.requires_subprocess() + class SubprocessMixin: + + def test_stdin_stdout(self): +diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py +index 01c1214c7f7..7e16e2a369d 100644 +--- a/Lib/test/test_asyncio/test_unix_events.py ++++ b/Lib/test/test_asyncio/test_unix_events.py +@@ -315,11 +315,15 @@ + self.loop.run_until_complete(coro) + + def test_create_unix_server_existing_path_nonsock(self): +- with tempfile.NamedTemporaryFile() as file: +- coro = self.loop.create_unix_server(lambda: None, file.name) +- with self.assertRaisesRegex(OSError, +- 'Address.*is already in use'): +- self.loop.run_until_complete(coro) ++ path = test_utils.gen_unix_socket_path() ++ self.addCleanup(os_helper.unlink, path) ++ # create the file ++ open(path, "wb").close() ++ ++ coro = self.loop.create_unix_server(lambda: None, path) ++ with self.assertRaisesRegex(OSError, ++ 'Address.*is already in use'): ++ self.loop.run_until_complete(coro) + + def test_create_unix_server_ssl_bool(self): + coro = self.loop.create_unix_server(lambda: None, path='spam', +diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py +index 0b9cde6878f..3f4c90e2ba6 100644 +--- a/Lib/test/test_asyncio/utils.py ++++ b/Lib/test/test_asyncio/utils.py +@@ -11,7 +11,6 @@ + import socket + import socketserver + import sys +-import tempfile + import threading + import time + import unittest +@@ -34,7 +33,7 @@ + from asyncio import tasks + from asyncio.log import logger + from test import support +-from test.support import threading_helper ++from test.support import threading_helper, socket_helper + + + def data_file(filename): +@@ -250,8 +249,7 @@ + + + def gen_unix_socket_path(): +- with tempfile.NamedTemporaryFile() as file: +- return file.name ++ return socket_helper.create_unix_domain_name() + + + @contextlib.contextmanager +diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py +index ecd1e120ecb..3616b9957fb 100644 +--- a/Lib/test/test_asyncore.py ++++ b/Lib/test/test_asyncore.py +@@ -9,6 +9,7 @@ + import threading + + from test import support ++from test.support import is_apple_mobile + from test.support import os_helper + from test.support import socket_helper + from test.support import threading_helper +@@ -658,6 +659,7 @@ + + @unittest.skipIf(sys.platform.startswith("sunos"), + "OOB support is broken on Solaris") ++ @unittest.skipIf(is_apple_mobile, "FIXME: edge case in removed test module") + def test_handle_expt(self): + # Make sure handle_expt is called on OOB data received. + # Note: this might fail on some platforms as OOB data is +diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py +index e0feef7c653..eab88bc256b 100644 +--- a/Lib/test/test_atexit.py ++++ b/Lib/test/test_atexit.py +@@ -1,6 +1,5 @@ + import atexit + import os +-import sys + import textwrap + import unittest + from test import support +diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py +index 10a61c60b57..2eab0fd6cf1 100644 +--- a/Lib/test/test_audit.py ++++ b/Lib/test/test_audit.py +@@ -18,6 +18,7 @@ + class AuditTest(unittest.TestCase): + maxDiff = None + ++ @support.requires_subprocess() + def do_test(self, *args): + with subprocess.Popen( + [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args], +@@ -31,6 +32,7 @@ + if p.returncode: + self.fail("".join(p.stderr)) + ++ @support.requires_subprocess() + def run_python(self, *args): + events = [] + with subprocess.Popen( +diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py +index 71f934756e2..ca976abb853 100644 +--- a/Lib/test/test_c_locale_coercion.py ++++ b/Lib/test/test_c_locale_coercion.py +@@ -403,6 +403,7 @@ + expected_warnings=[LEGACY_LOCALE_WARNING], + coercion_expected=False) + ++ @support.requires_subprocess() + def test_PYTHONCOERCECLOCALE_set_to_one(self): + # skip the test if the LC_CTYPE locale is C or coerced + old_loc = locale.setlocale(locale.LC_CTYPE, None) +diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py +index 404a13a0bcc..ffe6053aeb8 100644 +--- a/Lib/test/test_capi/test_misc.py ++++ b/Lib/test/test_capi/test_misc.py +@@ -791,6 +791,13 @@ + self.addCleanup(os.close, r) + self.addCleanup(os.close, w) + ++ # Apple extensions must be distributed as frameworks. This requires ++ # a specialist loader. ++ if support.is_apple_mobile: ++ loader = "AppleFrameworkLoader" ++ else: ++ loader = "ExtensionFileLoader" ++ + script = textwrap.dedent(f""" + import importlib.machinery + import importlib.util +@@ -798,7 +805,7 @@ + + fullname = '_test_module_state_shared' + origin = importlib.util.find_spec('_testmultiphase').origin +- loader = importlib.machinery.ExtensionFileLoader(fullname, origin) ++ loader = importlib.machinery.{loader}(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + attr_id = str(id(module.Error)).encode() +@@ -996,7 +1003,12 @@ + def setUp(self): + fullname = '_testmultiphase_meth_state_access' # XXX + origin = importlib.util.find_spec('_testmultiphase').origin +- loader = importlib.machinery.ExtensionFileLoader(fullname, origin) ++ # Apple extensions must be distributed as frameworks. This requires ++ # a specialist loader. ++ if support.is_apple_mobile: ++ loader = importlib.machinery.AppleFrameworkLoader(fullname, origin) ++ else: ++ loader = importlib.machinery.ExtensionFileLoader(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + loader.exec_module(module) +diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py +index 86bcafcf0e3..529d9fd61e7 100644 +--- a/Lib/test/test_cmd_line_script.py ++++ b/Lib/test/test_cmd_line_script.py +@@ -14,8 +14,7 @@ + + import textwrap + from test import support +-from test.support import import_helper +-from test.support import os_helper ++from test.support import import_helper, is_apple, os_helper + from test.support.script_helper import ( + make_pkg, make_script, make_zip_pkg, make_zip_script, + assert_python_ok, assert_python_failure, spawn_python, kill_python) +@@ -554,11 +553,14 @@ + self.assertTrue(text[3].startswith('NameError')) + + def test_non_ascii(self): +- # Mac OS X denies the creation of a file with an invalid UTF-8 name. ++ # Apple platforms deny the creation of a file with an invalid UTF-8 name. + # Windows allows creating a name with an arbitrary bytes name, but + # Python cannot a undecodable bytes argument to a subprocess. +- if (os_helper.TESTFN_UNDECODABLE +- and sys.platform not in ('win32', 'darwin')): ++ if ( ++ os_helper.TESTFN_UNDECODABLE ++ and sys.platform not in {"win32"} ++ and not is_apple ++ ): + name = os.fsdecode(os_helper.TESTFN_UNDECODABLE) + elif os_helper.TESTFN_NONASCII: + name = os_helper.TESTFN_NONASCII +diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py +index 6eae8c9cce3..0cac02e48c3 100644 +--- a/Lib/test/test_concurrent_futures.py ++++ b/Lib/test/test_concurrent_futures.py +@@ -152,6 +152,7 @@ + executor_type = futures.ThreadPoolExecutor + + ++@support.requires_subprocess() + class ProcessPoolForkMixin(ExecutorMixin): + executor_type = futures.ProcessPoolExecutor + ctx = "fork" +@@ -166,6 +167,7 @@ + return super().get_context() + + ++@support.requires_subprocess() + class ProcessPoolSpawnMixin(ExecutorMixin): + executor_type = futures.ProcessPoolExecutor + ctx = "spawn" +@@ -178,6 +180,7 @@ + return super().get_context() + + ++@support.requires_subprocess() + class ProcessPoolForkserverMixin(ExecutorMixin): + executor_type = futures.ProcessPoolExecutor + ctx = "forkserver" +diff --git a/Lib/test/test_distutils.py b/Lib/test/test_distutils.py +index d82d2b64234..f82aca2a01e 100644 +--- a/Lib/test/test_distutils.py ++++ b/Lib/test/test_distutils.py +@@ -14,6 +14,8 @@ + + import distutils.tests + ++if support.is_apple_mobile: ++ raise unittest.SkipTest("FIXME: Edge case of test loader") + + def load_tests(*_): + # used by unittest +diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py +index ebd4ad91924..d20dbc457c4 100644 +--- a/Lib/test/test_doctest.py ++++ b/Lib/test/test_doctest.py +@@ -4,7 +4,6 @@ + + from test import support + from test.support import import_helper +-from test.support import os_helper + import doctest + import functools + import os +@@ -14,7 +13,6 @@ + import importlib.util + import unittest + import tempfile +-import shutil + import types + import contextlib + +@@ -431,8 +429,9 @@ + + """ + +-class test_DocTestFinder: +- def basics(): r""" ++if not support.is_apple_mobile: ++ class test_DocTestFinder: ++ def basics(): r""" + Unit tests for the `DocTestFinder` class. + + DocTestFinder is used to extract DocTests from an object's docstring +@@ -2759,7 +2758,8 @@ + hook.remove() + + +-def test_lineendings(): r""" ++if not support.is_apple_mobile: ++ def test_lineendings(): r""" + *nix systems use \n line endings, while Windows systems use \r\n, and + old Mac systems used \r, which Python still recognizes as a line ending. Python + handles this using universal newline mode for reading files. Let's make +@@ -2875,7 +2875,8 @@ + TestResults(failed=1, attempted=1) + """ + +-def test_CLI(): r""" ++if not support.is_apple_mobile: ++ def test_CLI(): r""" + The doctest module can be used to run doctests against an arbitrary file. + These tests test this CLI functionality. + +diff --git a/Lib/test/test_doctest2.py b/Lib/test/test_doctest2.py +index ab8a0696736..f7007919113 100644 +--- a/Lib/test/test_doctest2.py ++++ b/Lib/test/test_doctest2.py +@@ -13,9 +13,12 @@ + + import sys + import unittest ++from test import support ++ + if sys.flags.optimize >= 2: + raise unittest.SkipTest("Cannot test docstrings with -O2") + ++ + class C(object): + """Class C. + +diff --git a/Lib/test/test_dtrace.py b/Lib/test/test_dtrace.py +index 8a436ad123b..4fa7571fe43 100644 +--- a/Lib/test/test_dtrace.py ++++ b/Lib/test/test_dtrace.py +@@ -6,7 +6,7 @@ + import types + import unittest + +-from test.support import findfile ++from test.support import findfile, requires_subprocess + + + def abspath(filename): +@@ -60,6 +60,7 @@ + command += ["-c", subcommand] + return command + ++ @requires_subprocess() + def trace(self, script_file, subcommand=None): + command = self.generate_trace_command(script_file, subcommand) + stdout, _ = subprocess.Popen(command, +diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py +index 8c343f37210..f13b5a1745b 100644 +--- a/Lib/test/test_embed.py ++++ b/Lib/test/test_embed.py +@@ -72,6 +72,7 @@ + def tearDown(self): + os.chdir(self.oldcwd) + ++ @support.requires_subprocess() + def run_embedded_interpreter(self, *args, env=None, + timeout=None, returncode=0, input=None, + cwd=None): +@@ -1421,6 +1422,7 @@ + + + class SetConfigTests(unittest.TestCase): ++ @support.requires_subprocess() + def test_set_config(self): + # bpo-42260: Test _PyInterpreterState_SetConfig() + cmd = [sys.executable, '-I', '-m', 'test._test_embed_set_config'] +diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py +index e0f09e821da..4bbdbdd1519 100644 +--- a/Lib/test/test_faulthandler.py ++++ b/Lib/test/test_faulthandler.py +@@ -401,6 +401,7 @@ + finally: + sys.stderr = orig_stderr + ++ @support.requires_subprocess() + def test_disabled_by_default(self): + # By default, the module should be disabled + code = "import faulthandler; print(faulthandler.is_enabled())" +@@ -409,6 +410,7 @@ + output = subprocess.check_output(args) + self.assertEqual(output.rstrip(), b"False") + ++ @support.requires_subprocess() + def test_sys_xoptions(self): + # Test python -X faulthandler + code = "import faulthandler; print(faulthandler.is_enabled())" +@@ -421,6 +423,7 @@ + output = subprocess.check_output(args, env=env) + self.assertEqual(output.rstrip(), b"True") + ++ @support.requires_subprocess() + def test_env_var(self): + # empty env var + code = "import faulthandler; print(faulthandler.is_enabled())" +diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py +index 8e98256a62c..7681e829d8b 100644 +--- a/Lib/test/test_fcntl.py ++++ b/Lib/test/test_fcntl.py +@@ -6,7 +6,7 @@ + import sys + import unittest + from multiprocessing import Process +-from test.support import verbose, cpython_only ++from test.support import cpython_only, is_apple, requires_subprocess, verbose + from test.support.import_helper import import_module + from test.support.os_helper import TESTFN, unlink + +@@ -25,7 +25,7 @@ + start_len = "qq" + + if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd')) +- or sys.platform == 'darwin'): ++ or is_apple): + if struct.calcsize('l') == 8: + off_t = 'l' + pid_t = 'i' +@@ -156,6 +156,7 @@ + self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH) + + @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError") ++ @requires_subprocess() + def test_lockf_exclusive(self): + self.f = open(TESTFN, 'wb+') + cmd = fcntl.LOCK_EX | fcntl.LOCK_NB +@@ -167,6 +168,7 @@ + self.assertEqual(p.exitcode, 0) + + @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError") ++ @requires_subprocess() + def test_lockf_share(self): + self.f = open(TESTFN, 'wb+') + cmd = fcntl.LOCK_SH | fcntl.LOCK_NB +diff --git a/Lib/test/test_file_eintr.py b/Lib/test/test_file_eintr.py +index 01408d838a8..0386d4d774d 100644 +--- a/Lib/test/test_file_eintr.py ++++ b/Lib/test/test_file_eintr.py +@@ -15,6 +15,7 @@ + import sys + import time + import unittest ++from test import support + + # Test import all of the things we're about to try testing up front. + import _io +@@ -69,6 +70,7 @@ + self.fail('Error from IO process %s:\nSTDOUT:\n%sSTDERR:\n%s\n' % + (why, stdout.decode(), stderr.decode())) + ++ @support.requires_subprocess() + def _test_reading(self, data_to_write, read_and_verify_code): + """Generic buffered read method test harness to validate EINTR behavior. + +diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py +index 2f5cc06ca4b..822324cfe19 100644 +--- a/Lib/test/test_ftplib.py ++++ b/Lib/test/test_ftplib.py +@@ -18,6 +18,7 @@ + + from unittest import TestCase, skipUnless + from test import support ++from test.support import requires_subprocess + from test.support import threading_helper + from test.support import socket_helper + from test.support import warnings_helper +@@ -904,6 +905,7 @@ + + + @skipUnless(ssl, "SSL not available") ++@requires_subprocess() + class TestTLS_FTPClassMixin(TestFTPClass): + """Repeat TestFTPClass tests starting the TLS layer for both control + and data connections first. +@@ -920,6 +922,7 @@ + + + @skipUnless(ssl, "SSL not available") ++@requires_subprocess() + class TestTLS_FTPClass(TestCase): + """Specific TLS_FTP class tests.""" + +diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py +index 6c28b2b677c..76ea55f14ad 100644 +--- a/Lib/test/test_gc.py ++++ b/Lib/test/test_gc.py +@@ -1,1415 +1,270 @@ ++import os + import unittest +-import unittest.mock +-from test.support import (verbose, refcount_test, +- cpython_only) +-from test.support.import_helper import import_module +-from test.support.os_helper import temp_dir, TESTFN, unlink +-from test.support.script_helper import assert_python_ok, make_script ++import random ++from test import support + from test.support import threading_helper +- +-import gc +-import sys +-import sysconfig +-import textwrap +-import threading ++import _thread as thread + import time + import weakref + +-try: +- from _testcapi import with_tp_del +-except ImportError: +- def with_tp_del(cls): +- class C(object): +- def __new__(cls, *args, **kwargs): +- raise TypeError('requires _testcapi.with_tp_del') +- return C +- +-try: +- from _testcapi import ContainerNoGC +-except ImportError: +- ContainerNoGC = None +- +-### Support code +-############################################################################### +- +-# Bug 1055820 has several tests of longstanding bugs involving weakrefs and +-# cyclic gc. +- +-# An instance of C1055820 has a self-loop, so becomes cyclic trash when +-# unreachable. +-class C1055820(object): +- def __init__(self, i): +- self.i = i +- self.loop = self +- +-class GC_Detector(object): +- # Create an instance I. Then gc hasn't happened again so long as +- # I.gc_happened is false. +- +- def __init__(self): +- self.gc_happened = False +- +- def it_happened(ignored): +- self.gc_happened = True +- +- # Create a piece of cyclic trash that triggers it_happened when +- # gc collects it. +- self.wr = weakref.ref(C1055820(666), it_happened) +- +-@with_tp_del +-class Uncollectable(object): +- """Create a reference cycle with multiple __del__ methods. +- +- An object in a reference cycle will never have zero references, +- and so must be garbage collected. If one or more objects in the +- cycle have __del__ methods, the gc refuses to guess an order, +- and leaves the cycle uncollected.""" +- def __init__(self, partner=None): +- if partner is None: +- self.partner = Uncollectable(partner=self) +- else: +- self.partner = partner +- def __tp_del__(self): +- pass +- +-if sysconfig.get_config_vars().get('PY_CFLAGS', ''): +- BUILD_WITH_NDEBUG = ('-DNDEBUG' in sysconfig.get_config_vars()['PY_CFLAGS']) +-else: +- # Usually, sys.gettotalrefcount() is only present if Python has been +- # compiled in debug mode. If it's missing, expect that Python has +- # been released in release mode: with NDEBUG defined. +- BUILD_WITH_NDEBUG = (not hasattr(sys, 'gettotalrefcount')) +- +-### Tests +-############################################################################### +- +-class GCTests(unittest.TestCase): +- def test_list(self): +- l = [] +- l.append(l) +- gc.collect() +- del l +- self.assertEqual(gc.collect(), 1) +- +- def test_dict(self): +- d = {} +- d[1] = d +- gc.collect() +- del d +- self.assertEqual(gc.collect(), 1) +- +- def test_tuple(self): +- # since tuples are immutable we close the loop with a list +- l = [] +- t = (l,) +- l.append(t) +- gc.collect() +- del t +- del l +- self.assertEqual(gc.collect(), 2) +- +- def test_class(self): +- class A: +- pass +- A.a = A +- gc.collect() +- del A +- self.assertNotEqual(gc.collect(), 0) +- +- def test_newstyleclass(self): +- class A(object): +- pass +- gc.collect() +- del A +- self.assertNotEqual(gc.collect(), 0) +- +- def test_instance(self): +- class A: +- pass +- a = A() +- a.a = a +- gc.collect() +- del a +- self.assertNotEqual(gc.collect(), 0) +- +- def test_newinstance(self): +- class A(object): +- pass +- a = A() +- a.a = a +- gc.collect() +- del a +- self.assertNotEqual(gc.collect(), 0) +- class B(list): +- pass +- class C(B, A): +- pass +- a = C() +- a.a = a +- gc.collect() +- del a +- self.assertNotEqual(gc.collect(), 0) +- del B, C +- self.assertNotEqual(gc.collect(), 0) +- A.a = A() +- del A +- self.assertNotEqual(gc.collect(), 0) +- self.assertEqual(gc.collect(), 0) +- +- def test_method(self): +- # Tricky: self.__init__ is a bound method, it references the instance. +- class A: +- def __init__(self): +- self.init = self.__init__ +- a = A() +- gc.collect() +- del a +- self.assertNotEqual(gc.collect(), 0) +- +- @cpython_only +- def test_legacy_finalizer(self): +- # A() is uncollectable if it is part of a cycle, make sure it shows up +- # in gc.garbage. +- @with_tp_del +- class A: +- def __tp_del__(self): pass +- class B: +- pass +- a = A() +- a.a = a +- id_a = id(a) +- b = B() +- b.b = b +- gc.collect() +- del a +- del b +- self.assertNotEqual(gc.collect(), 0) +- for obj in gc.garbage: +- if id(obj) == id_a: +- del obj.a +- break +- else: +- self.fail("didn't find obj in garbage (finalizer)") +- gc.garbage.remove(obj) +- +- @cpython_only +- def test_legacy_finalizer_newclass(self): +- # A() is uncollectable if it is part of a cycle, make sure it shows up +- # in gc.garbage. +- @with_tp_del +- class A(object): +- def __tp_del__(self): pass +- class B(object): +- pass +- a = A() +- a.a = a +- id_a = id(a) +- b = B() +- b.b = b +- gc.collect() +- del a +- del b +- self.assertNotEqual(gc.collect(), 0) +- for obj in gc.garbage: +- if id(obj) == id_a: +- del obj.a +- break +- else: +- self.fail("didn't find obj in garbage (finalizer)") +- gc.garbage.remove(obj) +- +- def test_function(self): +- # Tricky: f -> d -> f, code should call d.clear() after the exec to +- # break the cycle. +- d = {} +- exec("def f(): pass\n", d) +- gc.collect() +- del d +- self.assertEqual(gc.collect(), 2) +- +- @refcount_test +- def test_frame(self): +- def f(): +- frame = sys._getframe() +- gc.collect() +- f() +- self.assertEqual(gc.collect(), 1) +- +- def test_saveall(self): +- # Verify that cyclic garbage like lists show up in gc.garbage if the +- # SAVEALL option is enabled. +- +- # First make sure we don't save away other stuff that just happens to +- # be waiting for collection. +- gc.collect() +- # if this fails, someone else created immortal trash +- self.assertEqual(gc.garbage, []) +- +- L = [] +- L.append(L) +- id_L = id(L) ++from test import lock_tests + +- debug = gc.get_debug() +- gc.set_debug(debug | gc.DEBUG_SAVEALL) +- del L +- gc.collect() +- gc.set_debug(debug) ++NUMTASKS = 10 ++NUMTRIPS = 3 ++POLL_SLEEP = 0.010 # seconds = 10 ms + +- self.assertEqual(len(gc.garbage), 1) +- obj = gc.garbage.pop() +- self.assertEqual(id(obj), id_L) ++_print_mutex = thread.allocate_lock() + +- def test_del(self): +- # __del__ methods can trigger collection, make this to happen +- thresholds = gc.get_threshold() +- gc.enable() +- gc.set_threshold(1) ++def verbose_print(arg): ++ """Helper function for printing out debugging output.""" ++ if support.verbose: ++ with _print_mutex: ++ print(arg) + +- class A: +- def __del__(self): +- dir(self) +- a = A() +- del a + +- gc.disable() +- gc.set_threshold(*thresholds) ++class BasicThreadTest(unittest.TestCase): + +- def test_del_newclass(self): +- # __del__ methods can trigger collection, make this to happen +- thresholds = gc.get_threshold() +- gc.enable() +- gc.set_threshold(1) +- +- class A(object): +- def __del__(self): +- dir(self) +- a = A() +- del a +- +- gc.disable() +- gc.set_threshold(*thresholds) +- +- # The following two tests are fragile: +- # They precisely count the number of allocations, +- # which is highly implementation-dependent. +- # For example, disposed tuples are not freed, but reused. +- # To minimize variations, though, we first store the get_count() results +- # and check them at the end. +- @refcount_test +- def test_get_count(self): +- gc.collect() +- a, b, c = gc.get_count() +- x = [] +- d, e, f = gc.get_count() +- self.assertEqual((b, c), (0, 0)) +- self.assertEqual((e, f), (0, 0)) +- # This is less fragile than asserting that a equals 0. +- self.assertLess(a, 5) +- # Between the two calls to get_count(), at least one object was +- # created (the list). +- self.assertGreater(d, a) +- +- @refcount_test +- def test_collect_generations(self): +- gc.collect() +- # This object will "trickle" into generation N + 1 after +- # each call to collect(N) +- x = [] +- gc.collect(0) +- # x is now in gen 1 +- a, b, c = gc.get_count() +- gc.collect(1) +- # x is now in gen 2 +- d, e, f = gc.get_count() +- gc.collect(2) +- # x is now in gen 3 +- g, h, i = gc.get_count() +- # We don't check a, d, g since their exact values depends on +- # internal implementation details of the interpreter. +- self.assertEqual((b, c), (1, 0)) +- self.assertEqual((e, f), (0, 1)) +- self.assertEqual((h, i), (0, 0)) +- +- def test_trashcan(self): +- class Ouch: +- n = 0 +- def __del__(self): +- Ouch.n = Ouch.n + 1 +- if Ouch.n % 17 == 0: +- gc.collect() ++ def setUp(self): ++ self.done_mutex = thread.allocate_lock() ++ self.done_mutex.acquire() ++ self.running_mutex = thread.allocate_lock() ++ self.random_mutex = thread.allocate_lock() ++ self.created = 0 ++ self.running = 0 ++ self.next_ident = 0 ++ ++ key = threading_helper.threading_setup() ++ self.addCleanup(threading_helper.threading_cleanup, *key) ++ ++ ++class ThreadRunningTests(BasicThreadTest): ++ ++ def newtask(self): ++ with self.running_mutex: ++ self.next_ident += 1 ++ verbose_print("creating task %s" % self.next_ident) ++ thread.start_new_thread(self.task, (self.next_ident,)) ++ self.created += 1 ++ self.running += 1 ++ ++ def task(self, ident): ++ with self.random_mutex: ++ delay = random.random() / 10000.0 ++ verbose_print("task %s will run for %sus" % (ident, round(delay*1e6))) ++ time.sleep(delay) ++ verbose_print("task %s done" % ident) ++ with self.running_mutex: ++ self.running -= 1 ++ if self.created == NUMTASKS and self.running == 0: ++ self.done_mutex.release() ++ ++ def test_starting_threads(self): ++ with threading_helper.wait_threads_exit(): ++ # Basic test for thread creation. ++ for i in range(NUMTASKS): ++ self.newtask() ++ verbose_print("waiting for tasks to complete...") ++ self.done_mutex.acquire() ++ verbose_print("all tasks done") ++ ++ def test_stack_size(self): ++ # Various stack size tests. ++ self.assertEqual(thread.stack_size(), 0, "initial stack size is not 0") ++ ++ thread.stack_size(0) ++ self.assertEqual(thread.stack_size(), 0, "stack_size not reset to default") ++ ++ @unittest.skipIf(os.name not in ("nt", "posix"), 'test meant for nt and posix') ++ def test_nt_and_posix_stack_size(self): ++ try: ++ thread.stack_size(4096) ++ except ValueError: ++ verbose_print("caught expected ValueError setting " ++ "stack_size(4096)") ++ except thread.error: ++ self.skipTest("platform does not support changing thread stack " ++ "size") ++ ++ fail_msg = "stack_size(%d) failed - should succeed" ++ for tss in (262144, 0x100000, 0): ++ thread.stack_size(tss) ++ self.assertEqual(thread.stack_size(), tss, fail_msg % tss) ++ verbose_print("successfully set stack_size(%d)" % tss) ++ ++ for tss in (262144, 0x100000): ++ verbose_print("trying stack_size = (%d)" % tss) ++ self.next_ident = 0 ++ self.created = 0 ++ with threading_helper.wait_threads_exit(): ++ for i in range(NUMTASKS): ++ self.newtask() ++ ++ verbose_print("waiting for all tasks to complete") ++ self.done_mutex.acquire() ++ verbose_print("all tasks done") ++ ++ thread.stack_size(0) ++ ++ def test__count(self): ++ # Test the _count() function. ++ orig = thread._count() ++ mut = thread.allocate_lock() ++ mut.acquire() ++ started = [] ++ ++ def task(): ++ started.append(None) ++ mut.acquire() ++ mut.release() ++ ++ with threading_helper.wait_threads_exit(): ++ thread.start_new_thread(task, ()) ++ while not started: ++ time.sleep(POLL_SLEEP) ++ self.assertEqual(thread._count(), orig + 1) ++ # Allow the task to finish. ++ mut.release() ++ # The only reliable way to be sure that the thread ended from the ++ # interpreter's point of view is to wait for the function object to be ++ # destroyed. ++ done = [] ++ wr = weakref.ref(task, lambda _: done.append(None)) ++ del task ++ while not done: ++ time.sleep(POLL_SLEEP) ++ support.gc_collect() # For PyPy or other GCs. ++ self.assertEqual(thread._count(), orig) ++ ++ def test_unraisable_exception(self): ++ def task(): ++ started.release() ++ raise ValueError("task failed") ++ ++ started = thread.allocate_lock() ++ with support.catch_unraisable_exception() as cm: ++ with threading_helper.wait_threads_exit(): ++ started.acquire() ++ thread.start_new_thread(task, ()) ++ started.acquire() ++ ++ self.assertEqual(str(cm.unraisable.exc_value), "task failed") ++ self.assertIs(cm.unraisable.object, task) ++ self.assertEqual(cm.unraisable.err_msg, ++ "Exception ignored in thread started by") ++ self.assertIsNotNone(cm.unraisable.exc_traceback) ++ ++ ++class Barrier: ++ def __init__(self, num_threads): ++ self.num_threads = num_threads ++ self.waiting = 0 ++ self.checkin_mutex = thread.allocate_lock() ++ self.checkout_mutex = thread.allocate_lock() ++ self.checkout_mutex.acquire() ++ ++ def enter(self): ++ self.checkin_mutex.acquire() ++ self.waiting = self.waiting + 1 ++ if self.waiting == self.num_threads: ++ self.waiting = self.num_threads - 1 ++ self.checkout_mutex.release() ++ return ++ self.checkin_mutex.release() ++ ++ self.checkout_mutex.acquire() ++ self.waiting = self.waiting - 1 ++ if self.waiting == 0: ++ self.checkin_mutex.release() ++ return ++ self.checkout_mutex.release() ++ ++ ++class BarrierTest(BasicThreadTest): ++ ++ def test_barrier(self): ++ with threading_helper.wait_threads_exit(): ++ self.bar = Barrier(NUMTASKS) ++ self.running = NUMTASKS ++ for i in range(NUMTASKS): ++ thread.start_new_thread(self.task2, (i,)) ++ verbose_print("waiting for tasks to end") ++ self.done_mutex.acquire() ++ verbose_print("tasks done") ++ ++ def task2(self, ident): ++ for i in range(NUMTRIPS): ++ if ident == 0: ++ # give it a good chance to enter the next ++ # barrier before the others are all out ++ # of the current one ++ delay = 0 ++ else: ++ with self.random_mutex: ++ delay = random.random() / 10000.0 ++ verbose_print("task %s will run for %sus" % ++ (ident, round(delay * 1e6))) ++ time.sleep(delay) ++ verbose_print("task %s entering %s" % (ident, i)) ++ self.bar.enter() ++ verbose_print("task %s leaving barrier" % ident) ++ with self.running_mutex: ++ self.running -= 1 ++ # Must release mutex before releasing done, else the main thread can ++ # exit and set mutex to None as part of global teardown; then ++ # mutex.release() raises AttributeError. ++ finished = self.running == 0 ++ if finished: ++ self.done_mutex.release() ++ ++class LockTests(lock_tests.LockTests): ++ locktype = thread.allocate_lock ++ ++ ++class TestForkInThread(unittest.TestCase): ++ def setUp(self): ++ self.read_fd, self.write_fd = os.pipe() + +- # "trashcan" is a hack to prevent stack overflow when deallocating +- # very deeply nested tuples etc. It works in part by abusing the +- # type pointer and refcount fields, and that can yield horrible +- # problems when gc tries to traverse the structures. +- # If this test fails (as it does in 2.0, 2.1 and 2.2), it will +- # most likely die via segfault. ++ @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork') ++ @support.requires_fork() ++ @threading_helper.reap_threads ++ def test_forkinthread(self): ++ pid = None + +- # Note: In 2.3 the possibility for compiling without cyclic gc was +- # removed, and that in turn allows the trashcan mechanism to work +- # via much simpler means (e.g., it never abuses the type pointer or +- # refcount fields anymore). Since it's much less likely to cause a +- # problem now, the various constants in this expensive (we force a lot +- # of full collections) test are cut back from the 2.2 version. +- gc.enable() +- N = 150 +- for count in range(2): +- t = [] +- for i in range(N): +- t = [t, Ouch()] +- u = [] +- for i in range(N): +- u = [u, Ouch()] +- v = {} +- for i in range(N): +- v = {1: v, 2: Ouch()} +- gc.disable() ++ def fork_thread(read_fd, write_fd): ++ nonlocal pid + +- def test_trashcan_threads(self): +- # Issue #13992: trashcan mechanism should be thread-safe +- NESTING = 60 +- N_THREADS = 2 ++ # fork in a thread ++ pid = os.fork() ++ if pid: ++ # parent process ++ return + +- def sleeper_gen(): +- """A generator that releases the GIL when closed or dealloc'ed.""" ++ # child process + try: +- yield ++ os.close(read_fd) ++ os.write(write_fd, b"OK") + finally: +- time.sleep(0.000001) +- +- class C(list): +- # Appending to a list is atomic, which avoids the use of a lock. +- inits = [] +- dels = [] +- def __init__(self, alist): +- self[:] = alist +- C.inits.append(None) +- def __del__(self): +- # This __del__ is called by subtype_dealloc(). +- C.dels.append(None) +- # `g` will release the GIL when garbage-collected. This +- # helps assert subtype_dealloc's behaviour when threads +- # switch in the middle of it. +- g = sleeper_gen() +- next(g) +- # Now that __del__ is finished, subtype_dealloc will proceed +- # to call list_dealloc, which also uses the trashcan mechanism. ++ os._exit(0) + +- def make_nested(): +- """Create a sufficiently nested container object so that the +- trashcan mechanism is invoked when deallocating it.""" +- x = C([]) +- for i in range(NESTING): +- x = [C([x])] +- del x ++ with threading_helper.wait_threads_exit(): ++ thread.start_new_thread(fork_thread, (self.read_fd, self.write_fd)) ++ self.assertEqual(os.read(self.read_fd, 2), b"OK") ++ os.close(self.write_fd) + +- def run_thread(): +- """Exercise make_nested() in a loop.""" +- while not exit: +- make_nested() ++ self.assertIsNotNone(pid) ++ support.wait_process(pid, exitcode=0) + +- old_switchinterval = sys.getswitchinterval() +- sys.setswitchinterval(1e-5) ++ def tearDown(self): + try: +- exit = [] +- threads = [] +- for i in range(N_THREADS): +- t = threading.Thread(target=run_thread) +- threads.append(t) +- with threading_helper.start_threads(threads, lambda: exit.append(1)): +- time.sleep(1.0) +- finally: +- sys.setswitchinterval(old_switchinterval) +- gc.collect() +- self.assertEqual(len(C.inits), len(C.dels)) +- +- def test_boom(self): +- class Boom: +- def __getattr__(self, someattribute): +- del self.attr +- raise AttributeError +- +- a = Boom() +- b = Boom() +- a.attr = b +- b.attr = a +- +- gc.collect() +- garbagelen = len(gc.garbage) +- del a, b +- # a<->b are in a trash cycle now. Collection will invoke +- # Boom.__getattr__ (to see whether a and b have __del__ methods), and +- # __getattr__ deletes the internal "attr" attributes as a side effect. +- # That causes the trash cycle to get reclaimed via refcounts falling to +- # 0, thus mutating the trash graph as a side effect of merely asking +- # whether __del__ exists. This used to (before 2.3b1) crash Python. +- # Now __getattr__ isn't called. +- self.assertEqual(gc.collect(), 4) +- self.assertEqual(len(gc.garbage), garbagelen) +- +- def test_boom2(self): +- class Boom2: +- def __init__(self): +- self.x = 0 +- +- def __getattr__(self, someattribute): +- self.x += 1 +- if self.x > 1: +- del self.attr +- raise AttributeError +- +- a = Boom2() +- b = Boom2() +- a.attr = b +- b.attr = a +- +- gc.collect() +- garbagelen = len(gc.garbage) +- del a, b +- # Much like test_boom(), except that __getattr__ doesn't break the +- # cycle until the second time gc checks for __del__. As of 2.3b1, +- # there isn't a second time, so this simply cleans up the trash cycle. +- # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get +- # reclaimed this way. +- self.assertEqual(gc.collect(), 4) +- self.assertEqual(len(gc.garbage), garbagelen) +- +- def test_boom_new(self): +- # boom__new and boom2_new are exactly like boom and boom2, except use +- # new-style classes. +- +- class Boom_New(object): +- def __getattr__(self, someattribute): +- del self.attr +- raise AttributeError +- +- a = Boom_New() +- b = Boom_New() +- a.attr = b +- b.attr = a +- +- gc.collect() +- garbagelen = len(gc.garbage) +- del a, b +- self.assertEqual(gc.collect(), 4) +- self.assertEqual(len(gc.garbage), garbagelen) +- +- def test_boom2_new(self): +- class Boom2_New(object): +- def __init__(self): +- self.x = 0 +- +- def __getattr__(self, someattribute): +- self.x += 1 +- if self.x > 1: +- del self.attr +- raise AttributeError +- +- a = Boom2_New() +- b = Boom2_New() +- a.attr = b +- b.attr = a +- +- gc.collect() +- garbagelen = len(gc.garbage) +- del a, b +- self.assertEqual(gc.collect(), 4) +- self.assertEqual(len(gc.garbage), garbagelen) +- +- def test_get_referents(self): +- alist = [1, 3, 5] +- got = gc.get_referents(alist) +- got.sort() +- self.assertEqual(got, alist) +- +- atuple = tuple(alist) +- got = gc.get_referents(atuple) +- got.sort() +- self.assertEqual(got, alist) +- +- adict = {1: 3, 5: 7} +- expected = [1, 3, 5, 7] +- got = gc.get_referents(adict) +- got.sort() +- self.assertEqual(got, expected) +- +- got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0)) +- got.sort() +- self.assertEqual(got, [0, 0] + list(range(5))) +- +- self.assertEqual(gc.get_referents(1, 'a', 4j), []) +- +- def test_is_tracked(self): +- # Atomic built-in types are not tracked, user-defined objects and +- # mutable containers are. +- # NOTE: types with special optimizations (e.g. tuple) have tests +- # in their own test files instead. +- self.assertFalse(gc.is_tracked(None)) +- self.assertFalse(gc.is_tracked(1)) +- self.assertFalse(gc.is_tracked(1.0)) +- self.assertFalse(gc.is_tracked(1.0 + 5.0j)) +- self.assertFalse(gc.is_tracked(True)) +- self.assertFalse(gc.is_tracked(False)) +- self.assertFalse(gc.is_tracked(b"a")) +- self.assertFalse(gc.is_tracked("a")) +- self.assertFalse(gc.is_tracked(bytearray(b"a"))) +- self.assertFalse(gc.is_tracked(type)) +- self.assertFalse(gc.is_tracked(int)) +- self.assertFalse(gc.is_tracked(object)) +- self.assertFalse(gc.is_tracked(object())) +- +- class UserClass: +- pass +- +- class UserInt(int): +- pass +- +- # Base class is object; no extra fields. +- class UserClassSlots: +- __slots__ = () +- +- # Base class is fixed size larger than object; no extra fields. +- class UserFloatSlots(float): +- __slots__ = () +- +- # Base class is variable size; no extra fields. +- class UserIntSlots(int): +- __slots__ = () +- +- self.assertTrue(gc.is_tracked(gc)) +- self.assertTrue(gc.is_tracked(UserClass)) +- self.assertTrue(gc.is_tracked(UserClass())) +- self.assertTrue(gc.is_tracked(UserInt())) +- self.assertTrue(gc.is_tracked([])) +- self.assertTrue(gc.is_tracked(set())) +- self.assertTrue(gc.is_tracked(UserClassSlots())) +- self.assertTrue(gc.is_tracked(UserFloatSlots())) +- self.assertTrue(gc.is_tracked(UserIntSlots())) +- +- def test_is_finalized(self): +- # Objects not tracked by the always gc return false +- self.assertFalse(gc.is_finalized(3)) +- +- storage = [] +- class Lazarus: +- def __del__(self): +- storage.append(self) +- +- lazarus = Lazarus() +- self.assertFalse(gc.is_finalized(lazarus)) +- +- del lazarus +- gc.collect() +- +- lazarus = storage.pop() +- self.assertTrue(gc.is_finalized(lazarus)) +- +- def test_bug1055820b(self): +- # Corresponds to temp2b.py in the bug report. +- +- ouch = [] +- def callback(ignored): +- ouch[:] = [wr() for wr in WRs] +- +- Cs = [C1055820(i) for i in range(2)] +- WRs = [weakref.ref(c, callback) for c in Cs] +- c = None +- +- gc.collect() +- self.assertEqual(len(ouch), 0) +- # Make the two instances trash, and collect again. The bug was that +- # the callback materialized a strong reference to an instance, but gc +- # cleared the instance's dict anyway. +- Cs = None +- gc.collect() +- self.assertEqual(len(ouch), 2) # else the callbacks didn't run +- for x in ouch: +- # If the callback resurrected one of these guys, the instance +- # would be damaged, with an empty __dict__. +- self.assertEqual(x, None) +- +- def test_bug21435(self): +- # This is a poor test - its only virtue is that it happened to +- # segfault on Tim's Windows box before the patch for 21435 was +- # applied. That's a nasty bug relying on specific pieces of cyclic +- # trash appearing in exactly the right order in finalize_garbage()'s +- # input list. +- # But there's no reliable way to force that order from Python code, +- # so over time chances are good this test won't really be testing much +- # of anything anymore. Still, if it blows up, there's _some_ +- # problem ;-) +- gc.collect() +- +- class A: ++ os.close(self.read_fd) ++ except OSError: + pass + +- class B: +- def __init__(self, x): +- self.x = x +- +- def __del__(self): +- self.attr = None +- +- def do_work(): +- a = A() +- b = B(A()) +- +- a.attr = b +- b.attr = a +- +- do_work() +- gc.collect() # this blows up (bad C pointer) when it fails +- +- @cpython_only +- def test_garbage_at_shutdown(self): +- import subprocess +- code = """if 1: +- import gc +- import _testcapi +- @_testcapi.with_tp_del +- class X: +- def __init__(self, name): +- self.name = name +- def __repr__(self): +- return "" %% self.name +- def __tp_del__(self): +- pass +- +- x = X('first') +- x.x = x +- x.y = X('second') +- del x +- gc.set_debug(%s) +- """ +- def run_command(code): +- p = subprocess.Popen([sys.executable, "-Wd", "-c", code], +- stdout=subprocess.PIPE, +- stderr=subprocess.PIPE) +- stdout, stderr = p.communicate() +- p.stdout.close() +- p.stderr.close() +- self.assertEqual(p.returncode, 0) +- self.assertEqual(stdout, b"") +- return stderr +- +- stderr = run_command(code % "0") +- self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at " +- b"shutdown; use", stderr) +- self.assertNotIn(b"", stderr) +- # With DEBUG_UNCOLLECTABLE, the garbage list gets printed +- stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE") +- self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at " +- b"shutdown", stderr) +- self.assertTrue( +- (b"[, ]" in stderr) or +- (b"[, ]" in stderr), stderr) +- # With DEBUG_SAVEALL, no additional message should get printed +- # (because gc.garbage also contains normally reclaimable cyclic +- # references, and its elements get printed at runtime anyway). +- stderr = run_command(code % "gc.DEBUG_SAVEALL") +- self.assertNotIn(b"uncollectable objects at shutdown", stderr) +- +- def test_gc_main_module_at_shutdown(self): +- # Create a reference cycle through the __main__ module and check +- # it gets collected at interpreter shutdown. +- code = """if 1: +- class C: +- def __del__(self): +- print('__del__ called') +- l = [C()] +- l.append(l) +- """ +- rc, out, err = assert_python_ok('-c', code) +- self.assertEqual(out.strip(), b'__del__ called') +- +- def test_gc_ordinary_module_at_shutdown(self): +- # Same as above, but with a non-__main__ module. +- with temp_dir() as script_dir: +- module = """if 1: +- class C: +- def __del__(self): +- print('__del__ called') +- l = [C()] +- l.append(l) +- """ +- code = """if 1: +- import sys +- sys.path.insert(0, %r) +- import gctest +- """ % (script_dir,) +- make_script(script_dir, 'gctest', module) +- rc, out, err = assert_python_ok('-c', code) +- self.assertEqual(out.strip(), b'__del__ called') +- +- def test_global_del_SystemExit(self): +- code = """if 1: +- class ClassWithDel: +- def __del__(self): +- print('__del__ called') +- a = ClassWithDel() +- a.link = a +- raise SystemExit(0)""" +- self.addCleanup(unlink, TESTFN) +- with open(TESTFN, 'w', encoding="utf-8") as script: +- script.write(code) +- rc, out, err = assert_python_ok(TESTFN) +- self.assertEqual(out.strip(), b'__del__ called') +- +- def test_get_stats(self): +- stats = gc.get_stats() +- self.assertEqual(len(stats), 3) +- for st in stats: +- self.assertIsInstance(st, dict) +- self.assertEqual(set(st), +- {"collected", "collections", "uncollectable"}) +- self.assertGreaterEqual(st["collected"], 0) +- self.assertGreaterEqual(st["collections"], 0) +- self.assertGreaterEqual(st["uncollectable"], 0) +- # Check that collection counts are incremented correctly +- if gc.isenabled(): +- self.addCleanup(gc.enable) +- gc.disable() +- old = gc.get_stats() +- gc.collect(0) +- new = gc.get_stats() +- self.assertEqual(new[0]["collections"], old[0]["collections"] + 1) +- self.assertEqual(new[1]["collections"], old[1]["collections"]) +- self.assertEqual(new[2]["collections"], old[2]["collections"]) +- gc.collect(2) +- new = gc.get_stats() +- self.assertEqual(new[0]["collections"], old[0]["collections"] + 1) +- self.assertEqual(new[1]["collections"], old[1]["collections"]) +- self.assertEqual(new[2]["collections"], old[2]["collections"] + 1) +- +- def test_freeze(self): +- gc.freeze() +- self.assertGreater(gc.get_freeze_count(), 0) +- gc.unfreeze() +- self.assertEqual(gc.get_freeze_count(), 0) +- +- def test_get_objects(self): +- gc.collect() +- l = [] +- l.append(l) +- self.assertTrue( +- any(l is element for element in gc.get_objects(generation=0)) +- ) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=1)) +- ) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=2)) +- ) +- gc.collect(generation=0) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=0)) +- ) +- self.assertTrue( +- any(l is element for element in gc.get_objects(generation=1)) +- ) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=2)) +- ) +- gc.collect(generation=1) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=0)) +- ) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=1)) +- ) +- self.assertTrue( +- any(l is element for element in gc.get_objects(generation=2)) +- ) +- gc.collect(generation=2) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=0)) +- ) +- self.assertFalse( +- any(l is element for element in gc.get_objects(generation=1)) +- ) +- self.assertTrue( +- any(l is element for element in gc.get_objects(generation=2)) +- ) +- del l +- gc.collect() +- +- def test_get_objects_arguments(self): +- gc.collect() +- self.assertEqual(len(gc.get_objects()), +- len(gc.get_objects(generation=None))) +- +- self.assertRaises(ValueError, gc.get_objects, 1000) +- self.assertRaises(ValueError, gc.get_objects, -1000) +- self.assertRaises(TypeError, gc.get_objects, "1") +- self.assertRaises(TypeError, gc.get_objects, 1.234) +- +- def test_resurrection_only_happens_once_per_object(self): +- class A: # simple self-loop +- def __init__(self): +- self.me = self +- +- class Lazarus(A): +- resurrected = 0 +- resurrected_instances = [] +- +- def __del__(self): +- Lazarus.resurrected += 1 +- Lazarus.resurrected_instances.append(self) +- +- gc.collect() +- gc.disable() +- +- # We start with 0 resurrections +- laz = Lazarus() +- self.assertEqual(Lazarus.resurrected, 0) +- +- # Deleting the instance and triggering a collection +- # resurrects the object +- del laz +- gc.collect() +- self.assertEqual(Lazarus.resurrected, 1) +- self.assertEqual(len(Lazarus.resurrected_instances), 1) +- +- # Clearing the references and forcing a collection +- # should not resurrect the object again. +- Lazarus.resurrected_instances.clear() +- self.assertEqual(Lazarus.resurrected, 1) +- gc.collect() +- self.assertEqual(Lazarus.resurrected, 1) +- +- gc.enable() +- +- def test_resurrection_is_transitive(self): +- class Cargo: +- def __init__(self): +- self.me = self +- +- class Lazarus: +- resurrected_instances = [] +- +- def __del__(self): +- Lazarus.resurrected_instances.append(self) +- +- gc.collect() +- gc.disable() +- +- laz = Lazarus() +- cargo = Cargo() +- cargo_id = id(cargo) +- +- # Create a cycle between cargo and laz +- laz.cargo = cargo +- cargo.laz = laz +- +- # Drop the references, force a collection and check that +- # everything was resurrected. +- del laz, cargo +- gc.collect() +- self.assertEqual(len(Lazarus.resurrected_instances), 1) +- instance = Lazarus.resurrected_instances.pop() +- self.assertTrue(hasattr(instance, "cargo")) +- self.assertEqual(id(instance.cargo), cargo_id) +- +- gc.collect() +- gc.enable() +- +- def test_resurrection_does_not_block_cleanup_of_other_objects(self): +- +- # When a finalizer resurrects objects, stats were reporting them as +- # having been collected. This affected both collect()'s return +- # value and the dicts returned by get_stats(). +- N = 100 +- +- class A: # simple self-loop +- def __init__(self): +- self.me = self +- +- class Z(A): # resurrecting __del__ +- def __del__(self): +- zs.append(self) +- +- zs = [] +- +- def getstats(): +- d = gc.get_stats()[-1] +- return d['collected'], d['uncollectable'] +- +- gc.collect() +- gc.disable() +- +- # No problems if just collecting A() instances. +- oldc, oldnc = getstats() +- for i in range(N): +- A() +- t = gc.collect() +- c, nc = getstats() +- self.assertEqual(t, 2*N) # instance object & its dict +- self.assertEqual(c - oldc, 2*N) +- self.assertEqual(nc - oldnc, 0) +- +- # But Z() is not actually collected. +- oldc, oldnc = c, nc +- Z() +- # Nothing is collected - Z() is merely resurrected. +- t = gc.collect() +- c, nc = getstats() +- self.assertEqual(t, 0) +- self.assertEqual(c - oldc, 0) +- self.assertEqual(nc - oldnc, 0) +- +- # Z() should not prevent anything else from being collected. +- oldc, oldnc = c, nc +- for i in range(N): +- A() +- Z() +- t = gc.collect() +- c, nc = getstats() +- self.assertEqual(t, 2*N) +- self.assertEqual(c - oldc, 2*N) +- self.assertEqual(nc - oldnc, 0) +- +- # The A() trash should have been reclaimed already but the +- # 2 copies of Z are still in zs (and the associated dicts). +- oldc, oldnc = c, nc +- zs.clear() +- t = gc.collect() +- c, nc = getstats() +- self.assertEqual(t, 4) +- self.assertEqual(c - oldc, 4) +- self.assertEqual(nc - oldnc, 0) +- +- gc.enable() +- +- @unittest.skipIf(ContainerNoGC is None, +- 'requires ContainerNoGC extension type') +- def test_trash_weakref_clear(self): +- # Test that trash weakrefs are properly cleared (bpo-38006). +- # +- # Structure we are creating: +- # +- # Z <- Y <- A--+--> WZ -> C +- # ^ | +- # +--+ +- # where: +- # WZ is a weakref to Z with callback C +- # Y doesn't implement tp_traverse +- # A contains a reference to itself, Y and WZ +- # +- # A, Y, Z, WZ are all trash. The GC doesn't know that Z is trash +- # because Y does not implement tp_traverse. To show the bug, WZ needs +- # to live long enough so that Z is deallocated before it. Then, if +- # gcmodule is buggy, when Z is being deallocated, C will run. +- # +- # To ensure WZ lives long enough, we put it in a second reference +- # cycle. That trick only works due to the ordering of the GC prev/next +- # linked lists. So, this test is a bit fragile. +- # +- # The bug reported in bpo-38006 is caused because the GC did not +- # clear WZ before starting the process of calling tp_clear on the +- # trash. Normally, handle_weakrefs() would find the weakref via Z and +- # clear it. However, since the GC cannot find Z, WR is not cleared and +- # it can execute during delete_garbage(). That can lead to disaster +- # since the callback might tinker with objects that have already had +- # tp_clear called on them (leaving them in possibly invalid states). +- +- callback = unittest.mock.Mock() +- +- class A: +- __slots__ = ['a', 'y', 'wz'] +- +- class Z: ++ try: ++ os.close(self.write_fd) ++ except OSError: + pass + +- # setup required object graph, as described above +- a = A() +- a.a = a +- a.y = ContainerNoGC(Z()) +- a.wz = weakref.ref(a.y.value, callback) +- # create second cycle to keep WZ alive longer +- wr_cycle = [a.wz] +- wr_cycle.append(wr_cycle) +- # ensure trash unrelated to this test is gone +- gc.collect() +- gc.disable() +- # release references and create trash +- del a, wr_cycle +- gc.collect() +- # if called, it means there is a bug in the GC. The weakref should be +- # cleared before Z dies. +- callback.assert_not_called() +- gc.enable() +- +- +-class GCCallbackTests(unittest.TestCase): +- def setUp(self): +- # Save gc state and disable it. +- self.enabled = gc.isenabled() +- gc.disable() +- self.debug = gc.get_debug() +- gc.set_debug(0) +- gc.callbacks.append(self.cb1) +- gc.callbacks.append(self.cb2) +- self.othergarbage = [] +- +- def tearDown(self): +- # Restore gc state +- del self.visit +- gc.callbacks.remove(self.cb1) +- gc.callbacks.remove(self.cb2) +- gc.set_debug(self.debug) +- if self.enabled: +- gc.enable() +- # destroy any uncollectables +- gc.collect() +- for obj in gc.garbage: +- if isinstance(obj, Uncollectable): +- obj.partner = None +- del gc.garbage[:] +- del self.othergarbage +- gc.collect() +- +- def preclean(self): +- # Remove all fluff from the system. Invoke this function +- # manually rather than through self.setUp() for maximum +- # safety. +- self.visit = [] +- gc.collect() +- garbage, gc.garbage[:] = gc.garbage[:], [] +- self.othergarbage.append(garbage) +- self.visit = [] +- +- def cb1(self, phase, info): +- self.visit.append((1, phase, dict(info))) +- +- def cb2(self, phase, info): +- self.visit.append((2, phase, dict(info))) +- if phase == "stop" and hasattr(self, "cleanup"): +- # Clean Uncollectable from garbage +- uc = [e for e in gc.garbage if isinstance(e, Uncollectable)] +- gc.garbage[:] = [e for e in gc.garbage +- if not isinstance(e, Uncollectable)] +- for e in uc: +- e.partner = None +- +- def test_collect(self): +- self.preclean() +- gc.collect() +- # Algorithmically verify the contents of self.visit +- # because it is long and tortuous. +- +- # Count the number of visits to each callback +- n = [v[0] for v in self.visit] +- n1 = [i for i in n if i == 1] +- n2 = [i for i in n if i == 2] +- self.assertEqual(n1, [1]*2) +- self.assertEqual(n2, [2]*2) +- +- # Count that we got the right number of start and stop callbacks. +- n = [v[1] for v in self.visit] +- n1 = [i for i in n if i == "start"] +- n2 = [i for i in n if i == "stop"] +- self.assertEqual(n1, ["start"]*2) +- self.assertEqual(n2, ["stop"]*2) +- +- # Check that we got the right info dict for all callbacks +- for v in self.visit: +- info = v[2] +- self.assertTrue("generation" in info) +- self.assertTrue("collected" in info) +- self.assertTrue("uncollectable" in info) +- +- def test_collect_generation(self): +- self.preclean() +- gc.collect(2) +- for v in self.visit: +- info = v[2] +- self.assertEqual(info["generation"], 2) +- +- @cpython_only +- def test_collect_garbage(self): +- self.preclean() +- # Each of these cause four objects to be garbage: Two +- # Uncollectables and their instance dicts. +- Uncollectable() +- Uncollectable() +- C1055820(666) +- gc.collect() +- for v in self.visit: +- if v[1] != "stop": +- continue +- info = v[2] +- self.assertEqual(info["collected"], 2) +- self.assertEqual(info["uncollectable"], 8) +- +- # We should now have the Uncollectables in gc.garbage +- self.assertEqual(len(gc.garbage), 4) +- for e in gc.garbage: +- self.assertIsInstance(e, Uncollectable) +- +- # Now, let our callback handle the Uncollectable instances +- self.cleanup=True +- self.visit = [] +- gc.garbage[:] = [] +- gc.collect() +- for v in self.visit: +- if v[1] != "stop": +- continue +- info = v[2] +- self.assertEqual(info["collected"], 0) +- self.assertEqual(info["uncollectable"], 4) +- +- # Uncollectables should be gone +- self.assertEqual(len(gc.garbage), 0) +- +- +- @unittest.skipIf(BUILD_WITH_NDEBUG, +- 'built with -NDEBUG') +- def test_refcount_errors(self): +- self.preclean() +- # Verify the "handling" of objects with broken refcounts +- +- # Skip the test if ctypes is not available +- import_module("ctypes") +- +- import subprocess +- code = textwrap.dedent(''' +- from test.support import gc_collect, SuppressCrashReport +- +- a = [1, 2, 3] +- b = [a] +- +- # Avoid coredump when Py_FatalError() calls abort() +- SuppressCrashReport().__enter__() +- +- # Simulate the refcount of "a" being too low (compared to the +- # references held on it by live data), but keeping it above zero +- # (to avoid deallocating it): +- import ctypes +- ctypes.pythonapi.Py_DecRef(ctypes.py_object(a)) +- +- # The garbage collector should now have a fatal error +- # when it reaches the broken object +- gc_collect() +- ''') +- p = subprocess.Popen([sys.executable, "-c", code], +- stdout=subprocess.PIPE, +- stderr=subprocess.PIPE) +- stdout, stderr = p.communicate() +- p.stdout.close() +- p.stderr.close() +- # Verify that stderr has a useful error message: +- self.assertRegex(stderr, +- br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.') +- self.assertRegex(stderr, +- br'refcount is too small') +- # "address : 0x7fb5062efc18" +- # "address : 7FB5062EFC18" +- address_regex = br'[0-9a-fA-Fx]+' +- self.assertRegex(stderr, +- br'object address : ' + address_regex) +- self.assertRegex(stderr, +- br'object refcount : 1') +- self.assertRegex(stderr, +- br'object type : ' + address_regex) +- self.assertRegex(stderr, +- br'object type name: list') +- self.assertRegex(stderr, +- br'object repr : \[1, 2, 3\]') +- +- +-class GCTogglingTests(unittest.TestCase): +- def setUp(self): +- gc.enable() +- +- def tearDown(self): +- gc.disable() +- +- def test_bug1055820c(self): +- # Corresponds to temp2c.py in the bug report. This is pretty +- # elaborate. +- +- c0 = C1055820(0) +- # Move c0 into generation 2. +- gc.collect() +- +- c1 = C1055820(1) +- c1.keep_c0_alive = c0 +- del c0.loop # now only c1 keeps c0 alive +- +- c2 = C1055820(2) +- c2wr = weakref.ref(c2) # no callback! +- +- ouch = [] +- def callback(ignored): +- ouch[:] = [c2wr()] +- +- # The callback gets associated with a wr on an object in generation 2. +- c0wr = weakref.ref(c0, callback) +- +- c0 = c1 = c2 = None +- +- # What we've set up: c0, c1, and c2 are all trash now. c0 is in +- # generation 2. The only thing keeping it alive is that c1 points to +- # it. c1 and c2 are in generation 0, and are in self-loops. There's a +- # global weakref to c2 (c2wr), but that weakref has no callback. +- # There's also a global weakref to c0 (c0wr), and that does have a +- # callback, and that callback references c2 via c2wr(). +- # +- # c0 has a wr with callback, which references c2wr +- # ^ +- # | +- # | Generation 2 above dots +- #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . +- # | Generation 0 below dots +- # | +- # | +- # ^->c1 ^->c2 has a wr but no callback +- # | | | | +- # <--v <--v +- # +- # So this is the nightmare: when generation 0 gets collected, we see +- # that c2 has a callback-free weakref, and c1 doesn't even have a +- # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is +- # the only object that has a weakref with a callback. gc clears c1 +- # and c2. Clearing c1 has the side effect of dropping the refcount on +- # c0 to 0, so c0 goes away (despite that it's in an older generation) +- # and c0's wr callback triggers. That in turn materializes a reference +- # to c2 via c2wr(), but c2 gets cleared anyway by gc. +- +- # We want to let gc happen "naturally", to preserve the distinction +- # between generations. +- junk = [] +- i = 0 +- detector = GC_Detector() +- while not detector.gc_happened: +- i += 1 +- if i > 10000: +- self.fail("gc didn't happen after 10000 iterations") +- self.assertEqual(len(ouch), 0) +- junk.append([]) # this will eventually trigger gc +- +- self.assertEqual(len(ouch), 1) # else the callback wasn't invoked +- for x in ouch: +- # If the callback resurrected c2, the instance would be damaged, +- # with an empty __dict__. +- self.assertEqual(x, None) +- +- def test_bug1055820d(self): +- # Corresponds to temp2d.py in the bug report. This is very much like +- # test_bug1055820c, but uses a __del__ method instead of a weakref +- # callback to sneak in a resurrection of cyclic trash. +- +- ouch = [] +- class D(C1055820): +- def __del__(self): +- ouch[:] = [c2wr()] +- +- d0 = D(0) +- # Move all the above into generation 2. +- gc.collect() +- +- c1 = C1055820(1) +- c1.keep_d0_alive = d0 +- del d0.loop # now only c1 keeps d0 alive +- +- c2 = C1055820(2) +- c2wr = weakref.ref(c2) # no callback! +- +- d0 = c1 = c2 = None +- +- # What we've set up: d0, c1, and c2 are all trash now. d0 is in +- # generation 2. The only thing keeping it alive is that c1 points to +- # it. c1 and c2 are in generation 0, and are in self-loops. There's +- # a global weakref to c2 (c2wr), but that weakref has no callback. +- # There are no other weakrefs. +- # +- # d0 has a __del__ method that references c2wr +- # ^ +- # | +- # | Generation 2 above dots +- #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . +- # | Generation 0 below dots +- # | +- # | +- # ^->c1 ^->c2 has a wr but no callback +- # | | | | +- # <--v <--v +- # +- # So this is the nightmare: when generation 0 gets collected, we see +- # that c2 has a callback-free weakref, and c1 doesn't even have a +- # weakref. Collecting generation 0 doesn't see d0 at all. gc clears +- # c1 and c2. Clearing c1 has the side effect of dropping the refcount +- # on d0 to 0, so d0 goes away (despite that it's in an older +- # generation) and d0's __del__ triggers. That in turn materializes +- # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc. +- +- # We want to let gc happen "naturally", to preserve the distinction +- # between generations. +- detector = GC_Detector() +- junk = [] +- i = 0 +- while not detector.gc_happened: +- i += 1 +- if i > 10000: +- self.fail("gc didn't happen after 10000 iterations") +- self.assertEqual(len(ouch), 0) +- junk.append([]) # this will eventually trigger gc +- +- self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked +- for x in ouch: +- # If __del__ resurrected c2, the instance would be damaged, with an +- # empty __dict__. +- self.assertEqual(x, None) +- +- +-class PythonFinalizationTests(unittest.TestCase): +- def test_ast_fini(self): +- # bpo-44184: Regression test for subtype_dealloc() when deallocating +- # an AST instance also destroy its AST type: subtype_dealloc() must +- # not access the type memory after deallocating the instance, since +- # the type memory can be freed as well. The test is also related to +- # _PyAST_Fini() which clears references to AST types. +- code = textwrap.dedent(""" +- import ast +- import codecs +- +- # Small AST tree to keep their AST types alive +- tree = ast.parse("def f(x, y): return 2*x-y") +- x = [tree] +- x.append(x) +- +- # Put the cycle somewhere to survive until the last GC collection. +- # Codec search functions are only cleared at the end of +- # interpreter_clear(). +- def search_func(encoding): +- return None +- search_func.a = x +- codecs.register(search_func) +- """) +- assert_python_ok("-c", code) +- +- +-def setUpModule(): +- global enabled, debug +- enabled = gc.isenabled() +- gc.disable() +- assert not gc.isenabled() +- debug = gc.get_debug() +- gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak +- gc.collect() # Delete 2nd generation garbage +- +- +-def tearDownModule(): +- gc.set_debug(debug) +- # test gc.enable() even if GC is disabled by default +- if verbose: +- print("restoring automatic collection") +- # make sure to always test gc.enable() +- gc.enable() +- assert gc.isenabled() +- if not enabled: +- gc.disable() +- + + if __name__ == "__main__": + unittest.main() +diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py +index b0a13265c98..7d2d79ebfd4 100644 +--- a/Lib/test/test_genericpath.py ++++ b/Lib/test/test_genericpath.py +@@ -8,8 +8,9 @@ + import unittest + import warnings + from test import support +-from test.support import os_helper +-from test.support import warnings_helper ++from test.support import ( ++ is_apple, os_helper, warnings_helper ++) + from test.support.script_helper import assert_python_ok + from test.support.os_helper import FakePath + +@@ -489,12 +490,14 @@ + self.assertIsInstance(abspath(path), str) + + def test_nonascii_abspath(self): +- if (os_helper.TESTFN_UNDECODABLE +- # Mac OS X denies the creation of a directory with an invalid +- # UTF-8 name. Windows allows creating a directory with an +- # arbitrary bytes name, but fails to enter this directory +- # (when the bytes name is used). +- and sys.platform not in ('win32', 'darwin')): ++ if ( ++ os_helper.TESTFN_UNDECODABLE ++ # Apple platforms deny the creation of a ++ # directory with an invalid UTF-8 name. Windows allows creating a ++ # directory with an arbitrary bytes name, but fails to enter this ++ # directory (when the bytes name is used). ++ and sys.platform not in {"win32"} and not is_apple ++ ): + name = os_helper.TESTFN_UNDECODABLE + elif os_helper.TESTFN_NONASCII: + name = os_helper.TESTFN_NONASCII +diff --git a/Lib/test/test_getpass.py b/Lib/test/test_getpass.py +index 3452e46213a..3519f2f9837 100644 +--- a/Lib/test/test_getpass.py ++++ b/Lib/test/test_getpass.py +@@ -22,6 +22,8 @@ + environ.get.return_value = expected_name + self.assertEqual(expected_name, getpass.getuser()) + ++ @unittest.skipIf(support.is_apple_mobile, ++ "FIXME: getpwuid implementation not complete on simulator") + def test_username_priorities_of_env_values(self, environ): + environ.get.return_value = None + try: +diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py +index f86e767ac0e..14434981e95 100644 +--- a/Lib/test/test_gzip.py ++++ b/Lib/test/test_gzip.py +@@ -12,6 +12,7 @@ + from subprocess import PIPE, Popen + from test.support import import_helper + from test.support import os_helper ++from test.support import requires_subprocess + from test.support import _4G, bigmemtest + from test.support.script_helper import assert_python_ok, assert_python_failure + +@@ -752,6 +753,7 @@ + class TestCommandLine(unittest.TestCase): + data = b'This is a simple test with gzip' + ++ @requires_subprocess() + def test_decompress_stdin_stdout(self): + with io.BytesIO() as bytes_io: + with gzip.GzipFile(fileobj=bytes_io, mode='wb') as gzip_file: +@@ -787,6 +789,7 @@ + self.assertEqual(rc, 1) + self.assertEqual(out, b'') + ++ @requires_subprocess() + @create_and_remove_directory(TEMPDIR) + def test_compress_stdin_outfile(self): + args = sys.executable, '-m', 'gzip' +diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py +index 5eb3c82fbdb..a8d99320234 100644 +--- a/Lib/test/test_httpservers.py ++++ b/Lib/test/test_httpservers.py +@@ -30,8 +30,9 @@ + + import unittest + from test import support +-from test.support import os_helper +-from test.support import threading_helper ++from test.support import ( ++ is_apple, os_helper, requires_subprocess, threading_helper ++) + + + class NoLogRequestHandler: +@@ -388,8 +389,8 @@ + reader.close() + return body + +- @unittest.skipIf(sys.platform == 'darwin', +- 'undecodable name cannot always be decoded on macOS') ++ @unittest.skipIf(is_apple, ++ 'undecodable name cannot always be decoded on Apple platforms') + @unittest.skipIf(sys.platform == 'win32', + 'undecodable name cannot be decoded on win32') + @unittest.skipUnless(os_helper.TESTFN_UNDECODABLE, +@@ -400,11 +401,11 @@ + with open(os.path.join(self.tempdir, filename), 'wb') as f: + f.write(os_helper.TESTFN_UNDECODABLE) + response = self.request(self.base_url + '/') +- if sys.platform == 'darwin': +- # On Mac OS the HFS+ filesystem replaces bytes that aren't valid +- # UTF-8 into a percent-encoded value. ++ if is_apple: ++ # On Apple platforms the HFS+ filesystem replaces bytes that ++ # aren't valid UTF-8 into a percent-encoded value. + for name in os.listdir(self.tempdir): +- if name != 'test': # Ignore a filename created in setUp(). ++ if name != 'test': # Ignore a filename created in setUp(). + filename = name + break + body = self.check_status_and_reason(response, HTTPStatus.OK) +@@ -684,6 +685,7 @@ + + @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0, + "This test can't be run reliably as root (issue #13308).") ++@requires_subprocess() + class CGIHTTPServerTestCase(BaseTestCase): + class request_handler(NoLogRequestHandler, CGIHTTPRequestHandler): + pass +diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py +index 21fec2ad960..c1cecb42f99 100644 +--- a/Lib/test/test_imp.py ++++ b/Lib/test/test_imp.py +@@ -9,6 +9,7 @@ + from test.support import import_helper + from test.support import os_helper + from test.support import script_helper ++from test.support import is_apple_mobile + import unittest + import warnings + with warnings.catch_warnings(): +@@ -225,6 +226,7 @@ + self.assertIsNot(orig_getenv, new_os.getenv) + + @requires_load_dynamic ++ @unittest.skipIf(is_apple_mobile, "FIXME: edge case of module loader") + def test_issue15828_load_extensions(self): + # Issue 15828 picked up that the adapter between the old imp API + # and importlib couldn't handle C extensions +@@ -237,6 +239,7 @@ + self.assertEqual(mod.__name__, example) + + @requires_load_dynamic ++ @unittest.skipIf(is_apple_mobile, "FIXME: edge case of module loader") + def test_issue16421_multiple_modules_in_one_dll(self): + # Issue 16421: loading several modules from the same compiled file fails + m = '_testimportmultiple' +@@ -264,6 +267,7 @@ + self.assertEqual(name, err.exception.name) + + @requires_load_dynamic ++ @unittest.skipIf(is_apple_mobile, "FIXME: edge case of module loader") + def test_load_module_extension_file_is_None(self): + # When loading an extension module and the file is None, open one + # on the behalf of imp.load_dynamic(). +@@ -277,6 +281,7 @@ + imp.load_module(name, None, *found[1:]) + + @requires_load_dynamic ++ @unittest.skipIf(is_apple_mobile, "FIXME: edge case of module loader") + def test_issue24748_load_module_skips_sys_modules_check(self): + name = 'test.imp_dummy' + try: +diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py +index 97447619b90..9abe0e0b7c0 100644 +--- a/Lib/test/test_import/__init__.py ++++ b/Lib/test/test_import/__init__.py +@@ -19,7 +19,7 @@ + from unittest import mock + + from test.support import os_helper +-from test.support import (is_jython, swap_attr, swap_item, cpython_only) ++from test.support import (is_apple_mobile, is_jython, swap_attr, swap_item, cpython_only) + from test.support.import_helper import ( + forget, make_legacy_pyc, unlink, unload, DirsOnSysPath) + from test.support.os_helper import ( +@@ -93,6 +93,8 @@ + self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'os' \(.*os.py\)") + + @cpython_only ++ @unittest.skipIf(is_apple_mobile, ++ "FIXME: edge case in loader") + def test_from_import_missing_attr_has_name_and_so_path(self): + import _testcapi + with self.assertRaises(ImportError) as cm: +diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py +index e8065d7dade..d3e180db5eb 100644 +--- a/Lib/test/test_importlib/extension/test_finder.py ++++ b/Lib/test/test_importlib/extension/test_finder.py +@@ -1,5 +1,5 @@ +-from .. import abc +-from .. import util ++from test.support import is_apple_mobile ++from test.test_importlib import abc, util + + machinery = util.import_importlib('importlib.machinery') + +@@ -12,9 +12,27 @@ + """Test the finder for extension modules.""" + + def find_spec(self, fullname): +- importer = self.machinery.FileFinder(util.EXTENSIONS.path, +- (self.machinery.ExtensionFileLoader, +- self.machinery.EXTENSION_SUFFIXES)) ++ if is_apple_mobile: ++ # Apple mobile platforms require a specialist loader that uses ++ # .fwork files as placeholders for the true `.so` files. ++ loaders = [ ++ ( ++ self.machinery.AppleFrameworkLoader, ++ [ ++ ext.replace(".so", ".fwork") ++ for ext in self.machinery.EXTENSION_SUFFIXES ++ ] ++ ) ++ ] ++ else: ++ loaders = [ ++ ( ++ self.machinery.ExtensionFileLoader, ++ self.machinery.EXTENSION_SUFFIXES ++ ) ++ ] ++ ++ importer = self.machinery.FileFinder(util.EXTENSIONS.path, *loaders) + + return importer.find_spec(fullname) + +diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py +index 8fd556dbed5..36d9ba9f078 100644 +--- a/Lib/test/test_importlib/extension/test_loader.py ++++ b/Lib/test/test_importlib/extension/test_loader.py +@@ -1,3 +1,4 @@ ++from test.support import is_apple_mobile + from warnings import catch_warnings + from .. import abc + from .. import util +@@ -18,8 +19,15 @@ + """Test load_module() for extension modules.""" + + def setUp(self): +- self.loader = self.machinery.ExtensionFileLoader(util.EXTENSIONS.name, +- util.EXTENSIONS.file_path) ++ ++ # Apple extensions must be distributed as frameworks. This requires ++ # a specialist loader. ++ if is_apple_mobile: ++ self.LoaderClass = self.machinery.AppleFrameworkLoader ++ else: ++ self.LoaderClass = self.machinery.ExtensionFileLoader ++ ++ self.loader = self.LoaderClass(util.EXTENSIONS.name, util.EXTENSIONS.file_path) + + def load_module(self, fullname): + with warnings.catch_warnings(): +@@ -36,13 +44,11 @@ + self.load_module('XXX') + + def test_equality(self): +- other = self.machinery.ExtensionFileLoader(util.EXTENSIONS.name, +- util.EXTENSIONS.file_path) ++ other = self.LoaderClass(util.EXTENSIONS.name, util.EXTENSIONS.file_path) + self.assertEqual(self.loader, other) + + def test_inequality(self): +- other = self.machinery.ExtensionFileLoader('_' + util.EXTENSIONS.name, +- util.EXTENSIONS.file_path) ++ other = self.LoaderClass('_' + util.EXTENSIONS.name, util.EXTENSIONS.file_path) + self.assertNotEqual(self.loader, other) + + def test_module(self): +@@ -53,8 +59,7 @@ + ('__package__', '')]: + self.assertEqual(getattr(module, attr), value) + self.assertIn(util.EXTENSIONS.name, sys.modules) +- self.assertIsInstance(module.__loader__, +- self.machinery.ExtensionFileLoader) ++ self.assertIsInstance(module.__loader__, self.LoaderClass) + + # No extension module as __init__ available for testing. + test_package = None +@@ -81,7 +86,7 @@ + self.assertFalse(self.loader.is_package(util.EXTENSIONS.name)) + for suffix in self.machinery.EXTENSION_SUFFIXES: + path = os.path.join('some', 'path', 'pkg', '__init__' + suffix) +- loader = self.machinery.ExtensionFileLoader('pkg', path) ++ loader = self.LoaderClass('pkg', path) + self.assertTrue(loader.is_package('pkg')) + + (Frozen_LoaderTests, +@@ -92,12 +97,19 @@ + # Test loading extension modules with multi-phase initialization (PEP 489). + + def setUp(self): ++ ++ # Apple extensions must be distributed as frameworks. This requires ++ # a specialist loader. ++ if is_apple_mobile: ++ self.LoaderClass = self.machinery.AppleFrameworkLoader ++ else: ++ self.LoaderClass = self.machinery.ExtensionFileLoader ++ + self.name = '_testmultiphase' + finder = self.machinery.FileFinder(None) + self.spec = importlib.util.find_spec(self.name) + assert self.spec +- self.loader = self.machinery.ExtensionFileLoader( +- self.name, self.spec.origin) ++ self.loader = self.LoaderClass(self.name, self.spec.origin) + + def load_module(self): + # Load the module from the test extension. +@@ -108,7 +120,7 @@ + def load_module_by_name(self, fullname): + # Load a module from the test extension by name. + origin = self.spec.origin +- loader = self.machinery.ExtensionFileLoader(fullname, origin) ++ loader = self.LoaderClass(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + loader.exec_module(module) +@@ -134,8 +146,7 @@ + with self.assertRaises(AttributeError): + module.__path__ + self.assertIs(module, sys.modules[self.name]) +- self.assertIsInstance(module.__loader__, +- self.machinery.ExtensionFileLoader) ++ self.assertIsInstance(module.__loader__, self.LoaderClass) + + def test_functionality(self): + # Test basic functionality of stuff defined in an extension module. +diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py +index b14ecb51b25..7e58dc321a5 100644 +--- a/Lib/test/test_importlib/util.py ++++ b/Lib/test/test_importlib/util.py +@@ -13,6 +13,7 @@ + from pathlib import Path, PurePath + from test import support + from test.support import import_helper ++from test.support import is_apple_mobile + from test.support import os_helper + import unittest + import sys +@@ -42,6 +43,11 @@ + global EXTENSIONS + for path in sys.path: + for ext in machinery.EXTENSION_SUFFIXES: ++ # Apple mobile platforms mechanically load .so files, ++ # but the findable files are labelled .fwork ++ if is_apple_mobile: ++ ext = ext.replace(".so", ".fwork") ++ + filename = EXTENSIONS.name + ext + file_path = os.path.join(path, filename) + if os.path.exists(file_path): +diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py +index 5e430dad061..ad0728408df 100644 +--- a/Lib/test/test_inspect.py ++++ b/Lib/test/test_inspect.py +@@ -24,7 +24,7 @@ + except ImportError: + ThreadPoolExecutor = None + +-from test.support import cpython_only ++from test.support import cpython_only, is_apple_mobile + from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ + from test.support.import_helper import DirsOnSysPath + from test.support.os_helper import TESTFN +@@ -727,6 +727,7 @@ + @unittest.skipIf(not hasattr(unicodedata, '__file__') or + unicodedata.__file__.endswith('.py'), + "unicodedata is not an external binary module") ++ @unittest.skipIf(is_apple_mobile, "FIXME: Edge case of module loader") + def test_findsource_binary(self): + self.assertRaises(OSError, inspect.getsource, unicodedata) + self.assertRaises(OSError, inspect.findsource, unicodedata) +diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py +index 8dae85ac4f5..54359c36f15 100644 +--- a/Lib/test/test_io.py ++++ b/Lib/test/test_io.py +@@ -39,11 +39,9 @@ + from test import support + from test.support.script_helper import ( + assert_python_ok, assert_python_failure, run_python_until_end) +-from test.support import import_helper +-from test.support import os_helper +-from test.support import threading_helper +-from test.support import warnings_helper +-from test.support import skip_if_sanitizer ++from test.support import ( ++ import_helper, is_apple, os_helper, skip_if_sanitizer, threading_helper, warnings_helper ++) + from test.support.os_helper import FakePath + + import codecs +@@ -598,10 +596,10 @@ + self.read_ops(f, True) + + def test_large_file_ops(self): +- # On Windows and Mac OSX this test consumes large resources; It takes +- # a long time to build the >2 GiB file and takes >2 GiB of disk space +- # therefore the resource must be enabled to run this test. +- if sys.platform[:3] == 'win' or sys.platform == 'darwin': ++ # On Windows and Apple platforms this test consumes large resources; It ++ # takes a long time to build the >2 GiB file and takes >2 GiB of disk ++ # space therefore the resource must be enabled to run this test. ++ if sys.platform[:3] == 'win' or is_apple: + support.requires( + 'largefile', + 'test requires %s bytes and a long time to run' % self.LARGE) +diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py +index 1d7fca6efb1..0715cc75b66 100644 +--- a/Lib/test/test_json/test_tool.py ++++ b/Lib/test/test_json/test_tool.py +@@ -85,6 +85,7 @@ + } + """) + ++ @support.requires_subprocess() + def test_stdin_stdout(self): + args = sys.executable, '-m', 'json.tool' + process = subprocess.run(args, input=self.data, capture_output=True, text=True, check=True) +@@ -140,6 +141,7 @@ + self.assertEqual(out, b'') + self.assertEqual(err, b'') + ++ @support.requires_subprocess() + def test_jsonlines(self): + args = sys.executable, '-m', 'json.tool', '--json-lines' + process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True) +@@ -160,6 +162,7 @@ + self.expect_without_sort_keys.encode().splitlines()) + self.assertEqual(err, b'') + ++ @support.requires_subprocess() + def test_indent(self): + input_ = '[1, 2]' + expect = textwrap.dedent('''\ +@@ -173,6 +176,7 @@ + self.assertEqual(process.stdout, expect) + self.assertEqual(process.stderr, '') + ++ @support.requires_subprocess() + def test_no_indent(self): + input_ = '[1,\n2]' + expect = '[1, 2]\n' +@@ -181,6 +185,7 @@ + self.assertEqual(process.stdout, expect) + self.assertEqual(process.stderr, '') + ++ @support.requires_subprocess() + def test_tab(self): + input_ = '[1, 2]' + expect = '[\n\t1,\n\t2\n]\n' +@@ -189,6 +194,7 @@ + self.assertEqual(process.stdout, expect) + self.assertEqual(process.stderr, '') + ++ @support.requires_subprocess() + def test_compact(self): + input_ = '[ 1 ,\n 2]' + expect = '[1,2]\n' +@@ -197,6 +203,7 @@ + self.assertEqual(process.stdout, expect) + self.assertEqual(process.stderr, '') + ++ @unittest.skipIf(support.is_apple_mobile, "FIXME: Edge case in encoding handling") + def test_no_ensure_ascii_flag(self): + infile = self._create_infile('{"key":"💩"}') + outfile = os_helper.TESTFN + '.out' +@@ -208,6 +215,7 @@ + expected = [b'{', b' "key": "\xf0\x9f\x92\xa9"', b"}"] + self.assertEqual(lines, expected) + ++ @unittest.skipIf(support.is_apple_mobile, "FIXME: Edge case in encoding handling") + def test_ensure_ascii_default(self): + infile = self._create_infile('{"key":"💩"}') + outfile = os_helper.TESTFN + '.out' +@@ -220,6 +228,7 @@ + self.assertEqual(lines, expected) + + @unittest.skipIf(sys.platform =="win32", "The test is failed with ValueError on Windows") ++ @support.requires_subprocess() + def test_broken_pipe_error(self): + cmd = [sys.executable, '-m', 'json.tool'] + proc = subprocess.Popen(cmd, +diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py +index 74e950450cf..b3dc348d2bc 100644 +--- a/Lib/test/test_logging.py ++++ b/Lib/test/test_logging.py +@@ -43,6 +43,7 @@ + import tempfile + from test.support.script_helper import assert_python_ok, assert_python_failure + from test import support ++from test.support import is_apple_mobile + from test.support import os_helper + from test.support import socket_helper + from test.support import threading_helper +diff --git a/Lib/test/test_mailcap.py b/Lib/test/test_mailcap.py +index 32f07ab290f..3ca7616feef 100644 +--- a/Lib/test/test_mailcap.py ++++ b/Lib/test/test_mailcap.py +@@ -2,7 +2,7 @@ + import os + import copy + import test.support +-from test.support import os_helper ++from test.support import os_helper, requires_subprocess + import unittest + import sys + +@@ -220,6 +220,7 @@ + + @unittest.skipUnless(os.name == "posix", "Requires 'test' command on system") + @unittest.skipIf(sys.platform == "vxworks", "'test' command is not supported on VxWorks") ++ @requires_subprocess() + def test_test(self): + # findmatch() will automatically check any "test" conditions and skip + # the entry if the check fails. +diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py +index 7bcf8e8399a..6ff818ac893 100644 +--- a/Lib/test/test_marshal.py ++++ b/Lib/test/test_marshal.py +@@ -1,5 +1,5 @@ + from test import support +-from test.support import os_helper ++from test.support import is_apple_mobile, os_helper + import array + import io + import marshal +@@ -233,6 +233,8 @@ + #if os.name == 'nt' and hasattr(sys, 'gettotalrefcount'): + if os.name == 'nt': + MAX_MARSHAL_STACK_DEPTH = 1000 ++ elif is_apple_mobile: ++ MAX_MARSHAL_STACK_DEPTH = 1500 + else: + MAX_MARSHAL_STACK_DEPTH = 2000 + for i in range(MAX_MARSHAL_STACK_DEPTH - 2): +diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py +index 307e2b93559..f241bfdaaa7 100644 +--- a/Lib/test/test_mmap.py ++++ b/Lib/test/test_mmap.py +@@ -1,4 +1,6 @@ +-from test.support import (requires, _2G, _4G, gc_collect, cpython_only) ++from test.support import ( ++ requires, _2G, _4G, gc_collect, cpython_only, is_apple, ++) + from test.support.import_helper import import_module + from test.support.os_helper import TESTFN, unlink + import unittest +@@ -811,7 +813,7 @@ + unlink(TESTFN) + + def _make_test_file(self, num_zeroes, tail): +- if sys.platform[:3] == 'win' or sys.platform == 'darwin': ++ if sys.platform[:3] == 'win' or is_apple: + requires('largefile', + 'test requires %s bytes and a long time to run' % str(0x180000000)) + f = open(TESTFN, 'w+b') +diff --git a/Lib/test/test_multiprocessing_fork.py b/Lib/test/test_multiprocessing_fork.py +index 5000edb7c5c..5c2f1e08cc9 100644 +--- a/Lib/test/test_multiprocessing_fork.py ++++ b/Lib/test/test_multiprocessing_fork.py +@@ -13,6 +13,9 @@ + if sys.platform == 'darwin': + raise unittest.SkipTest("test may crash on macOS (bpo-33725)") + ++if support.is_apple_mobile: ++ raise unittest.SkipTest("Can't use fork on Apple mobile") ++ + test._test_multiprocessing.install_tests_in_module_dict(globals(), 'fork') + + if __name__ == '__main__': +diff --git a/Lib/test/test_multiprocessing_forkserver.py b/Lib/test/test_multiprocessing_forkserver.py +index 6ad5faf9e8a..0c0f470b6d3 100644 +--- a/Lib/test/test_multiprocessing_forkserver.py ++++ b/Lib/test/test_multiprocessing_forkserver.py +@@ -10,6 +10,9 @@ + if sys.platform == "win32": + raise unittest.SkipTest("forkserver is not available on Windows") + ++if support.is_apple_mobile: ++ raise unittest.SkipTest("Can't use fork on Apple mobile") ++ + test._test_multiprocessing.install_tests_in_module_dict(globals(), 'forkserver') + + if __name__ == '__main__': +diff --git a/Lib/test/test_multiprocessing_spawn.py b/Lib/test/test_multiprocessing_spawn.py +index 6558952308f..9c3901a63f3 100644 +--- a/Lib/test/test_multiprocessing_spawn.py ++++ b/Lib/test/test_multiprocessing_spawn.py +@@ -6,6 +6,9 @@ + if support.PGO: + raise unittest.SkipTest("test is not helpful for PGO") + ++if support.is_apple_mobile: ++ raise unittest.SkipTest("Can't use fork on Apple mobile") ++ + test._test_multiprocessing.install_tests_in_module_dict(globals(), 'spawn') + + if __name__ == '__main__': +diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py +index 044ce5c1a39..8daa5f4071d 100644 +--- a/Lib/test/test_os.py ++++ b/Lib/test/test_os.py +@@ -33,6 +33,8 @@ + from test import support + from test.support import import_helper + from test.support import os_helper ++from test.support import requires_fork ++from test.support import requires_subprocess + from test.support import socket_helper + from test.support import threading_helper + from test.support import warnings_helper +@@ -1095,6 +1097,7 @@ + value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape') + self.assertEqual(os.environ['bytes'], value_str) + ++ @requires_subprocess() + def test_putenv_unsetenv(self): + name = "PYTHONTESTVAR" + value = "testvalue" +@@ -2180,6 +2183,7 @@ + self.check(os.fchown, -1, -1) + + @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()') ++ @unittest.skipIf(support.is_apple_mobile, "gh-118201: Test is flaky on iOS") + def test_fpathconf(self): + self.check(os.pathconf, "PC_NAME_MAX") + self.check(os.fpathconf, "PC_NAME_MAX") +@@ -2306,6 +2310,7 @@ + self.assertRaises(OverflowError, os.setreuid, 0, self.UID_OVERFLOW) + + @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()') ++ @requires_subprocess() + def test_setreuid_neg1(self): + # Needs to accept -1. We run this in a subprocess to avoid + # altering the test runner's process state (issue8045). +@@ -2323,6 +2328,7 @@ + self.assertRaises(OverflowError, os.setregid, 0, self.GID_OVERFLOW) + + @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()') ++ @requires_subprocess() + def test_setregid_neg1(self): + # Needs to accept -1. We run this in a subprocess to avoid + # altering the test runner's process state (issue8045). +@@ -2995,6 +3001,7 @@ + + class PidTests(unittest.TestCase): + @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid") ++ @requires_subprocess() + def test_getppid(self): + p = subprocess.Popen([sys.executable, '-c', + 'import os; print(os.getppid())'], +@@ -3003,6 +3010,7 @@ + # We are the parent of our subprocess + self.assertEqual(int(stdout), os.getpid()) + ++ @requires_fork() + def check_waitpid(self, code, exitcode, callback=None): + if sys.platform == 'win32': + # On Windows, os.spawnv() simply joins arguments with spaces: +@@ -3065,6 +3073,7 @@ + self.check_waitpid(code, exitcode=-signum, callback=kill_process) + + ++@requires_fork() + class SpawnTests(unittest.TestCase): + def create_args(self, *, with_env=False, use_bytes=False): + self.exitcode = 17 +@@ -3147,6 +3156,7 @@ + self.assertEqual(exitcode, self.exitcode) + + @requires_os_func('spawnv') ++ @requires_fork() + def test_nowait(self): + args = self.create_args() + pid = os.spawnv(os.P_NOWAIT, args[0], args) +@@ -3690,6 +3700,7 @@ + self.assertGreaterEqual(size.columns, 0) + self.assertGreaterEqual(size.lines, 0) + ++ @support.requires_subprocess() + def test_stty_match(self): + """Check if stty returns the same results + +diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py +index bf3fc5fb249..3da409e9917 100644 +--- a/Lib/test/test_pathlib.py ++++ b/Lib/test/test_pathlib.py +@@ -12,6 +12,7 @@ + from unittest import mock + + from test.support import import_helper ++from test.support import is_apple_mobile + from test.support import os_helper + from test.support.os_helper import TESTFN, FakePath + +@@ -1468,6 +1469,7 @@ + self.assertIs(type(p), type(q)) + self.assertTrue(p.is_absolute()) + ++ @unittest.skipIf(is_apple_mobile, "No home folder on Apple mobile") + def test_home(self): + with os_helper.EnvironmentVarGuard() as env: + self._test_home(self.cls.home()) +@@ -2546,6 +2548,7 @@ + 'pwd module does not expose getpwall()') + @unittest.skipIf(sys.platform == "vxworks", + "no home directory on VxWorks") ++ @unittest.skipIf(is_apple_mobile, "No home folder on Apple mobile") + def test_expanduser(self): + P = self.cls + import_helper.import_module('pwd') +diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py +index 77f68084482..94cde4008ea 100644 +--- a/Lib/test/test_pdb.py ++++ b/Lib/test/test_pdb.py +@@ -13,7 +13,7 @@ + + from contextlib import ExitStack, redirect_stdout + from io import StringIO +-from test.support import os_helper ++from test.support import os_helper, requires_subprocess + # This little helper class is essential for testing pdb under doctest. + from test.test_doctest import _FakeInput + from unittest.mock import patch +@@ -1531,6 +1531,7 @@ + """ + + ++@requires_subprocess() + class PdbTestCase(unittest.TestCase): + def tearDown(self): + os_helper.unlink(os_helper.TESTFN) +diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py +index 2d41166644a..964e8fa3154 100644 +--- a/Lib/test/test_platform.py ++++ b/Lib/test/test_platform.py +@@ -10,6 +10,14 @@ + from test import support + from test.support import os_helper + ++try: ++ # Some of the iOS tests need ctypes to operate. ++ # Confirm that the ctypes module is available ++ # is available. ++ import _ctypes ++except ImportError: ++ _ctypes = None ++ + FEDORA_OS_RELEASE = """\ + NAME=Fedora + VERSION="32 (Thirty Two)" +@@ -228,6 +236,29 @@ + self.assertEqual(res[-1], res.processor) + self.assertEqual(len(res), 6) + ++ if os.name == "posix": ++ uname = os.uname() ++ self.assertEqual(res.node, uname.nodename) ++ self.assertEqual(res.version, uname.version) ++ self.assertEqual(res.machine, uname.machine) ++ ++ if sys.platform == "android": ++ self.assertEqual(res.system, "Android") ++ self.assertEqual(res.release, platform.android_ver().release) ++ elif sys.platform == "ios": ++ # Platform module needs ctypes for full operation. If ctypes ++ # isn't available, there's no ObjC module, and dummy values are ++ # returned. ++ if _ctypes: ++ self.assertIn(res.system, {"iOS", "iPadOS"}) ++ self.assertEqual(res.release, platform.ios_ver().release) ++ else: ++ self.assertEqual(res.system, "") ++ self.assertEqual(res.release, "") ++ else: ++ self.assertEqual(res.system, uname.sysname) ++ self.assertEqual(res.release, uname.release) ++ + def test_uname_cast_to_tuple(self): + res = platform.uname() + expected = ( +@@ -277,6 +308,7 @@ + self.assertIn('processor', res) + + @unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used") ++ @support.requires_subprocess() + def test_uname_processor(self): + """ + On some systems, the processor must match the output +@@ -318,6 +350,7 @@ + def test_win32_ver(self): + res = platform.win32_ver() + ++ @support.requires_subprocess() + def test_mac_ver(self): + res = platform.mac_ver() + +@@ -370,6 +403,56 @@ + # parent + support.wait_process(pid, exitcode=0) + ++ def test_ios_ver(self): ++ result = platform.ios_ver() ++ ++ # ios_ver is only fully available on iOS where ctypes is available. ++ if sys.platform == "ios" and _ctypes: ++ system, release, model, is_simulator = result ++ # Result is a namedtuple ++ self.assertEqual(result.system, system) ++ self.assertEqual(result.release, release) ++ self.assertEqual(result.model, model) ++ self.assertEqual(result.is_simulator, is_simulator) ++ ++ # We can't assert specific values without reproducing the logic of ++ # ios_ver(), so we check that the values are broadly what we expect. ++ ++ # System is either iOS or iPadOS, depending on the test device ++ self.assertIn(system, {"iOS", "iPadOS"}) ++ ++ # Release is a numeric version specifier with at least 2 parts ++ parts = release.split(".") ++ self.assertGreaterEqual(len(parts), 2) ++ self.assertTrue(all(part.isdigit() for part in parts)) ++ ++ # If this is a simulator, we get a high level device descriptor ++ # with no identifying model number. If this is a physical device, ++ # we get a model descriptor like "iPhone13,1" ++ if is_simulator: ++ self.assertIn(model, {"iPhone", "iPad"}) ++ else: ++ self.assertTrue( ++ (model.startswith("iPhone") or model.startswith("iPad")) ++ and "," in model ++ ) ++ ++ self.assertEqual(type(is_simulator), bool) ++ else: ++ # On non-iOS platforms, calling ios_ver doesn't fail; you get ++ # default values ++ self.assertEqual(result.system, "") ++ self.assertEqual(result.release, "") ++ self.assertEqual(result.model, "") ++ self.assertFalse(result.is_simulator) ++ ++ # Check the fallback values can be overridden by arguments ++ override = platform.ios_ver("Foo", "Bar", "Whiz", True) ++ self.assertEqual(override.system, "Foo") ++ self.assertEqual(override.release, "Bar") ++ self.assertEqual(override.model, "Whiz") ++ self.assertTrue(override.is_simulator) ++ + def test_libc_ver(self): + # check that libc_ver(executable) doesn't raise an exception + if os.path.isdir(sys.executable) and \ +@@ -464,7 +547,8 @@ + 'root:xnu-4570.71.2~1/RELEASE_X86_64'), + 'x86_64', 'i386') + arch = ('64bit', '') +- with mock.patch.object(platform, 'uname', return_value=uname), \ ++ with mock.patch.object(sys, "platform", "darwin"), \ ++ mock.patch.object(platform, 'uname', return_value=uname), \ + mock.patch.object(platform, 'architecture', return_value=arch): + for mac_ver, expected_terse, expected in [ + # darwin: mac_ver() returns empty strings +diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py +index 82bbb3af9f1..2a09eed55b6 100644 +--- a/Lib/test/test_poll.py ++++ b/Lib/test/test_poll.py +@@ -8,6 +8,7 @@ + import time + import unittest + from test.support import cpython_only ++from test.support import requires_subprocess + from test.support import threading_helper + from test.support.os_helper import TESTFN + +@@ -120,6 +121,7 @@ + # Another test case for poll(). This is copied from the test case for + # select(), modified to use poll() instead. + ++ @requires_subprocess() + def test_poll2(self): + cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done' + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, +diff --git a/Lib/test/test_popen.py b/Lib/test/test_popen.py +index cac2f6177f3..50ceffc81b8 100644 +--- a/Lib/test/test_popen.py ++++ b/Lib/test/test_popen.py +@@ -7,7 +7,7 @@ + from test import support + import os, sys + +-if not hasattr(os, 'popen'): ++if not hasattr(os, 'popen') or support.is_apple_mobile: + raise unittest.SkipTest("need os.popen()") + + # Test that command-lines get down as we expect. +diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py +index 19bc8853159..9f80e779dcc 100644 +--- a/Lib/test/test_posix.py ++++ b/Lib/test/test_posix.py +@@ -1,7 +1,7 @@ + "Test posix functions" + + from test import support +-from test.support import import_helper ++from test.support import is_apple + from test.support import os_helper + from test.support import warnings_helper + from test.support.script_helper import assert_python_ok +@@ -555,6 +555,7 @@ + + @unittest.skipUnless(hasattr(posix, 'confstr'), + 'test needs posix.confstr()') ++ @unittest.skipIf(support.is_apple_mobile, "gh-118201: Test is flaky on iOS") + def test_confstr(self): + self.assertRaises(ValueError, posix.confstr, "CS_garbage") + self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True) +@@ -766,9 +767,10 @@ + check_stat(uid, gid) + self.assertRaises(OSError, chown_func, first_param, 0, -1) + check_stat(uid, gid) +- if 0 not in os.getgroups(): +- self.assertRaises(OSError, chown_func, first_param, -1, 0) +- check_stat(uid, gid) ++ if hasattr(os, 'getgroups'): ++ if 0 not in os.getgroups(): ++ self.assertRaises(OSError, chown_func, first_param, -1, 0) ++ check_stat(uid, gid) + # test illegal types + for t in str, float: + self.assertRaises(TypeError, chown_func, first_param, t(uid), gid) +@@ -1048,6 +1050,7 @@ + @unittest.skipUnless(hasattr(posix, 'getgrouplist'), "test needs posix.getgrouplist()") + @unittest.skipUnless(hasattr(pwd, 'getpwuid'), "test needs pwd.getpwuid()") + @unittest.skipUnless(hasattr(os, 'getuid'), "test needs os.getuid()") ++ @unittest.skipIf(support.is_apple_mobile, "FIXME: edge case of getpwuid() on simulator") + def test_getgrouplist(self): + user = pwd.getpwuid(os.getuid())[0] + group = pwd.getpwuid(os.getuid())[3] +@@ -1056,6 +1059,7 @@ + + @unittest.skipUnless(hasattr(os, 'getegid'), "test needs os.getegid()") + @unittest.skipUnless(hasattr(os, 'popen'), "test needs os.popen()") ++ @support.requires_subprocess() + def test_getgroups(self): + with os.popen('id -G 2>/dev/null') as idg: + groups = idg.read().strip() +@@ -1113,8 +1117,8 @@ + self.assertIsInstance(lo, int) + self.assertIsInstance(hi, int) + self.assertGreaterEqual(hi, lo) +- # OSX evidently just returns 15 without checking the argument. +- if sys.platform != "darwin": ++ # Apple plaforms return 15 without checking the argument. ++ if not is_apple: + self.assertRaises(OSError, posix.sched_get_priority_min, -23) + self.assertRaises(OSError, posix.sched_get_priority_max, -23) + +@@ -1880,11 +1884,13 @@ + + + @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") ++@support.requires_subprocess() + class TestPosixSpawn(unittest.TestCase, _PosixSpawnMixin): + spawn_func = getattr(posix, 'posix_spawn', None) + + + @unittest.skipUnless(hasattr(os, 'posix_spawnp'), "test needs os.posix_spawnp") ++@support.requires_subprocess() + class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin): + spawn_func = getattr(posix, 'posix_spawnp', None) + +diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py +index cef227cba60..f06bed405d6 100644 +--- a/Lib/test/test_posixpath.py ++++ b/Lib/test/test_posixpath.py +@@ -7,6 +7,7 @@ + from test import support + from test import test_genericpath + from test.support import import_helper ++from test.support import is_apple_mobile + from test.support import os_helper + from test.support.os_helper import FakePath + from unittest import mock +@@ -289,6 +290,7 @@ + + @unittest.skipIf(sys.platform == "vxworks", + "no home directory on VxWorks") ++ @unittest.skipIf(is_apple_mobile, "FIXME: Edge case of getpwuid handling") + def test_expanduser_pwd(self): + pwd = import_helper.import_module('pwd') + +diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py +index 0243b8a30b9..f300555eaa1 100644 +--- a/Lib/test/test_pty.py ++++ b/Lib/test/test_pty.py +@@ -1,20 +1,24 @@ +-from test.support import verbose, reap_children ++import sys ++import unittest ++from test.support import is_apple_mobile, reap_children, verbose + from test.support.import_helper import import_module ++from test.support.os_helper import TESTFN, unlink + + # Skip these tests if termios is not available + import_module('termios') + ++# Skip tests on WASM platforms, plus iOS/tvOS/watchOS ++if is_apple_mobile: ++ raise unittest.SkipTest(f"pty tests not required on {sys.platform}") ++ + import errno + import os + import pty + import tty +-import sys + import select + import signal + import socket + import io # readline +-import unittest +- + import struct + import fcntl + import warnings +diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py +index 5ed98dbff17..794d6436b61 100644 +--- a/Lib/test/test_py_compile.py ++++ b/Lib/test/test_py_compile.py +@@ -230,6 +230,7 @@ + def tearDown(self): + os_helper.rmtree(self.directory) + ++ @support.requires_subprocess() + def pycompilecmd(self, *args, **kwargs): + # assert_python_* helpers don't return proc object. We'll just use + # subprocess.run() instead of spawn_python() and its friends to test +diff --git a/Lib/test/test_quopri.py b/Lib/test/test_quopri.py +index 715544c8a96..152d1858dcd 100644 +--- a/Lib/test/test_quopri.py ++++ b/Lib/test/test_quopri.py +@@ -3,6 +3,7 @@ + import sys, io, subprocess + import quopri + ++from test import support + + + ENCSAMPLE = b"""\ +@@ -180,6 +181,7 @@ + for p, e in self.HSTRINGS: + self.assertEqual(quopri.decodestring(e, header=True), p) + ++ @support.requires_subprocess() + def test_scriptencode(self): + (p, e) = self.STRINGS[-1] + process = subprocess.Popen([sys.executable, "-mquopri"], +@@ -196,6 +198,7 @@ + self.assertEqual(cout[i], e[i]) + self.assertEqual(cout, e) + ++ @support.requires_subprocess() + def test_scriptdecode(self): + (p, e) = self.STRINGS[-1] + process = subprocess.Popen([sys.executable, "-mquopri", "-d"], +diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py +index 62e6c28280e..76ae976e69a 100644 +--- a/Lib/test/test_regrtest.py ++++ b/Lib/test/test_regrtest.py +@@ -513,6 +513,7 @@ + self.assertTrue(0 <= randseed <= 10000000, randseed) + return randseed + ++ @support.requires_subprocess() + def run_command(self, args, input=None, exitcode=0, **kw): + if not input: + input = '' +diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py +index 03bf8d8b548..9775c3e89af 100644 +--- a/Lib/test/test_repl.py ++++ b/Lib/test/test_repl.py +@@ -5,9 +5,10 @@ + import unittest + import subprocess + from textwrap import dedent +-from test.support import cpython_only, SuppressCrashReport ++from test.support import cpython_only, SuppressCrashReport, requires_subprocess + from test.support.script_helper import kill_python + ++@requires_subprocess() + def spawn_repl(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): + """Run the Python REPL with the given arguments. + +diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py +index e6d36825f15..93e1ab556ae 100644 +--- a/Lib/test/test_runpy.py ++++ b/Lib/test/test_runpy.py +@@ -12,7 +12,7 @@ + import textwrap + import unittest + import warnings +-from test.support import no_tracing, verbose ++from test.support import no_tracing, verbose, requires_subprocess + from test.support.import_helper import forget, make_legacy_pyc, unload + from test.support.os_helper import create_empty_file, temp_dir + from test.support.script_helper import make_script, make_zip_script +@@ -780,6 +780,7 @@ + ) + super().run(*args, **kwargs) + ++ @requires_subprocess() + def assertSigInt(self, *args, **kwargs): + proc = subprocess.run(*args, **kwargs, text=True, stderr=subprocess.PIPE) + self.assertTrue(proc.stderr.endswith("\nKeyboardInterrupt\n")) +diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py +index cf32cf2f6a6..810c67aa2b3 100644 +--- a/Lib/test/test_select.py ++++ b/Lib/test/test_select.py +@@ -47,6 +47,7 @@ + self.assertIsNot(w, x) + + @unittest.skipUnless(hasattr(os, 'popen'), "need os.popen()") ++ @support.requires_subprocess() + def test_select(self): + code = textwrap.dedent(''' + import time +diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py +index fe6b725a4bd..456ee9aea7b 100644 +--- a/Lib/test/test_selectors.py ++++ b/Lib/test/test_selectors.py +@@ -6,8 +6,7 @@ + import socket + import sys + from test import support +-from test.support import os_helper +-from test.support import socket_helper ++from test.support import is_apple, os_helper, socket_helper + from time import sleep + import unittest + import unittest.mock +@@ -486,7 +485,7 @@ + try: + fds = s.select() + except OSError as e: +- if e.errno == errno.EINVAL and sys.platform == 'darwin': ++ if e.errno == errno.EINVAL and is_apple: + # unexplainable errors on macOS don't need to fail the test + self.skipTest("Invalid argument error calling poll()") + raise +diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py +index 72fb3afcbef..ccb37967780 100644 +--- a/Lib/test/test_shutil.py ++++ b/Lib/test/test_shutil.py +@@ -1777,6 +1777,7 @@ + check_chown(dirname, uid, gid) + + ++@support.requires_subprocess() + class TestWhich(BaseTest, unittest.TestCase): + + def setUp(self): +@@ -2644,6 +2645,7 @@ + self.assertGreaterEqual(size.lines, 0) + + @unittest.skipUnless(os.isatty(sys.__stdout__.fileno()), "not on tty") ++ @support.requires_subprocess() + @unittest.skipUnless(hasattr(os, 'get_terminal_size'), + 'need os.get_terminal_size()') + def test_stty_match(self): +diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py +index 294cf3888d1..26d51621647 100644 +--- a/Lib/test/test_signal.py ++++ b/Lib/test/test_signal.py +@@ -11,7 +11,7 @@ + import time + import unittest + from test import support +-from test.support import os_helper ++from test.support import is_apple, is_apple_mobile, os_helper + from test.support.script_helper import assert_python_ok, spawn_python + try: + import _testcapi +@@ -89,6 +89,7 @@ + self.assertLess(len(s), signal.NSIG) + + @unittest.skipUnless(sys.executable, "sys.executable required.") ++ @support.requires_subprocess() + def test_keyboard_interrupt_exit_code(self): + """KeyboardInterrupt triggers exit via SIGINT.""" + process = subprocess.run( +@@ -139,6 +140,7 @@ + signal.signal(7, handler) + + @unittest.skipUnless(sys.executable, "sys.executable required.") ++ @support.requires_subprocess() + def test_keyboard_interrupt_exit_code(self): + """KeyboardInterrupt triggers an exit using STATUS_CONTROL_C_EXIT.""" + # We don't test via os.kill(os.getpid(), signal.CTRL_C_EVENT) here +@@ -612,6 +614,7 @@ + @unittest.skipUnless(hasattr(signal, 'siginterrupt'), "needs signal.siginterrupt()") + class SiginterruptTest(unittest.TestCase): + ++ @support.requires_fork() + def readpipe_interrupted(self, interrupt): + """Perform a read during which a signal will arrive. Return True if the + read is interrupted by the signal and raises an exception. Return False +@@ -746,7 +749,7 @@ + self.assertEqual(self.hndl_called, True) + + # Issue 3864, unknown if this affects earlier versions of freebsd also +- @unittest.skipIf(sys.platform in ('netbsd5',), ++ @unittest.skipIf(sys.platform in ('netbsd5',) or is_apple_mobile, + 'itimer not reliable (does not mix well with threading) on some BSDs.') + def test_itimer_virtual(self): + self.itimer = signal.ITIMER_VIRTUAL +@@ -1261,6 +1264,7 @@ + # Python handler + self.assertEqual(len(sigs), N, "Some signals were lost") + ++ @unittest.skipIf(is_apple, "crashes due to system bug (FB13453490)") + @unittest.skipUnless(hasattr(signal, "SIGUSR1"), + "test needs SIGUSR1") + def test_stress_modifying_handlers(self): +diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py +index c70e1fa9ae1..18086ac55b9 100644 +--- a/Lib/test/test_site.py ++++ b/Lib/test/test_site.py +@@ -221,6 +221,7 @@ + pth_file.cleanup() + + @unittest.skipUnless(sys.platform == 'win32', 'test needs Windows') ++ @support.requires_subprocess() + def test_addsitedir_hidden_file_attribute(self): + pth_file = PthFile() + pth_file.cleanup(prep=True) +@@ -249,6 +250,7 @@ + + @unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 " + "user-site (site.ENABLE_USER_SITE)") ++ @support.requires_subprocess() + def test_s_option(self): + # (ncoghlan) Change this to use script_helper... + usersite = os.path.normpath(site.USER_SITE) +@@ -534,6 +536,7 @@ + + class StartupImportTests(unittest.TestCase): + ++ @support.requires_subprocess() + def test_startup_imports(self): + # Get sys.path in isolated mode (python3 -I) + popen = subprocess.Popen([sys.executable, '-I', '-c', +@@ -582,17 +585,20 @@ + }.difference(sys.builtin_module_names) + self.assertFalse(modules.intersection(collection_mods), stderr) + ++ @support.requires_subprocess() + def test_startup_interactivehook(self): + r = subprocess.Popen([sys.executable, '-c', + 'import sys; sys.exit(hasattr(sys, "__interactivehook__"))']).wait() + self.assertTrue(r, "'__interactivehook__' not added by site") + ++ @support.requires_subprocess() + def test_startup_interactivehook_isolated(self): + # issue28192 readline is not automatically enabled in isolated mode + r = subprocess.Popen([sys.executable, '-I', '-c', + 'import sys; sys.exit(hasattr(sys, "__interactivehook__"))']).wait() + self.assertFalse(r, "'__interactivehook__' added in isolated mode") + ++ @support.requires_subprocess() + def test_startup_interactivehook_isolated_explicit(self): + # issue28192 readline can be explicitly enabled in isolated mode + r = subprocess.Popen([sys.executable, '-I', '-c', +@@ -631,6 +637,7 @@ + sys_path.append(abs_path) + return sys_path + ++ @support.requires_subprocess() + def test_underpth_nosite_file(self): + libpath = os.path.dirname(os.path.dirname(encodings.__file__)) + exe_prefix = os.path.dirname(sys.executable) +@@ -659,6 +666,7 @@ + "sys.path is incorrect" + ) + ++ @support.requires_subprocess() + def test_underpth_file(self): + libpath = os.path.dirname(os.path.dirname(encodings.__file__)) + exe_prefix = os.path.dirname(sys.executable) +diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py +index 15f7fb4a808..bbd2c604be1 100644 +--- a/Lib/test/test_socket.py ++++ b/Lib/test/test_socket.py +@@ -3,6 +3,7 @@ + from test.support import os_helper + from test.support import socket_helper + from test.support import threading_helper ++from test.support import is_apple + + import errno + import io +@@ -707,7 +708,7 @@ + super().setUp() + + def bindSock(self, sock): +- path = tempfile.mktemp(dir=self.dir_path) ++ path = socket_helper.create_unix_domain_name() + socket_helper.bind_unix_socket(sock, path) + self.addCleanup(os_helper.unlink, path) + +@@ -1169,8 +1170,11 @@ + # Find one service that exists, then check all the related interfaces. + # I've ordered this by protocols that have both a tcp and udp + # protocol, at least for modern Linuxes. +- if (sys.platform.startswith(('freebsd', 'netbsd', 'gnukfreebsd')) +- or sys.platform in ('linux', 'darwin')): ++ if ( ++ sys.platform.startswith(('freebsd', 'netbsd', 'gnukfreebsd')) ++ or sys.platform == 'linux' ++ or is_apple ++ ): + # avoid the 'echo' service on this platform, as there is an + # assumption breaking non-standard port/protocol entry + services = ('daytime', 'qotd', 'domain') +@@ -1928,12 +1932,13 @@ + self._test_socket_fileno(s, socket.AF_INET6, socket.SOCK_STREAM) + + if hasattr(socket, "AF_UNIX"): +- tmpdir = tempfile.mkdtemp() +- self.addCleanup(shutil.rmtree, tmpdir) ++ unix_name = socket_helper.create_unix_domain_name() ++ self.addCleanup(os_helper.unlink, unix_name) ++ + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.addCleanup(s.close) + try: +- s.bind(os.path.join(tmpdir, 'socket')) ++ s.bind(unix_name) + except PermissionError: + pass + else: +@@ -3541,7 +3546,7 @@ + def _testFDPassCMSG_LEN(self): + self.createAndSendFDs(1) + +- @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") ++ @unittest.skipIf(is_apple, "skipping, see issue #12958") + @unittest.skipIf(AIX, "skipping, see issue #22397") + @requireAttrs(socket, "CMSG_SPACE") + def testFDPassSeparate(self): +@@ -3552,7 +3557,7 @@ + maxcmsgs=2) + + @testFDPassSeparate.client_skip +- @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") ++ @unittest.skipIf(is_apple, "skipping, see issue #12958") + @unittest.skipIf(AIX, "skipping, see issue #22397") + def _testFDPassSeparate(self): + fd0, fd1 = self.newFDs(2) +@@ -3565,7 +3570,7 @@ + array.array("i", [fd1]))]), + len(MSG)) + +- @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") ++ @unittest.skipIf(is_apple, "skipping, see issue #12958") + @unittest.skipIf(AIX, "skipping, see issue #22397") + @requireAttrs(socket, "CMSG_SPACE") + def testFDPassSeparateMinSpace(self): +@@ -3579,7 +3584,7 @@ + maxcmsgs=2, ignoreflags=socket.MSG_CTRUNC) + + @testFDPassSeparateMinSpace.client_skip +- @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") ++ @unittest.skipIf(is_apple, "skipping, see issue #12958") + @unittest.skipIf(AIX, "skipping, see issue #22397") + def _testFDPassSeparateMinSpace(self): + fd0, fd1 = self.newFDs(2) +@@ -3603,7 +3608,7 @@ + nbytes = self.sendmsgToServer([msg]) + self.assertEqual(nbytes, len(msg)) + +- @unittest.skipIf(sys.platform == "darwin", "see issue #24725") ++ @unittest.skipIf(is_apple, "skipping, see issue #12958") + def testFDPassEmpty(self): + # Try to pass an empty FD array. Can receive either no array + # or an empty array. +diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py +index 211321f3761..3ad5b9a43f2 100644 +--- a/Lib/test/test_socketserver.py ++++ b/Lib/test/test_socketserver.py +@@ -96,8 +96,7 @@ + else: + # XXX: We need a way to tell AF_UNIX to pick its own name + # like AF_INET provides port==0. +- dir = None +- fn = tempfile.mktemp(prefix='unix_socket.', dir=dir) ++ fn = socket_helper.create_unix_domain_name() + self.test_files.append(fn) + return fn + +@@ -233,12 +232,16 @@ + self.dgram_examine) + + @requires_unix_sockets ++ @unittest.skipIf(test.support.is_apple_mobile and test.support.on_github_actions, ++ "gh-140702: Test fails regularly on iOS simulator on GitHub Actions") + def test_UnixDatagramServer(self): + self.run_server(socketserver.UnixDatagramServer, + socketserver.DatagramRequestHandler, + self.dgram_examine) + + @requires_unix_sockets ++ @unittest.skipIf(test.support.is_apple_mobile and test.support.on_github_actions, ++ "gh-140702: Test fails regularly on iOS simulator on GitHub Actions") + def test_ThreadingUnixDatagramServer(self): + self.run_server(socketserver.ThreadingUnixDatagramServer, + socketserver.DatagramRequestHandler, +diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py +index 219c25cd2f6..d2ad941c051 100644 +--- a/Lib/test/test_source_encoding.py ++++ b/Lib/test/test_source_encoding.py +@@ -1,7 +1,7 @@ + # -*- coding: koi8-r -*- + + import unittest +-from test.support import script_helper, captured_stdout ++from test.support import script_helper, captured_stdout, requires_subprocess, is_apple_mobile + from test.support.os_helper import TESTFN, unlink, rmtree + from test.support.import_helper import unload + import importlib +@@ -12,13 +12,14 @@ + + class MiscSourceEncodingTest(unittest.TestCase): + ++ @unittest.skipIf(is_apple_mobile, "FIXME: Edge case of encoding") + def test_pep263(self): + self.assertEqual( +- "ðÉÔÏÎ".encode("utf-8"), ++ "�����".encode("utf-8"), + b'\xd0\x9f\xd0\xb8\xd1\x82\xd0\xbe\xd0\xbd' + ) + self.assertEqual( +- "\ð".encode("utf-8"), ++ "\�".encode("utf-8"), + b'\\\xd0\x9f' + ) + +@@ -65,6 +66,7 @@ + # two bytes in common with the UTF-8 BOM + self.assertRaises(SyntaxError, eval, b'\xef\xbb\x20') + ++ @requires_subprocess() + def test_20731(self): + sub = subprocess.Popen([sys.executable, + os.path.join(os.path.dirname(__file__), +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 0f1397de732..f6a054ec0ee 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -4987,15 +4987,27 @@ + return # Expect the full test setup to always work on Linux. + if (isinstance(err, ConnectionResetError) or + (isinstance(err, OSError) and err.errno == errno.EINVAL) or +- re.search('wrong.version.number', getattr(err, "reason", ""), re.I)): ++ re.search( ++ # Matches the following error messages: ++ # '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)' ++ # '[SSL: RECORD_LAYER_FAILURE] record layer failure (_ssl.c:1109)' ++ # '[SSL: HTTP_REQUEST] http request (_ssl.c:1143)' ++ r'wrong.version.number|record.layer.failure|http.request', ++ str(getattr(err, "reason", "")), ++ re.IGNORECASE, ++ ) ++ ): + # On Windows the TCP RST leads to a ConnectionResetError + # (ECONNRESET) which Linux doesn't appear to surface to userspace. + # If wrap_socket() winds up on the "if connected:" path and doing +- # the actual wrapping... we get an SSLError from OpenSSL. Typically +- # WRONG_VERSION_NUMBER. While appropriate, neither is the scenario +- # we're specifically trying to test. The way this test is written +- # is known to work on Linux. We'll skip it anywhere else that it +- # does not present as doing so. ++ # the actual wrapping... we get an SSLError from OpenSSL. This is ++ # typically WRONG_VERSION_NUMBER. The same happens on iOS, but ++ # RECORD_LAYER_FAILURE or HTTP_REQUEST is the error. ++ # ++ # While appropriate, these scenarios aren't what we're specifically ++ # trying to test. The way this test is written is known to work on ++ # Linux. We'll skip it anywhere else that it does not present as ++ # doing so. + try: + self.skipTest(f"Could not recreate conditions on {sys.platform}:" + f" {err=}") +diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py +index 2e1e2c349c8..867c4723086 100644 +--- a/Lib/test/test_stat.py ++++ b/Lib/test/test_stat.py +@@ -2,8 +2,7 @@ + import os + import socket + import sys +-from test.support import os_helper +-from test.support import socket_helper ++from test.support import is_apple, os_helper, socket_helper + from test.support.import_helper import import_fresh_module + from test.support.os_helper import TESTFN + +diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py +index 0d3afe612a3..3fc38f8a754 100644 +--- a/Lib/test/test_subprocess.py ++++ b/Lib/test/test_subprocess.py +@@ -48,6 +48,8 @@ + + if support.PGO: + raise unittest.SkipTest("test is not helpful for PGO") ++if not support.has_subprocess_support: ++ raise unittest.SkipTest("test requires subprocess support") + + mswindows = (sys.platform == "win32") + +diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py +index f27450e4a35..2a49771c5d4 100644 +--- a/Lib/test/test_sundry.py ++++ b/Lib/test/test_sundry.py +@@ -2,6 +2,7 @@ + import importlib + import platform + import sys ++import sys + from test import support + from test.support import import_helper + from test.support import warnings_helper +@@ -49,7 +50,8 @@ + + import distutils.bcppcompiler + import distutils.ccompiler +- import distutils.cygwinccompiler ++ if sys.platform.startswith("win"): ++ import distutils.cygwinccompiler + import distutils.filelist + import distutils.text_file + import distutils.unixccompiler +diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py +index 79290986c49..86c2e6ff817 100644 +--- a/Lib/test/test_support.py ++++ b/Lib/test/test_support.py +@@ -489,6 +489,7 @@ + # pending child process + support.reap_children() + ++ @support.requires_subprocess() + def check_options(self, args, func, expected=None): + code = f'from test.support import {func}; print(repr({func}()))' + cmd = [sys.executable, *args, '-c', code] +diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py +index 1094d40849d..61f6c6b2840 100644 +--- a/Lib/test/test_sys.py ++++ b/Lib/test/test_sys.py +@@ -633,6 +633,7 @@ + def test_clear_type_cache(self): + sys._clear_type_cache() + ++ @support.requires_subprocess() + def test_ioencoding(self): + env = dict(os.environ) + +@@ -680,6 +681,7 @@ + 'requires OS support of non-ASCII encodings') + @unittest.skipUnless(sys.getfilesystemencoding() == locale.getpreferredencoding(False), + 'requires FS encoding to match locale') ++ @support.requires_subprocess() + def test_ioencoding_nonascii(self): + env = dict(os.environ) + +@@ -692,6 +694,7 @@ + + @unittest.skipIf(sys.base_prefix != sys.prefix, + 'Test is not venv-compatible') ++ @support.requires_subprocess() + def test_executable(self): + # sys.executable should be absolute + self.assertEqual(os.path.abspath(sys.executable), sys.executable) +@@ -726,6 +729,7 @@ + expected = None + self.check_fsencoding(fs_encoding, expected) + ++ @support.requires_subprocess() + def c_locale_get_error_handler(self, locale, isolated=False, encoding=None): + # Force the POSIX locale + env = os.environ.copy() +@@ -933,6 +937,7 @@ + self.assertIsInstance(level, int) + self.assertGreater(level, 0) + ++ @support.requires_subprocess() + def test_sys_tracebacklimit(self): + code = """if 1: + import sys +@@ -979,6 +984,7 @@ + out = out.decode('ascii', 'replace').rstrip() + self.assertEqual(out, 'mbcs replace') + ++ @support.requires_subprocess() + def test_orig_argv(self): + code = textwrap.dedent(''' + import sys +diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py +index 5ee9839c048..e4b37afab4e 100644 +--- a/Lib/test/test_sysconfig.py ++++ b/Lib/test/test_sysconfig.py +@@ -5,7 +5,7 @@ + import shutil + from copy import copy + +-from test.support import (captured_stdout, PythonSymlink) ++from test.support import (is_apple_mobile, captured_stdout, PythonSymlink) + from test.support.import_helper import import_module + from test.support.os_helper import (TESTFN, unlink, skip_unless_symlink, + change_cwd) +@@ -258,12 +258,14 @@ + + # XXX more platforms to tests here + ++ @unittest.skipIf(is_apple_mobile, ++ f"{sys.platform} doesn't distribute header files in the runtime environment") + def test_get_config_h_filename(self): + config_h = sysconfig.get_config_h_filename() + self.assertTrue(os.path.isfile(config_h), config_h) + + def test_get_scheme_names(self): +- wanted = ['nt', 'posix_home', 'posix_prefix'] ++ wanted = ['nt', 'nt_venv', 'posix_home', 'posix_prefix', 'posix_venv'] + if HAS_USER_BASE: + wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) + self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) +@@ -364,6 +366,8 @@ + self.assertEqual(status, 0) + self.assertEqual(my_platform, test_platform) + ++ @unittest.skipIf(is_apple_mobile, ++ f"{sys.platform} doesn't include config folder at runtime") + def test_srcdir(self): + # See Issues #15322, #15364. + srcdir = sysconfig.get_config_var('srcdir') +@@ -440,6 +444,8 @@ + + @unittest.skipIf(sys.platform.startswith('win'), + 'Test is not Windows compatible') ++ @unittest.skipIf(is_apple_mobile, ++ f"{sys.platform} doesn't include config folder at runtime") + def test_get_makefile_filename(self): + makefile = sysconfig.get_makefile_filename() + self.assertTrue(os.path.isfile(makefile), makefile) +diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py +index 6e06bfc7f2f..e1fb2a39750 100644 +--- a/Lib/test/test_tempfile.py ++++ b/Lib/test/test_tempfile.py +@@ -201,6 +201,7 @@ + + @unittest.skipUnless(hasattr(os, 'fork'), + "os.fork is required for this test") ++ @support.requires_fork() + def test_process_awareness(self): + # ensure that the random source differs between + # child and parent. +@@ -462,6 +463,7 @@ + self.assertEqual(mode, expected) + + @unittest.skipUnless(has_spawnl, 'os.spawnl not available') ++ @support.requires_fork() + def test_noinherit(self): + # _mkstemp_inner file handles are not inherited by child processes + +diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py +index 4ae8a833b99..76ea55f14ad 100644 +--- a/Lib/test/test_thread.py ++++ b/Lib/test/test_thread.py +@@ -225,6 +225,7 @@ + self.read_fd, self.write_fd = os.pipe() + + @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork') ++ @support.requires_fork() + @threading_helper.reap_threads + def test_forkinthread(self): + pid = None +diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py +index c54806e5946..1a01b06e722 100644 +--- a/Lib/test/test_threading.py ++++ b/Lib/test/test_threading.py +@@ -1258,6 +1258,7 @@ + lock = threading.Lock() + self.assertRaises(RuntimeError, lock.release) + ++ @support.requires_subprocess() + def test_recursion_limit(self): + # Issue 9670 + # test that excessive recursion within a non-main thread causes +diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py +index 18cd4aba24a..1c65268411e 100644 +--- a/Lib/test/test_traceback.py ++++ b/Lib/test/test_traceback.py +@@ -130,6 +130,7 @@ + str_name = '.'.join([X.__module__, X.__qualname__]) + self.assertEqual(err[0], "%s: %s\n" % (str_name, str_value)) + ++ @support.requires_subprocess() + def test_encoded_file(self): + # Test that tracebacks are correctly printed for encoded source files: + # - correct line number (Issue2384) +diff --git a/Lib/test/test_unicode_file_functions.py b/Lib/test/test_unicode_file_functions.py +index 54916dec4ea..06f3f7051f3 100644 +--- a/Lib/test/test_unicode_file_functions.py ++++ b/Lib/test/test_unicode_file_functions.py +@@ -5,7 +5,7 @@ + import unittest + import warnings + from unicodedata import normalize +-from test.support import os_helper ++from test.support import is_apple, os_helper + + + filenames = [ +@@ -22,13 +22,13 @@ + '10_\u1fee\u1ffd', + ] + +-# Mac OS X decomposes Unicode names, using Normal Form D. ++# Apple platforms decompose Unicode names, using Normal Form D. + # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html + # "However, most volume formats do not follow the exact specification for + # these normal forms. For example, HFS Plus uses a variant of Normal Form D + # in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through + # U+2FAFF are not decomposed." +-if sys.platform != 'darwin': ++if not is_apple: + filenames.extend([ + # Specific code points: NFC(fn), NFD(fn), NFKC(fn) and NFKD(fn) all different + '11_\u0385\u03d3\u03d4', +@@ -118,11 +118,11 @@ + os.stat(name) + self._apply_failure(os.listdir, name, self._listdir_failure) + +- # Skip the test on darwin, because darwin does normalize the filename to ++ # Skip the test on Apple platforms, because they don't normalize the filename to + # NFD (a variant of Unicode NFD form). Normalize the filename to NFC, NFKC, + # NFKD in Python is useless, because darwin will normalize it later and so + # open(), os.stat(), etc. don't raise any exception. +- @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') ++ @unittest.skipIf(is_apple, 'irrelevant test on Apple platforms') + def test_normalize(self): + files = set(self.files) + others = set() +@@ -137,10 +137,10 @@ + self._apply_failure(os.remove, name) + self._apply_failure(os.listdir, name) + +- # Skip the test on darwin, because darwin uses a normalization different ++ # Skip the test on Apple platforms, because they use a normalization different + # than Python NFD normalization: filenames are different even if we use + # Python NFD normalization. +- @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') ++ @unittest.skipIf(is_apple, 'irrelevant test on Apple platforms') + def test_listdir(self): + sf0 = set(self.files) + with warnings.catch_warnings(): +diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py +index fe17aac6c1f..0df55745afd 100644 +--- a/Lib/test/test_urllib2.py ++++ b/Lib/test/test_urllib2.py +@@ -1,7 +1,7 @@ + import unittest + from test import support + from test.support import os_helper +-from test.support import socket_helper ++from test.support import requires_subprocess + from test.support import warnings_helper + from test import test_urllib + +@@ -985,6 +985,7 @@ + + file_obj.close() + ++ @requires_subprocess() + def test_http_body_pipe(self): + # A file reading from a pipe. + # A pipe cannot be seek'ed. There is no way to determine the +diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py +index d8ee66e4990..ebbd71aabe7 100644 +--- a/Lib/test/test_venv.py ++++ b/Lib/test/test_venv.py +@@ -17,7 +17,8 @@ + import tempfile + import shlex + from test.support import (captured_stdout, captured_stderr, requires_zlib, +- skip_if_broken_multiprocessing_synchronize) ++ skip_if_broken_multiprocessing_synchronize, ++ requires_subprocess, is_apple_mobile) + from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree) + import unittest + import venv +@@ -35,6 +36,12 @@ + or sys._base_executable != sys.executable, + 'cannot run venv.create from within a venv on this platform') + ++# Skip tests on iOS/tvOS/watchOS ++if is_apple_mobile: ++ raise unittest.SkipTest(f"venv tests not required on {sys.platform}") ++ ++ ++@requires_subprocess() + def check_output(cmd, encoding=None): + p = subprocess.Popen(cmd, + stdout=subprocess.PIPE, +diff --git a/Lib/test/test_wait3.py b/Lib/test/test_wait3.py +index aa166baa400..964fd82e38f 100644 +--- a/Lib/test/test_wait3.py ++++ b/Lib/test/test_wait3.py +@@ -15,6 +15,9 @@ + if not hasattr(os, 'wait3'): + raise unittest.SkipTest("os.wait3 not defined") + ++if support.is_apple_mobile: ++ raise unittest.SkipTest("os.wait3 doesn't work on Apple mobile") ++ + class Wait3Test(ForkWait): + def wait_impl(self, cpid, *, exitcode): + # This many iterations can be required, since some previously run +diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py +index 673cc995d3f..547fcf40ac7 100644 +--- a/Lib/test/test_webbrowser.py ++++ b/Lib/test/test_webbrowser.py +@@ -5,8 +5,10 @@ + import subprocess + from unittest import mock + from test import support ++from test.support import is_apple_mobile + from test.support import import_helper + from test.support import os_helper ++from test.support import requires_subprocess + + + URL = 'http://www.example.com' +@@ -22,6 +24,7 @@ + return 0 + + ++@requires_subprocess() + class CommandTestMixin: + + def _test(self, meth, *, args=[URL], kw={}, options, arguments): +@@ -217,6 +220,73 @@ + arguments=['openURL({},new-tab)'.format(URL)]) + + ++@unittest.skipUnless(sys.platform == "ios", "Test only applicable to iOS") ++class IOSBrowserTest(unittest.TestCase): ++ def _obj_ref(self, *args): ++ # Construct a string representation of the arguments that can be used ++ # as a proxy for object instance references ++ return "|".join(str(a) for a in args) ++ ++ @unittest.skipIf(getattr(webbrowser, "objc", None) is None, ++ "iOS Webbrowser tests require ctypes") ++ def setUp(self): ++ # Intercept the the objc library. Wrap the calls to get the ++ # references to classes and selectors to return strings, and ++ # wrap msgSend to return stringified object references ++ self.orig_objc = webbrowser.objc ++ ++ webbrowser.objc = mock.Mock() ++ webbrowser.objc.objc_getClass = lambda cls: f"C#{cls.decode()}" ++ webbrowser.objc.sel_registerName = lambda sel: f"S#{sel.decode()}" ++ webbrowser.objc.objc_msgSend.side_effect = self._obj_ref ++ ++ def tearDown(self): ++ webbrowser.objc = self.orig_objc ++ ++ def _test(self, meth, **kwargs): ++ # The browser always gets focus, there's no concept of separate browser ++ # windows, and there's no API-level control over creating a new tab. ++ # Therefore, all calls to webbrowser are effectively the same. ++ getattr(webbrowser, meth)(URL, **kwargs) ++ ++ # The ObjC String version of the URL is created with UTF-8 encoding ++ url_string_args = [ ++ "C#NSString", ++ "S#stringWithCString:encoding:", ++ b'http://www.example.com', ++ 4, ++ ] ++ # The NSURL version of the URL is created from that string ++ url_obj_args = [ ++ "C#NSURL", ++ "S#URLWithString:", ++ self._obj_ref(*url_string_args), ++ ] ++ # The openURL call is invoked on the shared application ++ shared_app_args = ["C#UIApplication", "S#sharedApplication"] ++ ++ # Verify that the last call is the one that opens the URL. ++ webbrowser.objc.objc_msgSend.assert_called_with( ++ self._obj_ref(*shared_app_args), ++ "S#openURL:options:completionHandler:", ++ self._obj_ref(*url_obj_args), ++ None, ++ None ++ ) ++ ++ def test_open(self): ++ self._test('open') ++ ++ def test_open_with_autoraise_false(self): ++ self._test('open', autoraise=False) ++ ++ def test_open_new(self): ++ self._test('open_new') ++ ++ def test_open_new_tab(self): ++ self._test('open_new_tab') ++ ++ + class BrowserRegistrationTest(unittest.TestCase): + + def setUp(self): +@@ -300,6 +370,10 @@ + webbrowser.register(name, None, webbrowser.GenericBrowser(name)) + webbrowser.get(sys.executable) + ++ @unittest.skipIf( ++ is_apple_mobile, ++ "Apple mobile doesn't allow modifying browser with environment" ++ ) + def test_environment(self): + webbrowser = import_helper.import_fresh_module('webbrowser') + try: +@@ -311,6 +385,10 @@ + webbrowser = import_helper.import_fresh_module('webbrowser') + webbrowser.get() + ++ @unittest.skipIf( ++ is_apple_mobile, ++ "Apple mobile doesn't allow modifying browser with environment" ++ ) + def test_environment_preferred(self): + webbrowser = import_helper.import_fresh_module('webbrowser') + try: +diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py +index 55e9792b36a..31ab7c51ab7 100644 +--- a/Lib/test/test_zipfile.py ++++ b/Lib/test/test_zipfile.py +@@ -21,7 +21,7 @@ + from tempfile import TemporaryFile + from random import randint, random, randbytes + +-from test.support import script_helper ++from test.support import script_helper, requires_subprocess + from test.support import (findfile, requires_zlib, requires_bz2, + requires_lzma, captured_stdout) + from test.support.os_helper import TESTFN, unlink, rmtree, temp_dir, temp_cwd +@@ -2913,6 +2913,7 @@ + @unittest.skipUnless(sys.executable, 'sys.executable required.') + @unittest.skipUnless(os.access('/bin/bash', os.X_OK), + 'Test relies on #!/bin/bash working.') ++ @requires_subprocess() + def test_execute_zip2(self): + output = subprocess.check_output([self.exe_zip, sys.executable]) + self.assertIn(b'number in executable: 5', output) +@@ -2920,6 +2921,7 @@ + @unittest.skipUnless(sys.executable, 'sys.executable required.') + @unittest.skipUnless(os.access('/bin/bash', os.X_OK), + 'Test relies on #!/bin/bash working.') ++ @requires_subprocess() + def test_execute_zip64(self): + output = subprocess.check_output([self.exe_zip64, sys.executable]) + self.assertIn(b'number in executable: 5', output) +diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py +index 7bf50a33728..d172895be51 100644 +--- a/Lib/test/test_zipimport_support.py ++++ b/Lib/test/test_zipimport_support.py +@@ -13,7 +13,7 @@ + import inspect + import linecache + import unittest +-from test.support import os_helper ++from test.support import os_helper, is_apple_mobile + from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, + make_script, make_zip_script) + +@@ -92,6 +92,7 @@ + finally: + del sys.modules["zip_pkg"] + ++ @unittest.skipIf(is_apple_mobile, "FIXME: Edge case of doctest importer") + def test_doctest_issue4197(self): + # To avoid having to keep two copies of the doctest module's + # unit tests in sync, this test works by taking the source of +diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py +index b7fbbc1e7ba..a544819d516 100644 +--- a/Lib/unittest/test/test_program.py ++++ b/Lib/unittest/test/test_program.py +@@ -1,5 +1,3 @@ +-import io +- + import os + import sys + import subprocess +@@ -427,6 +425,7 @@ + + self.assertEqual(program.testNamePatterns, ['*foo*', '*bar*', '*pat*']) + ++ @support.requires_subprocess() + def testSelectedTestNamesFunctionalTest(self): + def run_unittest(args): + p = subprocess.Popen([sys.executable, '-m', 'unittest'] + args, +diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py +index 0082d394dc9..c6ef4851745 100644 +--- a/Lib/unittest/test/test_runner.py ++++ b/Lib/unittest/test/test_runner.py +@@ -9,6 +9,7 @@ + + from unittest.test.support import (LoggingResult, + ResultWithNoStartTestRunStopTestRun) ++from test import support + + + def resultFactory(*_): +@@ -1176,6 +1177,7 @@ + expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY) + self.assertEqual(runner._makeResult(), expectedresult) + ++ @support.requires_subprocess() + def test_warnings(self): + """ + Check that warnings argument of TextTestRunner correctly affects the +diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py +index ec3cece48c9..34a772ab3c4 100755 +--- a/Lib/webbrowser.py ++++ b/Lib/webbrowser.py +@@ -532,6 +532,9 @@ + # OS X can use below Unix support (but we prefer using the OS X + # specific stuff) + ++ if sys.platform == "ios": ++ register("iosbrowser", None, IOSBrowser(), preferred=True) ++ + if sys.platform == "serenityos": + # SerenityOS webbrowser, simply called "Browser". + register("Browser", None, BackgroundBrowser("Browser")) +@@ -688,6 +691,70 @@ + rc = osapipe.close() + return not rc + ++# ++# Platform support for iOS ++# ++if sys.platform == "ios": ++ from _ios_support import objc ++ if objc: ++ # If objc exists, we know ctypes is also importable. ++ from ctypes import c_void_p, c_char_p, c_ulong ++ ++ class IOSBrowser(BaseBrowser): ++ def open(self, url, new=0, autoraise=True): ++ sys.audit("webbrowser.open", url) ++ # If ctypes isn't available, we can't open a browser ++ if objc is None: ++ return False ++ ++ # All the messages in this call return object references. ++ objc.objc_msgSend.restype = c_void_p ++ ++ # This is the equivalent of: ++ # NSString url_string = ++ # [NSString stringWithCString:url.encode("utf-8") ++ # encoding:NSUTF8StringEncoding]; ++ NSString = objc.objc_getClass(b"NSString") ++ constructor = objc.sel_registerName(b"stringWithCString:encoding:") ++ objc.objc_msgSend.argtypes = [c_void_p, c_void_p, c_char_p, c_ulong] ++ url_string = objc.objc_msgSend( ++ NSString, ++ constructor, ++ url.encode("utf-8"), ++ 4, # NSUTF8StringEncoding = 4 ++ ) ++ ++ # Create an NSURL object representing the URL ++ # This is the equivalent of: ++ # NSURL *nsurl = [NSURL URLWithString:url]; ++ NSURL = objc.objc_getClass(b"NSURL") ++ urlWithString_ = objc.sel_registerName(b"URLWithString:") ++ objc.objc_msgSend.argtypes = [c_void_p, c_void_p, c_void_p] ++ ns_url = objc.objc_msgSend(NSURL, urlWithString_, url_string) ++ ++ # Get the shared UIApplication instance ++ # This code is the equivalent of: ++ # UIApplication shared_app = [UIApplication sharedApplication] ++ UIApplication = objc.objc_getClass(b"UIApplication") ++ sharedApplication = objc.sel_registerName(b"sharedApplication") ++ objc.objc_msgSend.argtypes = [c_void_p, c_void_p] ++ shared_app = objc.objc_msgSend(UIApplication, sharedApplication) ++ ++ # Open the URL on the shared application ++ # This code is the equivalent of: ++ # [shared_app openURL:ns_url ++ # options:NIL ++ # completionHandler:NIL]; ++ openURL_ = objc.sel_registerName(b"openURL:options:completionHandler:") ++ objc.objc_msgSend.argtypes = [ ++ c_void_p, c_void_p, c_void_p, c_void_p, c_void_p ++ ] ++ # Method returns void ++ objc.objc_msgSend.restype = None ++ objc.objc_msgSend(shared_app, openURL_, ns_url, None, None) ++ ++ return True ++ + + def main(): + import getopt +diff --git a/Mac/Resources/app-store-compliance.patch b/Mac/Resources/app-store-compliance.patch +new file mode 100644 +index 00000000000..2ccb22b9482 +--- /dev/null ++++ b/Mac/Resources/app-store-compliance.patch +@@ -0,0 +1 @@ ++# No compliance patching required. +diff --git a/Makefile.pre.in b/Makefile.pre.in +index fa99dd86c41..51bd9edd8d5 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -170,18 +170,29 @@ + EXE= @EXEEXT@ + BUILDEXE= @BUILDEXEEXT@ + ++# Name of the patch file to apply for app store compliance ++APP_STORE_COMPLIANCE_PATCH=@APP_STORE_COMPLIANCE_PATCH@ ++ + # Short name and location for Mac OS X Python framework + UNIVERSALSDK=@UNIVERSALSDK@ + PYTHONFRAMEWORK= @PYTHONFRAMEWORK@ + PYTHONFRAMEWORKDIR= @PYTHONFRAMEWORKDIR@ + PYTHONFRAMEWORKPREFIX= @PYTHONFRAMEWORKPREFIX@ + PYTHONFRAMEWORKINSTALLDIR= @PYTHONFRAMEWORKINSTALLDIR@ +-# Deployment target selected during configure, to be checked ++PYTHONFRAMEWORKINSTALLNAMEPREFIX= @PYTHONFRAMEWORKINSTALLNAMEPREFIX@ ++RESSRCDIR= @RESSRCDIR@ ++# macOS deployment target selected during configure, to be checked + # by distutils. The export statement is needed to ensure that the + # deployment target is active during build. + MACOSX_DEPLOYMENT_TARGET=@CONFIGURE_MACOSX_DEPLOYMENT_TARGET@ + @EXPORT_MACOSX_DEPLOYMENT_TARGET@export MACOSX_DEPLOYMENT_TARGET + ++# iOS Deployment target selected during configure. Unlike macOS, the iOS ++# deployment target is controlled using `-mios-version-min` arguments added to ++# CFLAGS and LDFLAGS by the configure script. This variable is not used during ++# the build, and is only listed here so it will be included in sysconfigdata. ++IPHONEOS_DEPLOYMENT_TARGET=@IPHONEOS_DEPLOYMENT_TARGET@ ++ + # Option to install to strip binaries + STRIPFLAG=-s + +@@ -307,6 +318,8 @@ + ########################################################################## + + LIBFFI_INCLUDEDIR= @LIBFFI_INCLUDEDIR@ ++LIBFFI_LIBDIR= @LIBFFI_LIBDIR@ ++LIBFFI_LIB= @LIBFFI_LIB@ + + ########################################################################## + # Parser +@@ -471,7 +484,7 @@ + + # Default target + all: @DEF_MAKE_ALL_RULE@ +-build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \ ++build_all: check-clean-src check-app-store-compliance $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \ + Programs/_testembed python-config + + # Check that the source is clean when building out of source. +@@ -483,6 +496,16 @@ + exit 1; \ + fi + ++# Check that the app store compliance patch can be applied (if configured). ++# This is checked as a dry-run against the original library sources; ++# the patch will be actually applied during the install phase. ++.PHONY: check-app-store-compliance ++check-app-store-compliance: ++ @if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \ ++ patch --dry-run --quiet --force --strip 1 --directory "$(abs_srcdir)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)"; \ ++ echo "App store compliance patch can be applied."; \ ++ fi ++ + # Profile generation build must start from a clean tree. + profile-clean-stamp: + $(MAKE) clean +@@ -651,7 +674,7 @@ + $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ + + libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) +- $(CC) -dynamiclib -Wl,-single_module $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \ ++ $(CC) -dynamiclib $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \ + + + libpython$(VERSION).sl: $(LIBRARY_OBJS) +@@ -675,14 +698,13 @@ + # This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary + # minimal framework (not including the Lib directory and such) in the current + # directory. +-RESSRCDIR=Mac/Resources/framework + $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \ + $(LIBRARY) \ + $(RESSRCDIR)/Info.plist + $(INSTALL) -d -m $(DIRMODE) $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION) + $(CC) -o $(LDLIBRARY) $(PY_CORE_LDFLAGS) -dynamiclib \ +- -all_load $(LIBRARY) -Wl,-single_module \ +- -install_name $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK) \ ++ -all_load $(LIBRARY) \ ++ -install_name $(DESTDIR)$(PYTHONFRAMEWORKINSTALLNAMEPREFIX)/$(PYTHONFRAMEWORK) \ + -compatibility_version $(VERSION) \ + -current_version $(VERSION) \ + -framework CoreFoundation $(LIBS); +@@ -694,6 +716,21 @@ + $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK) + $(LN) -fsn Versions/Current/Resources $(PYTHONFRAMEWORKDIR)/Resources + ++# This rule is for iOS, which requires an annoyingly just slighly different ++# format for frameworks to macOS. It *doesn't* use a versioned framework, and ++# the Info.plist must be in the root of the framework. ++$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK): \ ++ $(LIBRARY) \ ++ $(RESSRCDIR)/Info.plist ++ $(INSTALL) -d -m $(DIRMODE) $(PYTHONFRAMEWORKDIR) ++ $(CC) -o $(LDLIBRARY) $(PY_CORE_LDFLAGS) -dynamiclib \ ++ -all_load $(LIBRARY) \ ++ -install_name $(PYTHONFRAMEWORKINSTALLNAMEPREFIX)/$(PYTHONFRAMEWORK) \ ++ -compatibility_version $(VERSION) \ ++ -current_version $(VERSION) \ ++ -framework CoreFoundation $(LIBS); ++ $(INSTALL_DATA) $(RESSRCDIR)/Info.plist $(PYTHONFRAMEWORKDIR)/Info.plist ++ + # This rule builds the Cygwin Python DLL and import library if configured + # for a shared core library; otherwise, this rule is a noop. + $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) +@@ -1236,6 +1273,36 @@ + $(RUNSHARED) /usr/libexec/oah/translate \ + ./$(BUILDPYTHON) -E -m test -j 0 -u all $(TESTOPTS) + ++# Run the test suite on the iOS simulator. Must be run on a macOS machine with ++# a full Xcode install that has an iPhone SE (3rd edition) simulator available. ++# This must be run *after* a `make install` has completed the build. The ++# `--with-framework-name` argument *cannot* be used when configuring the build. ++XCFOLDER:=iOSTestbed.$(MULTIARCH).$(shell date +%s) ++.PHONY: testios ++testios: ++ @if test "$(MACHDEP)" != "ios"; then \ ++ echo "Cannot run the iOS testbed for a non-iOS build."; \ ++ exit 1;\ ++ fi ++ @if test "$(findstring -iphonesimulator,$(MULTIARCH))" != "-iphonesimulator"; then \ ++ echo "Cannot run the iOS testbed for non-simulator builds."; \ ++ exit 1;\ ++ fi ++ @if test $(PYTHONFRAMEWORK) != "Python"; then \ ++ echo "Cannot run the iOS testbed with a non-default framework name."; \ ++ exit 1;\ ++ fi ++ @if ! test -d $(PYTHONFRAMEWORKPREFIX); then \ ++ echo "Cannot find a finalized iOS Python.framework. Have you run 'make install' to finalize the framework build?"; \ ++ exit 1;\ ++ fi ++ ++ # Clone the testbed project into the XCFOLDER ++ $(PYTHON_FOR_BUILD) $(srcdir)/Apple/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)" ++ ++ # Run the testbed project ++ $(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W ++ + # Like testall, but with only one pass and without multiple processes. + # Run an optional script to include information about the build environment. + buildbottest: build_all platform +@@ -1264,7 +1331,11 @@ + multissltest: build_all + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py + +-install: @FRAMEWORKINSTALLFIRST@ commoninstall bininstall maninstall @FRAMEWORKINSTALLLAST@ ++# All install targets use the "all" target as synchronization point to ++# prevent race conditions with PGO builds. PGO builds use recursive make, ++# which can lead to two parallel `./python setup.py build` processes that ++# step on each others toes. ++install: @FRAMEWORKINSTALLFIRST@ @INSTALLTARGETS@ @FRAMEWORKINSTALLLAST@ + if test "x$(ENSUREPIP)" != "xno" ; then \ + case $(ENSUREPIP) in \ + upgrade) ensurepip="--upgrade" ;; \ +@@ -1601,7 +1672,16 @@ + $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ + $(DESTDIR)$(LIBDEST)/distutils/tests ; \ + fi +- -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ ++ @ # If app store compliance has been configured, apply the patch to the ++ @ # installed library code. The patch has been previously validated against ++ @ # the original source tree, so we can ignore any errors that are raised ++ @ # due to files that are missing because of --disable-test-modules etc. ++ @if [ "$(APP_STORE_COMPLIANCE_PATCH)" != "" ]; then \ ++ echo "Applying app store compliance patch"; \ ++ patch --force --reject-file "$(abs_builddir)/app-store-compliance.rej" --strip 2 --directory "$(DESTDIR)$(LIBDEST)" --input "$(abs_srcdir)/$(APP_STORE_COMPLIANCE_PATCH)" || true ; \ ++ fi ++ @ # Build PYC files for the 3 optimization levels (0, 1, 2) ++ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \ + -j0 -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ +@@ -1771,9 +1851,11 @@ + # automatically set prefix to the location deep down in the framework, so we + # only have to cater for the structural bits of the framework. + +-frameworkinstallframework: frameworkinstallstructure install frameworkinstallmaclib ++frameworkinstallframework: @FRAMEWORKINSTALLFIRST@ install frameworkinstallmaclib + +-frameworkinstallstructure: $(LDLIBRARY) ++# macOS uses a versioned frameworks structure that includes a full install ++.PHONY: frameworkinstallversionedstructure ++frameworkinstallversionedstructure: $(LDLIBRARY) + @if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ + echo Not configured with --enable-framework; \ + exit 1; \ +@@ -1794,6 +1876,30 @@ + $(LN) -fsn Versions/Current/Resources $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Resources + $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY) + ++# iOS/tvOS/watchOS uses a non-versioned framework with Info.plist in the ++# framework root, no .lproj data, and only stub compilation assistance binaries ++.PHONY: frameworkinstallunversionedstructure ++frameworkinstallunversionedstructure: $(LDLIBRARY) ++ @if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ ++ echo Not configured with --enable-framework; \ ++ exit 1; \ ++ else true; \ ++ fi ++ if test -d $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/include; then \ ++ echo "Clearing stale header symlink directory"; \ ++ rm -rf $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/include; \ ++ fi ++ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR) ++ sed 's/%VERSION%/'"`$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import platform; print(platform.python_version())'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Info.plist ++ $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY) ++ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(LIBDIR) ++ $(LN) -fs "../$(LDLIBRARY)" "$(DESTDIR)$(prefix)/lib/libpython$(LDVERSION).dylib" ++ $(LN) -fs "../$(LDLIBRARY)" "$(DESTDIR)$(prefix)/lib/libpython$(VERSION).dylib" ++ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(BINDIR) ++ for file in $(srcdir)/$(RESSRCDIR)/bin/* ; do \ ++ $(INSTALL) -m $(EXEMODE) $$file $(DESTDIR)$(BINDIR); \ ++ done ++ + # This installs Mac/Lib into the framework + # Install a number of symlinks to keep software that expects a normal unix + # install (which includes python-config) happy. +@@ -1828,6 +1934,19 @@ + frameworkinstallextras: + cd Mac && $(MAKE) installextras DESTDIR="$(DESTDIR)" + ++# On iOS, bin/lib can't live inside the framework; include needs to be called ++# "Headers", but *must* be in the framework, and *not* include the `python3.X` ++# subdirectory. The install has put these folders in the same folder as ++# Python.framework; Move the headers to their final framework-compatible home. ++.PHONY: frameworkinstallmobileheaders ++frameworkinstallmobileheaders: frameworkinstallunversionedstructure inclinstall ++ if test -d $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers; then \ ++ echo "Removing old framework headers"; \ ++ rm -rf $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers; \ ++ fi ++ mv "$(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/include/python$(LDVERSION)" "$(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers" ++ $(LN) -fs "../$(PYTHONFRAMEWORKDIR)/Headers" "$(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/include/python$(LDVERSION)" ++ + # Build the toplevel Makefile + Makefile.pre: $(srcdir)/Makefile.pre.in config.status + CONFIG_FILES=Makefile.pre CONFIG_HEADERS= $(SHELL) config.status +@@ -1928,6 +2047,10 @@ + -find build -type f -a ! -name '*.gc??' -exec rm -f {} ';' + -rm -f Include/pydtrace_probes.h + -rm -f profile-gen-stamp ++ -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/bin ++ -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/lib ++ -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/include ++ -rm -rf Apple/iOS/testbed/Python.xcframework/ios-*/Python.framework + + profile-removal: + find . -name '*.gc??' -exec rm -f {} ';' +@@ -1949,6 +2072,8 @@ + config.cache config.log pyconfig.h Modules/config.c + -rm -rf build platform + -rm -rf $(PYTHONFRAMEWORKDIR) ++ -rm -rf Apple/iOS/Frameworks ++ -rm -rf iOSTestbed.* + -rm -f python-config.py python-config + + # Make things extra clean, before making a distribution: +@@ -2028,7 +2153,7 @@ + .PHONY: all build_all sharedmods check-clean-src oldsharedmods test quicktest + .PHONY: install altinstall oldsharedinstall bininstall altbininstall + .PHONY: maninstall libinstall inclinstall libainstall sharedinstall +-.PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure ++.PHONY: frameworkinstall frameworkinstallframework + .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools + .PHONY: frameworkaltinstallunixtools recheck clean clobber distclean + .PHONY: smelly funny patchcheck touch altmaninstall commoninstall +diff --git a/Modules/getpath.c b/Modules/getpath.c +index ef6dd59a084..e8f91831286 100644 +--- a/Modules/getpath.c ++++ b/Modules/getpath.c +@@ -10,6 +10,7 @@ + #include + + #ifdef __APPLE__ ++# include "TargetConditionals.h" + # include + #endif + +@@ -1090,7 +1091,7 @@ + #endif /* HAVE_READLINK */ + + +-#ifdef WITH_NEXT_FRAMEWORK ++#if defined(WITH_NEXT_FRAMEWORK) && !defined(TARGET_OS_IPHONE) + static PyStatus + calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig) + { +@@ -1184,7 +1185,7 @@ + return _PyStatus_NO_MEMORY(); + } + +-#ifdef WITH_NEXT_FRAMEWORK ++#if defined(WITH_NEXT_FRAMEWORK) && !defined(TARGET_OS_IPHONE) + status = calculate_argv0_path_framework(calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; +diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c +index feffa43cfd0..50397b35207 100644 +--- a/Modules/posixmodule.c ++++ b/Modules/posixmodule.c +@@ -332,8 +332,6 @@ + # else + /* Unix functions that the configure script doesn't check for */ + # ifndef __VXWORKS__ +-# define HAVE_EXECV 1 +-# define HAVE_FORK 1 + # if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ + # define HAVE_FORK1 1 + # endif +@@ -346,7 +344,6 @@ + # define HAVE_KILL 1 + # define HAVE_OPENDIR 1 + # define HAVE_PIPE 1 +-# define HAVE_SYSTEM 1 + # define HAVE_WAIT 1 + # define HAVE_TTYNAME 1 + # endif /* _MSC_VER */ +diff --git a/Python/importlib_external.h b/Python/importlib_external.h +index e77ca4c2194..724aefabdee 100644 +--- a/Python/importlib_external.h ++++ b/Python/importlib_external.h +@@ -1,7 +1,7 @@ + /* Auto-generated by Programs/_freeze_importlib.c */ + const unsigned char _Py_M__importlib_bootstrap_external[] = { + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +- 0,5,0,0,0,64,0,0,0,115,250,2,0,0,100,0, ++ 0,5,0,0,0,64,0,0,0,115,10,3,0,0,100,0, + 90,0,100,1,97,1,100,2,100,1,108,2,90,2,100,2, + 100,1,108,3,90,3,100,2,100,1,108,4,90,4,100,2, + 100,1,108,5,90,5,100,2,100,1,108,6,90,6,101,4, +@@ -21,21 +21,21 @@ + 132,0,90,30,100,28,100,29,132,0,90,31,100,30,100,31, + 132,0,90,32,100,32,100,33,132,0,90,33,101,8,114,150, + 100,34,100,35,132,0,90,34,110,4,100,36,100,35,132,0, +- 90,34,100,112,100,38,100,39,132,1,90,35,101,36,101,35, ++ 90,34,100,114,100,38,100,39,132,1,90,35,101,36,101,35, + 106,37,131,1,90,38,100,40,160,39,100,41,100,42,161,2, + 100,43,23,0,90,40,101,41,160,42,101,40,100,42,161,2, + 90,43,100,44,90,44,100,45,90,45,100,46,103,1,90,46, + 101,8,114,192,101,46,160,47,100,47,161,1,1,0,101,2, + 160,48,161,0,90,49,100,48,103,1,90,50,101,50,4,0, +- 90,51,90,52,100,113,100,1,100,49,156,1,100,50,100,51, ++ 90,51,90,52,100,115,100,1,100,49,156,1,100,50,100,51, + 132,3,90,53,100,52,100,53,132,0,90,54,100,54,100,55, + 132,0,90,55,100,56,100,57,132,0,90,56,100,58,100,59, + 132,0,90,57,100,60,100,61,132,0,90,58,100,62,100,63, + 132,0,90,59,100,64,100,65,132,0,90,60,100,66,100,67, +- 132,0,90,61,100,68,100,69,132,0,90,62,100,114,100,70, +- 100,71,132,1,90,63,100,115,100,72,100,73,132,1,90,64, +- 100,116,100,75,100,76,132,1,90,65,100,77,100,78,132,0, +- 90,66,101,67,131,0,90,68,100,113,100,1,101,68,100,79, ++ 132,0,90,61,100,68,100,69,132,0,90,62,100,116,100,70, ++ 100,71,132,1,90,63,100,117,100,72,100,73,132,1,90,64, ++ 100,118,100,75,100,76,132,1,90,65,100,77,100,78,132,0, ++ 90,66,101,67,131,0,90,68,100,115,100,1,101,68,100,79, + 156,2,100,80,100,81,132,3,90,69,71,0,100,82,100,83, + 132,0,100,83,131,2,90,70,71,0,100,84,100,85,132,0, + 100,85,131,2,90,71,71,0,100,86,100,87,132,0,100,87, +@@ -47,9 +47,10 @@ + 132,0,100,97,131,2,90,77,71,0,100,98,100,99,132,0, + 100,99,131,2,90,78,71,0,100,100,100,101,132,0,100,101, + 131,2,90,79,71,0,100,102,100,103,132,0,100,103,131,2, +- 90,80,100,113,100,104,100,105,132,1,90,81,100,106,100,107, +- 132,0,90,82,100,108,100,109,132,0,90,83,100,110,100,111, +- 132,0,90,84,100,1,83,0,41,117,97,94,1,0,0,67, ++ 90,80,71,0,100,104,100,105,132,0,100,105,101,76,131,3, ++ 90,81,100,115,100,106,100,107,132,1,90,82,100,108,100,109, ++ 132,0,90,83,100,110,100,111,132,0,90,84,100,112,100,113, ++ 132,0,90,85,100,1,83,0,41,119,97,94,1,0,0,67, + 111,114,101,32,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,32,111,102,32,112,97,116,104,45,98,97,115,101,100, + 32,105,109,112,111,114,116,46,10,10,84,104,105,115,32,109, +@@ -90,2569 +91,2629 @@ + 41,2,114,5,0,0,0,218,1,115,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,218,9,60,115,101,116,99, + 111,109,112,62,50,0,0,0,115,2,0,0,0,22,0,114, +- 13,0,0,0,41,1,218,3,119,105,110,41,2,90,6,99, +- 121,103,119,105,110,90,6,100,97,114,119,105,110,99,0,0, +- 0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0, +- 0,0,3,0,0,0,115,62,0,0,0,116,0,106,1,160, +- 2,116,3,161,1,114,25,116,0,106,1,160,2,116,4,161, +- 1,114,15,100,1,137,0,110,2,100,2,137,0,135,0,102, +- 1,100,3,100,4,132,8,125,0,124,0,83,0,100,5,100, +- 4,132,0,125,0,124,0,83,0,41,6,78,90,12,80,89, +- 84,72,79,78,67,65,83,69,79,75,115,12,0,0,0,80, +- 89,84,72,79,78,67,65,83,69,79,75,99,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, +- 19,0,0,0,115,20,0,0,0,116,0,106,1,106,2,12, +- 0,111,9,136,0,116,3,106,4,118,0,83,0,41,1,122, +- 94,84,114,117,101,32,105,102,32,102,105,108,101,110,97,109, +- 101,115,32,109,117,115,116,32,98,101,32,99,104,101,99,107, +- 101,100,32,99,97,115,101,45,105,110,115,101,110,115,105,116, +- 105,118,101,108,121,32,97,110,100,32,105,103,110,111,114,101, +- 32,101,110,118,105,114,111,110,109,101,110,116,32,102,108,97, +- 103,115,32,97,114,101,32,110,111,116,32,115,101,116,46,41, +- 5,218,3,115,121,115,218,5,102,108,97,103,115,218,18,105, +- 103,110,111,114,101,95,101,110,118,105,114,111,110,109,101,110, +- 116,218,3,95,111,115,90,7,101,110,118,105,114,111,110,114, +- 7,0,0,0,169,1,218,3,107,101,121,114,7,0,0,0, +- 114,8,0,0,0,218,11,95,114,101,108,97,120,95,99,97, +- 115,101,67,0,0,0,243,2,0,0,0,20,2,122,37,95, +- 109,97,107,101,95,114,101,108,97,120,95,99,97,115,101,46, +- 60,108,111,99,97,108,115,62,46,95,114,101,108,97,120,95, +- 99,97,115,101,99,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,1,0,0,0,83,0,0,0,243,4,0, +- 0,0,100,1,83,0,41,2,122,53,84,114,117,101,32,105, +- 102,32,102,105,108,101,110,97,109,101,115,32,109,117,115,116, +- 32,98,101,32,99,104,101,99,107,101,100,32,99,97,115,101, +- 45,105,110,115,101,110,115,105,116,105,118,101,108,121,46,70, +- 114,7,0,0,0,114,7,0,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,114,21,0,0,0,71,0, +- 0,0,243,2,0,0,0,4,2,41,5,114,15,0,0,0, +- 218,8,112,108,97,116,102,111,114,109,218,10,115,116,97,114, +- 116,115,119,105,116,104,218,27,95,67,65,83,69,95,73,78, +- 83,69,78,83,73,84,73,86,69,95,80,76,65,84,70,79, +- 82,77,83,218,35,95,67,65,83,69,95,73,78,83,69,78, +- 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, +- 95,83,84,82,95,75,69,89,41,1,114,21,0,0,0,114, +- 7,0,0,0,114,19,0,0,0,114,8,0,0,0,218,16, +- 95,109,97,107,101,95,114,101,108,97,120,95,99,97,115,101, +- 60,0,0,0,115,16,0,0,0,12,1,12,1,6,1,4, +- 2,12,2,4,7,8,253,4,3,114,29,0,0,0,99,1, +- 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4, +- 0,0,0,67,0,0,0,115,20,0,0,0,116,0,124,0, +- 131,1,100,1,64,0,160,1,100,2,100,3,161,2,83,0, +- 41,4,122,42,67,111,110,118,101,114,116,32,97,32,51,50, +- 45,98,105,116,32,105,110,116,101,103,101,114,32,116,111,32, +- 108,105,116,116,108,101,45,101,110,100,105,97,110,46,236,3, +- 0,0,0,255,127,255,127,3,0,233,4,0,0,0,218,6, +- 108,105,116,116,108,101,41,2,218,3,105,110,116,218,8,116, +- 111,95,98,121,116,101,115,41,1,218,1,120,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,218,12,95,112,97, +- 99,107,95,117,105,110,116,51,50,79,0,0,0,114,22,0, +- 0,0,114,36,0,0,0,99,1,0,0,0,0,0,0,0, +- 0,0,0,0,1,0,0,0,4,0,0,0,67,0,0,0, +- 243,28,0,0,0,116,0,124,0,131,1,100,1,107,2,115, +- 8,74,0,130,1,116,1,160,2,124,0,100,2,161,2,83, +- 0,41,3,122,47,67,111,110,118,101,114,116,32,52,32,98, ++ 13,0,0,0,41,1,218,3,119,105,110,41,5,90,6,99, ++ 121,103,119,105,110,90,6,100,97,114,119,105,110,218,3,105, ++ 111,115,218,4,116,118,111,115,218,7,119,97,116,99,104,111, ++ 115,99,0,0,0,0,0,0,0,0,0,0,0,0,1,0, ++ 0,0,3,0,0,0,3,0,0,0,115,62,0,0,0,116, ++ 0,106,1,160,2,116,3,161,1,114,25,116,0,106,1,160, ++ 2,116,4,161,1,114,15,100,1,137,0,110,2,100,2,137, ++ 0,135,0,102,1,100,3,100,4,132,8,125,0,124,0,83, ++ 0,100,5,100,4,132,0,125,0,124,0,83,0,41,6,78, ++ 90,12,80,89,84,72,79,78,67,65,83,69,79,75,115,12, ++ 0,0,0,80,89,84,72,79,78,67,65,83,69,79,75,99, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 2,0,0,0,19,0,0,0,115,20,0,0,0,116,0,106, ++ 1,106,2,12,0,111,9,136,0,116,3,106,4,118,0,83, ++ 0,41,1,122,94,84,114,117,101,32,105,102,32,102,105,108, ++ 101,110,97,109,101,115,32,109,117,115,116,32,98,101,32,99, ++ 104,101,99,107,101,100,32,99,97,115,101,45,105,110,115,101, ++ 110,115,105,116,105,118,101,108,121,32,97,110,100,32,105,103, ++ 110,111,114,101,32,101,110,118,105,114,111,110,109,101,110,116, ++ 32,102,108,97,103,115,32,97,114,101,32,110,111,116,32,115, ++ 101,116,46,41,5,218,3,115,121,115,218,5,102,108,97,103, ++ 115,218,18,105,103,110,111,114,101,95,101,110,118,105,114,111, ++ 110,109,101,110,116,218,3,95,111,115,90,7,101,110,118,105, ++ 114,111,110,114,7,0,0,0,169,1,218,3,107,101,121,114, ++ 7,0,0,0,114,8,0,0,0,218,11,95,114,101,108,97, ++ 120,95,99,97,115,101,67,0,0,0,243,2,0,0,0,20, ++ 2,122,37,95,109,97,107,101,95,114,101,108,97,120,95,99, ++ 97,115,101,46,60,108,111,99,97,108,115,62,46,95,114,101, ++ 108,97,120,95,99,97,115,101,99,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,1,0,0,0,83,0,0, ++ 0,243,4,0,0,0,100,1,83,0,41,2,122,53,84,114, ++ 117,101,32,105,102,32,102,105,108,101,110,97,109,101,115,32, ++ 109,117,115,116,32,98,101,32,99,104,101,99,107,101,100,32, ++ 99,97,115,101,45,105,110,115,101,110,115,105,116,105,118,101, ++ 108,121,46,70,114,7,0,0,0,114,7,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,114,24,0, ++ 0,0,71,0,0,0,243,2,0,0,0,4,2,41,5,114, ++ 18,0,0,0,218,8,112,108,97,116,102,111,114,109,218,10, ++ 115,116,97,114,116,115,119,105,116,104,218,27,95,67,65,83, ++ 69,95,73,78,83,69,78,83,73,84,73,86,69,95,80,76, ++ 65,84,70,79,82,77,83,218,35,95,67,65,83,69,95,73, ++ 78,83,69,78,83,73,84,73,86,69,95,80,76,65,84,70, ++ 79,82,77,83,95,83,84,82,95,75,69,89,41,1,114,24, ++ 0,0,0,114,7,0,0,0,114,22,0,0,0,114,8,0, ++ 0,0,218,16,95,109,97,107,101,95,114,101,108,97,120,95, ++ 99,97,115,101,60,0,0,0,115,16,0,0,0,12,1,12, ++ 1,6,1,4,2,12,2,4,7,8,253,4,3,114,32,0, ++ 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,1, ++ 0,0,0,4,0,0,0,67,0,0,0,115,20,0,0,0, ++ 116,0,124,0,131,1,100,1,64,0,160,1,100,2,100,3, ++ 161,2,83,0,41,4,122,42,67,111,110,118,101,114,116,32, ++ 97,32,51,50,45,98,105,116,32,105,110,116,101,103,101,114, ++ 32,116,111,32,108,105,116,116,108,101,45,101,110,100,105,97, ++ 110,46,236,3,0,0,0,255,127,255,127,3,0,233,4,0, ++ 0,0,218,6,108,105,116,116,108,101,41,2,218,3,105,110, ++ 116,218,8,116,111,95,98,121,116,101,115,41,1,218,1,120, ++ 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, ++ 12,95,112,97,99,107,95,117,105,110,116,51,50,79,0,0, ++ 0,114,25,0,0,0,114,39,0,0,0,99,1,0,0,0, ++ 0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0, ++ 67,0,0,0,243,28,0,0,0,116,0,124,0,131,1,100, ++ 1,107,2,115,8,74,0,130,1,116,1,160,2,124,0,100, ++ 2,161,2,83,0,41,3,122,47,67,111,110,118,101,114,116, ++ 32,52,32,98,121,116,101,115,32,105,110,32,108,105,116,116, ++ 108,101,45,101,110,100,105,97,110,32,116,111,32,97,110,32, ++ 105,110,116,101,103,101,114,46,114,34,0,0,0,114,35,0, ++ 0,0,169,3,114,4,0,0,0,114,36,0,0,0,218,10, ++ 102,114,111,109,95,98,121,116,101,115,169,1,218,4,100,97, ++ 116,97,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,218,14,95,117,110,112,97,99,107,95,117,105,110,116,51, ++ 50,84,0,0,0,243,4,0,0,0,16,2,12,1,114,45, ++ 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, ++ 1,0,0,0,4,0,0,0,67,0,0,0,114,40,0,0, ++ 0,41,3,122,47,67,111,110,118,101,114,116,32,50,32,98, + 121,116,101,115,32,105,110,32,108,105,116,116,108,101,45,101, + 110,100,105,97,110,32,116,111,32,97,110,32,105,110,116,101, +- 103,101,114,46,114,31,0,0,0,114,32,0,0,0,169,3, +- 114,4,0,0,0,114,33,0,0,0,218,10,102,114,111,109, +- 95,98,121,116,101,115,169,1,218,4,100,97,116,97,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,218,14,95, +- 117,110,112,97,99,107,95,117,105,110,116,51,50,84,0,0, +- 0,243,4,0,0,0,16,2,12,1,114,42,0,0,0,99, +- 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +- 4,0,0,0,67,0,0,0,114,37,0,0,0,41,3,122, +- 47,67,111,110,118,101,114,116,32,50,32,98,121,116,101,115, +- 32,105,110,32,108,105,116,116,108,101,45,101,110,100,105,97, +- 110,32,116,111,32,97,110,32,105,110,116,101,103,101,114,46, +- 233,2,0,0,0,114,32,0,0,0,114,38,0,0,0,114, +- 40,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,14,95,117,110,112,97,99,107,95,117,105,110, +- 116,49,54,89,0,0,0,114,43,0,0,0,114,45,0,0, +- 0,99,0,0,0,0,0,0,0,0,0,0,0,0,5,0, +- 0,0,4,0,0,0,71,0,0,0,115,228,0,0,0,124, +- 0,115,4,100,1,83,0,116,0,124,0,131,1,100,2,107, +- 2,114,14,124,0,100,3,25,0,83,0,100,1,125,1,103, +- 0,125,2,116,1,116,2,106,3,124,0,131,2,68,0,93, +- 61,92,2,125,3,125,4,124,3,160,4,116,5,161,1,115, +- 38,124,3,160,6,116,5,161,1,114,51,124,3,160,7,116, +- 8,161,1,112,44,124,1,125,1,116,9,124,4,23,0,103, +- 1,125,2,113,24,124,3,160,6,100,4,161,1,114,76,124, +- 1,160,10,161,0,124,3,160,10,161,0,107,3,114,70,124, +- 3,125,1,124,4,103,1,125,2,113,24,124,2,160,11,124, +- 4,161,1,1,0,113,24,124,3,112,79,124,1,125,1,124, +- 2,160,11,124,4,161,1,1,0,113,24,100,5,100,6,132, +- 0,124,2,68,0,131,1,125,2,116,0,124,2,131,1,100, +- 2,107,2,114,107,124,2,100,3,25,0,115,107,124,1,116, +- 9,23,0,83,0,124,1,116,9,160,12,124,2,161,1,23, +- 0,83,0,41,7,250,31,82,101,112,108,97,99,101,109,101, +- 110,116,32,102,111,114,32,111,115,46,112,97,116,104,46,106, +- 111,105,110,40,41,46,114,10,0,0,0,114,3,0,0,0, +- 114,0,0,0,0,114,11,0,0,0,99,1,0,0,0,0, +- 0,0,0,0,0,0,0,2,0,0,0,5,0,0,0,83, +- 0,0,0,243,26,0,0,0,103,0,124,0,93,9,125,1, +- 124,1,114,2,124,1,160,0,116,1,161,1,145,2,113,2, +- 83,0,114,7,0,0,0,169,2,218,6,114,115,116,114,105, +- 112,218,15,112,97,116,104,95,115,101,112,97,114,97,116,111, +- 114,115,169,2,114,5,0,0,0,218,1,112,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,218,10,60,108,105, +- 115,116,99,111,109,112,62,119,0,0,0,115,2,0,0,0, +- 26,0,250,30,95,112,97,116,104,95,106,111,105,110,46,60, +- 108,111,99,97,108,115,62,46,60,108,105,115,116,99,111,109, +- 112,62,41,13,114,4,0,0,0,218,3,109,97,112,114,18, +- 0,0,0,218,15,95,112,97,116,104,95,115,112,108,105,116, +- 114,111,111,116,114,26,0,0,0,218,14,112,97,116,104,95, +- 115,101,112,95,116,117,112,108,101,218,8,101,110,100,115,119, +- 105,116,104,114,49,0,0,0,114,50,0,0,0,218,8,112, +- 97,116,104,95,115,101,112,218,8,99,97,115,101,102,111,108, +- 100,218,6,97,112,112,101,110,100,218,4,106,111,105,110,41, +- 5,218,10,112,97,116,104,95,112,97,114,116,115,218,4,114, +- 111,111,116,218,4,112,97,116,104,90,8,110,101,119,95,114, +- 111,111,116,218,4,116,97,105,108,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,218,10,95,112,97,116,104,95, +- 106,111,105,110,96,0,0,0,115,42,0,0,0,4,2,4, +- 1,12,1,8,1,4,1,4,1,20,1,20,1,14,1,12, +- 1,10,1,16,1,4,3,8,1,12,2,8,2,12,1,14, +- 1,20,1,8,2,14,1,114,67,0,0,0,99,0,0,0, +- 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, +- 0,71,0,0,0,115,20,0,0,0,116,0,160,1,100,1, +- 100,2,132,0,124,0,68,0,131,1,161,1,83,0,41,3, +- 114,46,0,0,0,99,1,0,0,0,0,0,0,0,0,0, +- 0,0,2,0,0,0,5,0,0,0,83,0,0,0,114,47, +- 0,0,0,114,7,0,0,0,114,48,0,0,0,41,2,114, +- 5,0,0,0,218,4,112,97,114,116,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,114,53,0,0,0,128,0, +- 0,0,115,6,0,0,0,6,0,4,1,16,255,114,54,0, +- 0,0,41,2,114,59,0,0,0,114,62,0,0,0,41,1, +- 114,63,0,0,0,114,7,0,0,0,114,7,0,0,0,114, +- 8,0,0,0,114,67,0,0,0,126,0,0,0,115,6,0, +- 0,0,10,2,2,1,8,255,99,1,0,0,0,0,0,0, +- 0,0,0,0,0,2,0,0,0,4,0,0,0,3,0,0, +- 0,115,66,0,0,0,116,0,135,0,102,1,100,1,100,2, +- 132,8,116,1,68,0,131,1,131,1,125,1,124,1,100,3, +- 107,0,114,19,100,4,136,0,102,2,83,0,136,0,100,5, +- 124,1,133,2,25,0,136,0,124,1,100,6,23,0,100,5, +- 133,2,25,0,102,2,83,0,41,7,122,32,82,101,112,108, +- 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, +- 97,116,104,46,115,112,108,105,116,40,41,46,99,1,0,0, +- 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, +- 0,51,0,0,0,115,26,0,0,0,129,0,124,0,93,8, +- 125,1,136,0,160,0,124,1,161,1,86,0,1,0,113,2, +- 100,0,83,0,169,1,78,41,1,218,5,114,102,105,110,100, +- 114,51,0,0,0,169,1,114,65,0,0,0,114,7,0,0, +- 0,114,8,0,0,0,114,9,0,0,0,134,0,0,0,115, +- 4,0,0,0,2,128,24,0,122,30,95,112,97,116,104,95, +- 115,112,108,105,116,46,60,108,111,99,97,108,115,62,46,60, +- 103,101,110,101,120,112,114,62,114,0,0,0,0,114,10,0, +- 0,0,78,114,3,0,0,0,41,2,218,3,109,97,120,114, +- 50,0,0,0,41,2,114,65,0,0,0,218,1,105,114,7, +- 0,0,0,114,71,0,0,0,114,8,0,0,0,218,11,95, +- 112,97,116,104,95,115,112,108,105,116,132,0,0,0,115,8, +- 0,0,0,22,2,8,1,8,1,28,1,114,74,0,0,0, +- 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +- 0,3,0,0,0,67,0,0,0,115,10,0,0,0,116,0, +- 160,1,124,0,161,1,83,0,41,1,122,126,83,116,97,116, +- 32,116,104,101,32,112,97,116,104,46,10,10,32,32,32,32, +- 77,97,100,101,32,97,32,115,101,112,97,114,97,116,101,32, +- 102,117,110,99,116,105,111,110,32,116,111,32,109,97,107,101, +- 32,105,116,32,101,97,115,105,101,114,32,116,111,32,111,118, +- 101,114,114,105,100,101,32,105,110,32,101,120,112,101,114,105, +- 109,101,110,116,115,10,32,32,32,32,40,101,46,103,46,32, +- 99,97,99,104,101,32,115,116,97,116,32,114,101,115,117,108, +- 116,115,41,46,10,10,32,32,32,32,41,2,114,18,0,0, +- 0,90,4,115,116,97,116,114,71,0,0,0,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,218,10,95,112,97, +- 116,104,95,115,116,97,116,140,0,0,0,115,2,0,0,0, +- 10,7,114,75,0,0,0,99,2,0,0,0,0,0,0,0, +- 0,0,0,0,3,0,0,0,8,0,0,0,67,0,0,0, +- 115,48,0,0,0,122,6,116,0,124,0,131,1,125,2,87, +- 0,110,10,4,0,116,1,121,16,1,0,1,0,1,0,89, +- 0,100,1,83,0,119,0,124,2,106,2,100,2,64,0,124, +- 1,107,2,83,0,41,3,122,49,84,101,115,116,32,119,104, +- 101,116,104,101,114,32,116,104,101,32,112,97,116,104,32,105, +- 115,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, +- 109,111,100,101,32,116,121,112,101,46,70,105,0,240,0,0, +- 41,3,114,75,0,0,0,218,7,79,83,69,114,114,111,114, +- 218,7,115,116,95,109,111,100,101,41,3,114,65,0,0,0, +- 218,4,109,111,100,101,90,9,115,116,97,116,95,105,110,102, +- 111,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, +- 218,18,95,112,97,116,104,95,105,115,95,109,111,100,101,95, +- 116,121,112,101,150,0,0,0,115,12,0,0,0,2,2,12, +- 1,12,1,6,1,2,255,14,2,114,79,0,0,0,99,1, +- 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3, +- 0,0,0,67,0,0,0,115,10,0,0,0,116,0,124,0, +- 100,1,131,2,83,0,41,2,122,31,82,101,112,108,97,99, +- 101,109,101,110,116,32,102,111,114,32,111,115,46,112,97,116, +- 104,46,105,115,102,105,108,101,46,105,0,128,0,0,41,1, +- 114,79,0,0,0,114,71,0,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,218,12,95,112,97,116,104, +- 95,105,115,102,105,108,101,159,0,0,0,243,2,0,0,0, +- 10,2,114,80,0,0,0,99,1,0,0,0,0,0,0,0, +- 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, +- 115,22,0,0,0,124,0,115,6,116,0,160,1,161,0,125, +- 0,116,2,124,0,100,1,131,2,83,0,41,2,122,30,82, +- 101,112,108,97,99,101,109,101,110,116,32,102,111,114,32,111, +- 115,46,112,97,116,104,46,105,115,100,105,114,46,105,0,64, +- 0,0,41,3,114,18,0,0,0,218,6,103,101,116,99,119, +- 100,114,79,0,0,0,114,71,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,218,11,95,112,97,116, +- 104,95,105,115,100,105,114,164,0,0,0,115,6,0,0,0, +- 4,2,8,1,10,1,114,83,0,0,0,99,1,0,0,0, +- 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, +- 67,0,0,0,115,62,0,0,0,124,0,115,4,100,1,83, +- 0,116,0,160,1,124,0,161,1,100,2,25,0,160,2,100, +- 3,100,4,161,2,125,1,116,3,124,1,131,1,100,5,107, +- 4,111,30,124,1,160,4,100,6,161,1,112,30,124,1,160, +- 5,100,4,161,1,83,0,41,7,250,30,82,101,112,108,97, ++ 103,101,114,46,233,2,0,0,0,114,35,0,0,0,114,41, ++ 0,0,0,114,43,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,14,95,117,110,112,97,99,107, ++ 95,117,105,110,116,49,54,89,0,0,0,114,46,0,0,0, ++ 114,48,0,0,0,99,0,0,0,0,0,0,0,0,0,0, ++ 0,0,5,0,0,0,4,0,0,0,71,0,0,0,115,228, ++ 0,0,0,124,0,115,4,100,1,83,0,116,0,124,0,131, ++ 1,100,2,107,2,114,14,124,0,100,3,25,0,83,0,100, ++ 1,125,1,103,0,125,2,116,1,116,2,106,3,124,0,131, ++ 2,68,0,93,61,92,2,125,3,125,4,124,3,160,4,116, ++ 5,161,1,115,38,124,3,160,6,116,5,161,1,114,51,124, ++ 3,160,7,116,8,161,1,112,44,124,1,125,1,116,9,124, ++ 4,23,0,103,1,125,2,113,24,124,3,160,6,100,4,161, ++ 1,114,76,124,1,160,10,161,0,124,3,160,10,161,0,107, ++ 3,114,70,124,3,125,1,124,4,103,1,125,2,113,24,124, ++ 2,160,11,124,4,161,1,1,0,113,24,124,3,112,79,124, ++ 1,125,1,124,2,160,11,124,4,161,1,1,0,113,24,100, ++ 5,100,6,132,0,124,2,68,0,131,1,125,2,116,0,124, ++ 2,131,1,100,2,107,2,114,107,124,2,100,3,25,0,115, ++ 107,124,1,116,9,23,0,83,0,124,1,116,9,160,12,124, ++ 2,161,1,23,0,83,0,41,7,250,31,82,101,112,108,97, + 99,101,109,101,110,116,32,102,111,114,32,111,115,46,112,97, +- 116,104,46,105,115,97,98,115,46,70,114,0,0,0,0,114, +- 2,0,0,0,114,1,0,0,0,114,3,0,0,0,122,2, +- 92,92,41,6,114,18,0,0,0,114,56,0,0,0,218,7, +- 114,101,112,108,97,99,101,114,4,0,0,0,114,26,0,0, +- 0,114,58,0,0,0,41,2,114,65,0,0,0,114,64,0, +- 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, +- 0,218,11,95,112,97,116,104,95,105,115,97,98,115,172,0, +- 0,0,115,8,0,0,0,4,2,4,1,22,1,32,1,114, +- 86,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, +- 0,1,0,0,0,3,0,0,0,67,0,0,0,115,10,0, +- 0,0,124,0,160,0,116,1,161,1,83,0,41,1,114,84, +- 0,0,0,41,2,114,26,0,0,0,114,50,0,0,0,114, +- 71,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,114,86,0,0,0,180,0,0,0,114,81,0,0, +- 0,233,182,1,0,0,99,3,0,0,0,0,0,0,0,0, +- 0,0,0,6,0,0,0,11,0,0,0,67,0,0,0,115, +- 170,0,0,0,100,1,160,0,124,0,116,1,124,0,131,1, +- 161,2,125,3,116,2,160,3,124,3,116,2,106,4,116,2, +- 106,5,66,0,116,2,106,6,66,0,124,2,100,2,64,0, +- 161,3,125,4,122,36,116,7,160,8,124,4,100,3,161,2, +- 143,13,125,5,124,5,160,9,124,1,161,1,1,0,87,0, +- 100,4,4,0,4,0,131,3,1,0,110,8,49,0,115,47, +- 119,1,1,0,1,0,1,0,89,0,1,0,116,2,160,10, +- 124,3,124,0,161,2,1,0,87,0,100,4,83,0,4,0, +- 116,11,121,84,1,0,1,0,1,0,122,7,116,2,160,12, +- 124,3,161,1,1,0,87,0,130,0,4,0,116,11,121,83, +- 1,0,1,0,1,0,89,0,130,0,119,0,119,0,41,5, +- 122,162,66,101,115,116,45,101,102,102,111,114,116,32,102,117, +- 110,99,116,105,111,110,32,116,111,32,119,114,105,116,101,32, +- 100,97,116,97,32,116,111,32,97,32,112,97,116,104,32,97, +- 116,111,109,105,99,97,108,108,121,46,10,32,32,32,32,66, +- 101,32,112,114,101,112,97,114,101,100,32,116,111,32,104,97, +- 110,100,108,101,32,97,32,70,105,108,101,69,120,105,115,116, +- 115,69,114,114,111,114,32,105,102,32,99,111,110,99,117,114, +- 114,101,110,116,32,119,114,105,116,105,110,103,32,111,102,32, +- 116,104,101,10,32,32,32,32,116,101,109,112,111,114,97,114, +- 121,32,102,105,108,101,32,105,115,32,97,116,116,101,109,112, +- 116,101,100,46,250,5,123,125,46,123,125,114,87,0,0,0, +- 90,2,119,98,78,41,13,218,6,102,111,114,109,97,116,218, +- 2,105,100,114,18,0,0,0,90,4,111,112,101,110,90,6, +- 79,95,69,88,67,76,90,7,79,95,67,82,69,65,84,90, +- 8,79,95,87,82,79,78,76,89,218,3,95,105,111,218,6, +- 70,105,108,101,73,79,218,5,119,114,105,116,101,114,85,0, +- 0,0,114,76,0,0,0,90,6,117,110,108,105,110,107,41, +- 6,114,65,0,0,0,114,41,0,0,0,114,78,0,0,0, +- 90,8,112,97,116,104,95,116,109,112,90,2,102,100,218,4, +- 102,105,108,101,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,13,95,119,114,105,116,101,95,97,116,111,109, +- 105,99,185,0,0,0,115,36,0,0,0,16,5,6,1,22, +- 1,4,255,2,2,14,3,12,1,28,255,18,2,12,1,2, +- 1,12,1,2,3,12,254,2,1,2,1,2,254,2,253,114, +- 95,0,0,0,105,111,13,0,0,114,44,0,0,0,114,32, +- 0,0,0,115,2,0,0,0,13,10,90,11,95,95,112,121, +- 99,97,99,104,101,95,95,122,4,111,112,116,45,122,3,46, +- 112,121,122,4,46,112,121,119,122,4,46,112,121,99,41,1, +- 218,12,111,112,116,105,109,105,122,97,116,105,111,110,99,2, +- 0,0,0,0,0,0,0,1,0,0,0,12,0,0,0,5, +- 0,0,0,67,0,0,0,115,80,1,0,0,124,1,100,1, +- 117,1,114,26,116,0,160,1,100,2,116,2,161,2,1,0, +- 124,2,100,1,117,1,114,20,100,3,125,3,116,3,124,3, +- 131,1,130,1,124,1,114,24,100,4,110,1,100,5,125,2, +- 116,4,160,5,124,0,161,1,125,0,116,6,124,0,131,1, +- 92,2,125,4,125,5,124,5,160,7,100,6,161,1,92,3, +- 125,6,125,7,125,8,116,8,106,9,106,10,125,9,124,9, +- 100,1,117,0,114,57,116,11,100,7,131,1,130,1,100,4, +- 160,12,124,6,114,63,124,6,110,1,124,8,124,7,124,9, +- 103,3,161,1,125,10,124,2,100,1,117,0,114,86,116,8, +- 106,13,106,14,100,8,107,2,114,82,100,4,125,2,110,4, +- 116,8,106,13,106,14,125,2,116,15,124,2,131,1,125,2, +- 124,2,100,4,107,3,114,112,124,2,160,16,161,0,115,105, +- 116,17,100,9,160,18,124,2,161,1,131,1,130,1,100,10, +- 160,18,124,10,116,19,124,2,161,3,125,10,124,10,116,20, +- 100,8,25,0,23,0,125,11,116,8,106,21,100,1,117,1, +- 114,162,116,22,124,4,131,1,115,134,116,23,116,4,160,24, +- 161,0,124,4,131,2,125,4,124,4,100,5,25,0,100,11, +- 107,2,114,152,124,4,100,8,25,0,116,25,118,1,114,152, +- 124,4,100,12,100,1,133,2,25,0,125,4,116,23,116,8, +- 106,21,124,4,160,26,116,25,161,1,124,11,131,3,83,0, +- 116,23,124,4,116,27,124,11,131,3,83,0,41,13,97,254, +- 2,0,0,71,105,118,101,110,32,116,104,101,32,112,97,116, +- 104,32,116,111,32,97,32,46,112,121,32,102,105,108,101,44, +- 32,114,101,116,117,114,110,32,116,104,101,32,112,97,116,104, +- 32,116,111,32,105,116,115,32,46,112,121,99,32,102,105,108, +- 101,46,10,10,32,32,32,32,84,104,101,32,46,112,121,32, +- 102,105,108,101,32,100,111,101,115,32,110,111,116,32,110,101, +- 101,100,32,116,111,32,101,120,105,115,116,59,32,116,104,105, +- 115,32,115,105,109,112,108,121,32,114,101,116,117,114,110,115, +- 32,116,104,101,32,112,97,116,104,32,116,111,32,116,104,101, +- 10,32,32,32,32,46,112,121,99,32,102,105,108,101,32,99, +- 97,108,99,117,108,97,116,101,100,32,97,115,32,105,102,32, +- 116,104,101,32,46,112,121,32,102,105,108,101,32,119,101,114, +- 101,32,105,109,112,111,114,116,101,100,46,10,10,32,32,32, +- 32,84,104,101,32,39,111,112,116,105,109,105,122,97,116,105, +- 111,110,39,32,112,97,114,97,109,101,116,101,114,32,99,111, +- 110,116,114,111,108,115,32,116,104,101,32,112,114,101,115,117, +- 109,101,100,32,111,112,116,105,109,105,122,97,116,105,111,110, +- 32,108,101,118,101,108,32,111,102,10,32,32,32,32,116,104, +- 101,32,98,121,116,101,99,111,100,101,32,102,105,108,101,46, +- 32,73,102,32,39,111,112,116,105,109,105,122,97,116,105,111, +- 110,39,32,105,115,32,110,111,116,32,78,111,110,101,44,32, +- 116,104,101,32,115,116,114,105,110,103,32,114,101,112,114,101, +- 115,101,110,116,97,116,105,111,110,10,32,32,32,32,111,102, +- 32,116,104,101,32,97,114,103,117,109,101,110,116,32,105,115, +- 32,116,97,107,101,110,32,97,110,100,32,118,101,114,105,102, +- 105,101,100,32,116,111,32,98,101,32,97,108,112,104,97,110, +- 117,109,101,114,105,99,32,40,101,108,115,101,32,86,97,108, +- 117,101,69,114,114,111,114,10,32,32,32,32,105,115,32,114, +- 97,105,115,101,100,41,46,10,10,32,32,32,32,84,104,101, +- 32,100,101,98,117,103,95,111,118,101,114,114,105,100,101,32, +- 112,97,114,97,109,101,116,101,114,32,105,115,32,100,101,112, +- 114,101,99,97,116,101,100,46,32,73,102,32,100,101,98,117, +- 103,95,111,118,101,114,114,105,100,101,32,105,115,32,110,111, +- 116,32,78,111,110,101,44,10,32,32,32,32,97,32,84,114, +- 117,101,32,118,97,108,117,101,32,105,115,32,116,104,101,32, +- 115,97,109,101,32,97,115,32,115,101,116,116,105,110,103,32, +- 39,111,112,116,105,109,105,122,97,116,105,111,110,39,32,116, +- 111,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105, +- 110,103,10,32,32,32,32,119,104,105,108,101,32,97,32,70, +- 97,108,115,101,32,118,97,108,117,101,32,105,115,32,101,113, +- 117,105,118,97,108,101,110,116,32,116,111,32,115,101,116,116, +- 105,110,103,32,39,111,112,116,105,109,105,122,97,116,105,111, +- 110,39,32,116,111,32,39,49,39,46,10,10,32,32,32,32, +- 73,102,32,115,121,115,46,105,109,112,108,101,109,101,110,116, +- 97,116,105,111,110,46,99,97,99,104,101,95,116,97,103,32, +- 105,115,32,78,111,110,101,32,116,104,101,110,32,78,111,116, +- 73,109,112,108,101,109,101,110,116,101,100,69,114,114,111,114, +- 32,105,115,32,114,97,105,115,101,100,46,10,10,32,32,32, +- 32,78,122,70,116,104,101,32,100,101,98,117,103,95,111,118, +- 101,114,114,105,100,101,32,112,97,114,97,109,101,116,101,114, +- 32,105,115,32,100,101,112,114,101,99,97,116,101,100,59,32, +- 117,115,101,32,39,111,112,116,105,109,105,122,97,116,105,111, +- 110,39,32,105,110,115,116,101,97,100,122,50,100,101,98,117, +- 103,95,111,118,101,114,114,105,100,101,32,111,114,32,111,112, +- 116,105,109,105,122,97,116,105,111,110,32,109,117,115,116,32, +- 98,101,32,115,101,116,32,116,111,32,78,111,110,101,114,10, +- 0,0,0,114,3,0,0,0,218,1,46,250,36,115,121,115, +- 46,105,109,112,108,101,109,101,110,116,97,116,105,111,110,46, +- 99,97,99,104,101,95,116,97,103,32,105,115,32,78,111,110, +- 101,114,0,0,0,0,122,24,123,33,114,125,32,105,115,32, +- 110,111,116,32,97,108,112,104,97,110,117,109,101,114,105,99, +- 122,7,123,125,46,123,125,123,125,114,11,0,0,0,114,44, +- 0,0,0,41,28,218,9,95,119,97,114,110,105,110,103,115, +- 218,4,119,97,114,110,218,18,68,101,112,114,101,99,97,116, +- 105,111,110,87,97,114,110,105,110,103,218,9,84,121,112,101, +- 69,114,114,111,114,114,18,0,0,0,218,6,102,115,112,97, +- 116,104,114,74,0,0,0,218,10,114,112,97,114,116,105,116, +- 105,111,110,114,15,0,0,0,218,14,105,109,112,108,101,109, +- 101,110,116,97,116,105,111,110,218,9,99,97,99,104,101,95, +- 116,97,103,218,19,78,111,116,73,109,112,108,101,109,101,110, +- 116,101,100,69,114,114,111,114,114,62,0,0,0,114,16,0, +- 0,0,218,8,111,112,116,105,109,105,122,101,218,3,115,116, +- 114,218,7,105,115,97,108,110,117,109,218,10,86,97,108,117, +- 101,69,114,114,111,114,114,89,0,0,0,218,4,95,79,80, +- 84,218,17,66,89,84,69,67,79,68,69,95,83,85,70,70, +- 73,88,69,83,218,14,112,121,99,97,99,104,101,95,112,114, +- 101,102,105,120,114,86,0,0,0,114,67,0,0,0,114,82, +- 0,0,0,114,50,0,0,0,218,6,108,115,116,114,105,112, +- 218,8,95,80,89,67,65,67,72,69,41,12,114,65,0,0, +- 0,90,14,100,101,98,117,103,95,111,118,101,114,114,105,100, +- 101,114,96,0,0,0,218,7,109,101,115,115,97,103,101,218, +- 4,104,101,97,100,114,66,0,0,0,90,4,98,97,115,101, +- 114,6,0,0,0,218,4,114,101,115,116,90,3,116,97,103, +- 90,15,97,108,109,111,115,116,95,102,105,108,101,110,97,109, +- 101,218,8,102,105,108,101,110,97,109,101,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,218,17,99,97,99,104, +- 101,95,102,114,111,109,95,115,111,117,114,99,101,124,1,0, +- 0,115,72,0,0,0,8,18,6,1,2,1,4,255,8,2, +- 4,1,8,1,12,1,10,1,12,1,16,1,8,1,8,1, +- 8,1,24,1,8,1,12,1,6,1,8,2,8,1,8,1, +- 8,1,14,1,14,1,12,1,10,1,8,9,14,1,24,5, +- 12,1,2,4,4,1,8,1,2,1,4,253,12,5,114,121, +- 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, +- 10,0,0,0,5,0,0,0,67,0,0,0,115,40,1,0, +- 0,116,0,106,1,106,2,100,1,117,0,114,10,116,3,100, +- 2,131,1,130,1,116,4,160,5,124,0,161,1,125,0,116, +- 6,124,0,131,1,92,2,125,1,125,2,100,3,125,3,116, +- 0,106,7,100,1,117,1,114,51,116,0,106,7,160,8,116, +- 9,161,1,125,4,124,1,160,10,124,4,116,11,23,0,161, +- 1,114,51,124,1,116,12,124,4,131,1,100,1,133,2,25, +- 0,125,1,100,4,125,3,124,3,115,72,116,6,124,1,131, +- 1,92,2,125,1,125,5,124,5,116,13,107,3,114,72,116, +- 14,116,13,155,0,100,5,124,0,155,2,157,3,131,1,130, +- 1,124,2,160,15,100,6,161,1,125,6,124,6,100,7,118, +- 1,114,88,116,14,100,8,124,2,155,2,157,2,131,1,130, +- 1,124,6,100,9,107,2,114,132,124,2,160,16,100,6,100, +- 10,161,2,100,11,25,0,125,7,124,7,160,10,116,17,161, +- 1,115,112,116,14,100,12,116,17,155,2,157,2,131,1,130, +- 1,124,7,116,12,116,17,131,1,100,1,133,2,25,0,125, +- 8,124,8,160,18,161,0,115,132,116,14,100,13,124,7,155, +- 2,100,14,157,3,131,1,130,1,124,2,160,19,100,6,161, +- 1,100,15,25,0,125,9,116,20,124,1,124,9,116,21,100, +- 15,25,0,23,0,131,2,83,0,41,16,97,110,1,0,0, +- 71,105,118,101,110,32,116,104,101,32,112,97,116,104,32,116, +- 111,32,97,32,46,112,121,99,46,32,102,105,108,101,44,32, +- 114,101,116,117,114,110,32,116,104,101,32,112,97,116,104,32, +- 116,111,32,105,116,115,32,46,112,121,32,102,105,108,101,46, +- 10,10,32,32,32,32,84,104,101,32,46,112,121,99,32,102, +- 105,108,101,32,100,111,101,115,32,110,111,116,32,110,101,101, +- 100,32,116,111,32,101,120,105,115,116,59,32,116,104,105,115, +- 32,115,105,109,112,108,121,32,114,101,116,117,114,110,115,32, +- 116,104,101,32,112,97,116,104,32,116,111,10,32,32,32,32, +- 116,104,101,32,46,112,121,32,102,105,108,101,32,99,97,108, +- 99,117,108,97,116,101,100,32,116,111,32,99,111,114,114,101, +- 115,112,111,110,100,32,116,111,32,116,104,101,32,46,112,121, +- 99,32,102,105,108,101,46,32,32,73,102,32,112,97,116,104, +- 32,100,111,101,115,10,32,32,32,32,110,111,116,32,99,111, +- 110,102,111,114,109,32,116,111,32,80,69,80,32,51,49,52, +- 55,47,52,56,56,32,102,111,114,109,97,116,44,32,86,97, +- 108,117,101,69,114,114,111,114,32,119,105,108,108,32,98,101, +- 32,114,97,105,115,101,100,46,32,73,102,10,32,32,32,32, +- 115,121,115,46,105,109,112,108,101,109,101,110,116,97,116,105, +- 111,110,46,99,97,99,104,101,95,116,97,103,32,105,115,32, +- 78,111,110,101,32,116,104,101,110,32,78,111,116,73,109,112, +- 108,101,109,101,110,116,101,100,69,114,114,111,114,32,105,115, +- 32,114,97,105,115,101,100,46,10,10,32,32,32,32,78,114, +- 98,0,0,0,70,84,122,31,32,110,111,116,32,98,111,116, +- 116,111,109,45,108,101,118,101,108,32,100,105,114,101,99,116, +- 111,114,121,32,105,110,32,114,97,0,0,0,62,2,0,0, +- 0,114,44,0,0,0,233,3,0,0,0,122,29,101,120,112, +- 101,99,116,101,100,32,111,110,108,121,32,50,32,111,114,32, +- 51,32,100,111,116,115,32,105,110,32,114,122,0,0,0,114, +- 44,0,0,0,233,254,255,255,255,122,53,111,112,116,105,109, +- 105,122,97,116,105,111,110,32,112,111,114,116,105,111,110,32, +- 111,102,32,102,105,108,101,110,97,109,101,32,100,111,101,115, +- 32,110,111,116,32,115,116,97,114,116,32,119,105,116,104,32, +- 122,19,111,112,116,105,109,105,122,97,116,105,111,110,32,108, +- 101,118,101,108,32,122,29,32,105,115,32,110,111,116,32,97, +- 110,32,97,108,112,104,97,110,117,109,101,114,105,99,32,118, +- 97,108,117,101,114,0,0,0,0,41,22,114,15,0,0,0, +- 114,105,0,0,0,114,106,0,0,0,114,107,0,0,0,114, +- 18,0,0,0,114,103,0,0,0,114,74,0,0,0,114,114, +- 0,0,0,114,49,0,0,0,114,50,0,0,0,114,26,0, +- 0,0,114,59,0,0,0,114,4,0,0,0,114,116,0,0, +- 0,114,111,0,0,0,218,5,99,111,117,110,116,218,6,114, +- 115,112,108,105,116,114,112,0,0,0,114,110,0,0,0,218, +- 9,112,97,114,116,105,116,105,111,110,114,67,0,0,0,218, +- 15,83,79,85,82,67,69,95,83,85,70,70,73,88,69,83, +- 41,10,114,65,0,0,0,114,118,0,0,0,90,16,112,121, +- 99,97,99,104,101,95,102,105,108,101,110,97,109,101,90,23, +- 102,111,117,110,100,95,105,110,95,112,121,99,97,99,104,101, +- 95,112,114,101,102,105,120,90,13,115,116,114,105,112,112,101, +- 100,95,112,97,116,104,90,7,112,121,99,97,99,104,101,90, +- 9,100,111,116,95,99,111,117,110,116,114,96,0,0,0,90, +- 9,111,112,116,95,108,101,118,101,108,90,13,98,97,115,101, +- 95,102,105,108,101,110,97,109,101,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,218,17,115,111,117,114,99,101, +- 95,102,114,111,109,95,99,97,99,104,101,195,1,0,0,115, +- 60,0,0,0,12,9,8,1,10,1,12,1,4,1,10,1, +- 12,1,14,1,16,1,4,1,4,1,12,1,8,1,8,1, +- 2,1,8,255,10,2,8,1,14,1,8,1,16,1,10,1, +- 4,1,2,1,8,255,16,2,8,1,16,1,14,2,18,1, +- 114,128,0,0,0,99,1,0,0,0,0,0,0,0,0,0, +- 0,0,5,0,0,0,9,0,0,0,67,0,0,0,115,124, +- 0,0,0,116,0,124,0,131,1,100,1,107,2,114,8,100, +- 2,83,0,124,0,160,1,100,3,161,1,92,3,125,1,125, +- 2,125,3,124,1,114,28,124,3,160,2,161,0,100,4,100, +- 5,133,2,25,0,100,6,107,3,114,30,124,0,83,0,122, +- 6,116,3,124,0,131,1,125,4,87,0,110,17,4,0,116, +- 4,116,5,102,2,121,53,1,0,1,0,1,0,124,0,100, +- 2,100,5,133,2,25,0,125,4,89,0,110,1,119,0,116, +- 6,124,4,131,1,114,60,124,4,83,0,124,0,83,0,41, +- 7,122,188,67,111,110,118,101,114,116,32,97,32,98,121,116, +- 101,99,111,100,101,32,102,105,108,101,32,112,97,116,104,32, +- 116,111,32,97,32,115,111,117,114,99,101,32,112,97,116,104, +- 32,40,105,102,32,112,111,115,115,105,98,108,101,41,46,10, +- 10,32,32,32,32,84,104,105,115,32,102,117,110,99,116,105, +- 111,110,32,101,120,105,115,116,115,32,112,117,114,101,108,121, +- 32,102,111,114,32,98,97,99,107,119,97,114,100,115,45,99, +- 111,109,112,97,116,105,98,105,108,105,116,121,32,102,111,114, +- 10,32,32,32,32,80,121,73,109,112,111,114,116,95,69,120, +- 101,99,67,111,100,101,77,111,100,117,108,101,87,105,116,104, +- 70,105,108,101,110,97,109,101,115,40,41,32,105,110,32,116, +- 104,101,32,67,32,65,80,73,46,10,10,32,32,32,32,114, +- 0,0,0,0,78,114,97,0,0,0,233,253,255,255,255,233, +- 255,255,255,255,90,2,112,121,41,7,114,4,0,0,0,114, +- 104,0,0,0,218,5,108,111,119,101,114,114,128,0,0,0, +- 114,107,0,0,0,114,111,0,0,0,114,80,0,0,0,41, +- 5,218,13,98,121,116,101,99,111,100,101,95,112,97,116,104, +- 114,119,0,0,0,218,1,95,90,9,101,120,116,101,110,115, +- 105,111,110,218,11,115,111,117,114,99,101,95,112,97,116,104, ++ 116,104,46,106,111,105,110,40,41,46,114,10,0,0,0,114, ++ 3,0,0,0,114,0,0,0,0,114,11,0,0,0,99,1, ++ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,5, ++ 0,0,0,83,0,0,0,243,26,0,0,0,103,0,124,0, ++ 93,9,125,1,124,1,114,2,124,1,160,0,116,1,161,1, ++ 145,2,113,2,83,0,114,7,0,0,0,169,2,218,6,114, ++ 115,116,114,105,112,218,15,112,97,116,104,95,115,101,112,97, ++ 114,97,116,111,114,115,169,2,114,5,0,0,0,218,1,112, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, +- 15,95,103,101,116,95,115,111,117,114,99,101,102,105,108,101, +- 235,1,0,0,115,22,0,0,0,12,7,4,1,16,1,24, +- 1,4,1,2,1,12,1,16,1,16,1,2,255,16,2,114, +- 135,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, +- 0,1,0,0,0,8,0,0,0,67,0,0,0,115,68,0, +- 0,0,124,0,160,0,116,1,116,2,131,1,161,1,114,23, +- 122,5,116,3,124,0,131,1,87,0,83,0,4,0,116,4, +- 121,22,1,0,1,0,1,0,89,0,100,0,83,0,119,0, +- 124,0,160,0,116,1,116,5,131,1,161,1,114,32,124,0, +- 83,0,100,0,83,0,114,69,0,0,0,41,6,114,58,0, +- 0,0,218,5,116,117,112,108,101,114,127,0,0,0,114,121, +- 0,0,0,114,107,0,0,0,114,113,0,0,0,41,1,114, +- 120,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,11,95,103,101,116,95,99,97,99,104,101,100, +- 254,1,0,0,115,18,0,0,0,14,1,2,1,10,1,12, +- 1,6,1,2,255,14,2,4,1,4,2,114,137,0,0,0, ++ 10,60,108,105,115,116,99,111,109,112,62,119,0,0,0,115, ++ 2,0,0,0,26,0,250,30,95,112,97,116,104,95,106,111, ++ 105,110,46,60,108,111,99,97,108,115,62,46,60,108,105,115, ++ 116,99,111,109,112,62,41,13,114,4,0,0,0,218,3,109, ++ 97,112,114,21,0,0,0,218,15,95,112,97,116,104,95,115, ++ 112,108,105,116,114,111,111,116,114,29,0,0,0,218,14,112, ++ 97,116,104,95,115,101,112,95,116,117,112,108,101,218,8,101, ++ 110,100,115,119,105,116,104,114,52,0,0,0,114,53,0,0, ++ 0,218,8,112,97,116,104,95,115,101,112,218,8,99,97,115, ++ 101,102,111,108,100,218,6,97,112,112,101,110,100,218,4,106, ++ 111,105,110,41,5,218,10,112,97,116,104,95,112,97,114,116, ++ 115,218,4,114,111,111,116,218,4,112,97,116,104,90,8,110, ++ 101,119,95,114,111,111,116,218,4,116,97,105,108,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,218,10,95,112, ++ 97,116,104,95,106,111,105,110,96,0,0,0,115,42,0,0, ++ 0,4,2,4,1,12,1,8,1,4,1,4,1,20,1,20, ++ 1,14,1,12,1,10,1,16,1,4,3,8,1,12,2,8, ++ 2,12,1,14,1,20,1,8,2,14,1,114,70,0,0,0, ++ 99,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, ++ 0,4,0,0,0,71,0,0,0,115,20,0,0,0,116,0, ++ 160,1,100,1,100,2,132,0,124,0,68,0,131,1,161,1, ++ 83,0,41,3,114,49,0,0,0,99,1,0,0,0,0,0, ++ 0,0,0,0,0,0,2,0,0,0,5,0,0,0,83,0, ++ 0,0,114,50,0,0,0,114,7,0,0,0,114,51,0,0, ++ 0,41,2,114,5,0,0,0,218,4,112,97,114,116,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,114,56,0, ++ 0,0,128,0,0,0,115,6,0,0,0,6,0,4,1,16, ++ 255,114,57,0,0,0,41,2,114,62,0,0,0,114,65,0, ++ 0,0,41,1,114,66,0,0,0,114,7,0,0,0,114,7, ++ 0,0,0,114,8,0,0,0,114,70,0,0,0,126,0,0, ++ 0,115,6,0,0,0,10,2,2,1,8,255,99,1,0,0, ++ 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, ++ 0,3,0,0,0,115,66,0,0,0,116,0,135,0,102,1, ++ 100,1,100,2,132,8,116,1,68,0,131,1,131,1,125,1, ++ 124,1,100,3,107,0,114,19,100,4,136,0,102,2,83,0, ++ 136,0,100,5,124,1,133,2,25,0,136,0,124,1,100,6, ++ 23,0,100,5,133,2,25,0,102,2,83,0,41,7,122,32, ++ 82,101,112,108,97,99,101,109,101,110,116,32,102,111,114,32, ++ 111,115,46,112,97,116,104,46,115,112,108,105,116,40,41,46, + 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, +- 0,8,0,0,0,67,0,0,0,115,50,0,0,0,122,7, +- 116,0,124,0,131,1,106,1,125,1,87,0,110,11,4,0, +- 116,2,121,18,1,0,1,0,1,0,100,1,125,1,89,0, +- 110,1,119,0,124,1,100,2,79,0,125,1,124,1,83,0, +- 41,3,122,51,67,97,108,99,117,108,97,116,101,32,116,104, +- 101,32,109,111,100,101,32,112,101,114,109,105,115,115,105,111, +- 110,115,32,102,111,114,32,97,32,98,121,116,101,99,111,100, +- 101,32,102,105,108,101,46,114,87,0,0,0,233,128,0,0, +- 0,41,3,114,75,0,0,0,114,77,0,0,0,114,76,0, +- 0,0,41,2,114,65,0,0,0,114,78,0,0,0,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,218,10,95, +- 99,97,108,99,95,109,111,100,101,10,2,0,0,115,14,0, +- 0,0,2,2,14,1,12,1,8,1,2,255,8,4,4,1, +- 114,139,0,0,0,99,1,0,0,0,0,0,0,0,0,0, +- 0,0,3,0,0,0,4,0,0,0,3,0,0,0,115,52, +- 0,0,0,100,6,135,0,102,1,100,2,100,3,132,9,125, +- 1,116,0,100,1,117,1,114,15,116,0,106,1,125,2,110, +- 4,100,4,100,5,132,0,125,2,124,2,124,1,136,0,131, +- 2,1,0,124,1,83,0,41,7,122,252,68,101,99,111,114, +- 97,116,111,114,32,116,111,32,118,101,114,105,102,121,32,116, +- 104,97,116,32,116,104,101,32,109,111,100,117,108,101,32,98, +- 101,105,110,103,32,114,101,113,117,101,115,116,101,100,32,109, +- 97,116,99,104,101,115,32,116,104,101,32,111,110,101,32,116, +- 104,101,10,32,32,32,32,108,111,97,100,101,114,32,99,97, +- 110,32,104,97,110,100,108,101,46,10,10,32,32,32,32,84, +- 104,101,32,102,105,114,115,116,32,97,114,103,117,109,101,110, +- 116,32,40,115,101,108,102,41,32,109,117,115,116,32,100,101, +- 102,105,110,101,32,95,110,97,109,101,32,119,104,105,99,104, +- 32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117, +- 109,101,110,116,32,105,115,10,32,32,32,32,99,111,109,112, +- 97,114,101,100,32,97,103,97,105,110,115,116,46,32,73,102, +- 32,116,104,101,32,99,111,109,112,97,114,105,115,111,110,32, +- 102,97,105,108,115,32,116,104,101,110,32,73,109,112,111,114, +- 116,69,114,114,111,114,32,105,115,32,114,97,105,115,101,100, +- 46,10,10,32,32,32,32,78,99,2,0,0,0,0,0,0, +- 0,0,0,0,0,4,0,0,0,4,0,0,0,31,0,0, +- 0,115,72,0,0,0,124,1,100,0,117,0,114,8,124,0, +- 106,0,125,1,110,16,124,0,106,0,124,1,107,3,114,24, +- 116,1,100,1,124,0,106,0,124,1,102,2,22,0,124,1, +- 100,2,141,2,130,1,136,0,124,0,124,1,103,2,124,2, +- 162,1,82,0,105,0,124,3,164,1,142,1,83,0,41,3, +- 78,122,30,108,111,97,100,101,114,32,102,111,114,32,37,115, +- 32,99,97,110,110,111,116,32,104,97,110,100,108,101,32,37, +- 115,169,1,218,4,110,97,109,101,41,2,114,141,0,0,0, +- 218,11,73,109,112,111,114,116,69,114,114,111,114,41,4,218, +- 4,115,101,108,102,114,141,0,0,0,218,4,97,114,103,115, +- 218,6,107,119,97,114,103,115,169,1,218,6,109,101,116,104, +- 111,100,114,7,0,0,0,114,8,0,0,0,218,19,95,99, +- 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, +- 114,30,2,0,0,115,18,0,0,0,8,1,8,1,10,1, +- 4,1,8,1,2,255,2,1,6,255,24,2,122,40,95,99, +- 104,101,99,107,95,110,97,109,101,46,60,108,111,99,97,108, +- 115,62,46,95,99,104,101,99,107,95,110,97,109,101,95,119, +- 114,97,112,112,101,114,99,2,0,0,0,0,0,0,0,0, +- 0,0,0,3,0,0,0,7,0,0,0,83,0,0,0,115, +- 56,0,0,0,100,1,68,0,93,16,125,2,116,0,124,1, +- 124,2,131,2,114,18,116,1,124,0,124,2,116,2,124,1, +- 124,2,131,2,131,3,1,0,113,2,124,0,106,3,160,4, +- 124,1,106,3,161,1,1,0,100,0,83,0,41,2,78,41, +- 4,218,10,95,95,109,111,100,117,108,101,95,95,218,8,95, +- 95,110,97,109,101,95,95,218,12,95,95,113,117,97,108,110, +- 97,109,101,95,95,218,7,95,95,100,111,99,95,95,41,5, +- 218,7,104,97,115,97,116,116,114,218,7,115,101,116,97,116, +- 116,114,218,7,103,101,116,97,116,116,114,218,8,95,95,100, +- 105,99,116,95,95,218,6,117,112,100,97,116,101,41,3,90, +- 3,110,101,119,90,3,111,108,100,114,85,0,0,0,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,218,5,95, +- 119,114,97,112,43,2,0,0,115,10,0,0,0,8,1,10, +- 1,18,1,2,128,18,1,122,26,95,99,104,101,99,107,95, +- 110,97,109,101,46,60,108,111,99,97,108,115,62,46,95,119, +- 114,97,112,114,69,0,0,0,41,2,218,10,95,98,111,111, +- 116,115,116,114,97,112,114,158,0,0,0,41,3,114,147,0, +- 0,0,114,148,0,0,0,114,158,0,0,0,114,7,0,0, +- 0,114,146,0,0,0,114,8,0,0,0,218,11,95,99,104, +- 101,99,107,95,110,97,109,101,22,2,0,0,115,12,0,0, +- 0,14,8,8,10,8,1,8,2,10,6,4,1,114,160,0, +- 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,5, +- 0,0,0,6,0,0,0,67,0,0,0,115,72,0,0,0, +- 116,0,160,1,100,1,116,2,161,2,1,0,124,0,160,3, +- 124,1,161,1,92,2,125,2,125,3,124,2,100,2,117,0, +- 114,34,116,4,124,3,131,1,114,34,100,3,125,4,116,0, +- 160,1,124,4,160,5,124,3,100,4,25,0,161,1,116,6, +- 161,2,1,0,124,2,83,0,41,5,122,155,84,114,121,32, +- 116,111,32,102,105,110,100,32,97,32,108,111,97,100,101,114, +- 32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105, +- 101,100,32,109,111,100,117,108,101,32,98,121,32,100,101,108, +- 101,103,97,116,105,110,103,32,116,111,10,32,32,32,32,115, +- 101,108,102,46,102,105,110,100,95,108,111,97,100,101,114,40, +- 41,46,10,10,32,32,32,32,84,104,105,115,32,109,101,116, +- 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, +- 100,32,105,110,32,102,97,118,111,114,32,111,102,32,102,105, +- 110,100,101,114,46,102,105,110,100,95,115,112,101,99,40,41, +- 46,10,10,32,32,32,32,122,90,102,105,110,100,95,109,111, +- 100,117,108,101,40,41,32,105,115,32,100,101,112,114,101,99, +- 97,116,101,100,32,97,110,100,32,115,108,97,116,101,100,32, +- 102,111,114,32,114,101,109,111,118,97,108,32,105,110,32,80, +- 121,116,104,111,110,32,51,46,49,50,59,32,117,115,101,32, +- 102,105,110,100,95,115,112,101,99,40,41,32,105,110,115,116, +- 101,97,100,78,122,44,78,111,116,32,105,109,112,111,114,116, +- 105,110,103,32,100,105,114,101,99,116,111,114,121,32,123,125, +- 58,32,109,105,115,115,105,110,103,32,95,95,105,110,105,116, +- 95,95,114,0,0,0,0,41,7,114,99,0,0,0,114,100, +- 0,0,0,114,101,0,0,0,218,11,102,105,110,100,95,108, +- 111,97,100,101,114,114,4,0,0,0,114,89,0,0,0,218, +- 13,73,109,112,111,114,116,87,97,114,110,105,110,103,41,5, +- 114,143,0,0,0,218,8,102,117,108,108,110,97,109,101,218, +- 6,108,111,97,100,101,114,218,8,112,111,114,116,105,111,110, +- 115,218,3,109,115,103,114,7,0,0,0,114,7,0,0,0, +- 114,8,0,0,0,218,17,95,102,105,110,100,95,109,111,100, +- 117,108,101,95,115,104,105,109,53,2,0,0,115,16,0,0, +- 0,6,7,2,2,4,254,14,6,16,1,4,1,22,1,4, +- 1,114,167,0,0,0,99,3,0,0,0,0,0,0,0,0, +- 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, +- 166,0,0,0,124,0,100,1,100,2,133,2,25,0,125,3, +- 124,3,116,0,107,3,114,32,100,3,124,1,155,2,100,4, +- 124,3,155,2,157,4,125,4,116,1,160,2,100,5,124,4, +- 161,2,1,0,116,3,124,4,102,1,105,0,124,2,164,1, +- 142,1,130,1,116,4,124,0,131,1,100,6,107,0,114,53, +- 100,7,124,1,155,2,157,2,125,4,116,1,160,2,100,5, +- 124,4,161,2,1,0,116,5,124,4,131,1,130,1,116,6, +- 124,0,100,2,100,8,133,2,25,0,131,1,125,5,124,5, +- 100,9,64,0,114,81,100,10,124,5,155,2,100,11,124,1, +- 155,2,157,4,125,4,116,3,124,4,102,1,105,0,124,2, +- 164,1,142,1,130,1,124,5,83,0,41,12,97,84,2,0, +- 0,80,101,114,102,111,114,109,32,98,97,115,105,99,32,118, +- 97,108,105,100,105,116,121,32,99,104,101,99,107,105,110,103, +- 32,111,102,32,97,32,112,121,99,32,104,101,97,100,101,114, +- 32,97,110,100,32,114,101,116,117,114,110,32,116,104,101,32, +- 102,108,97,103,115,32,102,105,101,108,100,44,10,32,32,32, +- 32,119,104,105,99,104,32,100,101,116,101,114,109,105,110,101, +- 115,32,104,111,119,32,116,104,101,32,112,121,99,32,115,104, +- 111,117,108,100,32,98,101,32,102,117,114,116,104,101,114,32, +- 118,97,108,105,100,97,116,101,100,32,97,103,97,105,110,115, +- 116,32,116,104,101,32,115,111,117,114,99,101,46,10,10,32, +- 32,32,32,42,100,97,116,97,42,32,105,115,32,116,104,101, +- 32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101, +- 32,112,121,99,32,102,105,108,101,46,32,40,79,110,108,121, +- 32,116,104,101,32,102,105,114,115,116,32,49,54,32,98,121, +- 116,101,115,32,97,114,101,10,32,32,32,32,114,101,113,117, +- 105,114,101,100,44,32,116,104,111,117,103,104,46,41,10,10, +- 32,32,32,32,42,110,97,109,101,42,32,105,115,32,116,104, +- 101,32,110,97,109,101,32,111,102,32,116,104,101,32,109,111, +- 100,117,108,101,32,98,101,105,110,103,32,105,109,112,111,114, +- 116,101,100,46,32,73,116,32,105,115,32,117,115,101,100,32, +- 102,111,114,32,108,111,103,103,105,110,103,46,10,10,32,32, +- 32,32,42,101,120,99,95,100,101,116,97,105,108,115,42,32, +- 105,115,32,97,32,100,105,99,116,105,111,110,97,114,121,32, +- 112,97,115,115,101,100,32,116,111,32,73,109,112,111,114,116, +- 69,114,114,111,114,32,105,102,32,105,116,32,114,97,105,115, +- 101,100,32,102,111,114,10,32,32,32,32,105,109,112,114,111, +- 118,101,100,32,100,101,98,117,103,103,105,110,103,46,10,10, +- 32,32,32,32,73,109,112,111,114,116,69,114,114,111,114,32, +- 105,115,32,114,97,105,115,101,100,32,119,104,101,110,32,116, +- 104,101,32,109,97,103,105,99,32,110,117,109,98,101,114,32, +- 105,115,32,105,110,99,111,114,114,101,99,116,32,111,114,32, +- 119,104,101,110,32,116,104,101,32,102,108,97,103,115,10,32, +- 32,32,32,102,105,101,108,100,32,105,115,32,105,110,118,97, +- 108,105,100,46,32,69,79,70,69,114,114,111,114,32,105,115, +- 32,114,97,105,115,101,100,32,119,104,101,110,32,116,104,101, +- 32,100,97,116,97,32,105,115,32,102,111,117,110,100,32,116, +- 111,32,98,101,32,116,114,117,110,99,97,116,101,100,46,10, +- 10,32,32,32,32,78,114,31,0,0,0,122,20,98,97,100, +- 32,109,97,103,105,99,32,110,117,109,98,101,114,32,105,110, +- 32,122,2,58,32,250,2,123,125,233,16,0,0,0,122,40, +- 114,101,97,99,104,101,100,32,69,79,70,32,119,104,105,108, +- 101,32,114,101,97,100,105,110,103,32,112,121,99,32,104,101, +- 97,100,101,114,32,111,102,32,233,8,0,0,0,233,252,255, +- 255,255,122,14,105,110,118,97,108,105,100,32,102,108,97,103, +- 115,32,122,4,32,105,110,32,41,7,218,12,77,65,71,73, +- 67,95,78,85,77,66,69,82,114,159,0,0,0,218,16,95, +- 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,114, +- 142,0,0,0,114,4,0,0,0,218,8,69,79,70,69,114, +- 114,111,114,114,42,0,0,0,41,6,114,41,0,0,0,114, +- 141,0,0,0,218,11,101,120,99,95,100,101,116,97,105,108, +- 115,90,5,109,97,103,105,99,114,117,0,0,0,114,16,0, ++ 0,4,0,0,0,51,0,0,0,115,26,0,0,0,129,0, ++ 124,0,93,8,125,1,136,0,160,0,124,1,161,1,86,0, ++ 1,0,113,2,100,0,83,0,169,1,78,41,1,218,5,114, ++ 102,105,110,100,114,54,0,0,0,169,1,114,68,0,0,0, ++ 114,7,0,0,0,114,8,0,0,0,114,9,0,0,0,134, ++ 0,0,0,115,4,0,0,0,2,128,24,0,122,30,95,112, ++ 97,116,104,95,115,112,108,105,116,46,60,108,111,99,97,108, ++ 115,62,46,60,103,101,110,101,120,112,114,62,114,0,0,0, ++ 0,114,10,0,0,0,78,114,3,0,0,0,41,2,218,3, ++ 109,97,120,114,53,0,0,0,41,2,114,68,0,0,0,218, ++ 1,105,114,7,0,0,0,114,74,0,0,0,114,8,0,0, ++ 0,218,11,95,112,97,116,104,95,115,112,108,105,116,132,0, ++ 0,0,115,8,0,0,0,22,2,8,1,8,1,28,1,114, ++ 77,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, ++ 0,1,0,0,0,3,0,0,0,67,0,0,0,115,10,0, ++ 0,0,116,0,160,1,124,0,161,1,83,0,41,1,122,126, ++ 83,116,97,116,32,116,104,101,32,112,97,116,104,46,10,10, ++ 32,32,32,32,77,97,100,101,32,97,32,115,101,112,97,114, ++ 97,116,101,32,102,117,110,99,116,105,111,110,32,116,111,32, ++ 109,97,107,101,32,105,116,32,101,97,115,105,101,114,32,116, ++ 111,32,111,118,101,114,114,105,100,101,32,105,110,32,101,120, ++ 112,101,114,105,109,101,110,116,115,10,32,32,32,32,40,101, ++ 46,103,46,32,99,97,99,104,101,32,115,116,97,116,32,114, ++ 101,115,117,108,116,115,41,46,10,10,32,32,32,32,41,2, ++ 114,21,0,0,0,90,4,115,116,97,116,114,74,0,0,0, ++ 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, ++ 10,95,112,97,116,104,95,115,116,97,116,140,0,0,0,115, ++ 2,0,0,0,10,7,114,78,0,0,0,99,2,0,0,0, ++ 0,0,0,0,0,0,0,0,3,0,0,0,8,0,0,0, ++ 67,0,0,0,115,48,0,0,0,122,6,116,0,124,0,131, ++ 1,125,2,87,0,110,10,4,0,116,1,121,16,1,0,1, ++ 0,1,0,89,0,100,1,83,0,119,0,124,2,106,2,100, ++ 2,64,0,124,1,107,2,83,0,41,3,122,49,84,101,115, ++ 116,32,119,104,101,116,104,101,114,32,116,104,101,32,112,97, ++ 116,104,32,105,115,32,116,104,101,32,115,112,101,99,105,102, ++ 105,101,100,32,109,111,100,101,32,116,121,112,101,46,70,105, ++ 0,240,0,0,41,3,114,78,0,0,0,218,7,79,83,69, ++ 114,114,111,114,218,7,115,116,95,109,111,100,101,41,3,114, ++ 68,0,0,0,218,4,109,111,100,101,90,9,115,116,97,116, ++ 95,105,110,102,111,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,218,18,95,112,97,116,104,95,105,115,95,109, ++ 111,100,101,95,116,121,112,101,150,0,0,0,115,12,0,0, ++ 0,2,2,12,1,12,1,6,1,2,255,14,2,114,82,0, ++ 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,1, ++ 0,0,0,3,0,0,0,67,0,0,0,115,10,0,0,0, ++ 116,0,124,0,100,1,131,2,83,0,41,2,122,31,82,101, ++ 112,108,97,99,101,109,101,110,116,32,102,111,114,32,111,115, ++ 46,112,97,116,104,46,105,115,102,105,108,101,46,105,0,128, ++ 0,0,41,1,114,82,0,0,0,114,74,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,218,12,95, ++ 112,97,116,104,95,105,115,102,105,108,101,159,0,0,0,243, ++ 2,0,0,0,10,2,114,83,0,0,0,99,1,0,0,0, ++ 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, ++ 67,0,0,0,115,22,0,0,0,124,0,115,6,116,0,160, ++ 1,161,0,125,0,116,2,124,0,100,1,131,2,83,0,41, ++ 2,122,30,82,101,112,108,97,99,101,109,101,110,116,32,102, ++ 111,114,32,111,115,46,112,97,116,104,46,105,115,100,105,114, ++ 46,105,0,64,0,0,41,3,114,21,0,0,0,218,6,103, ++ 101,116,99,119,100,114,82,0,0,0,114,74,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,11, ++ 95,112,97,116,104,95,105,115,100,105,114,164,0,0,0,115, ++ 6,0,0,0,4,2,8,1,10,1,114,86,0,0,0,99, ++ 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, ++ 4,0,0,0,67,0,0,0,115,62,0,0,0,124,0,115, ++ 4,100,1,83,0,116,0,160,1,124,0,161,1,100,2,25, ++ 0,160,2,100,3,100,4,161,2,125,1,116,3,124,1,131, ++ 1,100,5,107,4,111,30,124,1,160,4,100,6,161,1,112, ++ 30,124,1,160,5,100,4,161,1,83,0,41,7,250,30,82, ++ 101,112,108,97,99,101,109,101,110,116,32,102,111,114,32,111, ++ 115,46,112,97,116,104,46,105,115,97,98,115,46,70,114,0, ++ 0,0,0,114,2,0,0,0,114,1,0,0,0,114,3,0, ++ 0,0,122,2,92,92,41,6,114,21,0,0,0,114,59,0, ++ 0,0,218,7,114,101,112,108,97,99,101,114,4,0,0,0, ++ 114,29,0,0,0,114,61,0,0,0,41,2,114,68,0,0, ++ 0,114,67,0,0,0,114,7,0,0,0,114,7,0,0,0, ++ 114,8,0,0,0,218,11,95,112,97,116,104,95,105,115,97, ++ 98,115,172,0,0,0,115,8,0,0,0,4,2,4,1,22, ++ 1,32,1,114,89,0,0,0,99,1,0,0,0,0,0,0, ++ 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, ++ 0,115,10,0,0,0,124,0,160,0,116,1,161,1,83,0, ++ 41,1,114,87,0,0,0,41,2,114,29,0,0,0,114,53, ++ 0,0,0,114,74,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,114,89,0,0,0,180,0,0,0, ++ 114,84,0,0,0,233,182,1,0,0,99,3,0,0,0,0, ++ 0,0,0,0,0,0,0,6,0,0,0,11,0,0,0,67, ++ 0,0,0,115,170,0,0,0,100,1,160,0,124,0,116,1, ++ 124,0,131,1,161,2,125,3,116,2,160,3,124,3,116,2, ++ 106,4,116,2,106,5,66,0,116,2,106,6,66,0,124,2, ++ 100,2,64,0,161,3,125,4,122,36,116,7,160,8,124,4, ++ 100,3,161,2,143,13,125,5,124,5,160,9,124,1,161,1, ++ 1,0,87,0,100,4,4,0,4,0,131,3,1,0,110,8, ++ 49,0,115,47,119,1,1,0,1,0,1,0,89,0,1,0, ++ 116,2,160,10,124,3,124,0,161,2,1,0,87,0,100,4, ++ 83,0,4,0,116,11,121,84,1,0,1,0,1,0,122,7, ++ 116,2,160,12,124,3,161,1,1,0,87,0,130,0,4,0, ++ 116,11,121,83,1,0,1,0,1,0,89,0,130,0,119,0, ++ 119,0,41,5,122,162,66,101,115,116,45,101,102,102,111,114, ++ 116,32,102,117,110,99,116,105,111,110,32,116,111,32,119,114, ++ 105,116,101,32,100,97,116,97,32,116,111,32,97,32,112,97, ++ 116,104,32,97,116,111,109,105,99,97,108,108,121,46,10,32, ++ 32,32,32,66,101,32,112,114,101,112,97,114,101,100,32,116, ++ 111,32,104,97,110,100,108,101,32,97,32,70,105,108,101,69, ++ 120,105,115,116,115,69,114,114,111,114,32,105,102,32,99,111, ++ 110,99,117,114,114,101,110,116,32,119,114,105,116,105,110,103, ++ 32,111,102,32,116,104,101,10,32,32,32,32,116,101,109,112, ++ 111,114,97,114,121,32,102,105,108,101,32,105,115,32,97,116, ++ 116,101,109,112,116,101,100,46,250,5,123,125,46,123,125,114, ++ 90,0,0,0,90,2,119,98,78,41,13,218,6,102,111,114, ++ 109,97,116,218,2,105,100,114,21,0,0,0,90,4,111,112, ++ 101,110,90,6,79,95,69,88,67,76,90,7,79,95,67,82, ++ 69,65,84,90,8,79,95,87,82,79,78,76,89,218,3,95, ++ 105,111,218,6,70,105,108,101,73,79,218,5,119,114,105,116, ++ 101,114,88,0,0,0,114,79,0,0,0,90,6,117,110,108, ++ 105,110,107,41,6,114,68,0,0,0,114,44,0,0,0,114, ++ 81,0,0,0,90,8,112,97,116,104,95,116,109,112,90,2, ++ 102,100,218,4,102,105,108,101,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,13,95,119,114,105,116,101,95, ++ 97,116,111,109,105,99,185,0,0,0,115,36,0,0,0,16, ++ 5,6,1,22,1,4,255,2,2,14,3,12,1,28,255,18, ++ 2,12,1,2,1,12,1,2,3,12,254,2,1,2,1,2, ++ 254,2,253,114,98,0,0,0,105,111,13,0,0,114,47,0, ++ 0,0,114,35,0,0,0,115,2,0,0,0,13,10,90,11, ++ 95,95,112,121,99,97,99,104,101,95,95,122,4,111,112,116, ++ 45,122,3,46,112,121,122,4,46,112,121,119,122,4,46,112, ++ 121,99,41,1,218,12,111,112,116,105,109,105,122,97,116,105, ++ 111,110,99,2,0,0,0,0,0,0,0,1,0,0,0,12, ++ 0,0,0,5,0,0,0,67,0,0,0,115,80,1,0,0, ++ 124,1,100,1,117,1,114,26,116,0,160,1,100,2,116,2, ++ 161,2,1,0,124,2,100,1,117,1,114,20,100,3,125,3, ++ 116,3,124,3,131,1,130,1,124,1,114,24,100,4,110,1, ++ 100,5,125,2,116,4,160,5,124,0,161,1,125,0,116,6, ++ 124,0,131,1,92,2,125,4,125,5,124,5,160,7,100,6, ++ 161,1,92,3,125,6,125,7,125,8,116,8,106,9,106,10, ++ 125,9,124,9,100,1,117,0,114,57,116,11,100,7,131,1, ++ 130,1,100,4,160,12,124,6,114,63,124,6,110,1,124,8, ++ 124,7,124,9,103,3,161,1,125,10,124,2,100,1,117,0, ++ 114,86,116,8,106,13,106,14,100,8,107,2,114,82,100,4, ++ 125,2,110,4,116,8,106,13,106,14,125,2,116,15,124,2, ++ 131,1,125,2,124,2,100,4,107,3,114,112,124,2,160,16, ++ 161,0,115,105,116,17,100,9,160,18,124,2,161,1,131,1, ++ 130,1,100,10,160,18,124,10,116,19,124,2,161,3,125,10, ++ 124,10,116,20,100,8,25,0,23,0,125,11,116,8,106,21, ++ 100,1,117,1,114,162,116,22,124,4,131,1,115,134,116,23, ++ 116,4,160,24,161,0,124,4,131,2,125,4,124,4,100,5, ++ 25,0,100,11,107,2,114,152,124,4,100,8,25,0,116,25, ++ 118,1,114,152,124,4,100,12,100,1,133,2,25,0,125,4, ++ 116,23,116,8,106,21,124,4,160,26,116,25,161,1,124,11, ++ 131,3,83,0,116,23,124,4,116,27,124,11,131,3,83,0, ++ 41,13,97,254,2,0,0,71,105,118,101,110,32,116,104,101, ++ 32,112,97,116,104,32,116,111,32,97,32,46,112,121,32,102, ++ 105,108,101,44,32,114,101,116,117,114,110,32,116,104,101,32, ++ 112,97,116,104,32,116,111,32,105,116,115,32,46,112,121,99, ++ 32,102,105,108,101,46,10,10,32,32,32,32,84,104,101,32, ++ 46,112,121,32,102,105,108,101,32,100,111,101,115,32,110,111, ++ 116,32,110,101,101,100,32,116,111,32,101,120,105,115,116,59, ++ 32,116,104,105,115,32,115,105,109,112,108,121,32,114,101,116, ++ 117,114,110,115,32,116,104,101,32,112,97,116,104,32,116,111, ++ 32,116,104,101,10,32,32,32,32,46,112,121,99,32,102,105, ++ 108,101,32,99,97,108,99,117,108,97,116,101,100,32,97,115, ++ 32,105,102,32,116,104,101,32,46,112,121,32,102,105,108,101, ++ 32,119,101,114,101,32,105,109,112,111,114,116,101,100,46,10, ++ 10,32,32,32,32,84,104,101,32,39,111,112,116,105,109,105, ++ 122,97,116,105,111,110,39,32,112,97,114,97,109,101,116,101, ++ 114,32,99,111,110,116,114,111,108,115,32,116,104,101,32,112, ++ 114,101,115,117,109,101,100,32,111,112,116,105,109,105,122,97, ++ 116,105,111,110,32,108,101,118,101,108,32,111,102,10,32,32, ++ 32,32,116,104,101,32,98,121,116,101,99,111,100,101,32,102, ++ 105,108,101,46,32,73,102,32,39,111,112,116,105,109,105,122, ++ 97,116,105,111,110,39,32,105,115,32,110,111,116,32,78,111, ++ 110,101,44,32,116,104,101,32,115,116,114,105,110,103,32,114, ++ 101,112,114,101,115,101,110,116,97,116,105,111,110,10,32,32, ++ 32,32,111,102,32,116,104,101,32,97,114,103,117,109,101,110, ++ 116,32,105,115,32,116,97,107,101,110,32,97,110,100,32,118, ++ 101,114,105,102,105,101,100,32,116,111,32,98,101,32,97,108, ++ 112,104,97,110,117,109,101,114,105,99,32,40,101,108,115,101, ++ 32,86,97,108,117,101,69,114,114,111,114,10,32,32,32,32, ++ 105,115,32,114,97,105,115,101,100,41,46,10,10,32,32,32, ++ 32,84,104,101,32,100,101,98,117,103,95,111,118,101,114,114, ++ 105,100,101,32,112,97,114,97,109,101,116,101,114,32,105,115, ++ 32,100,101,112,114,101,99,97,116,101,100,46,32,73,102,32, ++ 100,101,98,117,103,95,111,118,101,114,114,105,100,101,32,105, ++ 115,32,110,111,116,32,78,111,110,101,44,10,32,32,32,32, ++ 97,32,84,114,117,101,32,118,97,108,117,101,32,105,115,32, ++ 116,104,101,32,115,97,109,101,32,97,115,32,115,101,116,116, ++ 105,110,103,32,39,111,112,116,105,109,105,122,97,116,105,111, ++ 110,39,32,116,111,32,116,104,101,32,101,109,112,116,121,32, ++ 115,116,114,105,110,103,10,32,32,32,32,119,104,105,108,101, ++ 32,97,32,70,97,108,115,101,32,118,97,108,117,101,32,105, ++ 115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32, ++ 115,101,116,116,105,110,103,32,39,111,112,116,105,109,105,122, ++ 97,116,105,111,110,39,32,116,111,32,39,49,39,46,10,10, ++ 32,32,32,32,73,102,32,115,121,115,46,105,109,112,108,101, ++ 109,101,110,116,97,116,105,111,110,46,99,97,99,104,101,95, ++ 116,97,103,32,105,115,32,78,111,110,101,32,116,104,101,110, ++ 32,78,111,116,73,109,112,108,101,109,101,110,116,101,100,69, ++ 114,114,111,114,32,105,115,32,114,97,105,115,101,100,46,10, ++ 10,32,32,32,32,78,122,70,116,104,101,32,100,101,98,117, ++ 103,95,111,118,101,114,114,105,100,101,32,112,97,114,97,109, ++ 101,116,101,114,32,105,115,32,100,101,112,114,101,99,97,116, ++ 101,100,59,32,117,115,101,32,39,111,112,116,105,109,105,122, ++ 97,116,105,111,110,39,32,105,110,115,116,101,97,100,122,50, ++ 100,101,98,117,103,95,111,118,101,114,114,105,100,101,32,111, ++ 114,32,111,112,116,105,109,105,122,97,116,105,111,110,32,109, ++ 117,115,116,32,98,101,32,115,101,116,32,116,111,32,78,111, ++ 110,101,114,10,0,0,0,114,3,0,0,0,218,1,46,250, ++ 36,115,121,115,46,105,109,112,108,101,109,101,110,116,97,116, ++ 105,111,110,46,99,97,99,104,101,95,116,97,103,32,105,115, ++ 32,78,111,110,101,114,0,0,0,0,122,24,123,33,114,125, ++ 32,105,115,32,110,111,116,32,97,108,112,104,97,110,117,109, ++ 101,114,105,99,122,7,123,125,46,123,125,123,125,114,11,0, ++ 0,0,114,47,0,0,0,41,28,218,9,95,119,97,114,110, ++ 105,110,103,115,218,4,119,97,114,110,218,18,68,101,112,114, ++ 101,99,97,116,105,111,110,87,97,114,110,105,110,103,218,9, ++ 84,121,112,101,69,114,114,111,114,114,21,0,0,0,218,6, ++ 102,115,112,97,116,104,114,77,0,0,0,218,10,114,112,97, ++ 114,116,105,116,105,111,110,114,18,0,0,0,218,14,105,109, ++ 112,108,101,109,101,110,116,97,116,105,111,110,218,9,99,97, ++ 99,104,101,95,116,97,103,218,19,78,111,116,73,109,112,108, ++ 101,109,101,110,116,101,100,69,114,114,111,114,114,65,0,0, ++ 0,114,19,0,0,0,218,8,111,112,116,105,109,105,122,101, ++ 218,3,115,116,114,218,7,105,115,97,108,110,117,109,218,10, ++ 86,97,108,117,101,69,114,114,111,114,114,92,0,0,0,218, ++ 4,95,79,80,84,218,17,66,89,84,69,67,79,68,69,95, ++ 83,85,70,70,73,88,69,83,218,14,112,121,99,97,99,104, ++ 101,95,112,114,101,102,105,120,114,89,0,0,0,114,70,0, ++ 0,0,114,85,0,0,0,114,53,0,0,0,218,6,108,115, ++ 116,114,105,112,218,8,95,80,89,67,65,67,72,69,41,12, ++ 114,68,0,0,0,90,14,100,101,98,117,103,95,111,118,101, ++ 114,114,105,100,101,114,99,0,0,0,218,7,109,101,115,115, ++ 97,103,101,218,4,104,101,97,100,114,69,0,0,0,90,4, ++ 98,97,115,101,114,6,0,0,0,218,4,114,101,115,116,90, ++ 3,116,97,103,90,15,97,108,109,111,115,116,95,102,105,108, ++ 101,110,97,109,101,218,8,102,105,108,101,110,97,109,101,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,17, ++ 99,97,99,104,101,95,102,114,111,109,95,115,111,117,114,99, ++ 101,124,1,0,0,115,72,0,0,0,8,18,6,1,2,1, ++ 4,255,8,2,4,1,8,1,12,1,10,1,12,1,16,1, ++ 8,1,8,1,8,1,24,1,8,1,12,1,6,1,8,2, ++ 8,1,8,1,8,1,14,1,14,1,12,1,10,1,8,9, ++ 14,1,24,5,12,1,2,4,4,1,8,1,2,1,4,253, ++ 12,5,114,124,0,0,0,99,1,0,0,0,0,0,0,0, ++ 0,0,0,0,10,0,0,0,5,0,0,0,67,0,0,0, ++ 115,40,1,0,0,116,0,106,1,106,2,100,1,117,0,114, ++ 10,116,3,100,2,131,1,130,1,116,4,160,5,124,0,161, ++ 1,125,0,116,6,124,0,131,1,92,2,125,1,125,2,100, ++ 3,125,3,116,0,106,7,100,1,117,1,114,51,116,0,106, ++ 7,160,8,116,9,161,1,125,4,124,1,160,10,124,4,116, ++ 11,23,0,161,1,114,51,124,1,116,12,124,4,131,1,100, ++ 1,133,2,25,0,125,1,100,4,125,3,124,3,115,72,116, ++ 6,124,1,131,1,92,2,125,1,125,5,124,5,116,13,107, ++ 3,114,72,116,14,116,13,155,0,100,5,124,0,155,2,157, ++ 3,131,1,130,1,124,2,160,15,100,6,161,1,125,6,124, ++ 6,100,7,118,1,114,88,116,14,100,8,124,2,155,2,157, ++ 2,131,1,130,1,124,6,100,9,107,2,114,132,124,2,160, ++ 16,100,6,100,10,161,2,100,11,25,0,125,7,124,7,160, ++ 10,116,17,161,1,115,112,116,14,100,12,116,17,155,2,157, ++ 2,131,1,130,1,124,7,116,12,116,17,131,1,100,1,133, ++ 2,25,0,125,8,124,8,160,18,161,0,115,132,116,14,100, ++ 13,124,7,155,2,100,14,157,3,131,1,130,1,124,2,160, ++ 19,100,6,161,1,100,15,25,0,125,9,116,20,124,1,124, ++ 9,116,21,100,15,25,0,23,0,131,2,83,0,41,16,97, ++ 110,1,0,0,71,105,118,101,110,32,116,104,101,32,112,97, ++ 116,104,32,116,111,32,97,32,46,112,121,99,46,32,102,105, ++ 108,101,44,32,114,101,116,117,114,110,32,116,104,101,32,112, ++ 97,116,104,32,116,111,32,105,116,115,32,46,112,121,32,102, ++ 105,108,101,46,10,10,32,32,32,32,84,104,101,32,46,112, ++ 121,99,32,102,105,108,101,32,100,111,101,115,32,110,111,116, ++ 32,110,101,101,100,32,116,111,32,101,120,105,115,116,59,32, ++ 116,104,105,115,32,115,105,109,112,108,121,32,114,101,116,117, ++ 114,110,115,32,116,104,101,32,112,97,116,104,32,116,111,10, ++ 32,32,32,32,116,104,101,32,46,112,121,32,102,105,108,101, ++ 32,99,97,108,99,117,108,97,116,101,100,32,116,111,32,99, ++ 111,114,114,101,115,112,111,110,100,32,116,111,32,116,104,101, ++ 32,46,112,121,99,32,102,105,108,101,46,32,32,73,102,32, ++ 112,97,116,104,32,100,111,101,115,10,32,32,32,32,110,111, ++ 116,32,99,111,110,102,111,114,109,32,116,111,32,80,69,80, ++ 32,51,49,52,55,47,52,56,56,32,102,111,114,109,97,116, ++ 44,32,86,97,108,117,101,69,114,114,111,114,32,119,105,108, ++ 108,32,98,101,32,114,97,105,115,101,100,46,32,73,102,10, ++ 32,32,32,32,115,121,115,46,105,109,112,108,101,109,101,110, ++ 116,97,116,105,111,110,46,99,97,99,104,101,95,116,97,103, ++ 32,105,115,32,78,111,110,101,32,116,104,101,110,32,78,111, ++ 116,73,109,112,108,101,109,101,110,116,101,100,69,114,114,111, ++ 114,32,105,115,32,114,97,105,115,101,100,46,10,10,32,32, ++ 32,32,78,114,101,0,0,0,70,84,122,31,32,110,111,116, ++ 32,98,111,116,116,111,109,45,108,101,118,101,108,32,100,105, ++ 114,101,99,116,111,114,121,32,105,110,32,114,100,0,0,0, ++ 62,2,0,0,0,114,47,0,0,0,233,3,0,0,0,122, ++ 29,101,120,112,101,99,116,101,100,32,111,110,108,121,32,50, ++ 32,111,114,32,51,32,100,111,116,115,32,105,110,32,114,125, ++ 0,0,0,114,47,0,0,0,233,254,255,255,255,122,53,111, ++ 112,116,105,109,105,122,97,116,105,111,110,32,112,111,114,116, ++ 105,111,110,32,111,102,32,102,105,108,101,110,97,109,101,32, ++ 100,111,101,115,32,110,111,116,32,115,116,97,114,116,32,119, ++ 105,116,104,32,122,19,111,112,116,105,109,105,122,97,116,105, ++ 111,110,32,108,101,118,101,108,32,122,29,32,105,115,32,110, ++ 111,116,32,97,110,32,97,108,112,104,97,110,117,109,101,114, ++ 105,99,32,118,97,108,117,101,114,0,0,0,0,41,22,114, ++ 18,0,0,0,114,108,0,0,0,114,109,0,0,0,114,110, ++ 0,0,0,114,21,0,0,0,114,106,0,0,0,114,77,0, ++ 0,0,114,117,0,0,0,114,52,0,0,0,114,53,0,0, ++ 0,114,29,0,0,0,114,62,0,0,0,114,4,0,0,0, ++ 114,119,0,0,0,114,114,0,0,0,218,5,99,111,117,110, ++ 116,218,6,114,115,112,108,105,116,114,115,0,0,0,114,113, ++ 0,0,0,218,9,112,97,114,116,105,116,105,111,110,114,70, ++ 0,0,0,218,15,83,79,85,82,67,69,95,83,85,70,70, ++ 73,88,69,83,41,10,114,68,0,0,0,114,121,0,0,0, ++ 90,16,112,121,99,97,99,104,101,95,102,105,108,101,110,97, ++ 109,101,90,23,102,111,117,110,100,95,105,110,95,112,121,99, ++ 97,99,104,101,95,112,114,101,102,105,120,90,13,115,116,114, ++ 105,112,112,101,100,95,112,97,116,104,90,7,112,121,99,97, ++ 99,104,101,90,9,100,111,116,95,99,111,117,110,116,114,99, ++ 0,0,0,90,9,111,112,116,95,108,101,118,101,108,90,13, ++ 98,97,115,101,95,102,105,108,101,110,97,109,101,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,218,17,115,111, ++ 117,114,99,101,95,102,114,111,109,95,99,97,99,104,101,195, ++ 1,0,0,115,60,0,0,0,12,9,8,1,10,1,12,1, ++ 4,1,10,1,12,1,14,1,16,1,4,1,4,1,12,1, ++ 8,1,8,1,2,1,8,255,10,2,8,1,14,1,8,1, ++ 16,1,10,1,4,1,2,1,8,255,16,2,8,1,16,1, ++ 14,2,18,1,114,131,0,0,0,99,1,0,0,0,0,0, ++ 0,0,0,0,0,0,5,0,0,0,9,0,0,0,67,0, ++ 0,0,115,124,0,0,0,116,0,124,0,131,1,100,1,107, ++ 2,114,8,100,2,83,0,124,0,160,1,100,3,161,1,92, ++ 3,125,1,125,2,125,3,124,1,114,28,124,3,160,2,161, ++ 0,100,4,100,5,133,2,25,0,100,6,107,3,114,30,124, ++ 0,83,0,122,6,116,3,124,0,131,1,125,4,87,0,110, ++ 17,4,0,116,4,116,5,102,2,121,53,1,0,1,0,1, ++ 0,124,0,100,2,100,5,133,2,25,0,125,4,89,0,110, ++ 1,119,0,116,6,124,4,131,1,114,60,124,4,83,0,124, ++ 0,83,0,41,7,122,188,67,111,110,118,101,114,116,32,97, ++ 32,98,121,116,101,99,111,100,101,32,102,105,108,101,32,112, ++ 97,116,104,32,116,111,32,97,32,115,111,117,114,99,101,32, ++ 112,97,116,104,32,40,105,102,32,112,111,115,115,105,98,108, ++ 101,41,46,10,10,32,32,32,32,84,104,105,115,32,102,117, ++ 110,99,116,105,111,110,32,101,120,105,115,116,115,32,112,117, ++ 114,101,108,121,32,102,111,114,32,98,97,99,107,119,97,114, ++ 100,115,45,99,111,109,112,97,116,105,98,105,108,105,116,121, ++ 32,102,111,114,10,32,32,32,32,80,121,73,109,112,111,114, ++ 116,95,69,120,101,99,67,111,100,101,77,111,100,117,108,101, ++ 87,105,116,104,70,105,108,101,110,97,109,101,115,40,41,32, ++ 105,110,32,116,104,101,32,67,32,65,80,73,46,10,10,32, ++ 32,32,32,114,0,0,0,0,78,114,100,0,0,0,233,253, ++ 255,255,255,233,255,255,255,255,90,2,112,121,41,7,114,4, ++ 0,0,0,114,107,0,0,0,218,5,108,111,119,101,114,114, ++ 131,0,0,0,114,110,0,0,0,114,114,0,0,0,114,83, ++ 0,0,0,41,5,218,13,98,121,116,101,99,111,100,101,95, ++ 112,97,116,104,114,122,0,0,0,218,1,95,90,9,101,120, ++ 116,101,110,115,105,111,110,218,11,115,111,117,114,99,101,95, ++ 112,97,116,104,114,7,0,0,0,114,7,0,0,0,114,8, ++ 0,0,0,218,15,95,103,101,116,95,115,111,117,114,99,101, ++ 102,105,108,101,235,1,0,0,115,22,0,0,0,12,7,4, ++ 1,16,1,24,1,4,1,2,1,12,1,16,1,16,1,2, ++ 255,16,2,114,138,0,0,0,99,1,0,0,0,0,0,0, ++ 0,0,0,0,0,1,0,0,0,8,0,0,0,67,0,0, ++ 0,115,68,0,0,0,124,0,160,0,116,1,116,2,131,1, ++ 161,1,114,23,122,5,116,3,124,0,131,1,87,0,83,0, ++ 4,0,116,4,121,22,1,0,1,0,1,0,89,0,100,0, ++ 83,0,119,0,124,0,160,0,116,1,116,5,131,1,161,1, ++ 114,32,124,0,83,0,100,0,83,0,114,72,0,0,0,41, ++ 6,114,61,0,0,0,218,5,116,117,112,108,101,114,130,0, ++ 0,0,114,124,0,0,0,114,110,0,0,0,114,116,0,0, ++ 0,41,1,114,123,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,11,95,103,101,116,95,99,97, ++ 99,104,101,100,254,1,0,0,115,18,0,0,0,14,1,2, ++ 1,10,1,12,1,6,1,2,255,14,2,4,1,4,2,114, ++ 140,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, ++ 0,2,0,0,0,8,0,0,0,67,0,0,0,115,50,0, ++ 0,0,122,7,116,0,124,0,131,1,106,1,125,1,87,0, ++ 110,11,4,0,116,2,121,18,1,0,1,0,1,0,100,1, ++ 125,1,89,0,110,1,119,0,124,1,100,2,79,0,125,1, ++ 124,1,83,0,41,3,122,51,67,97,108,99,117,108,97,116, ++ 101,32,116,104,101,32,109,111,100,101,32,112,101,114,109,105, ++ 115,115,105,111,110,115,32,102,111,114,32,97,32,98,121,116, ++ 101,99,111,100,101,32,102,105,108,101,46,114,90,0,0,0, ++ 233,128,0,0,0,41,3,114,78,0,0,0,114,80,0,0, ++ 0,114,79,0,0,0,41,2,114,68,0,0,0,114,81,0, ++ 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,218,10,95,99,97,108,99,95,109,111,100,101,10,2,0, ++ 0,115,14,0,0,0,2,2,14,1,12,1,8,1,2,255, ++ 8,4,4,1,114,142,0,0,0,99,1,0,0,0,0,0, ++ 0,0,0,0,0,0,3,0,0,0,4,0,0,0,3,0, ++ 0,0,115,52,0,0,0,100,6,135,0,102,1,100,2,100, ++ 3,132,9,125,1,116,0,100,1,117,1,114,15,116,0,106, ++ 1,125,2,110,4,100,4,100,5,132,0,125,2,124,2,124, ++ 1,136,0,131,2,1,0,124,1,83,0,41,7,122,252,68, ++ 101,99,111,114,97,116,111,114,32,116,111,32,118,101,114,105, ++ 102,121,32,116,104,97,116,32,116,104,101,32,109,111,100,117, ++ 108,101,32,98,101,105,110,103,32,114,101,113,117,101,115,116, ++ 101,100,32,109,97,116,99,104,101,115,32,116,104,101,32,111, ++ 110,101,32,116,104,101,10,32,32,32,32,108,111,97,100,101, ++ 114,32,99,97,110,32,104,97,110,100,108,101,46,10,10,32, ++ 32,32,32,84,104,101,32,102,105,114,115,116,32,97,114,103, ++ 117,109,101,110,116,32,40,115,101,108,102,41,32,109,117,115, ++ 116,32,100,101,102,105,110,101,32,95,110,97,109,101,32,119, ++ 104,105,99,104,32,116,104,101,32,115,101,99,111,110,100,32, ++ 97,114,103,117,109,101,110,116,32,105,115,10,32,32,32,32, ++ 99,111,109,112,97,114,101,100,32,97,103,97,105,110,115,116, ++ 46,32,73,102,32,116,104,101,32,99,111,109,112,97,114,105, ++ 115,111,110,32,102,97,105,108,115,32,116,104,101,110,32,73, ++ 109,112,111,114,116,69,114,114,111,114,32,105,115,32,114,97, ++ 105,115,101,100,46,10,10,32,32,32,32,78,99,2,0,0, ++ 0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0, ++ 0,31,0,0,0,115,72,0,0,0,124,1,100,0,117,0, ++ 114,8,124,0,106,0,125,1,110,16,124,0,106,0,124,1, ++ 107,3,114,24,116,1,100,1,124,0,106,0,124,1,102,2, ++ 22,0,124,1,100,2,141,2,130,1,136,0,124,0,124,1, ++ 103,2,124,2,162,1,82,0,105,0,124,3,164,1,142,1, ++ 83,0,41,3,78,122,30,108,111,97,100,101,114,32,102,111, ++ 114,32,37,115,32,99,97,110,110,111,116,32,104,97,110,100, ++ 108,101,32,37,115,169,1,218,4,110,97,109,101,41,2,114, ++ 144,0,0,0,218,11,73,109,112,111,114,116,69,114,114,111, ++ 114,41,4,218,4,115,101,108,102,114,144,0,0,0,218,4, ++ 97,114,103,115,218,6,107,119,97,114,103,115,169,1,218,6, ++ 109,101,116,104,111,100,114,7,0,0,0,114,8,0,0,0, ++ 218,19,95,99,104,101,99,107,95,110,97,109,101,95,119,114, ++ 97,112,112,101,114,30,2,0,0,115,18,0,0,0,8,1, ++ 8,1,10,1,4,1,8,1,2,255,2,1,6,255,24,2, ++ 122,40,95,99,104,101,99,107,95,110,97,109,101,46,60,108, ++ 111,99,97,108,115,62,46,95,99,104,101,99,107,95,110,97, ++ 109,101,95,119,114,97,112,112,101,114,99,2,0,0,0,0, ++ 0,0,0,0,0,0,0,3,0,0,0,7,0,0,0,83, ++ 0,0,0,115,56,0,0,0,100,1,68,0,93,16,125,2, ++ 116,0,124,1,124,2,131,2,114,18,116,1,124,0,124,2, ++ 116,2,124,1,124,2,131,2,131,3,1,0,113,2,124,0, ++ 106,3,160,4,124,1,106,3,161,1,1,0,100,0,83,0, ++ 41,2,78,41,4,218,10,95,95,109,111,100,117,108,101,95, ++ 95,218,8,95,95,110,97,109,101,95,95,218,12,95,95,113, ++ 117,97,108,110,97,109,101,95,95,218,7,95,95,100,111,99, ++ 95,95,41,5,218,7,104,97,115,97,116,116,114,218,7,115, ++ 101,116,97,116,116,114,218,7,103,101,116,97,116,116,114,218, ++ 8,95,95,100,105,99,116,95,95,218,6,117,112,100,97,116, ++ 101,41,3,90,3,110,101,119,90,3,111,108,100,114,88,0, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, +- 0,218,13,95,99,108,97,115,115,105,102,121,95,112,121,99, +- 73,2,0,0,115,28,0,0,0,12,16,8,1,16,1,12, +- 1,16,1,12,1,10,1,12,1,8,1,16,1,8,2,16, +- 1,16,1,4,1,114,176,0,0,0,99,5,0,0,0,0, ++ 0,218,5,95,119,114,97,112,43,2,0,0,115,10,0,0, ++ 0,8,1,10,1,18,1,2,128,18,1,122,26,95,99,104, ++ 101,99,107,95,110,97,109,101,46,60,108,111,99,97,108,115, ++ 62,46,95,119,114,97,112,114,72,0,0,0,41,2,218,10, ++ 95,98,111,111,116,115,116,114,97,112,114,161,0,0,0,41, ++ 3,114,150,0,0,0,114,151,0,0,0,114,161,0,0,0, ++ 114,7,0,0,0,114,149,0,0,0,114,8,0,0,0,218, ++ 11,95,99,104,101,99,107,95,110,97,109,101,22,2,0,0, ++ 115,12,0,0,0,14,8,8,10,8,1,8,2,10,6,4, ++ 1,114,163,0,0,0,99,2,0,0,0,0,0,0,0,0, ++ 0,0,0,5,0,0,0,6,0,0,0,67,0,0,0,115, ++ 72,0,0,0,116,0,160,1,100,1,116,2,161,2,1,0, ++ 124,0,160,3,124,1,161,1,92,2,125,2,125,3,124,2, ++ 100,2,117,0,114,34,116,4,124,3,131,1,114,34,100,3, ++ 125,4,116,0,160,1,124,4,160,5,124,3,100,4,25,0, ++ 161,1,116,6,161,2,1,0,124,2,83,0,41,5,122,155, ++ 84,114,121,32,116,111,32,102,105,110,100,32,97,32,108,111, ++ 97,100,101,114,32,102,111,114,32,116,104,101,32,115,112,101, ++ 99,105,102,105,101,100,32,109,111,100,117,108,101,32,98,121, ++ 32,100,101,108,101,103,97,116,105,110,103,32,116,111,10,32, ++ 32,32,32,115,101,108,102,46,102,105,110,100,95,108,111,97, ++ 100,101,114,40,41,46,10,10,32,32,32,32,84,104,105,115, ++ 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, ++ 99,97,116,101,100,32,105,110,32,102,97,118,111,114,32,111, ++ 102,32,102,105,110,100,101,114,46,102,105,110,100,95,115,112, ++ 101,99,40,41,46,10,10,32,32,32,32,122,90,102,105,110, ++ 100,95,109,111,100,117,108,101,40,41,32,105,115,32,100,101, ++ 112,114,101,99,97,116,101,100,32,97,110,100,32,115,108,97, ++ 116,101,100,32,102,111,114,32,114,101,109,111,118,97,108,32, ++ 105,110,32,80,121,116,104,111,110,32,51,46,49,50,59,32, ++ 117,115,101,32,102,105,110,100,95,115,112,101,99,40,41,32, ++ 105,110,115,116,101,97,100,78,122,44,78,111,116,32,105,109, ++ 112,111,114,116,105,110,103,32,100,105,114,101,99,116,111,114, ++ 121,32,123,125,58,32,109,105,115,115,105,110,103,32,95,95, ++ 105,110,105,116,95,95,114,0,0,0,0,41,7,114,102,0, ++ 0,0,114,103,0,0,0,114,104,0,0,0,218,11,102,105, ++ 110,100,95,108,111,97,100,101,114,114,4,0,0,0,114,92, ++ 0,0,0,218,13,73,109,112,111,114,116,87,97,114,110,105, ++ 110,103,41,5,114,146,0,0,0,218,8,102,117,108,108,110, ++ 97,109,101,218,6,108,111,97,100,101,114,218,8,112,111,114, ++ 116,105,111,110,115,218,3,109,115,103,114,7,0,0,0,114, ++ 7,0,0,0,114,8,0,0,0,218,17,95,102,105,110,100, ++ 95,109,111,100,117,108,101,95,115,104,105,109,53,2,0,0, ++ 115,16,0,0,0,6,7,2,2,4,254,14,6,16,1,4, ++ 1,22,1,4,1,114,170,0,0,0,99,3,0,0,0,0, + 0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,67, +- 0,0,0,115,124,0,0,0,116,0,124,0,100,1,100,2, +- 133,2,25,0,131,1,124,1,100,3,64,0,107,3,114,31, +- 100,4,124,3,155,2,157,2,125,5,116,1,160,2,100,5, +- 124,5,161,2,1,0,116,3,124,5,102,1,105,0,124,4, +- 164,1,142,1,130,1,124,2,100,6,117,1,114,58,116,0, +- 124,0,100,2,100,7,133,2,25,0,131,1,124,2,100,3, +- 64,0,107,3,114,60,116,3,100,4,124,3,155,2,157,2, +- 102,1,105,0,124,4,164,1,142,1,130,1,100,6,83,0, +- 100,6,83,0,41,8,97,7,2,0,0,86,97,108,105,100, +- 97,116,101,32,97,32,112,121,99,32,97,103,97,105,110,115, +- 116,32,116,104,101,32,115,111,117,114,99,101,32,108,97,115, +- 116,45,109,111,100,105,102,105,101,100,32,116,105,109,101,46, +- 10,10,32,32,32,32,42,100,97,116,97,42,32,105,115,32, +- 116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32, +- 116,104,101,32,112,121,99,32,102,105,108,101,46,32,40,79, +- 110,108,121,32,116,104,101,32,102,105,114,115,116,32,49,54, +- 32,98,121,116,101,115,32,97,114,101,10,32,32,32,32,114, +- 101,113,117,105,114,101,100,46,41,10,10,32,32,32,32,42, +- 115,111,117,114,99,101,95,109,116,105,109,101,42,32,105,115, +- 32,116,104,101,32,108,97,115,116,32,109,111,100,105,102,105, +- 101,100,32,116,105,109,101,115,116,97,109,112,32,111,102,32, +- 116,104,101,32,115,111,117,114,99,101,32,102,105,108,101,46, +- 10,10,32,32,32,32,42,115,111,117,114,99,101,95,115,105, +- 122,101,42,32,105,115,32,78,111,110,101,32,111,114,32,116, +- 104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,115, +- 111,117,114,99,101,32,102,105,108,101,32,105,110,32,98,121, +- 116,101,115,46,10,10,32,32,32,32,42,110,97,109,101,42, +- 32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32, +- 116,104,101,32,109,111,100,117,108,101,32,98,101,105,110,103, +- 32,105,109,112,111,114,116,101,100,46,32,73,116,32,105,115, +- 32,117,115,101,100,32,102,111,114,32,108,111,103,103,105,110, +- 103,46,10,10,32,32,32,32,42,101,120,99,95,100,101,116, +- 97,105,108,115,42,32,105,115,32,97,32,100,105,99,116,105, +- 111,110,97,114,121,32,112,97,115,115,101,100,32,116,111,32, +- 73,109,112,111,114,116,69,114,114,111,114,32,105,102,32,105, +- 116,32,114,97,105,115,101,100,32,102,111,114,10,32,32,32, +- 32,105,109,112,114,111,118,101,100,32,100,101,98,117,103,103, +- 105,110,103,46,10,10,32,32,32,32,65,110,32,73,109,112, +- 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, +- 101,100,32,105,102,32,116,104,101,32,98,121,116,101,99,111, +- 100,101,32,105,115,32,115,116,97,108,101,46,10,10,32,32, +- 32,32,114,170,0,0,0,233,12,0,0,0,114,30,0,0, +- 0,122,22,98,121,116,101,99,111,100,101,32,105,115,32,115, +- 116,97,108,101,32,102,111,114,32,114,168,0,0,0,78,114, +- 169,0,0,0,41,4,114,42,0,0,0,114,159,0,0,0, +- 114,173,0,0,0,114,142,0,0,0,41,6,114,41,0,0, +- 0,218,12,115,111,117,114,99,101,95,109,116,105,109,101,218, +- 11,115,111,117,114,99,101,95,115,105,122,101,114,141,0,0, +- 0,114,175,0,0,0,114,117,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,218,23,95,118,97,108, +- 105,100,97,116,101,95,116,105,109,101,115,116,97,109,112,95, +- 112,121,99,106,2,0,0,115,18,0,0,0,24,19,10,1, +- 12,1,16,1,8,1,24,1,22,1,4,254,4,1,114,180, +- 0,0,0,99,4,0,0,0,0,0,0,0,0,0,0,0, +- 4,0,0,0,4,0,0,0,67,0,0,0,115,42,0,0, +- 0,124,0,100,1,100,2,133,2,25,0,124,1,107,3,114, +- 19,116,0,100,3,124,2,155,2,157,2,102,1,105,0,124, +- 3,164,1,142,1,130,1,100,4,83,0,41,5,97,243,1, +- 0,0,86,97,108,105,100,97,116,101,32,97,32,104,97,115, +- 104,45,98,97,115,101,100,32,112,121,99,32,98,121,32,99, +- 104,101,99,107,105,110,103,32,116,104,101,32,114,101,97,108, +- 32,115,111,117,114,99,101,32,104,97,115,104,32,97,103,97, +- 105,110,115,116,32,116,104,101,32,111,110,101,32,105,110,10, +- 32,32,32,32,116,104,101,32,112,121,99,32,104,101,97,100, +- 101,114,46,10,10,32,32,32,32,42,100,97,116,97,42,32, +- 105,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32, +- 111,102,32,116,104,101,32,112,121,99,32,102,105,108,101,46, +- 32,40,79,110,108,121,32,116,104,101,32,102,105,114,115,116, +- 32,49,54,32,98,121,116,101,115,32,97,114,101,10,32,32, +- 32,32,114,101,113,117,105,114,101,100,46,41,10,10,32,32, +- 32,32,42,115,111,117,114,99,101,95,104,97,115,104,42,32, +- 105,115,32,116,104,101,32,105,109,112,111,114,116,108,105,98, +- 46,117,116,105,108,46,115,111,117,114,99,101,95,104,97,115, +- 104,40,41,32,111,102,32,116,104,101,32,115,111,117,114,99, +- 101,32,102,105,108,101,46,10,10,32,32,32,32,42,110,97, +- 109,101,42,32,105,115,32,116,104,101,32,110,97,109,101,32, +- 111,102,32,116,104,101,32,109,111,100,117,108,101,32,98,101, +- 105,110,103,32,105,109,112,111,114,116,101,100,46,32,73,116, +- 32,105,115,32,117,115,101,100,32,102,111,114,32,108,111,103, +- 103,105,110,103,46,10,10,32,32,32,32,42,101,120,99,95, +- 100,101,116,97,105,108,115,42,32,105,115,32,97,32,100,105, +- 99,116,105,111,110,97,114,121,32,112,97,115,115,101,100,32, +- 116,111,32,73,109,112,111,114,116,69,114,114,111,114,32,105, +- 102,32,105,116,32,114,97,105,115,101,100,32,102,111,114,10, +- 32,32,32,32,105,109,112,114,111,118,101,100,32,100,101,98, +- 117,103,103,105,110,103,46,10,10,32,32,32,32,65,110,32, +- 73,109,112,111,114,116,69,114,114,111,114,32,105,115,32,114, +- 97,105,115,101,100,32,105,102,32,116,104,101,32,98,121,116, +- 101,99,111,100,101,32,105,115,32,115,116,97,108,101,46,10, +- 10,32,32,32,32,114,170,0,0,0,114,169,0,0,0,122, +- 46,104,97,115,104,32,105,110,32,98,121,116,101,99,111,100, +- 101,32,100,111,101,115,110,39,116,32,109,97,116,99,104,32, +- 104,97,115,104,32,111,102,32,115,111,117,114,99,101,32,78, +- 41,1,114,142,0,0,0,41,4,114,41,0,0,0,218,11, +- 115,111,117,114,99,101,95,104,97,115,104,114,141,0,0,0, +- 114,175,0,0,0,114,7,0,0,0,114,7,0,0,0,114, +- 8,0,0,0,218,18,95,118,97,108,105,100,97,116,101,95, +- 104,97,115,104,95,112,121,99,134,2,0,0,115,14,0,0, +- 0,16,17,2,1,8,1,4,255,2,2,6,254,4,255,114, +- 182,0,0,0,99,4,0,0,0,0,0,0,0,0,0,0, +- 0,5,0,0,0,5,0,0,0,67,0,0,0,115,76,0, +- 0,0,116,0,160,1,124,0,161,1,125,4,116,2,124,4, +- 116,3,131,2,114,28,116,4,160,5,100,1,124,2,161,2, +- 1,0,124,3,100,2,117,1,114,26,116,6,160,7,124,4, +- 124,3,161,2,1,0,124,4,83,0,116,8,100,3,160,9, +- 124,2,161,1,124,1,124,2,100,4,141,3,130,1,41,5, +- 122,35,67,111,109,112,105,108,101,32,98,121,116,101,99,111, +- 100,101,32,97,115,32,102,111,117,110,100,32,105,110,32,97, +- 32,112,121,99,46,122,21,99,111,100,101,32,111,98,106,101, +- 99,116,32,102,114,111,109,32,123,33,114,125,78,122,23,78, +- 111,110,45,99,111,100,101,32,111,98,106,101,99,116,32,105, +- 110,32,123,33,114,125,169,2,114,141,0,0,0,114,65,0, +- 0,0,41,10,218,7,109,97,114,115,104,97,108,90,5,108, +- 111,97,100,115,218,10,105,115,105,110,115,116,97,110,99,101, +- 218,10,95,99,111,100,101,95,116,121,112,101,114,159,0,0, +- 0,114,173,0,0,0,218,4,95,105,109,112,90,16,95,102, +- 105,120,95,99,111,95,102,105,108,101,110,97,109,101,114,142, +- 0,0,0,114,89,0,0,0,41,5,114,41,0,0,0,114, +- 141,0,0,0,114,132,0,0,0,114,134,0,0,0,218,4, +- 99,111,100,101,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,17,95,99,111,109,112,105,108,101,95,98,121, +- 116,101,99,111,100,101,158,2,0,0,115,18,0,0,0,10, +- 2,10,1,12,1,8,1,12,1,4,1,10,2,4,1,6, +- 255,114,189,0,0,0,99,3,0,0,0,0,0,0,0,0, +- 0,0,0,4,0,0,0,5,0,0,0,67,0,0,0,115, +- 70,0,0,0,116,0,116,1,131,1,125,3,124,3,160,2, +- 116,3,100,1,131,1,161,1,1,0,124,3,160,2,116,3, +- 124,1,131,1,161,1,1,0,124,3,160,2,116,3,124,2, +- 131,1,161,1,1,0,124,3,160,2,116,4,160,5,124,0, +- 161,1,161,1,1,0,124,3,83,0,41,2,122,43,80,114, +- 111,100,117,99,101,32,116,104,101,32,100,97,116,97,32,102, +- 111,114,32,97,32,116,105,109,101,115,116,97,109,112,45,98, +- 97,115,101,100,32,112,121,99,46,114,0,0,0,0,41,6, +- 218,9,98,121,116,101,97,114,114,97,121,114,172,0,0,0, +- 218,6,101,120,116,101,110,100,114,36,0,0,0,114,184,0, +- 0,0,218,5,100,117,109,112,115,41,4,114,188,0,0,0, +- 218,5,109,116,105,109,101,114,179,0,0,0,114,41,0,0, ++ 0,0,0,115,166,0,0,0,124,0,100,1,100,2,133,2, ++ 25,0,125,3,124,3,116,0,107,3,114,32,100,3,124,1, ++ 155,2,100,4,124,3,155,2,157,4,125,4,116,1,160,2, ++ 100,5,124,4,161,2,1,0,116,3,124,4,102,1,105,0, ++ 124,2,164,1,142,1,130,1,116,4,124,0,131,1,100,6, ++ 107,0,114,53,100,7,124,1,155,2,157,2,125,4,116,1, ++ 160,2,100,5,124,4,161,2,1,0,116,5,124,4,131,1, ++ 130,1,116,6,124,0,100,2,100,8,133,2,25,0,131,1, ++ 125,5,124,5,100,9,64,0,114,81,100,10,124,5,155,2, ++ 100,11,124,1,155,2,157,4,125,4,116,3,124,4,102,1, ++ 105,0,124,2,164,1,142,1,130,1,124,5,83,0,41,12, ++ 97,84,2,0,0,80,101,114,102,111,114,109,32,98,97,115, ++ 105,99,32,118,97,108,105,100,105,116,121,32,99,104,101,99, ++ 107,105,110,103,32,111,102,32,97,32,112,121,99,32,104,101, ++ 97,100,101,114,32,97,110,100,32,114,101,116,117,114,110,32, ++ 116,104,101,32,102,108,97,103,115,32,102,105,101,108,100,44, ++ 10,32,32,32,32,119,104,105,99,104,32,100,101,116,101,114, ++ 109,105,110,101,115,32,104,111,119,32,116,104,101,32,112,121, ++ 99,32,115,104,111,117,108,100,32,98,101,32,102,117,114,116, ++ 104,101,114,32,118,97,108,105,100,97,116,101,100,32,97,103, ++ 97,105,110,115,116,32,116,104,101,32,115,111,117,114,99,101, ++ 46,10,10,32,32,32,32,42,100,97,116,97,42,32,105,115, ++ 32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102, ++ 32,116,104,101,32,112,121,99,32,102,105,108,101,46,32,40, ++ 79,110,108,121,32,116,104,101,32,102,105,114,115,116,32,49, ++ 54,32,98,121,116,101,115,32,97,114,101,10,32,32,32,32, ++ 114,101,113,117,105,114,101,100,44,32,116,104,111,117,103,104, ++ 46,41,10,10,32,32,32,32,42,110,97,109,101,42,32,105, ++ 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, ++ 101,32,109,111,100,117,108,101,32,98,101,105,110,103,32,105, ++ 109,112,111,114,116,101,100,46,32,73,116,32,105,115,32,117, ++ 115,101,100,32,102,111,114,32,108,111,103,103,105,110,103,46, ++ 10,10,32,32,32,32,42,101,120,99,95,100,101,116,97,105, ++ 108,115,42,32,105,115,32,97,32,100,105,99,116,105,111,110, ++ 97,114,121,32,112,97,115,115,101,100,32,116,111,32,73,109, ++ 112,111,114,116,69,114,114,111,114,32,105,102,32,105,116,32, ++ 114,97,105,115,101,100,32,102,111,114,10,32,32,32,32,105, ++ 109,112,114,111,118,101,100,32,100,101,98,117,103,103,105,110, ++ 103,46,10,10,32,32,32,32,73,109,112,111,114,116,69,114, ++ 114,111,114,32,105,115,32,114,97,105,115,101,100,32,119,104, ++ 101,110,32,116,104,101,32,109,97,103,105,99,32,110,117,109, ++ 98,101,114,32,105,115,32,105,110,99,111,114,114,101,99,116, ++ 32,111,114,32,119,104,101,110,32,116,104,101,32,102,108,97, ++ 103,115,10,32,32,32,32,102,105,101,108,100,32,105,115,32, ++ 105,110,118,97,108,105,100,46,32,69,79,70,69,114,114,111, ++ 114,32,105,115,32,114,97,105,115,101,100,32,119,104,101,110, ++ 32,116,104,101,32,100,97,116,97,32,105,115,32,102,111,117, ++ 110,100,32,116,111,32,98,101,32,116,114,117,110,99,97,116, ++ 101,100,46,10,10,32,32,32,32,78,114,34,0,0,0,122, ++ 20,98,97,100,32,109,97,103,105,99,32,110,117,109,98,101, ++ 114,32,105,110,32,122,2,58,32,250,2,123,125,233,16,0, ++ 0,0,122,40,114,101,97,99,104,101,100,32,69,79,70,32, ++ 119,104,105,108,101,32,114,101,97,100,105,110,103,32,112,121, ++ 99,32,104,101,97,100,101,114,32,111,102,32,233,8,0,0, ++ 0,233,252,255,255,255,122,14,105,110,118,97,108,105,100,32, ++ 102,108,97,103,115,32,122,4,32,105,110,32,41,7,218,12, ++ 77,65,71,73,67,95,78,85,77,66,69,82,114,162,0,0, ++ 0,218,16,95,118,101,114,98,111,115,101,95,109,101,115,115, ++ 97,103,101,114,145,0,0,0,114,4,0,0,0,218,8,69, ++ 79,70,69,114,114,111,114,114,45,0,0,0,41,6,114,44, ++ 0,0,0,114,144,0,0,0,218,11,101,120,99,95,100,101, ++ 116,97,105,108,115,90,5,109,97,103,105,99,114,120,0,0, ++ 0,114,19,0,0,0,114,7,0,0,0,114,7,0,0,0, ++ 114,8,0,0,0,218,13,95,99,108,97,115,115,105,102,121, ++ 95,112,121,99,73,2,0,0,115,28,0,0,0,12,16,8, ++ 1,16,1,12,1,16,1,12,1,10,1,12,1,8,1,16, ++ 1,8,2,16,1,16,1,4,1,114,179,0,0,0,99,5, ++ 0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4, ++ 0,0,0,67,0,0,0,115,124,0,0,0,116,0,124,0, ++ 100,1,100,2,133,2,25,0,131,1,124,1,100,3,64,0, ++ 107,3,114,31,100,4,124,3,155,2,157,2,125,5,116,1, ++ 160,2,100,5,124,5,161,2,1,0,116,3,124,5,102,1, ++ 105,0,124,4,164,1,142,1,130,1,124,2,100,6,117,1, ++ 114,58,116,0,124,0,100,2,100,7,133,2,25,0,131,1, ++ 124,2,100,3,64,0,107,3,114,60,116,3,100,4,124,3, ++ 155,2,157,2,102,1,105,0,124,4,164,1,142,1,130,1, ++ 100,6,83,0,100,6,83,0,41,8,97,7,2,0,0,86, ++ 97,108,105,100,97,116,101,32,97,32,112,121,99,32,97,103, ++ 97,105,110,115,116,32,116,104,101,32,115,111,117,114,99,101, ++ 32,108,97,115,116,45,109,111,100,105,102,105,101,100,32,116, ++ 105,109,101,46,10,10,32,32,32,32,42,100,97,116,97,42, ++ 32,105,115,32,116,104,101,32,99,111,110,116,101,110,116,115, ++ 32,111,102,32,116,104,101,32,112,121,99,32,102,105,108,101, ++ 46,32,40,79,110,108,121,32,116,104,101,32,102,105,114,115, ++ 116,32,49,54,32,98,121,116,101,115,32,97,114,101,10,32, ++ 32,32,32,114,101,113,117,105,114,101,100,46,41,10,10,32, ++ 32,32,32,42,115,111,117,114,99,101,95,109,116,105,109,101, ++ 42,32,105,115,32,116,104,101,32,108,97,115,116,32,109,111, ++ 100,105,102,105,101,100,32,116,105,109,101,115,116,97,109,112, ++ 32,111,102,32,116,104,101,32,115,111,117,114,99,101,32,102, ++ 105,108,101,46,10,10,32,32,32,32,42,115,111,117,114,99, ++ 101,95,115,105,122,101,42,32,105,115,32,78,111,110,101,32, ++ 111,114,32,116,104,101,32,115,105,122,101,32,111,102,32,116, ++ 104,101,32,115,111,117,114,99,101,32,102,105,108,101,32,105, ++ 110,32,98,121,116,101,115,46,10,10,32,32,32,32,42,110, ++ 97,109,101,42,32,105,115,32,116,104,101,32,110,97,109,101, ++ 32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,98, ++ 101,105,110,103,32,105,109,112,111,114,116,101,100,46,32,73, ++ 116,32,105,115,32,117,115,101,100,32,102,111,114,32,108,111, ++ 103,103,105,110,103,46,10,10,32,32,32,32,42,101,120,99, ++ 95,100,101,116,97,105,108,115,42,32,105,115,32,97,32,100, ++ 105,99,116,105,111,110,97,114,121,32,112,97,115,115,101,100, ++ 32,116,111,32,73,109,112,111,114,116,69,114,114,111,114,32, ++ 105,102,32,105,116,32,114,97,105,115,101,100,32,102,111,114, ++ 10,32,32,32,32,105,109,112,114,111,118,101,100,32,100,101, ++ 98,117,103,103,105,110,103,46,10,10,32,32,32,32,65,110, ++ 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,32, ++ 114,97,105,115,101,100,32,105,102,32,116,104,101,32,98,121, ++ 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,46, ++ 10,10,32,32,32,32,114,173,0,0,0,233,12,0,0,0, ++ 114,33,0,0,0,122,22,98,121,116,101,99,111,100,101,32, ++ 105,115,32,115,116,97,108,101,32,102,111,114,32,114,171,0, ++ 0,0,78,114,172,0,0,0,41,4,114,45,0,0,0,114, ++ 162,0,0,0,114,176,0,0,0,114,145,0,0,0,41,6, ++ 114,44,0,0,0,218,12,115,111,117,114,99,101,95,109,116, ++ 105,109,101,218,11,115,111,117,114,99,101,95,115,105,122,101, ++ 114,144,0,0,0,114,178,0,0,0,114,120,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,23, ++ 95,118,97,108,105,100,97,116,101,95,116,105,109,101,115,116, ++ 97,109,112,95,112,121,99,106,2,0,0,115,18,0,0,0, ++ 24,19,10,1,12,1,16,1,8,1,24,1,22,1,4,254, ++ 4,1,114,183,0,0,0,99,4,0,0,0,0,0,0,0, ++ 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, ++ 115,42,0,0,0,124,0,100,1,100,2,133,2,25,0,124, ++ 1,107,3,114,19,116,0,100,3,124,2,155,2,157,2,102, ++ 1,105,0,124,3,164,1,142,1,130,1,100,4,83,0,41, ++ 5,97,243,1,0,0,86,97,108,105,100,97,116,101,32,97, ++ 32,104,97,115,104,45,98,97,115,101,100,32,112,121,99,32, ++ 98,121,32,99,104,101,99,107,105,110,103,32,116,104,101,32, ++ 114,101,97,108,32,115,111,117,114,99,101,32,104,97,115,104, ++ 32,97,103,97,105,110,115,116,32,116,104,101,32,111,110,101, ++ 32,105,110,10,32,32,32,32,116,104,101,32,112,121,99,32, ++ 104,101,97,100,101,114,46,10,10,32,32,32,32,42,100,97, ++ 116,97,42,32,105,115,32,116,104,101,32,99,111,110,116,101, ++ 110,116,115,32,111,102,32,116,104,101,32,112,121,99,32,102, ++ 105,108,101,46,32,40,79,110,108,121,32,116,104,101,32,102, ++ 105,114,115,116,32,49,54,32,98,121,116,101,115,32,97,114, ++ 101,10,32,32,32,32,114,101,113,117,105,114,101,100,46,41, ++ 10,10,32,32,32,32,42,115,111,117,114,99,101,95,104,97, ++ 115,104,42,32,105,115,32,116,104,101,32,105,109,112,111,114, ++ 116,108,105,98,46,117,116,105,108,46,115,111,117,114,99,101, ++ 95,104,97,115,104,40,41,32,111,102,32,116,104,101,32,115, ++ 111,117,114,99,101,32,102,105,108,101,46,10,10,32,32,32, ++ 32,42,110,97,109,101,42,32,105,115,32,116,104,101,32,110, ++ 97,109,101,32,111,102,32,116,104,101,32,109,111,100,117,108, ++ 101,32,98,101,105,110,103,32,105,109,112,111,114,116,101,100, ++ 46,32,73,116,32,105,115,32,117,115,101,100,32,102,111,114, ++ 32,108,111,103,103,105,110,103,46,10,10,32,32,32,32,42, ++ 101,120,99,95,100,101,116,97,105,108,115,42,32,105,115,32, ++ 97,32,100,105,99,116,105,111,110,97,114,121,32,112,97,115, ++ 115,101,100,32,116,111,32,73,109,112,111,114,116,69,114,114, ++ 111,114,32,105,102,32,105,116,32,114,97,105,115,101,100,32, ++ 102,111,114,10,32,32,32,32,105,109,112,114,111,118,101,100, ++ 32,100,101,98,117,103,103,105,110,103,46,10,10,32,32,32, ++ 32,65,110,32,73,109,112,111,114,116,69,114,114,111,114,32, ++ 105,115,32,114,97,105,115,101,100,32,105,102,32,116,104,101, ++ 32,98,121,116,101,99,111,100,101,32,105,115,32,115,116,97, ++ 108,101,46,10,10,32,32,32,32,114,173,0,0,0,114,172, ++ 0,0,0,122,46,104,97,115,104,32,105,110,32,98,121,116, ++ 101,99,111,100,101,32,100,111,101,115,110,39,116,32,109,97, ++ 116,99,104,32,104,97,115,104,32,111,102,32,115,111,117,114, ++ 99,101,32,78,41,1,114,145,0,0,0,41,4,114,44,0, ++ 0,0,218,11,115,111,117,114,99,101,95,104,97,115,104,114, ++ 144,0,0,0,114,178,0,0,0,114,7,0,0,0,114,7, ++ 0,0,0,114,8,0,0,0,218,18,95,118,97,108,105,100, ++ 97,116,101,95,104,97,115,104,95,112,121,99,134,2,0,0, ++ 115,14,0,0,0,16,17,2,1,8,1,4,255,2,2,6, ++ 254,4,255,114,185,0,0,0,99,4,0,0,0,0,0,0, ++ 0,0,0,0,0,5,0,0,0,5,0,0,0,67,0,0, ++ 0,115,76,0,0,0,116,0,160,1,124,0,161,1,125,4, ++ 116,2,124,4,116,3,131,2,114,28,116,4,160,5,100,1, ++ 124,2,161,2,1,0,124,3,100,2,117,1,114,26,116,6, ++ 160,7,124,4,124,3,161,2,1,0,124,4,83,0,116,8, ++ 100,3,160,9,124,2,161,1,124,1,124,2,100,4,141,3, ++ 130,1,41,5,122,35,67,111,109,112,105,108,101,32,98,121, ++ 116,101,99,111,100,101,32,97,115,32,102,111,117,110,100,32, ++ 105,110,32,97,32,112,121,99,46,122,21,99,111,100,101,32, ++ 111,98,106,101,99,116,32,102,114,111,109,32,123,33,114,125, ++ 78,122,23,78,111,110,45,99,111,100,101,32,111,98,106,101, ++ 99,116,32,105,110,32,123,33,114,125,169,2,114,144,0,0, ++ 0,114,68,0,0,0,41,10,218,7,109,97,114,115,104,97, ++ 108,90,5,108,111,97,100,115,218,10,105,115,105,110,115,116, ++ 97,110,99,101,218,10,95,99,111,100,101,95,116,121,112,101, ++ 114,162,0,0,0,114,176,0,0,0,218,4,95,105,109,112, ++ 90,16,95,102,105,120,95,99,111,95,102,105,108,101,110,97, ++ 109,101,114,145,0,0,0,114,92,0,0,0,41,5,114,44, ++ 0,0,0,114,144,0,0,0,114,135,0,0,0,114,137,0, ++ 0,0,218,4,99,111,100,101,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,17,95,99,111,109,112,105,108, ++ 101,95,98,121,116,101,99,111,100,101,158,2,0,0,115,18, ++ 0,0,0,10,2,10,1,12,1,8,1,12,1,4,1,10, ++ 2,4,1,6,255,114,192,0,0,0,99,3,0,0,0,0, ++ 0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,67, ++ 0,0,0,115,70,0,0,0,116,0,116,1,131,1,125,3, ++ 124,3,160,2,116,3,100,1,131,1,161,1,1,0,124,3, ++ 160,2,116,3,124,1,131,1,161,1,1,0,124,3,160,2, ++ 116,3,124,2,131,1,161,1,1,0,124,3,160,2,116,4, ++ 160,5,124,0,161,1,161,1,1,0,124,3,83,0,41,2, ++ 122,43,80,114,111,100,117,99,101,32,116,104,101,32,100,97, ++ 116,97,32,102,111,114,32,97,32,116,105,109,101,115,116,97, ++ 109,112,45,98,97,115,101,100,32,112,121,99,46,114,0,0, ++ 0,0,41,6,218,9,98,121,116,101,97,114,114,97,121,114, ++ 175,0,0,0,218,6,101,120,116,101,110,100,114,39,0,0, ++ 0,114,187,0,0,0,218,5,100,117,109,112,115,41,4,114, ++ 191,0,0,0,218,5,109,116,105,109,101,114,182,0,0,0, ++ 114,44,0,0,0,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,218,22,95,99,111,100,101,95,116,111,95,116, ++ 105,109,101,115,116,97,109,112,95,112,121,99,171,2,0,0, ++ 115,12,0,0,0,8,2,14,1,14,1,14,1,16,1,4, ++ 1,114,197,0,0,0,84,99,3,0,0,0,0,0,0,0, ++ 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, ++ 115,80,0,0,0,116,0,116,1,131,1,125,3,100,1,124, ++ 2,100,1,62,0,66,0,125,4,124,3,160,2,116,3,124, ++ 4,131,1,161,1,1,0,116,4,124,1,131,1,100,2,107, ++ 2,115,25,74,0,130,1,124,3,160,2,124,1,161,1,1, ++ 0,124,3,160,2,116,5,160,6,124,0,161,1,161,1,1, ++ 0,124,3,83,0,41,3,122,38,80,114,111,100,117,99,101, ++ 32,116,104,101,32,100,97,116,97,32,102,111,114,32,97,32, ++ 104,97,115,104,45,98,97,115,101,100,32,112,121,99,46,114, ++ 3,0,0,0,114,173,0,0,0,41,7,114,193,0,0,0, ++ 114,175,0,0,0,114,194,0,0,0,114,39,0,0,0,114, ++ 4,0,0,0,114,187,0,0,0,114,195,0,0,0,41,5, ++ 114,191,0,0,0,114,184,0,0,0,90,7,99,104,101,99, ++ 107,101,100,114,44,0,0,0,114,19,0,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,218,17,95,99, ++ 111,100,101,95,116,111,95,104,97,115,104,95,112,121,99,181, ++ 2,0,0,115,14,0,0,0,8,2,12,1,14,1,16,1, ++ 10,1,16,1,4,1,114,198,0,0,0,99,1,0,0,0, ++ 0,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0, ++ 67,0,0,0,115,62,0,0,0,100,1,100,2,108,0,125, ++ 1,116,1,160,2,124,0,161,1,106,3,125,2,124,1,160, ++ 4,124,2,161,1,125,3,116,1,160,5,100,2,100,3,161, ++ 2,125,4,124,4,160,6,124,0,160,6,124,3,100,1,25, ++ 0,161,1,161,1,83,0,41,4,122,121,68,101,99,111,100, ++ 101,32,98,121,116,101,115,32,114,101,112,114,101,115,101,110, ++ 116,105,110,103,32,115,111,117,114,99,101,32,99,111,100,101, ++ 32,97,110,100,32,114,101,116,117,114,110,32,116,104,101,32, ++ 115,116,114,105,110,103,46,10,10,32,32,32,32,85,110,105, ++ 118,101,114,115,97,108,32,110,101,119,108,105,110,101,32,115, ++ 117,112,112,111,114,116,32,105,115,32,117,115,101,100,32,105, ++ 110,32,116,104,101,32,100,101,99,111,100,105,110,103,46,10, ++ 32,32,32,32,114,0,0,0,0,78,84,41,7,218,8,116, ++ 111,107,101,110,105,122,101,114,94,0,0,0,90,7,66,121, ++ 116,101,115,73,79,90,8,114,101,97,100,108,105,110,101,90, ++ 15,100,101,116,101,99,116,95,101,110,99,111,100,105,110,103, ++ 90,25,73,110,99,114,101,109,101,110,116,97,108,78,101,119, ++ 108,105,110,101,68,101,99,111,100,101,114,218,6,100,101,99, ++ 111,100,101,41,5,218,12,115,111,117,114,99,101,95,98,121, ++ 116,101,115,114,199,0,0,0,90,21,115,111,117,114,99,101, ++ 95,98,121,116,101,115,95,114,101,97,100,108,105,110,101,218, ++ 8,101,110,99,111,100,105,110,103,90,15,110,101,119,108,105, ++ 110,101,95,100,101,99,111,100,101,114,114,7,0,0,0,114, ++ 7,0,0,0,114,8,0,0,0,218,13,100,101,99,111,100, ++ 101,95,115,111,117,114,99,101,192,2,0,0,115,10,0,0, ++ 0,8,5,12,1,10,1,12,1,20,1,114,203,0,0,0, ++ 169,2,114,167,0,0,0,218,26,115,117,98,109,111,100,117, ++ 108,101,95,115,101,97,114,99,104,95,108,111,99,97,116,105, ++ 111,110,115,99,2,0,0,0,0,0,0,0,2,0,0,0, ++ 9,0,0,0,8,0,0,0,67,0,0,0,115,54,1,0, ++ 0,124,1,100,1,117,0,114,29,100,2,125,1,116,0,124, ++ 2,100,3,131,2,114,28,122,7,124,2,160,1,124,0,161, ++ 1,125,1,87,0,110,38,4,0,116,2,121,27,1,0,1, ++ 0,1,0,89,0,110,30,119,0,110,28,116,3,160,4,124, ++ 1,161,1,125,1,116,5,124,1,131,1,115,57,122,9,116, ++ 6,116,3,160,7,161,0,124,1,131,2,125,1,87,0,110, ++ 9,4,0,116,8,121,56,1,0,1,0,1,0,89,0,110, ++ 1,119,0,116,9,106,10,124,0,124,2,124,1,100,4,141, ++ 3,125,4,100,5,124,4,95,11,124,2,100,1,117,0,114, ++ 99,116,12,131,0,68,0,93,21,92,2,125,5,125,6,124, ++ 1,160,13,116,14,124,6,131,1,161,1,114,96,124,5,124, ++ 0,124,1,131,2,125,2,124,2,124,4,95,15,1,0,110, ++ 3,113,75,100,1,83,0,124,3,116,16,117,0,114,131,116, ++ 0,124,2,100,6,131,2,114,130,122,7,124,2,160,17,124, ++ 0,161,1,125,7,87,0,110,9,4,0,116,2,121,124,1, ++ 0,1,0,1,0,89,0,110,10,119,0,124,7,114,130,103, ++ 0,124,4,95,18,110,3,124,3,124,4,95,18,124,4,106, ++ 18,103,0,107,2,114,153,124,1,114,153,116,19,124,1,131, ++ 1,100,7,25,0,125,8,124,4,106,18,160,20,124,8,161, ++ 1,1,0,124,4,83,0,41,8,97,61,1,0,0,82,101, ++ 116,117,114,110,32,97,32,109,111,100,117,108,101,32,115,112, ++ 101,99,32,98,97,115,101,100,32,111,110,32,97,32,102,105, ++ 108,101,32,108,111,99,97,116,105,111,110,46,10,10,32,32, ++ 32,32,84,111,32,105,110,100,105,99,97,116,101,32,116,104, ++ 97,116,32,116,104,101,32,109,111,100,117,108,101,32,105,115, ++ 32,97,32,112,97,99,107,97,103,101,44,32,115,101,116,10, ++ 32,32,32,32,115,117,98,109,111,100,117,108,101,95,115,101, ++ 97,114,99,104,95,108,111,99,97,116,105,111,110,115,32,116, ++ 111,32,97,32,108,105,115,116,32,111,102,32,100,105,114,101, ++ 99,116,111,114,121,32,112,97,116,104,115,46,32,32,65,110, ++ 10,32,32,32,32,101,109,112,116,121,32,108,105,115,116,32, ++ 105,115,32,115,117,102,102,105,99,105,101,110,116,44,32,116, ++ 104,111,117,103,104,32,105,116,115,32,110,111,116,32,111,116, ++ 104,101,114,119,105,115,101,32,117,115,101,102,117,108,32,116, ++ 111,32,116,104,101,10,32,32,32,32,105,109,112,111,114,116, ++ 32,115,121,115,116,101,109,46,10,10,32,32,32,32,84,104, ++ 101,32,108,111,97,100,101,114,32,109,117,115,116,32,116,97, ++ 107,101,32,97,32,115,112,101,99,32,97,115,32,105,116,115, ++ 32,111,110,108,121,32,95,95,105,110,105,116,95,95,40,41, ++ 32,97,114,103,46,10,10,32,32,32,32,78,122,9,60,117, ++ 110,107,110,111,119,110,62,218,12,103,101,116,95,102,105,108, ++ 101,110,97,109,101,169,1,218,6,111,114,105,103,105,110,84, ++ 218,10,105,115,95,112,97,99,107,97,103,101,114,0,0,0, ++ 0,41,21,114,156,0,0,0,114,206,0,0,0,114,145,0, ++ 0,0,114,21,0,0,0,114,106,0,0,0,114,89,0,0, ++ 0,114,70,0,0,0,114,85,0,0,0,114,79,0,0,0, ++ 114,162,0,0,0,218,10,77,111,100,117,108,101,83,112,101, ++ 99,90,13,95,115,101,116,95,102,105,108,101,97,116,116,114, ++ 218,27,95,103,101,116,95,115,117,112,112,111,114,116,101,100, ++ 95,102,105,108,101,95,108,111,97,100,101,114,115,114,61,0, ++ 0,0,114,139,0,0,0,114,167,0,0,0,218,9,95,80, ++ 79,80,85,76,65,84,69,114,209,0,0,0,114,205,0,0, ++ 0,114,77,0,0,0,114,64,0,0,0,41,9,114,144,0, ++ 0,0,90,8,108,111,99,97,116,105,111,110,114,167,0,0, ++ 0,114,205,0,0,0,218,4,115,112,101,99,218,12,108,111, ++ 97,100,101,114,95,99,108,97,115,115,218,8,115,117,102,102, ++ 105,120,101,115,114,209,0,0,0,90,7,100,105,114,110,97, ++ 109,101,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,218,23,115,112,101,99,95,102,114,111,109,95,102,105,108, ++ 101,95,108,111,99,97,116,105,111,110,209,2,0,0,115,84, ++ 0,0,0,8,12,4,4,10,1,2,2,14,1,12,1,4, ++ 1,2,255,2,252,10,7,8,1,2,1,18,1,12,1,4, ++ 1,2,255,16,9,6,1,8,3,14,1,14,1,10,1,6, ++ 1,4,1,2,253,4,5,8,3,10,2,2,1,14,1,12, ++ 1,4,1,2,255,4,3,6,1,2,128,6,2,10,1,4, ++ 1,12,1,12,1,4,2,114,216,0,0,0,99,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, ++ 0,64,0,0,0,115,88,0,0,0,101,0,90,1,100,0, ++ 90,2,100,1,90,3,100,2,90,4,100,3,90,5,101,6, ++ 111,15,100,4,101,7,118,0,90,8,101,9,100,5,100,6, ++ 132,0,131,1,90,10,101,11,100,7,100,8,132,0,131,1, ++ 90,12,101,11,100,14,100,10,100,11,132,1,131,1,90,13, ++ 101,11,100,15,100,12,100,13,132,1,131,1,90,14,100,9, ++ 83,0,41,16,218,21,87,105,110,100,111,119,115,82,101,103, ++ 105,115,116,114,121,70,105,110,100,101,114,122,62,77,101,116, ++ 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, ++ 114,32,109,111,100,117,108,101,115,32,100,101,99,108,97,114, ++ 101,100,32,105,110,32,116,104,101,32,87,105,110,100,111,119, ++ 115,32,114,101,103,105,115,116,114,121,46,122,59,83,111,102, ++ 116,119,97,114,101,92,80,121,116,104,111,110,92,80,121,116, ++ 104,111,110,67,111,114,101,92,123,115,121,115,95,118,101,114, ++ 115,105,111,110,125,92,77,111,100,117,108,101,115,92,123,102, ++ 117,108,108,110,97,109,101,125,122,65,83,111,102,116,119,97, ++ 114,101,92,80,121,116,104,111,110,92,80,121,116,104,111,110, ++ 67,111,114,101,92,123,115,121,115,95,118,101,114,115,105,111, ++ 110,125,92,77,111,100,117,108,101,115,92,123,102,117,108,108, ++ 110,97,109,101,125,92,68,101,98,117,103,122,6,95,100,46, ++ 112,121,100,99,1,0,0,0,0,0,0,0,0,0,0,0, ++ 1,0,0,0,8,0,0,0,67,0,0,0,115,50,0,0, ++ 0,122,8,116,0,160,1,116,0,106,2,124,0,161,2,87, ++ 0,83,0,4,0,116,3,121,24,1,0,1,0,1,0,116, ++ 0,160,1,116,0,106,4,124,0,161,2,6,0,89,0,83, ++ 0,119,0,114,72,0,0,0,41,5,218,6,119,105,110,114, ++ 101,103,90,7,79,112,101,110,75,101,121,90,17,72,75,69, ++ 89,95,67,85,82,82,69,78,84,95,85,83,69,82,114,79, ++ 0,0,0,90,18,72,75,69,89,95,76,79,67,65,76,95, ++ 77,65,67,72,73,78,69,114,22,0,0,0,114,7,0,0, ++ 0,114,7,0,0,0,114,8,0,0,0,218,14,95,111,112, ++ 101,110,95,114,101,103,105,115,116,114,121,38,3,0,0,115, ++ 10,0,0,0,2,2,16,1,12,1,18,1,2,255,122,36, ++ 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, ++ 105,110,100,101,114,46,95,111,112,101,110,95,114,101,103,105, ++ 115,116,114,121,99,2,0,0,0,0,0,0,0,0,0,0, ++ 0,6,0,0,0,8,0,0,0,67,0,0,0,115,134,0, ++ 0,0,124,0,106,0,114,7,124,0,106,1,125,2,110,3, ++ 124,0,106,2,125,2,124,2,106,3,124,1,100,1,116,4, ++ 106,5,100,0,100,2,133,2,25,0,22,0,100,3,141,2, ++ 125,3,122,32,124,0,160,6,124,3,161,1,143,16,125,4, ++ 116,7,160,8,124,4,100,4,161,2,125,5,87,0,100,0, ++ 4,0,4,0,131,3,1,0,87,0,124,5,83,0,49,0, ++ 115,49,119,1,1,0,1,0,1,0,89,0,1,0,87,0, ++ 124,5,83,0,4,0,116,9,121,66,1,0,1,0,1,0, ++ 89,0,100,0,83,0,119,0,41,5,78,122,5,37,100,46, ++ 37,100,114,47,0,0,0,41,2,114,166,0,0,0,90,11, ++ 115,121,115,95,118,101,114,115,105,111,110,114,10,0,0,0, ++ 41,10,218,11,68,69,66,85,71,95,66,85,73,76,68,218, ++ 18,82,69,71,73,83,84,82,89,95,75,69,89,95,68,69, ++ 66,85,71,218,12,82,69,71,73,83,84,82,89,95,75,69, ++ 89,114,92,0,0,0,114,18,0,0,0,218,12,118,101,114, ++ 115,105,111,110,95,105,110,102,111,114,219,0,0,0,114,218, ++ 0,0,0,90,10,81,117,101,114,121,86,97,108,117,101,114, ++ 79,0,0,0,41,6,218,3,99,108,115,114,166,0,0,0, ++ 90,12,114,101,103,105,115,116,114,121,95,107,101,121,114,23, ++ 0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,112, ++ 97,116,104,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,105, ++ 115,116,114,121,45,3,0,0,115,32,0,0,0,6,2,8, ++ 1,6,2,6,1,16,1,6,255,2,2,12,1,14,1,12, ++ 255,4,4,18,252,4,4,12,254,6,1,2,255,122,38,87, ++ 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, ++ 110,100,101,114,46,95,115,101,97,114,99,104,95,114,101,103, ++ 105,115,116,114,121,78,99,4,0,0,0,0,0,0,0,0, ++ 0,0,0,8,0,0,0,8,0,0,0,67,0,0,0,115, ++ 120,0,0,0,124,0,160,0,124,1,161,1,125,4,124,4, ++ 100,0,117,0,114,11,100,0,83,0,122,6,116,1,124,4, ++ 131,1,1,0,87,0,110,10,4,0,116,2,121,27,1,0, ++ 1,0,1,0,89,0,100,0,83,0,119,0,116,3,131,0, ++ 68,0,93,26,92,2,125,5,125,6,124,4,160,4,116,5, ++ 124,6,131,1,161,1,114,57,116,6,106,7,124,1,124,5, ++ 124,1,124,4,131,2,124,4,100,1,141,3,125,7,124,7, ++ 2,0,1,0,83,0,113,31,100,0,83,0,41,2,78,114, ++ 207,0,0,0,41,8,114,226,0,0,0,114,78,0,0,0, ++ 114,79,0,0,0,114,211,0,0,0,114,61,0,0,0,114, ++ 139,0,0,0,114,162,0,0,0,218,16,115,112,101,99,95, ++ 102,114,111,109,95,108,111,97,100,101,114,41,8,114,224,0, ++ 0,0,114,166,0,0,0,114,68,0,0,0,218,6,116,97, ++ 114,103,101,116,114,225,0,0,0,114,167,0,0,0,114,215, ++ 0,0,0,114,213,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,9,102,105,110,100,95,115,112, ++ 101,99,60,3,0,0,115,34,0,0,0,10,2,8,1,4, ++ 1,2,1,12,1,12,1,6,1,2,255,14,2,14,1,6, ++ 1,8,1,2,1,6,254,8,3,2,252,4,255,122,31,87, ++ 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, ++ 110,100,101,114,46,102,105,110,100,95,115,112,101,99,99,3, ++ 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4, ++ 0,0,0,67,0,0,0,115,42,0,0,0,116,0,160,1, ++ 100,1,116,2,161,2,1,0,124,0,160,3,124,1,124,2, ++ 161,2,125,3,124,3,100,2,117,1,114,19,124,3,106,4, ++ 83,0,100,2,83,0,41,3,122,106,70,105,110,100,32,109, ++ 111,100,117,108,101,32,110,97,109,101,100,32,105,110,32,116, ++ 104,101,32,114,101,103,105,115,116,114,121,46,10,10,32,32, ++ 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, ++ 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, ++ 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, ++ 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, ++ 32,32,32,32,122,112,87,105,110,100,111,119,115,82,101,103, ++ 105,115,116,114,121,70,105,110,100,101,114,46,102,105,110,100, ++ 95,109,111,100,117,108,101,40,41,32,105,115,32,100,101,112, ++ 114,101,99,97,116,101,100,32,97,110,100,32,115,108,97,116, ++ 101,100,32,102,111,114,32,114,101,109,111,118,97,108,32,105, ++ 110,32,80,121,116,104,111,110,32,51,46,49,50,59,32,117, ++ 115,101,32,102,105,110,100,95,115,112,101,99,40,41,32,105, ++ 110,115,116,101,97,100,78,169,5,114,102,0,0,0,114,103, ++ 0,0,0,114,104,0,0,0,114,229,0,0,0,114,167,0, ++ 0,0,169,4,114,224,0,0,0,114,166,0,0,0,114,68, ++ 0,0,0,114,213,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,11,102,105,110,100,95,109,111, ++ 100,117,108,101,76,3,0,0,115,14,0,0,0,6,7,2, ++ 2,4,254,12,3,8,1,6,1,4,2,122,33,87,105,110, ++ 100,111,119,115,82,101,103,105,115,116,114,121,70,105,110,100, ++ 101,114,46,102,105,110,100,95,109,111,100,117,108,101,169,2, ++ 78,78,114,72,0,0,0,41,15,114,153,0,0,0,114,152, ++ 0,0,0,114,154,0,0,0,114,155,0,0,0,114,222,0, ++ 0,0,114,221,0,0,0,218,11,95,77,83,95,87,73,78, ++ 68,79,87,83,218,18,69,88,84,69,78,83,73,79,78,95, ++ 83,85,70,70,73,88,69,83,114,220,0,0,0,218,12,115, ++ 116,97,116,105,99,109,101,116,104,111,100,114,219,0,0,0, ++ 218,11,99,108,97,115,115,109,101,116,104,111,100,114,226,0, ++ 0,0,114,229,0,0,0,114,232,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, +- 218,22,95,99,111,100,101,95,116,111,95,116,105,109,101,115, +- 116,97,109,112,95,112,121,99,171,2,0,0,115,12,0,0, +- 0,8,2,14,1,14,1,14,1,16,1,4,1,114,194,0, +- 0,0,84,99,3,0,0,0,0,0,0,0,0,0,0,0, +- 5,0,0,0,5,0,0,0,67,0,0,0,115,80,0,0, +- 0,116,0,116,1,131,1,125,3,100,1,124,2,100,1,62, +- 0,66,0,125,4,124,3,160,2,116,3,124,4,131,1,161, +- 1,1,0,116,4,124,1,131,1,100,2,107,2,115,25,74, +- 0,130,1,124,3,160,2,124,1,161,1,1,0,124,3,160, +- 2,116,5,160,6,124,0,161,1,161,1,1,0,124,3,83, +- 0,41,3,122,38,80,114,111,100,117,99,101,32,116,104,101, +- 32,100,97,116,97,32,102,111,114,32,97,32,104,97,115,104, +- 45,98,97,115,101,100,32,112,121,99,46,114,3,0,0,0, +- 114,170,0,0,0,41,7,114,190,0,0,0,114,172,0,0, +- 0,114,191,0,0,0,114,36,0,0,0,114,4,0,0,0, +- 114,184,0,0,0,114,192,0,0,0,41,5,114,188,0,0, +- 0,114,181,0,0,0,90,7,99,104,101,99,107,101,100,114, +- 41,0,0,0,114,16,0,0,0,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,218,17,95,99,111,100,101,95, +- 116,111,95,104,97,115,104,95,112,121,99,181,2,0,0,115, +- 14,0,0,0,8,2,12,1,14,1,16,1,10,1,16,1, +- 4,1,114,195,0,0,0,99,1,0,0,0,0,0,0,0, +- 0,0,0,0,5,0,0,0,6,0,0,0,67,0,0,0, +- 115,62,0,0,0,100,1,100,2,108,0,125,1,116,1,160, +- 2,124,0,161,1,106,3,125,2,124,1,160,4,124,2,161, +- 1,125,3,116,1,160,5,100,2,100,3,161,2,125,4,124, +- 4,160,6,124,0,160,6,124,3,100,1,25,0,161,1,161, +- 1,83,0,41,4,122,121,68,101,99,111,100,101,32,98,121, +- 116,101,115,32,114,101,112,114,101,115,101,110,116,105,110,103, +- 32,115,111,117,114,99,101,32,99,111,100,101,32,97,110,100, +- 32,114,101,116,117,114,110,32,116,104,101,32,115,116,114,105, +- 110,103,46,10,10,32,32,32,32,85,110,105,118,101,114,115, +- 97,108,32,110,101,119,108,105,110,101,32,115,117,112,112,111, +- 114,116,32,105,115,32,117,115,101,100,32,105,110,32,116,104, +- 101,32,100,101,99,111,100,105,110,103,46,10,32,32,32,32, +- 114,0,0,0,0,78,84,41,7,218,8,116,111,107,101,110, +- 105,122,101,114,91,0,0,0,90,7,66,121,116,101,115,73, +- 79,90,8,114,101,97,100,108,105,110,101,90,15,100,101,116, +- 101,99,116,95,101,110,99,111,100,105,110,103,90,25,73,110, +- 99,114,101,109,101,110,116,97,108,78,101,119,108,105,110,101, +- 68,101,99,111,100,101,114,218,6,100,101,99,111,100,101,41, +- 5,218,12,115,111,117,114,99,101,95,98,121,116,101,115,114, +- 196,0,0,0,90,21,115,111,117,114,99,101,95,98,121,116, +- 101,115,95,114,101,97,100,108,105,110,101,218,8,101,110,99, +- 111,100,105,110,103,90,15,110,101,119,108,105,110,101,95,100, +- 101,99,111,100,101,114,114,7,0,0,0,114,7,0,0,0, +- 114,8,0,0,0,218,13,100,101,99,111,100,101,95,115,111, +- 117,114,99,101,192,2,0,0,115,10,0,0,0,8,5,12, +- 1,10,1,12,1,20,1,114,200,0,0,0,169,2,114,164, +- 0,0,0,218,26,115,117,98,109,111,100,117,108,101,95,115, +- 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,99, +- 2,0,0,0,0,0,0,0,2,0,0,0,9,0,0,0, +- 8,0,0,0,67,0,0,0,115,54,1,0,0,124,1,100, +- 1,117,0,114,29,100,2,125,1,116,0,124,2,100,3,131, +- 2,114,28,122,7,124,2,160,1,124,0,161,1,125,1,87, +- 0,110,38,4,0,116,2,121,27,1,0,1,0,1,0,89, +- 0,110,30,119,0,110,28,116,3,160,4,124,1,161,1,125, +- 1,116,5,124,1,131,1,115,57,122,9,116,6,116,3,160, +- 7,161,0,124,1,131,2,125,1,87,0,110,9,4,0,116, +- 8,121,56,1,0,1,0,1,0,89,0,110,1,119,0,116, +- 9,106,10,124,0,124,2,124,1,100,4,141,3,125,4,100, +- 5,124,4,95,11,124,2,100,1,117,0,114,99,116,12,131, +- 0,68,0,93,21,92,2,125,5,125,6,124,1,160,13,116, +- 14,124,6,131,1,161,1,114,96,124,5,124,0,124,1,131, +- 2,125,2,124,2,124,4,95,15,1,0,110,3,113,75,100, +- 1,83,0,124,3,116,16,117,0,114,131,116,0,124,2,100, +- 6,131,2,114,130,122,7,124,2,160,17,124,0,161,1,125, +- 7,87,0,110,9,4,0,116,2,121,124,1,0,1,0,1, +- 0,89,0,110,10,119,0,124,7,114,130,103,0,124,4,95, +- 18,110,3,124,3,124,4,95,18,124,4,106,18,103,0,107, +- 2,114,153,124,1,114,153,116,19,124,1,131,1,100,7,25, +- 0,125,8,124,4,106,18,160,20,124,8,161,1,1,0,124, +- 4,83,0,41,8,97,61,1,0,0,82,101,116,117,114,110, +- 32,97,32,109,111,100,117,108,101,32,115,112,101,99,32,98, +- 97,115,101,100,32,111,110,32,97,32,102,105,108,101,32,108, +- 111,99,97,116,105,111,110,46,10,10,32,32,32,32,84,111, +- 32,105,110,100,105,99,97,116,101,32,116,104,97,116,32,116, +- 104,101,32,109,111,100,117,108,101,32,105,115,32,97,32,112, +- 97,99,107,97,103,101,44,32,115,101,116,10,32,32,32,32, +- 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, +- 95,108,111,99,97,116,105,111,110,115,32,116,111,32,97,32, +- 108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114, +- 121,32,112,97,116,104,115,46,32,32,65,110,10,32,32,32, +- 32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,115, +- 117,102,102,105,99,105,101,110,116,44,32,116,104,111,117,103, +- 104,32,105,116,115,32,110,111,116,32,111,116,104,101,114,119, +- 105,115,101,32,117,115,101,102,117,108,32,116,111,32,116,104, +- 101,10,32,32,32,32,105,109,112,111,114,116,32,115,121,115, +- 116,101,109,46,10,10,32,32,32,32,84,104,101,32,108,111, +- 97,100,101,114,32,109,117,115,116,32,116,97,107,101,32,97, +- 32,115,112,101,99,32,97,115,32,105,116,115,32,111,110,108, +- 121,32,95,95,105,110,105,116,95,95,40,41,32,97,114,103, +- 46,10,10,32,32,32,32,78,122,9,60,117,110,107,110,111, +- 119,110,62,218,12,103,101,116,95,102,105,108,101,110,97,109, +- 101,169,1,218,6,111,114,105,103,105,110,84,218,10,105,115, +- 95,112,97,99,107,97,103,101,114,0,0,0,0,41,21,114, +- 153,0,0,0,114,203,0,0,0,114,142,0,0,0,114,18, +- 0,0,0,114,103,0,0,0,114,86,0,0,0,114,67,0, +- 0,0,114,82,0,0,0,114,76,0,0,0,114,159,0,0, +- 0,218,10,77,111,100,117,108,101,83,112,101,99,90,13,95, +- 115,101,116,95,102,105,108,101,97,116,116,114,218,27,95,103, +- 101,116,95,115,117,112,112,111,114,116,101,100,95,102,105,108, +- 101,95,108,111,97,100,101,114,115,114,58,0,0,0,114,136, +- 0,0,0,114,164,0,0,0,218,9,95,80,79,80,85,76, +- 65,84,69,114,206,0,0,0,114,202,0,0,0,114,74,0, +- 0,0,114,61,0,0,0,41,9,114,141,0,0,0,90,8, +- 108,111,99,97,116,105,111,110,114,164,0,0,0,114,202,0, +- 0,0,218,4,115,112,101,99,218,12,108,111,97,100,101,114, +- 95,99,108,97,115,115,218,8,115,117,102,102,105,120,101,115, +- 114,206,0,0,0,90,7,100,105,114,110,97,109,101,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,218,23,115, +- 112,101,99,95,102,114,111,109,95,102,105,108,101,95,108,111, +- 99,97,116,105,111,110,209,2,0,0,115,84,0,0,0,8, +- 12,4,4,10,1,2,2,14,1,12,1,4,1,2,255,2, +- 252,10,7,8,1,2,1,18,1,12,1,4,1,2,255,16, +- 9,6,1,8,3,14,1,14,1,10,1,6,1,4,1,2, +- 253,4,5,8,3,10,2,2,1,14,1,12,1,4,1,2, +- 255,4,3,6,1,2,128,6,2,10,1,4,1,12,1,12, +- 1,4,2,114,213,0,0,0,99,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0, +- 0,115,88,0,0,0,101,0,90,1,100,0,90,2,100,1, +- 90,3,100,2,90,4,100,3,90,5,101,6,111,15,100,4, +- 101,7,118,0,90,8,101,9,100,5,100,6,132,0,131,1, +- 90,10,101,11,100,7,100,8,132,0,131,1,90,12,101,11, +- 100,14,100,10,100,11,132,1,131,1,90,13,101,11,100,15, +- 100,12,100,13,132,1,131,1,90,14,100,9,83,0,41,16, +- 218,21,87,105,110,100,111,119,115,82,101,103,105,115,116,114, +- 121,70,105,110,100,101,114,122,62,77,101,116,97,32,112,97, +- 116,104,32,102,105,110,100,101,114,32,102,111,114,32,109,111, +- 100,117,108,101,115,32,100,101,99,108,97,114,101,100,32,105, +- 110,32,116,104,101,32,87,105,110,100,111,119,115,32,114,101, +- 103,105,115,116,114,121,46,122,59,83,111,102,116,119,97,114, +- 101,92,80,121,116,104,111,110,92,80,121,116,104,111,110,67, +- 111,114,101,92,123,115,121,115,95,118,101,114,115,105,111,110, +- 125,92,77,111,100,117,108,101,115,92,123,102,117,108,108,110, +- 97,109,101,125,122,65,83,111,102,116,119,97,114,101,92,80, +- 121,116,104,111,110,92,80,121,116,104,111,110,67,111,114,101, +- 92,123,115,121,115,95,118,101,114,115,105,111,110,125,92,77, +- 111,100,117,108,101,115,92,123,102,117,108,108,110,97,109,101, +- 125,92,68,101,98,117,103,122,6,95,100,46,112,121,100,99, +- 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +- 8,0,0,0,67,0,0,0,115,50,0,0,0,122,8,116, +- 0,160,1,116,0,106,2,124,0,161,2,87,0,83,0,4, +- 0,116,3,121,24,1,0,1,0,1,0,116,0,160,1,116, +- 0,106,4,124,0,161,2,6,0,89,0,83,0,119,0,114, +- 69,0,0,0,41,5,218,6,119,105,110,114,101,103,90,7, +- 79,112,101,110,75,101,121,90,17,72,75,69,89,95,67,85, +- 82,82,69,78,84,95,85,83,69,82,114,76,0,0,0,90, +- 18,72,75,69,89,95,76,79,67,65,76,95,77,65,67,72, +- 73,78,69,114,19,0,0,0,114,7,0,0,0,114,7,0, +- 0,0,114,8,0,0,0,218,14,95,111,112,101,110,95,114, +- 101,103,105,115,116,114,121,38,3,0,0,115,10,0,0,0, +- 2,2,16,1,12,1,18,1,2,255,122,36,87,105,110,100, +- 111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,101, +- 114,46,95,111,112,101,110,95,114,101,103,105,115,116,114,121, +- 99,2,0,0,0,0,0,0,0,0,0,0,0,6,0,0, +- 0,8,0,0,0,67,0,0,0,115,134,0,0,0,124,0, +- 106,0,114,7,124,0,106,1,125,2,110,3,124,0,106,2, +- 125,2,124,2,106,3,124,1,100,1,116,4,106,5,100,0, +- 100,2,133,2,25,0,22,0,100,3,141,2,125,3,122,32, +- 124,0,160,6,124,3,161,1,143,16,125,4,116,7,160,8, +- 124,4,100,4,161,2,125,5,87,0,100,0,4,0,4,0, +- 131,3,1,0,87,0,124,5,83,0,49,0,115,49,119,1, +- 1,0,1,0,1,0,89,0,1,0,87,0,124,5,83,0, +- 4,0,116,9,121,66,1,0,1,0,1,0,89,0,100,0, +- 83,0,119,0,41,5,78,122,5,37,100,46,37,100,114,44, +- 0,0,0,41,2,114,163,0,0,0,90,11,115,121,115,95, +- 118,101,114,115,105,111,110,114,10,0,0,0,41,10,218,11, +- 68,69,66,85,71,95,66,85,73,76,68,218,18,82,69,71, +- 73,83,84,82,89,95,75,69,89,95,68,69,66,85,71,218, +- 12,82,69,71,73,83,84,82,89,95,75,69,89,114,89,0, +- 0,0,114,15,0,0,0,218,12,118,101,114,115,105,111,110, +- 95,105,110,102,111,114,216,0,0,0,114,215,0,0,0,90, +- 10,81,117,101,114,121,86,97,108,117,101,114,76,0,0,0, +- 41,6,218,3,99,108,115,114,163,0,0,0,90,12,114,101, +- 103,105,115,116,114,121,95,107,101,121,114,20,0,0,0,90, +- 4,104,107,101,121,218,8,102,105,108,101,112,97,116,104,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,16, +- 95,115,101,97,114,99,104,95,114,101,103,105,115,116,114,121, +- 45,3,0,0,115,32,0,0,0,6,2,8,1,6,2,6, +- 1,16,1,6,255,2,2,12,1,14,1,12,255,4,4,18, +- 252,4,4,12,254,6,1,2,255,122,38,87,105,110,100,111, +- 119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114, +- 46,95,115,101,97,114,99,104,95,114,101,103,105,115,116,114, +- 121,78,99,4,0,0,0,0,0,0,0,0,0,0,0,8, +- 0,0,0,8,0,0,0,67,0,0,0,115,120,0,0,0, +- 124,0,160,0,124,1,161,1,125,4,124,4,100,0,117,0, +- 114,11,100,0,83,0,122,6,116,1,124,4,131,1,1,0, +- 87,0,110,10,4,0,116,2,121,27,1,0,1,0,1,0, +- 89,0,100,0,83,0,119,0,116,3,131,0,68,0,93,26, +- 92,2,125,5,125,6,124,4,160,4,116,5,124,6,131,1, +- 161,1,114,57,116,6,106,7,124,1,124,5,124,1,124,4, +- 131,2,124,4,100,1,141,3,125,7,124,7,2,0,1,0, +- 83,0,113,31,100,0,83,0,41,2,78,114,204,0,0,0, +- 41,8,114,223,0,0,0,114,75,0,0,0,114,76,0,0, +- 0,114,208,0,0,0,114,58,0,0,0,114,136,0,0,0, +- 114,159,0,0,0,218,16,115,112,101,99,95,102,114,111,109, +- 95,108,111,97,100,101,114,41,8,114,221,0,0,0,114,163, +- 0,0,0,114,65,0,0,0,218,6,116,97,114,103,101,116, +- 114,222,0,0,0,114,164,0,0,0,114,212,0,0,0,114, +- 210,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,9,102,105,110,100,95,115,112,101,99,60,3, +- 0,0,115,34,0,0,0,10,2,8,1,4,1,2,1,12, +- 1,12,1,6,1,2,255,14,2,14,1,6,1,8,1,2, +- 1,6,254,8,3,2,252,4,255,122,31,87,105,110,100,111, +- 119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114, +- 46,102,105,110,100,95,115,112,101,99,99,3,0,0,0,0, +- 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, +- 0,0,0,115,42,0,0,0,116,0,160,1,100,1,116,2, +- 161,2,1,0,124,0,160,3,124,1,124,2,161,2,125,3, +- 124,3,100,2,117,1,114,19,124,3,106,4,83,0,100,2, +- 83,0,41,3,122,106,70,105,110,100,32,109,111,100,117,108, +- 101,32,110,97,109,101,100,32,105,110,32,116,104,101,32,114, +- 101,103,105,115,116,114,121,46,10,10,32,32,32,32,32,32, +- 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, +- 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, +- 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, +- 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, +- 122,112,87,105,110,100,111,119,115,82,101,103,105,115,116,114, +- 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, +- 117,108,101,40,41,32,105,115,32,100,101,112,114,101,99,97, +- 116,101,100,32,97,110,100,32,115,108,97,116,101,100,32,102, +- 111,114,32,114,101,109,111,118,97,108,32,105,110,32,80,121, +- 116,104,111,110,32,51,46,49,50,59,32,117,115,101,32,102, +- 105,110,100,95,115,112,101,99,40,41,32,105,110,115,116,101, +- 97,100,78,169,5,114,99,0,0,0,114,100,0,0,0,114, +- 101,0,0,0,114,226,0,0,0,114,164,0,0,0,169,4, +- 114,221,0,0,0,114,163,0,0,0,114,65,0,0,0,114, +- 210,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,11,102,105,110,100,95,109,111,100,117,108,101, +- 76,3,0,0,115,14,0,0,0,6,7,2,2,4,254,12, +- 3,8,1,6,1,4,2,122,33,87,105,110,100,111,119,115, +- 82,101,103,105,115,116,114,121,70,105,110,100,101,114,46,102, +- 105,110,100,95,109,111,100,117,108,101,169,2,78,78,114,69, +- 0,0,0,41,15,114,150,0,0,0,114,149,0,0,0,114, +- 151,0,0,0,114,152,0,0,0,114,219,0,0,0,114,218, +- 0,0,0,218,11,95,77,83,95,87,73,78,68,79,87,83, +- 218,18,69,88,84,69,78,83,73,79,78,95,83,85,70,70, +- 73,88,69,83,114,217,0,0,0,218,12,115,116,97,116,105, +- 99,109,101,116,104,111,100,114,216,0,0,0,218,11,99,108, +- 97,115,115,109,101,116,104,111,100,114,223,0,0,0,114,226, +- 0,0,0,114,229,0,0,0,114,7,0,0,0,114,7,0, +- 0,0,114,7,0,0,0,114,8,0,0,0,114,214,0,0, +- 0,26,3,0,0,115,30,0,0,0,8,0,4,2,2,3, +- 2,255,2,4,2,255,12,3,2,2,10,1,2,6,10,1, +- 2,14,12,1,2,15,16,1,114,214,0,0,0,99,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +- 0,0,64,0,0,0,115,48,0,0,0,101,0,90,1,100, +- 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, +- 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,100, +- 8,100,9,132,0,90,7,100,10,83,0,41,11,218,13,95, +- 76,111,97,100,101,114,66,97,115,105,99,115,122,83,66,97, +- 115,101,32,99,108,97,115,115,32,111,102,32,99,111,109,109, +- 111,110,32,99,111,100,101,32,110,101,101,100,101,100,32,98, +- 121,32,98,111,116,104,32,83,111,117,114,99,101,76,111,97, +- 100,101,114,32,97,110,100,10,32,32,32,32,83,111,117,114, +- 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, +- 46,99,2,0,0,0,0,0,0,0,0,0,0,0,5,0, +- 0,0,4,0,0,0,67,0,0,0,115,64,0,0,0,116, +- 0,124,0,160,1,124,1,161,1,131,1,100,1,25,0,125, +- 2,124,2,160,2,100,2,100,1,161,2,100,3,25,0,125, +- 3,124,1,160,3,100,2,161,1,100,4,25,0,125,4,124, +- 3,100,5,107,2,111,31,124,4,100,5,107,3,83,0,41, +- 6,122,141,67,111,110,99,114,101,116,101,32,105,109,112,108, +- 101,109,101,110,116,97,116,105,111,110,32,111,102,32,73,110, +- 115,112,101,99,116,76,111,97,100,101,114,46,105,115,95,112, +- 97,99,107,97,103,101,32,98,121,32,99,104,101,99,107,105, +- 110,103,32,105,102,10,32,32,32,32,32,32,32,32,116,104, +- 101,32,112,97,116,104,32,114,101,116,117,114,110,101,100,32, +- 98,121,32,103,101,116,95,102,105,108,101,110,97,109,101,32, +- 104,97,115,32,97,32,102,105,108,101,110,97,109,101,32,111, +- 102,32,39,95,95,105,110,105,116,95,95,46,112,121,39,46, +- 114,3,0,0,0,114,97,0,0,0,114,0,0,0,0,114, +- 44,0,0,0,218,8,95,95,105,110,105,116,95,95,41,4, +- 114,74,0,0,0,114,203,0,0,0,114,125,0,0,0,114, +- 104,0,0,0,41,5,114,143,0,0,0,114,163,0,0,0, +- 114,120,0,0,0,90,13,102,105,108,101,110,97,109,101,95, +- 98,97,115,101,90,9,116,97,105,108,95,110,97,109,101,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,206, +- 0,0,0,98,3,0,0,115,8,0,0,0,18,3,16,1, +- 14,1,16,1,122,24,95,76,111,97,100,101,114,66,97,115, +- 105,99,115,46,105,115,95,112,97,99,107,97,103,101,99,2, +- 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, +- 0,0,0,67,0,0,0,114,23,0,0,0,169,2,122,42, +- 85,115,101,32,100,101,102,97,117,108,116,32,115,101,109,97, +- 110,116,105,99,115,32,102,111,114,32,109,111,100,117,108,101, +- 32,99,114,101,97,116,105,111,110,46,78,114,7,0,0,0, +- 169,2,114,143,0,0,0,114,210,0,0,0,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,218,13,99,114,101, +- 97,116,101,95,109,111,100,117,108,101,106,3,0,0,243,2, +- 0,0,0,4,0,122,27,95,76,111,97,100,101,114,66,97, +- 115,105,99,115,46,99,114,101,97,116,101,95,109,111,100,117, +- 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,3, +- 0,0,0,5,0,0,0,67,0,0,0,115,56,0,0,0, +- 124,0,160,0,124,1,106,1,161,1,125,2,124,2,100,1, +- 117,0,114,18,116,2,100,2,160,3,124,1,106,1,161,1, +- 131,1,130,1,116,4,160,5,116,6,124,2,124,1,106,7, +- 161,3,1,0,100,1,83,0,41,3,122,19,69,120,101,99, +- 117,116,101,32,116,104,101,32,109,111,100,117,108,101,46,78, +- 122,52,99,97,110,110,111,116,32,108,111,97,100,32,109,111, +- 100,117,108,101,32,123,33,114,125,32,119,104,101,110,32,103, +- 101,116,95,99,111,100,101,40,41,32,114,101,116,117,114,110, +- 115,32,78,111,110,101,41,8,218,8,103,101,116,95,99,111, +- 100,101,114,150,0,0,0,114,142,0,0,0,114,89,0,0, +- 0,114,159,0,0,0,218,25,95,99,97,108,108,95,119,105, +- 116,104,95,102,114,97,109,101,115,95,114,101,109,111,118,101, +- 100,218,4,101,120,101,99,114,156,0,0,0,41,3,114,143, +- 0,0,0,218,6,109,111,100,117,108,101,114,188,0,0,0, ++ 114,217,0,0,0,26,3,0,0,115,30,0,0,0,8,0, ++ 4,2,2,3,2,255,2,4,2,255,12,3,2,2,10,1, ++ 2,6,10,1,2,14,12,1,2,15,16,1,114,217,0,0, ++ 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,2,0,0,0,64,0,0,0,115,48,0,0,0,101, ++ 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, ++ 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, ++ 0,90,6,100,8,100,9,132,0,90,7,100,10,83,0,41, ++ 11,218,13,95,76,111,97,100,101,114,66,97,115,105,99,115, ++ 122,83,66,97,115,101,32,99,108,97,115,115,32,111,102,32, ++ 99,111,109,109,111,110,32,99,111,100,101,32,110,101,101,100, ++ 101,100,32,98,121,32,98,111,116,104,32,83,111,117,114,99, ++ 101,76,111,97,100,101,114,32,97,110,100,10,32,32,32,32, ++ 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, ++ 97,100,101,114,46,99,2,0,0,0,0,0,0,0,0,0, ++ 0,0,5,0,0,0,4,0,0,0,67,0,0,0,115,64, ++ 0,0,0,116,0,124,0,160,1,124,1,161,1,131,1,100, ++ 1,25,0,125,2,124,2,160,2,100,2,100,1,161,2,100, ++ 3,25,0,125,3,124,1,160,3,100,2,161,1,100,4,25, ++ 0,125,4,124,3,100,5,107,2,111,31,124,4,100,5,107, ++ 3,83,0,41,6,122,141,67,111,110,99,114,101,116,101,32, ++ 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, ++ 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, ++ 105,115,95,112,97,99,107,97,103,101,32,98,121,32,99,104, ++ 101,99,107,105,110,103,32,105,102,10,32,32,32,32,32,32, ++ 32,32,116,104,101,32,112,97,116,104,32,114,101,116,117,114, ++ 110,101,100,32,98,121,32,103,101,116,95,102,105,108,101,110, ++ 97,109,101,32,104,97,115,32,97,32,102,105,108,101,110,97, ++ 109,101,32,111,102,32,39,95,95,105,110,105,116,95,95,46, ++ 112,121,39,46,114,3,0,0,0,114,100,0,0,0,114,0, ++ 0,0,0,114,47,0,0,0,218,8,95,95,105,110,105,116, ++ 95,95,41,4,114,77,0,0,0,114,206,0,0,0,114,128, ++ 0,0,0,114,107,0,0,0,41,5,114,146,0,0,0,114, ++ 166,0,0,0,114,123,0,0,0,90,13,102,105,108,101,110, ++ 97,109,101,95,98,97,115,101,90,9,116,97,105,108,95,110, ++ 97,109,101,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,114,209,0,0,0,98,3,0,0,115,8,0,0,0, ++ 18,3,16,1,14,1,16,1,122,24,95,76,111,97,100,101, ++ 114,66,97,115,105,99,115,46,105,115,95,112,97,99,107,97, ++ 103,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, ++ 0,0,0,1,0,0,0,67,0,0,0,114,26,0,0,0, ++ 169,2,122,42,85,115,101,32,100,101,102,97,117,108,116,32, ++ 115,101,109,97,110,116,105,99,115,32,102,111,114,32,109,111, ++ 100,117,108,101,32,99,114,101,97,116,105,111,110,46,78,114, ++ 7,0,0,0,169,2,114,146,0,0,0,114,213,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, +- 11,101,120,101,99,95,109,111,100,117,108,101,109,3,0,0, +- 115,12,0,0,0,12,2,8,1,4,1,8,1,4,255,20, +- 2,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, +- 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, +- 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, +- 0,67,0,0,0,115,12,0,0,0,116,0,160,1,124,0, +- 124,1,161,2,83,0,41,1,122,26,84,104,105,115,32,109, +- 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, +- 116,101,100,46,41,2,114,159,0,0,0,218,17,95,108,111, +- 97,100,95,109,111,100,117,108,101,95,115,104,105,109,169,2, +- 114,143,0,0,0,114,163,0,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,218,11,108,111,97,100,95, +- 109,111,100,117,108,101,117,3,0,0,115,2,0,0,0,12, +- 3,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, +- 46,108,111,97,100,95,109,111,100,117,108,101,78,41,8,114, +- 150,0,0,0,114,149,0,0,0,114,151,0,0,0,114,152, +- 0,0,0,114,206,0,0,0,114,239,0,0,0,114,245,0, +- 0,0,114,248,0,0,0,114,7,0,0,0,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,114,235,0,0,0, +- 93,3,0,0,115,12,0,0,0,8,0,4,2,8,3,8, +- 8,8,3,12,8,114,235,0,0,0,99,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, +- 0,0,0,115,74,0,0,0,101,0,90,1,100,0,90,2, +- 100,1,100,2,132,0,90,3,100,3,100,4,132,0,90,4, +- 100,5,100,6,132,0,90,5,100,7,100,8,132,0,90,6, +- 100,9,100,10,132,0,90,7,100,11,100,12,156,1,100,13, +- 100,14,132,2,90,8,100,15,100,16,132,0,90,9,100,17, +- 83,0,41,18,218,12,83,111,117,114,99,101,76,111,97,100, +- 101,114,99,2,0,0,0,0,0,0,0,0,0,0,0,2, +- 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, +- 116,0,130,1,41,1,122,165,79,112,116,105,111,110,97,108, +- 32,109,101,116,104,111,100,32,116,104,97,116,32,114,101,116, +- 117,114,110,115,32,116,104,101,32,109,111,100,105,102,105,99, +- 97,116,105,111,110,32,116,105,109,101,32,40,97,110,32,105, +- 110,116,41,32,102,111,114,32,116,104,101,10,32,32,32,32, +- 32,32,32,32,115,112,101,99,105,102,105,101,100,32,112,97, +- 116,104,32,40,97,32,115,116,114,41,46,10,10,32,32,32, +- 32,32,32,32,32,82,97,105,115,101,115,32,79,83,69,114, +- 114,111,114,32,119,104,101,110,32,116,104,101,32,112,97,116, +- 104,32,99,97,110,110,111,116,32,98,101,32,104,97,110,100, +- 108,101,100,46,10,32,32,32,32,32,32,32,32,41,1,114, +- 76,0,0,0,169,2,114,143,0,0,0,114,65,0,0,0, +- 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, +- 10,112,97,116,104,95,109,116,105,109,101,125,3,0,0,115, +- 2,0,0,0,4,6,122,23,83,111,117,114,99,101,76,111, +- 97,100,101,114,46,112,97,116,104,95,109,116,105,109,101,99, +- 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, +- 4,0,0,0,67,0,0,0,115,14,0,0,0,100,1,124, +- 0,160,0,124,1,161,1,105,1,83,0,41,2,97,158,1, +- 0,0,79,112,116,105,111,110,97,108,32,109,101,116,104,111, +- 100,32,114,101,116,117,114,110,105,110,103,32,97,32,109,101, +- 116,97,100,97,116,97,32,100,105,99,116,32,102,111,114,32, +- 116,104,101,32,115,112,101,99,105,102,105,101,100,10,32,32, +- 32,32,32,32,32,32,112,97,116,104,32,40,97,32,115,116, +- 114,41,46,10,10,32,32,32,32,32,32,32,32,80,111,115, +- 115,105,98,108,101,32,107,101,121,115,58,10,32,32,32,32, +- 32,32,32,32,45,32,39,109,116,105,109,101,39,32,40,109, +- 97,110,100,97,116,111,114,121,41,32,105,115,32,116,104,101, +- 32,110,117,109,101,114,105,99,32,116,105,109,101,115,116,97, +- 109,112,32,111,102,32,108,97,115,116,32,115,111,117,114,99, +- 101,10,32,32,32,32,32,32,32,32,32,32,99,111,100,101, +- 32,109,111,100,105,102,105,99,97,116,105,111,110,59,10,32, +- 32,32,32,32,32,32,32,45,32,39,115,105,122,101,39,32, +- 40,111,112,116,105,111,110,97,108,41,32,105,115,32,116,104, +- 101,32,115,105,122,101,32,105,110,32,98,121,116,101,115,32, +- 111,102,32,116,104,101,32,115,111,117,114,99,101,32,99,111, +- 100,101,46,10,10,32,32,32,32,32,32,32,32,73,109,112, +- 108,101,109,101,110,116,105,110,103,32,116,104,105,115,32,109, +- 101,116,104,111,100,32,97,108,108,111,119,115,32,116,104,101, +- 32,108,111,97,100,101,114,32,116,111,32,114,101,97,100,32, +- 98,121,116,101,99,111,100,101,32,102,105,108,101,115,46,10, +- 32,32,32,32,32,32,32,32,82,97,105,115,101,115,32,79, +- 83,69,114,114,111,114,32,119,104,101,110,32,116,104,101,32, +- 112,97,116,104,32,99,97,110,110,111,116,32,98,101,32,104, +- 97,110,100,108,101,100,46,10,32,32,32,32,32,32,32,32, +- 114,193,0,0,0,41,1,114,251,0,0,0,114,250,0,0, +- 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, +- 218,10,112,97,116,104,95,115,116,97,116,115,133,3,0,0, +- 115,2,0,0,0,14,12,122,23,83,111,117,114,99,101,76, +- 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, +- 99,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +- 0,4,0,0,0,67,0,0,0,115,12,0,0,0,124,0, +- 160,0,124,2,124,3,161,2,83,0,41,1,122,228,79,112, +- 116,105,111,110,97,108,32,109,101,116,104,111,100,32,119,104, +- 105,99,104,32,119,114,105,116,101,115,32,100,97,116,97,32, +- 40,98,121,116,101,115,41,32,116,111,32,97,32,102,105,108, +- 101,32,112,97,116,104,32,40,97,32,115,116,114,41,46,10, +- 10,32,32,32,32,32,32,32,32,73,109,112,108,101,109,101, +- 110,116,105,110,103,32,116,104,105,115,32,109,101,116,104,111, +- 100,32,97,108,108,111,119,115,32,102,111,114,32,116,104,101, +- 32,119,114,105,116,105,110,103,32,111,102,32,98,121,116,101, +- 99,111,100,101,32,102,105,108,101,115,46,10,10,32,32,32, +- 32,32,32,32,32,84,104,101,32,115,111,117,114,99,101,32, +- 112,97,116,104,32,105,115,32,110,101,101,100,101,100,32,105, +- 110,32,111,114,100,101,114,32,116,111,32,99,111,114,114,101, +- 99,116,108,121,32,116,114,97,110,115,102,101,114,32,112,101, +- 114,109,105,115,115,105,111,110,115,10,32,32,32,32,32,32, +- 32,32,41,1,218,8,115,101,116,95,100,97,116,97,41,4, +- 114,143,0,0,0,114,134,0,0,0,90,10,99,97,99,104, +- 101,95,112,97,116,104,114,41,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,218,15,95,99,97,99, +- 104,101,95,98,121,116,101,99,111,100,101,147,3,0,0,115, +- 2,0,0,0,12,8,122,28,83,111,117,114,99,101,76,111, +- 97,100,101,114,46,95,99,97,99,104,101,95,98,121,116,101, +- 99,111,100,101,99,3,0,0,0,0,0,0,0,0,0,0, +- 0,3,0,0,0,1,0,0,0,67,0,0,0,114,23,0, +- 0,0,41,2,122,150,79,112,116,105,111,110,97,108,32,109, +- 101,116,104,111,100,32,119,104,105,99,104,32,119,114,105,116, +- 101,115,32,100,97,116,97,32,40,98,121,116,101,115,41,32, +- 116,111,32,97,32,102,105,108,101,32,112,97,116,104,32,40, ++ 13,99,114,101,97,116,101,95,109,111,100,117,108,101,106,3, ++ 0,0,243,2,0,0,0,4,0,122,27,95,76,111,97,100, ++ 101,114,66,97,115,105,99,115,46,99,114,101,97,116,101,95, ++ 109,111,100,117,108,101,99,2,0,0,0,0,0,0,0,0, ++ 0,0,0,3,0,0,0,5,0,0,0,67,0,0,0,115, ++ 56,0,0,0,124,0,160,0,124,1,106,1,161,1,125,2, ++ 124,2,100,1,117,0,114,18,116,2,100,2,160,3,124,1, ++ 106,1,161,1,131,1,130,1,116,4,160,5,116,6,124,2, ++ 124,1,106,7,161,3,1,0,100,1,83,0,41,3,122,19, ++ 69,120,101,99,117,116,101,32,116,104,101,32,109,111,100,117, ++ 108,101,46,78,122,52,99,97,110,110,111,116,32,108,111,97, ++ 100,32,109,111,100,117,108,101,32,123,33,114,125,32,119,104, ++ 101,110,32,103,101,116,95,99,111,100,101,40,41,32,114,101, ++ 116,117,114,110,115,32,78,111,110,101,41,8,218,8,103,101, ++ 116,95,99,111,100,101,114,153,0,0,0,114,145,0,0,0, ++ 114,92,0,0,0,114,162,0,0,0,218,25,95,99,97,108, ++ 108,95,119,105,116,104,95,102,114,97,109,101,115,95,114,101, ++ 109,111,118,101,100,218,4,101,120,101,99,114,159,0,0,0, ++ 41,3,114,146,0,0,0,218,6,109,111,100,117,108,101,114, ++ 191,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, ++ 0,0,0,218,11,101,120,101,99,95,109,111,100,117,108,101, ++ 109,3,0,0,115,12,0,0,0,12,2,8,1,4,1,8, ++ 1,4,255,20,2,122,25,95,76,111,97,100,101,114,66,97, ++ 115,105,99,115,46,101,120,101,99,95,109,111,100,117,108,101, ++ 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, ++ 0,4,0,0,0,67,0,0,0,115,12,0,0,0,116,0, ++ 160,1,124,0,124,1,161,2,83,0,41,1,122,26,84,104, ++ 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, ++ 114,101,99,97,116,101,100,46,41,2,114,162,0,0,0,218, ++ 17,95,108,111,97,100,95,109,111,100,117,108,101,95,115,104, ++ 105,109,169,2,114,146,0,0,0,114,166,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,218,11,108, ++ 111,97,100,95,109,111,100,117,108,101,117,3,0,0,115,2, ++ 0,0,0,12,3,122,25,95,76,111,97,100,101,114,66,97, ++ 115,105,99,115,46,108,111,97,100,95,109,111,100,117,108,101, ++ 78,41,8,114,153,0,0,0,114,152,0,0,0,114,154,0, ++ 0,0,114,155,0,0,0,114,209,0,0,0,114,242,0,0, ++ 0,114,248,0,0,0,114,251,0,0,0,114,7,0,0,0, ++ 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, ++ 238,0,0,0,93,3,0,0,115,12,0,0,0,8,0,4, ++ 2,8,3,8,8,8,3,12,8,114,238,0,0,0,99,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, ++ 0,0,0,64,0,0,0,115,74,0,0,0,101,0,90,1, ++ 100,0,90,2,100,1,100,2,132,0,90,3,100,3,100,4, ++ 132,0,90,4,100,5,100,6,132,0,90,5,100,7,100,8, ++ 132,0,90,6,100,9,100,10,132,0,90,7,100,11,100,12, ++ 156,1,100,13,100,14,132,2,90,8,100,15,100,16,132,0, ++ 90,9,100,17,83,0,41,18,218,12,83,111,117,114,99,101, ++ 76,111,97,100,101,114,99,2,0,0,0,0,0,0,0,0, ++ 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, ++ 4,0,0,0,116,0,130,1,41,1,122,165,79,112,116,105, ++ 111,110,97,108,32,109,101,116,104,111,100,32,116,104,97,116, ++ 32,114,101,116,117,114,110,115,32,116,104,101,32,109,111,100, ++ 105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,40, ++ 97,110,32,105,110,116,41,32,102,111,114,32,116,104,101,10, ++ 32,32,32,32,32,32,32,32,115,112,101,99,105,102,105,101, ++ 100,32,112,97,116,104,32,40,97,32,115,116,114,41,46,10, ++ 10,32,32,32,32,32,32,32,32,82,97,105,115,101,115,32, ++ 79,83,69,114,114,111,114,32,119,104,101,110,32,116,104,101, ++ 32,112,97,116,104,32,99,97,110,110,111,116,32,98,101,32, ++ 104,97,110,100,108,101,100,46,10,32,32,32,32,32,32,32, ++ 32,41,1,114,79,0,0,0,169,2,114,146,0,0,0,114, ++ 68,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, ++ 0,0,0,218,10,112,97,116,104,95,109,116,105,109,101,125, ++ 3,0,0,115,2,0,0,0,4,6,122,23,83,111,117,114, ++ 99,101,76,111,97,100,101,114,46,112,97,116,104,95,109,116, ++ 105,109,101,99,2,0,0,0,0,0,0,0,0,0,0,0, ++ 2,0,0,0,4,0,0,0,67,0,0,0,115,14,0,0, ++ 0,100,1,124,0,160,0,124,1,161,1,105,1,83,0,41, ++ 2,97,158,1,0,0,79,112,116,105,111,110,97,108,32,109, ++ 101,116,104,111,100,32,114,101,116,117,114,110,105,110,103,32, ++ 97,32,109,101,116,97,100,97,116,97,32,100,105,99,116,32, ++ 102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101, ++ 100,10,32,32,32,32,32,32,32,32,112,97,116,104,32,40, + 97,32,115,116,114,41,46,10,10,32,32,32,32,32,32,32, ++ 32,80,111,115,115,105,98,108,101,32,107,101,121,115,58,10, ++ 32,32,32,32,32,32,32,32,45,32,39,109,116,105,109,101, ++ 39,32,40,109,97,110,100,97,116,111,114,121,41,32,105,115, ++ 32,116,104,101,32,110,117,109,101,114,105,99,32,116,105,109, ++ 101,115,116,97,109,112,32,111,102,32,108,97,115,116,32,115, ++ 111,117,114,99,101,10,32,32,32,32,32,32,32,32,32,32, ++ 99,111,100,101,32,109,111,100,105,102,105,99,97,116,105,111, ++ 110,59,10,32,32,32,32,32,32,32,32,45,32,39,115,105, ++ 122,101,39,32,40,111,112,116,105,111,110,97,108,41,32,105, ++ 115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,121, ++ 116,101,115,32,111,102,32,116,104,101,32,115,111,117,114,99, ++ 101,32,99,111,100,101,46,10,10,32,32,32,32,32,32,32, + 32,73,109,112,108,101,109,101,110,116,105,110,103,32,116,104, + 105,115,32,109,101,116,104,111,100,32,97,108,108,111,119,115, +- 32,102,111,114,32,116,104,101,32,119,114,105,116,105,110,103, +- 32,111,102,32,98,121,116,101,99,111,100,101,32,102,105,108, +- 101,115,46,10,32,32,32,32,32,32,32,32,78,114,7,0, +- 0,0,41,3,114,143,0,0,0,114,65,0,0,0,114,41, +- 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, +- 0,0,114,253,0,0,0,157,3,0,0,114,240,0,0,0, +- 122,21,83,111,117,114,99,101,76,111,97,100,101,114,46,115, +- 101,116,95,100,97,116,97,99,2,0,0,0,0,0,0,0, +- 0,0,0,0,5,0,0,0,10,0,0,0,67,0,0,0, +- 115,70,0,0,0,124,0,160,0,124,1,161,1,125,2,122, +- 10,124,0,160,1,124,2,161,1,125,3,87,0,116,4,124, +- 3,131,1,83,0,4,0,116,2,121,34,1,0,125,4,1, +- 0,122,7,116,3,100,1,124,1,100,2,141,2,124,4,130, +- 2,100,3,125,4,126,4,119,1,119,0,41,4,122,52,67, +- 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, +- 116,97,116,105,111,110,32,111,102,32,73,110,115,112,101,99, +- 116,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, +- 99,101,46,122,39,115,111,117,114,99,101,32,110,111,116,32, +- 97,118,97,105,108,97,98,108,101,32,116,104,114,111,117,103, +- 104,32,103,101,116,95,100,97,116,97,40,41,114,140,0,0, +- 0,78,41,5,114,203,0,0,0,218,8,103,101,116,95,100, +- 97,116,97,114,76,0,0,0,114,142,0,0,0,114,200,0, +- 0,0,41,5,114,143,0,0,0,114,163,0,0,0,114,65, +- 0,0,0,114,198,0,0,0,218,3,101,120,99,114,7,0, +- 0,0,114,7,0,0,0,114,8,0,0,0,218,10,103,101, +- 116,95,115,111,117,114,99,101,164,3,0,0,115,24,0,0, +- 0,10,2,2,1,12,1,8,4,14,253,4,1,2,1,4, +- 255,2,1,2,255,8,128,2,255,122,23,83,111,117,114,99, +- 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, +- 99,101,114,130,0,0,0,41,1,218,9,95,111,112,116,105, +- 109,105,122,101,99,3,0,0,0,0,0,0,0,1,0,0, +- 0,4,0,0,0,8,0,0,0,67,0,0,0,115,22,0, +- 0,0,116,0,106,1,116,2,124,1,124,2,100,1,100,2, +- 124,3,100,3,141,6,83,0,41,4,122,130,82,101,116,117, +- 114,110,32,116,104,101,32,99,111,100,101,32,111,98,106,101, +- 99,116,32,99,111,109,112,105,108,101,100,32,102,114,111,109, +- 32,115,111,117,114,99,101,46,10,10,32,32,32,32,32,32, +- 32,32,84,104,101,32,39,100,97,116,97,39,32,97,114,103, +- 117,109,101,110,116,32,99,97,110,32,98,101,32,97,110,121, +- 32,111,98,106,101,99,116,32,116,121,112,101,32,116,104,97, +- 116,32,99,111,109,112,105,108,101,40,41,32,115,117,112,112, +- 111,114,116,115,46,10,32,32,32,32,32,32,32,32,114,243, +- 0,0,0,84,41,2,218,12,100,111,110,116,95,105,110,104, +- 101,114,105,116,114,108,0,0,0,41,3,114,159,0,0,0, +- 114,242,0,0,0,218,7,99,111,109,112,105,108,101,41,4, +- 114,143,0,0,0,114,41,0,0,0,114,65,0,0,0,114, +- 2,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,14,115,111,117,114,99,101,95,116,111,95,99, +- 111,100,101,174,3,0,0,115,6,0,0,0,12,5,4,1, +- 6,255,122,27,83,111,117,114,99,101,76,111,97,100,101,114, +- 46,115,111,117,114,99,101,95,116,111,95,99,111,100,101,99, +- 2,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0, +- 9,0,0,0,67,0,0,0,115,2,2,0,0,124,0,160, +- 0,124,1,161,1,125,2,100,1,125,3,100,1,125,4,100, +- 1,125,5,100,2,125,6,100,3,125,7,122,6,116,1,124, +- 2,131,1,125,8,87,0,110,11,4,0,116,2,121,32,1, +- 0,1,0,1,0,100,1,125,8,89,0,110,144,119,0,122, +- 7,124,0,160,3,124,2,161,1,125,9,87,0,110,9,4, +- 0,116,4,121,49,1,0,1,0,1,0,89,0,110,127,119, +- 0,116,5,124,9,100,4,25,0,131,1,125,3,122,7,124, +- 0,160,6,124,8,161,1,125,10,87,0,110,9,4,0,116, +- 4,121,72,1,0,1,0,1,0,89,0,110,104,119,0,124, +- 1,124,8,100,5,156,2,125,11,122,71,116,7,124,10,124, +- 1,124,11,131,3,125,12,116,8,124,10,131,1,100,6,100, +- 1,133,2,25,0,125,13,124,12,100,7,64,0,100,8,107, +- 3,125,6,124,6,114,138,124,12,100,9,64,0,100,8,107, +- 3,125,7,116,9,106,10,100,10,107,3,114,137,124,7,115, +- 119,116,9,106,10,100,11,107,2,114,137,124,0,160,6,124, +- 2,161,1,125,4,116,9,160,11,116,12,124,4,161,2,125, +- 5,116,13,124,10,124,5,124,1,124,11,131,4,1,0,110, +- 10,116,14,124,10,124,3,124,9,100,12,25,0,124,1,124, +- 11,131,5,1,0,87,0,110,11,4,0,116,15,116,16,102, +- 2,121,160,1,0,1,0,1,0,89,0,110,16,119,0,116, +- 17,160,18,100,13,124,8,124,2,161,3,1,0,116,19,124, +- 13,124,1,124,8,124,2,100,14,141,4,83,0,124,4,100, +- 1,117,0,114,185,124,0,160,6,124,2,161,1,125,4,124, +- 0,160,20,124,4,124,2,161,2,125,14,116,17,160,18,100, +- 15,124,2,161,2,1,0,116,21,106,22,115,255,124,8,100, +- 1,117,1,114,255,124,3,100,1,117,1,114,255,124,6,114, +- 226,124,5,100,1,117,0,114,219,116,9,160,11,124,4,161, +- 1,125,5,116,23,124,14,124,5,124,7,131,3,125,10,110, +- 8,116,24,124,14,124,3,116,25,124,4,131,1,131,3,125, +- 10,122,10,124,0,160,26,124,2,124,8,124,10,161,3,1, +- 0,87,0,124,14,83,0,4,0,116,2,121,254,1,0,1, +- 0,1,0,89,0,124,14,83,0,119,0,124,14,83,0,41, +- 16,122,190,67,111,110,99,114,101,116,101,32,105,109,112,108, ++ 32,116,104,101,32,108,111,97,100,101,114,32,116,111,32,114, ++ 101,97,100,32,98,121,116,101,99,111,100,101,32,102,105,108, ++ 101,115,46,10,32,32,32,32,32,32,32,32,82,97,105,115, ++ 101,115,32,79,83,69,114,114,111,114,32,119,104,101,110,32, ++ 116,104,101,32,112,97,116,104,32,99,97,110,110,111,116,32, ++ 98,101,32,104,97,110,100,108,101,100,46,10,32,32,32,32, ++ 32,32,32,32,114,196,0,0,0,41,1,114,254,0,0,0, ++ 114,253,0,0,0,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,218,10,112,97,116,104,95,115,116,97,116,115, ++ 133,3,0,0,115,2,0,0,0,14,12,122,23,83,111,117, ++ 114,99,101,76,111,97,100,101,114,46,112,97,116,104,95,115, ++ 116,97,116,115,99,4,0,0,0,0,0,0,0,0,0,0, ++ 0,4,0,0,0,4,0,0,0,67,0,0,0,115,12,0, ++ 0,0,124,0,160,0,124,2,124,3,161,2,83,0,41,1, ++ 122,228,79,112,116,105,111,110,97,108,32,109,101,116,104,111, ++ 100,32,119,104,105,99,104,32,119,114,105,116,101,115,32,100, ++ 97,116,97,32,40,98,121,116,101,115,41,32,116,111,32,97, ++ 32,102,105,108,101,32,112,97,116,104,32,40,97,32,115,116, ++ 114,41,46,10,10,32,32,32,32,32,32,32,32,73,109,112, ++ 108,101,109,101,110,116,105,110,103,32,116,104,105,115,32,109, ++ 101,116,104,111,100,32,97,108,108,111,119,115,32,102,111,114, ++ 32,116,104,101,32,119,114,105,116,105,110,103,32,111,102,32, ++ 98,121,116,101,99,111,100,101,32,102,105,108,101,115,46,10, ++ 10,32,32,32,32,32,32,32,32,84,104,101,32,115,111,117, ++ 114,99,101,32,112,97,116,104,32,105,115,32,110,101,101,100, ++ 101,100,32,105,110,32,111,114,100,101,114,32,116,111,32,99, ++ 111,114,114,101,99,116,108,121,32,116,114,97,110,115,102,101, ++ 114,32,112,101,114,109,105,115,115,105,111,110,115,10,32,32, ++ 32,32,32,32,32,32,41,1,218,8,115,101,116,95,100,97, ++ 116,97,41,4,114,146,0,0,0,114,137,0,0,0,90,10, ++ 99,97,99,104,101,95,112,97,116,104,114,44,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,15, ++ 95,99,97,99,104,101,95,98,121,116,101,99,111,100,101,147, ++ 3,0,0,115,2,0,0,0,12,8,122,28,83,111,117,114, ++ 99,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95, ++ 98,121,116,101,99,111,100,101,99,3,0,0,0,0,0,0, ++ 0,0,0,0,0,3,0,0,0,1,0,0,0,67,0,0, ++ 0,114,26,0,0,0,41,2,122,150,79,112,116,105,111,110, ++ 97,108,32,109,101,116,104,111,100,32,119,104,105,99,104,32, ++ 119,114,105,116,101,115,32,100,97,116,97,32,40,98,121,116, ++ 101,115,41,32,116,111,32,97,32,102,105,108,101,32,112,97, ++ 116,104,32,40,97,32,115,116,114,41,46,10,10,32,32,32, ++ 32,32,32,32,32,73,109,112,108,101,109,101,110,116,105,110, ++ 103,32,116,104,105,115,32,109,101,116,104,111,100,32,97,108, ++ 108,111,119,115,32,102,111,114,32,116,104,101,32,119,114,105, ++ 116,105,110,103,32,111,102,32,98,121,116,101,99,111,100,101, ++ 32,102,105,108,101,115,46,10,32,32,32,32,32,32,32,32, ++ 78,114,7,0,0,0,41,3,114,146,0,0,0,114,68,0, ++ 0,0,114,44,0,0,0,114,7,0,0,0,114,7,0,0, ++ 0,114,8,0,0,0,114,0,1,0,0,157,3,0,0,114, ++ 243,0,0,0,122,21,83,111,117,114,99,101,76,111,97,100, ++ 101,114,46,115,101,116,95,100,97,116,97,99,2,0,0,0, ++ 0,0,0,0,0,0,0,0,5,0,0,0,10,0,0,0, ++ 67,0,0,0,115,70,0,0,0,124,0,160,0,124,1,161, ++ 1,125,2,122,10,124,0,160,1,124,2,161,1,125,3,87, ++ 0,116,4,124,3,131,1,83,0,4,0,116,2,121,34,1, ++ 0,125,4,1,0,122,7,116,3,100,1,124,1,100,2,141, ++ 2,124,4,130,2,100,3,125,4,126,4,119,1,119,0,41, ++ 4,122,52,67,111,110,99,114,101,116,101,32,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,32,111,102,32,73,110, + 115,112,101,99,116,76,111,97,100,101,114,46,103,101,116,95, +- 99,111,100,101,46,10,10,32,32,32,32,32,32,32,32,82, +- 101,97,100,105,110,103,32,111,102,32,98,121,116,101,99,111, +- 100,101,32,114,101,113,117,105,114,101,115,32,112,97,116,104, +- 95,115,116,97,116,115,32,116,111,32,98,101,32,105,109,112, +- 108,101,109,101,110,116,101,100,46,32,84,111,32,119,114,105, +- 116,101,10,32,32,32,32,32,32,32,32,98,121,116,101,99, +- 111,100,101,44,32,115,101,116,95,100,97,116,97,32,109,117, +- 115,116,32,97,108,115,111,32,98,101,32,105,109,112,108,101, +- 109,101,110,116,101,100,46,10,10,32,32,32,32,32,32,32, +- 32,78,70,84,114,193,0,0,0,114,183,0,0,0,114,169, +- 0,0,0,114,3,0,0,0,114,0,0,0,0,114,44,0, +- 0,0,90,5,110,101,118,101,114,90,6,97,108,119,97,121, +- 115,218,4,115,105,122,101,122,13,123,125,32,109,97,116,99, +- 104,101,115,32,123,125,41,3,114,141,0,0,0,114,132,0, +- 0,0,114,134,0,0,0,122,19,99,111,100,101,32,111,98, +- 106,101,99,116,32,102,114,111,109,32,123,125,41,27,114,203, +- 0,0,0,114,121,0,0,0,114,107,0,0,0,114,252,0, +- 0,0,114,76,0,0,0,114,33,0,0,0,114,255,0,0, +- 0,114,176,0,0,0,218,10,109,101,109,111,114,121,118,105, +- 101,119,114,187,0,0,0,90,21,99,104,101,99,107,95,104, +- 97,115,104,95,98,97,115,101,100,95,112,121,99,115,114,181, +- 0,0,0,218,17,95,82,65,87,95,77,65,71,73,67,95, +- 78,85,77,66,69,82,114,182,0,0,0,114,180,0,0,0, +- 114,142,0,0,0,114,174,0,0,0,114,159,0,0,0,114, +- 173,0,0,0,114,189,0,0,0,114,5,1,0,0,114,15, +- 0,0,0,218,19,100,111,110,116,95,119,114,105,116,101,95, +- 98,121,116,101,99,111,100,101,114,195,0,0,0,114,194,0, +- 0,0,114,4,0,0,0,114,254,0,0,0,41,15,114,143, +- 0,0,0,114,163,0,0,0,114,134,0,0,0,114,178,0, +- 0,0,114,198,0,0,0,114,181,0,0,0,90,10,104,97, +- 115,104,95,98,97,115,101,100,90,12,99,104,101,99,107,95, +- 115,111,117,114,99,101,114,132,0,0,0,218,2,115,116,114, +- 41,0,0,0,114,175,0,0,0,114,16,0,0,0,90,10, +- 98,121,116,101,115,95,100,97,116,97,90,11,99,111,100,101, +- 95,111,98,106,101,99,116,114,7,0,0,0,114,7,0,0, +- 0,114,8,0,0,0,114,241,0,0,0,182,3,0,0,115, +- 166,0,0,0,10,7,4,1,4,1,4,1,4,1,4,1, +- 2,1,12,1,12,1,8,1,2,255,2,3,14,1,12,1, +- 4,1,2,255,12,3,2,1,14,1,12,1,4,1,2,255, +- 2,4,2,1,6,254,2,4,12,1,16,1,12,1,4,1, +- 12,1,10,1,2,1,2,255,10,2,10,1,4,1,2,1, +- 2,1,4,254,8,4,2,1,4,255,2,128,2,3,2,1, +- 2,1,6,1,2,1,2,1,4,251,4,128,16,7,4,1, +- 2,255,8,3,2,1,4,255,6,2,2,1,2,1,6,254, +- 8,3,10,1,12,1,12,1,14,1,8,1,4,1,8,1, +- 10,1,14,1,6,2,6,1,4,255,2,2,16,1,4,3, +- 12,254,2,1,4,1,2,254,4,2,122,21,83,111,117,114, +- 99,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, +- 101,78,41,10,114,150,0,0,0,114,149,0,0,0,114,151, +- 0,0,0,114,251,0,0,0,114,252,0,0,0,114,254,0, +- 0,0,114,253,0,0,0,114,1,1,0,0,114,5,1,0, +- 0,114,241,0,0,0,114,7,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,114,249,0,0,0,123, +- 3,0,0,115,16,0,0,0,8,0,8,2,8,8,8,14, +- 8,10,8,7,14,10,12,8,114,249,0,0,0,99,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +- 0,0,0,0,0,0,115,92,0,0,0,101,0,90,1,100, +- 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, +- 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,101, +- 7,135,0,102,1,100,8,100,9,132,8,131,1,90,8,101, +- 7,100,10,100,11,132,0,131,1,90,9,100,12,100,13,132, +- 0,90,10,101,7,100,14,100,15,132,0,131,1,90,11,135, +- 0,4,0,90,12,83,0,41,16,218,10,70,105,108,101,76, +- 111,97,100,101,114,122,103,66,97,115,101,32,102,105,108,101, +- 32,108,111,97,100,101,114,32,99,108,97,115,115,32,119,104, +- 105,99,104,32,105,109,112,108,101,109,101,110,116,115,32,116, +- 104,101,32,108,111,97,100,101,114,32,112,114,111,116,111,99, +- 111,108,32,109,101,116,104,111,100,115,32,116,104,97,116,10, +- 32,32,32,32,114,101,113,117,105,114,101,32,102,105,108,101, +- 32,115,121,115,116,101,109,32,117,115,97,103,101,46,99,3, +- 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, +- 0,0,0,67,0,0,0,115,16,0,0,0,124,1,124,0, +- 95,0,124,2,124,0,95,1,100,1,83,0,41,2,122,75, +- 67,97,99,104,101,32,116,104,101,32,109,111,100,117,108,101, +- 32,110,97,109,101,32,97,110,100,32,116,104,101,32,112,97, +- 116,104,32,116,111,32,116,104,101,32,102,105,108,101,32,102, +- 111,117,110,100,32,98,121,32,116,104,101,10,32,32,32,32, +- 32,32,32,32,102,105,110,100,101,114,46,78,114,183,0,0, +- 0,41,3,114,143,0,0,0,114,163,0,0,0,114,65,0, +- 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, +- 0,114,236,0,0,0,16,4,0,0,115,4,0,0,0,6, +- 3,10,1,122,19,70,105,108,101,76,111,97,100,101,114,46, +- 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, +- 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, +- 0,243,24,0,0,0,124,0,106,0,124,1,106,0,107,2, +- 111,11,124,0,106,1,124,1,106,1,107,2,83,0,114,69, +- 0,0,0,169,2,218,9,95,95,99,108,97,115,115,95,95, +- 114,156,0,0,0,169,2,114,143,0,0,0,90,5,111,116, +- 104,101,114,114,7,0,0,0,114,7,0,0,0,114,8,0, +- 0,0,218,6,95,95,101,113,95,95,22,4,0,0,243,6, +- 0,0,0,12,1,10,1,2,255,122,17,70,105,108,101,76, +- 111,97,100,101,114,46,95,95,101,113,95,95,99,1,0,0, +- 0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0, +- 0,67,0,0,0,243,20,0,0,0,116,0,124,0,106,1, +- 131,1,116,0,124,0,106,2,131,1,65,0,83,0,114,69, +- 0,0,0,169,3,218,4,104,97,115,104,114,141,0,0,0, +- 114,65,0,0,0,169,1,114,143,0,0,0,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,218,8,95,95,104, +- 97,115,104,95,95,26,4,0,0,243,2,0,0,0,20,1, +- 122,19,70,105,108,101,76,111,97,100,101,114,46,95,95,104, +- 97,115,104,95,95,99,2,0,0,0,0,0,0,0,0,0, +- 0,0,2,0,0,0,3,0,0,0,3,0,0,0,115,16, +- 0,0,0,116,0,116,1,124,0,131,2,160,2,124,1,161, +- 1,83,0,41,1,122,100,76,111,97,100,32,97,32,109,111, +- 100,117,108,101,32,102,114,111,109,32,97,32,102,105,108,101, +- 46,10,10,32,32,32,32,32,32,32,32,84,104,105,115,32, +- 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, +- 97,116,101,100,46,32,32,85,115,101,32,101,120,101,99,95, +- 109,111,100,117,108,101,40,41,32,105,110,115,116,101,97,100, +- 46,10,10,32,32,32,32,32,32,32,32,41,3,218,5,115, +- 117,112,101,114,114,11,1,0,0,114,248,0,0,0,114,247, +- 0,0,0,169,1,114,14,1,0,0,114,7,0,0,0,114, +- 8,0,0,0,114,248,0,0,0,29,4,0,0,115,2,0, +- 0,0,16,10,122,22,70,105,108,101,76,111,97,100,101,114, +- 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, +- 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, +- 0,67,0,0,0,243,6,0,0,0,124,0,106,0,83,0, +- 169,1,122,58,82,101,116,117,114,110,32,116,104,101,32,112, +- 97,116,104,32,116,111,32,116,104,101,32,115,111,117,114,99, +- 101,32,102,105,108,101,32,97,115,32,102,111,117,110,100,32, +- 98,121,32,116,104,101,32,102,105,110,100,101,114,46,114,71, +- 0,0,0,114,247,0,0,0,114,7,0,0,0,114,7,0, +- 0,0,114,8,0,0,0,114,203,0,0,0,41,4,0,0, +- 243,2,0,0,0,6,3,122,23,70,105,108,101,76,111,97, +- 100,101,114,46,103,101,116,95,102,105,108,101,110,97,109,101, +- 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, +- 0,8,0,0,0,67,0,0,0,115,128,0,0,0,116,0, +- 124,0,116,1,116,2,102,2,131,2,114,36,116,3,160,4, +- 116,5,124,1,131,1,161,1,143,12,125,2,124,2,160,6, +- 161,0,87,0,2,0,100,1,4,0,4,0,131,3,1,0, +- 83,0,49,0,115,29,119,1,1,0,1,0,1,0,89,0, +- 1,0,100,1,83,0,116,3,160,7,124,1,100,2,161,2, +- 143,12,125,2,124,2,160,6,161,0,87,0,2,0,100,1, +- 4,0,4,0,131,3,1,0,83,0,49,0,115,57,119,1, +- 1,0,1,0,1,0,89,0,1,0,100,1,83,0,41,3, +- 122,39,82,101,116,117,114,110,32,116,104,101,32,100,97,116, +- 97,32,102,114,111,109,32,112,97,116,104,32,97,115,32,114, +- 97,119,32,98,121,116,101,115,46,78,218,1,114,41,8,114, +- 185,0,0,0,114,249,0,0,0,218,19,69,120,116,101,110, +- 115,105,111,110,70,105,108,101,76,111,97,100,101,114,114,91, +- 0,0,0,90,9,111,112,101,110,95,99,111,100,101,114,109, +- 0,0,0,90,4,114,101,97,100,114,92,0,0,0,41,3, +- 114,143,0,0,0,114,65,0,0,0,114,94,0,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,255, +- 0,0,0,46,4,0,0,115,14,0,0,0,14,2,16,1, +- 6,1,36,255,14,3,6,1,36,255,122,19,70,105,108,101, +- 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,99, +- 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, +- 2,0,0,0,67,0,0,0,115,20,0,0,0,100,1,100, +- 2,108,0,109,1,125,2,1,0,124,2,124,0,131,1,83, +- 0,41,3,78,114,0,0,0,0,41,1,218,10,70,105,108, +- 101,82,101,97,100,101,114,41,2,218,17,105,109,112,111,114, +- 116,108,105,98,46,114,101,97,100,101,114,115,114,31,1,0, +- 0,41,3,114,143,0,0,0,114,244,0,0,0,114,31,1, +- 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, +- 0,218,19,103,101,116,95,114,101,115,111,117,114,99,101,95, +- 114,101,97,100,101,114,55,4,0,0,115,4,0,0,0,12, +- 2,8,1,122,30,70,105,108,101,76,111,97,100,101,114,46, +- 103,101,116,95,114,101,115,111,117,114,99,101,95,114,101,97, +- 100,101,114,41,13,114,150,0,0,0,114,149,0,0,0,114, +- 151,0,0,0,114,152,0,0,0,114,236,0,0,0,114,16, +- 1,0,0,114,22,1,0,0,114,160,0,0,0,114,248,0, +- 0,0,114,203,0,0,0,114,255,0,0,0,114,33,1,0, +- 0,90,13,95,95,99,108,97,115,115,99,101,108,108,95,95, +- 114,7,0,0,0,114,7,0,0,0,114,25,1,0,0,114, +- 8,0,0,0,114,11,1,0,0,11,4,0,0,115,24,0, +- 0,0,8,0,4,2,8,3,8,6,8,4,2,3,14,1, +- 2,11,10,1,8,4,2,9,18,1,114,11,1,0,0,99, +- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +- 3,0,0,0,64,0,0,0,115,46,0,0,0,101,0,90, +- 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, +- 4,100,4,100,5,132,0,90,5,100,6,100,7,156,1,100, +- 8,100,9,132,2,90,6,100,10,83,0,41,11,218,16,83, +- 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,122, +- 62,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, +- 101,110,116,97,116,105,111,110,32,111,102,32,83,111,117,114, +- 99,101,76,111,97,100,101,114,32,117,115,105,110,103,32,116, +- 104,101,32,102,105,108,101,32,115,121,115,116,101,109,46,99, +- 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, +- 3,0,0,0,67,0,0,0,115,22,0,0,0,116,0,124, +- 1,131,1,125,2,124,2,106,1,124,2,106,2,100,1,156, +- 2,83,0,41,2,122,33,82,101,116,117,114,110,32,116,104, +- 101,32,109,101,116,97,100,97,116,97,32,102,111,114,32,116, +- 104,101,32,112,97,116,104,46,41,2,114,193,0,0,0,114, +- 6,1,0,0,41,3,114,75,0,0,0,218,8,115,116,95, +- 109,116,105,109,101,90,7,115,116,95,115,105,122,101,41,3, +- 114,143,0,0,0,114,65,0,0,0,114,10,1,0,0,114, ++ 115,111,117,114,99,101,46,122,39,115,111,117,114,99,101,32, ++ 110,111,116,32,97,118,97,105,108,97,98,108,101,32,116,104, ++ 114,111,117,103,104,32,103,101,116,95,100,97,116,97,40,41, ++ 114,143,0,0,0,78,41,5,114,206,0,0,0,218,8,103, ++ 101,116,95,100,97,116,97,114,79,0,0,0,114,145,0,0, ++ 0,114,203,0,0,0,41,5,114,146,0,0,0,114,166,0, ++ 0,0,114,68,0,0,0,114,201,0,0,0,218,3,101,120, ++ 99,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, ++ 218,10,103,101,116,95,115,111,117,114,99,101,164,3,0,0, ++ 115,24,0,0,0,10,2,2,1,12,1,8,4,14,253,4, ++ 1,2,1,4,255,2,1,2,255,8,128,2,255,122,23,83, ++ 111,117,114,99,101,76,111,97,100,101,114,46,103,101,116,95, ++ 115,111,117,114,99,101,114,133,0,0,0,41,1,218,9,95, ++ 111,112,116,105,109,105,122,101,99,3,0,0,0,0,0,0, ++ 0,1,0,0,0,4,0,0,0,8,0,0,0,67,0,0, ++ 0,115,22,0,0,0,116,0,106,1,116,2,124,1,124,2, ++ 100,1,100,2,124,3,100,3,141,6,83,0,41,4,122,130, ++ 82,101,116,117,114,110,32,116,104,101,32,99,111,100,101,32, ++ 111,98,106,101,99,116,32,99,111,109,112,105,108,101,100,32, ++ 102,114,111,109,32,115,111,117,114,99,101,46,10,10,32,32, ++ 32,32,32,32,32,32,84,104,101,32,39,100,97,116,97,39, ++ 32,97,114,103,117,109,101,110,116,32,99,97,110,32,98,101, ++ 32,97,110,121,32,111,98,106,101,99,116,32,116,121,112,101, ++ 32,116,104,97,116,32,99,111,109,112,105,108,101,40,41,32, ++ 115,117,112,112,111,114,116,115,46,10,32,32,32,32,32,32, ++ 32,32,114,246,0,0,0,84,41,2,218,12,100,111,110,116, ++ 95,105,110,104,101,114,105,116,114,111,0,0,0,41,3,114, ++ 162,0,0,0,114,245,0,0,0,218,7,99,111,109,112,105, ++ 108,101,41,4,114,146,0,0,0,114,44,0,0,0,114,68, ++ 0,0,0,114,5,1,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,14,115,111,117,114,99,101,95, ++ 116,111,95,99,111,100,101,174,3,0,0,115,6,0,0,0, ++ 12,5,4,1,6,255,122,27,83,111,117,114,99,101,76,111, ++ 97,100,101,114,46,115,111,117,114,99,101,95,116,111,95,99, ++ 111,100,101,99,2,0,0,0,0,0,0,0,0,0,0,0, ++ 15,0,0,0,9,0,0,0,67,0,0,0,115,2,2,0, ++ 0,124,0,160,0,124,1,161,1,125,2,100,1,125,3,100, ++ 1,125,4,100,1,125,5,100,2,125,6,100,3,125,7,122, ++ 6,116,1,124,2,131,1,125,8,87,0,110,11,4,0,116, ++ 2,121,32,1,0,1,0,1,0,100,1,125,8,89,0,110, ++ 144,119,0,122,7,124,0,160,3,124,2,161,1,125,9,87, ++ 0,110,9,4,0,116,4,121,49,1,0,1,0,1,0,89, ++ 0,110,127,119,0,116,5,124,9,100,4,25,0,131,1,125, ++ 3,122,7,124,0,160,6,124,8,161,1,125,10,87,0,110, ++ 9,4,0,116,4,121,72,1,0,1,0,1,0,89,0,110, ++ 104,119,0,124,1,124,8,100,5,156,2,125,11,122,71,116, ++ 7,124,10,124,1,124,11,131,3,125,12,116,8,124,10,131, ++ 1,100,6,100,1,133,2,25,0,125,13,124,12,100,7,64, ++ 0,100,8,107,3,125,6,124,6,114,138,124,12,100,9,64, ++ 0,100,8,107,3,125,7,116,9,106,10,100,10,107,3,114, ++ 137,124,7,115,119,116,9,106,10,100,11,107,2,114,137,124, ++ 0,160,6,124,2,161,1,125,4,116,9,160,11,116,12,124, ++ 4,161,2,125,5,116,13,124,10,124,5,124,1,124,11,131, ++ 4,1,0,110,10,116,14,124,10,124,3,124,9,100,12,25, ++ 0,124,1,124,11,131,5,1,0,87,0,110,11,4,0,116, ++ 15,116,16,102,2,121,160,1,0,1,0,1,0,89,0,110, ++ 16,119,0,116,17,160,18,100,13,124,8,124,2,161,3,1, ++ 0,116,19,124,13,124,1,124,8,124,2,100,14,141,4,83, ++ 0,124,4,100,1,117,0,114,185,124,0,160,6,124,2,161, ++ 1,125,4,124,0,160,20,124,4,124,2,161,2,125,14,116, ++ 17,160,18,100,15,124,2,161,2,1,0,116,21,106,22,115, ++ 255,124,8,100,1,117,1,114,255,124,3,100,1,117,1,114, ++ 255,124,6,114,226,124,5,100,1,117,0,114,219,116,9,160, ++ 11,124,4,161,1,125,5,116,23,124,14,124,5,124,7,131, ++ 3,125,10,110,8,116,24,124,14,124,3,116,25,124,4,131, ++ 1,131,3,125,10,122,10,124,0,160,26,124,2,124,8,124, ++ 10,161,3,1,0,87,0,124,14,83,0,4,0,116,2,121, ++ 254,1,0,1,0,1,0,89,0,124,14,83,0,119,0,124, ++ 14,83,0,41,16,122,190,67,111,110,99,114,101,116,101,32, ++ 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, ++ 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, ++ 103,101,116,95,99,111,100,101,46,10,10,32,32,32,32,32, ++ 32,32,32,82,101,97,100,105,110,103,32,111,102,32,98,121, ++ 116,101,99,111,100,101,32,114,101,113,117,105,114,101,115,32, ++ 112,97,116,104,95,115,116,97,116,115,32,116,111,32,98,101, ++ 32,105,109,112,108,101,109,101,110,116,101,100,46,32,84,111, ++ 32,119,114,105,116,101,10,32,32,32,32,32,32,32,32,98, ++ 121,116,101,99,111,100,101,44,32,115,101,116,95,100,97,116, ++ 97,32,109,117,115,116,32,97,108,115,111,32,98,101,32,105, ++ 109,112,108,101,109,101,110,116,101,100,46,10,10,32,32,32, ++ 32,32,32,32,32,78,70,84,114,196,0,0,0,114,186,0, ++ 0,0,114,172,0,0,0,114,3,0,0,0,114,0,0,0, ++ 0,114,47,0,0,0,90,5,110,101,118,101,114,90,6,97, ++ 108,119,97,121,115,218,4,115,105,122,101,122,13,123,125,32, ++ 109,97,116,99,104,101,115,32,123,125,41,3,114,144,0,0, ++ 0,114,135,0,0,0,114,137,0,0,0,122,19,99,111,100, ++ 101,32,111,98,106,101,99,116,32,102,114,111,109,32,123,125, ++ 41,27,114,206,0,0,0,114,124,0,0,0,114,110,0,0, ++ 0,114,255,0,0,0,114,79,0,0,0,114,36,0,0,0, ++ 114,2,1,0,0,114,179,0,0,0,218,10,109,101,109,111, ++ 114,121,118,105,101,119,114,190,0,0,0,90,21,99,104,101, ++ 99,107,95,104,97,115,104,95,98,97,115,101,100,95,112,121, ++ 99,115,114,184,0,0,0,218,17,95,82,65,87,95,77,65, ++ 71,73,67,95,78,85,77,66,69,82,114,185,0,0,0,114, ++ 183,0,0,0,114,145,0,0,0,114,177,0,0,0,114,162, ++ 0,0,0,114,176,0,0,0,114,192,0,0,0,114,8,1, ++ 0,0,114,18,0,0,0,218,19,100,111,110,116,95,119,114, ++ 105,116,101,95,98,121,116,101,99,111,100,101,114,198,0,0, ++ 0,114,197,0,0,0,114,4,0,0,0,114,1,1,0,0, ++ 41,15,114,146,0,0,0,114,166,0,0,0,114,137,0,0, ++ 0,114,181,0,0,0,114,201,0,0,0,114,184,0,0,0, ++ 90,10,104,97,115,104,95,98,97,115,101,100,90,12,99,104, ++ 101,99,107,95,115,111,117,114,99,101,114,135,0,0,0,218, ++ 2,115,116,114,44,0,0,0,114,178,0,0,0,114,19,0, ++ 0,0,90,10,98,121,116,101,115,95,100,97,116,97,90,11, ++ 99,111,100,101,95,111,98,106,101,99,116,114,7,0,0,0, ++ 114,7,0,0,0,114,8,0,0,0,114,244,0,0,0,182, ++ 3,0,0,115,166,0,0,0,10,7,4,1,4,1,4,1, ++ 4,1,4,1,2,1,12,1,12,1,8,1,2,255,2,3, ++ 14,1,12,1,4,1,2,255,12,3,2,1,14,1,12,1, ++ 4,1,2,255,2,4,2,1,6,254,2,4,12,1,16,1, ++ 12,1,4,1,12,1,10,1,2,1,2,255,10,2,10,1, ++ 4,1,2,1,2,1,4,254,8,4,2,1,4,255,2,128, ++ 2,3,2,1,2,1,6,1,2,1,2,1,4,251,4,128, ++ 16,7,4,1,2,255,8,3,2,1,4,255,6,2,2,1, ++ 2,1,6,254,8,3,10,1,12,1,12,1,14,1,8,1, ++ 4,1,8,1,10,1,14,1,6,2,6,1,4,255,2,2, ++ 16,1,4,3,12,254,2,1,4,1,2,254,4,2,122,21, ++ 83,111,117,114,99,101,76,111,97,100,101,114,46,103,101,116, ++ 95,99,111,100,101,78,41,10,114,153,0,0,0,114,152,0, ++ 0,0,114,154,0,0,0,114,254,0,0,0,114,255,0,0, ++ 0,114,1,1,0,0,114,0,1,0,0,114,4,1,0,0, ++ 114,8,1,0,0,114,244,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,252, +- 0,0,0,65,4,0,0,115,4,0,0,0,8,2,14,1, +- 122,27,83,111,117,114,99,101,70,105,108,101,76,111,97,100, +- 101,114,46,112,97,116,104,95,115,116,97,116,115,99,4,0, +- 0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0, +- 0,0,67,0,0,0,115,24,0,0,0,116,0,124,1,131, +- 1,125,4,124,0,106,1,124,2,124,3,124,4,100,1,141, +- 3,83,0,41,2,78,169,1,218,5,95,109,111,100,101,41, +- 2,114,139,0,0,0,114,253,0,0,0,41,5,114,143,0, +- 0,0,114,134,0,0,0,114,132,0,0,0,114,41,0,0, +- 0,114,78,0,0,0,114,7,0,0,0,114,7,0,0,0, +- 114,8,0,0,0,114,254,0,0,0,70,4,0,0,115,4, +- 0,0,0,8,2,16,1,122,32,83,111,117,114,99,101,70, +- 105,108,101,76,111,97,100,101,114,46,95,99,97,99,104,101, +- 95,98,121,116,101,99,111,100,101,114,87,0,0,0,114,36, +- 1,0,0,99,3,0,0,0,0,0,0,0,1,0,0,0, +- 9,0,0,0,11,0,0,0,67,0,0,0,115,254,0,0, +- 0,116,0,124,1,131,1,92,2,125,4,125,5,103,0,125, +- 6,124,4,114,31,116,1,124,4,131,1,115,31,116,0,124, +- 4,131,1,92,2,125,4,125,7,124,6,160,2,124,7,161, +- 1,1,0,124,4,114,31,116,1,124,4,131,1,114,14,116, +- 3,124,6,131,1,68,0,93,49,125,7,116,4,124,4,124, +- 7,131,2,125,4,122,7,116,5,160,6,124,4,161,1,1, +- 0,87,0,113,35,4,0,116,7,121,58,1,0,1,0,1, +- 0,89,0,113,35,4,0,116,8,121,84,1,0,125,8,1, +- 0,122,15,116,9,160,10,100,1,124,4,124,8,161,3,1, +- 0,87,0,89,0,100,2,125,8,126,8,1,0,100,2,83, +- 0,100,2,125,8,126,8,119,1,119,0,122,15,116,11,124, +- 1,124,2,124,3,131,3,1,0,116,9,160,10,100,3,124, +- 1,161,2,1,0,87,0,100,2,83,0,4,0,116,8,121, +- 126,1,0,125,8,1,0,122,14,116,9,160,10,100,1,124, +- 1,124,8,161,3,1,0,87,0,89,0,100,2,125,8,126, +- 8,100,2,83,0,100,2,125,8,126,8,119,1,119,0,41, +- 4,122,27,87,114,105,116,101,32,98,121,116,101,115,32,100, +- 97,116,97,32,116,111,32,97,32,102,105,108,101,46,122,27, +- 99,111,117,108,100,32,110,111,116,32,99,114,101,97,116,101, +- 32,123,33,114,125,58,32,123,33,114,125,78,122,12,99,114, +- 101,97,116,101,100,32,123,33,114,125,41,12,114,74,0,0, +- 0,114,83,0,0,0,114,61,0,0,0,218,8,114,101,118, +- 101,114,115,101,100,114,67,0,0,0,114,18,0,0,0,90, +- 5,109,107,100,105,114,218,15,70,105,108,101,69,120,105,115, +- 116,115,69,114,114,111,114,114,76,0,0,0,114,159,0,0, +- 0,114,173,0,0,0,114,95,0,0,0,41,9,114,143,0, +- 0,0,114,65,0,0,0,114,41,0,0,0,114,37,1,0, +- 0,218,6,112,97,114,101,110,116,114,120,0,0,0,114,63, +- 0,0,0,114,68,0,0,0,114,0,1,0,0,114,7,0, +- 0,0,114,7,0,0,0,114,8,0,0,0,114,253,0,0, +- 0,75,4,0,0,115,56,0,0,0,12,2,4,1,12,2, +- 12,1,10,1,12,254,12,4,10,1,2,1,14,1,12,1, +- 4,2,14,1,6,3,4,1,4,255,16,2,8,128,2,251, +- 2,6,12,1,18,1,14,1,8,2,2,1,18,255,8,128, +- 2,254,122,25,83,111,117,114,99,101,70,105,108,101,76,111, +- 97,100,101,114,46,115,101,116,95,100,97,116,97,78,41,7, +- 114,150,0,0,0,114,149,0,0,0,114,151,0,0,0,114, +- 152,0,0,0,114,252,0,0,0,114,254,0,0,0,114,253, +- 0,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, +- 0,0,114,8,0,0,0,114,34,1,0,0,61,4,0,0, +- 115,10,0,0,0,8,0,4,2,8,2,8,5,18,5,114, +- 34,1,0,0,99,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,2,0,0,0,64,0,0,0,115,32,0, +- 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, +- 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, +- 83,0,41,7,218,20,83,111,117,114,99,101,108,101,115,115, +- 70,105,108,101,76,111,97,100,101,114,122,45,76,111,97,100, +- 101,114,32,119,104,105,99,104,32,104,97,110,100,108,101,115, +- 32,115,111,117,114,99,101,108,101,115,115,32,102,105,108,101, +- 32,105,109,112,111,114,116,115,46,99,2,0,0,0,0,0, +- 0,0,0,0,0,0,5,0,0,0,5,0,0,0,67,0, +- 0,0,115,68,0,0,0,124,0,160,0,124,1,161,1,125, +- 2,124,0,160,1,124,2,161,1,125,3,124,1,124,2,100, +- 1,156,2,125,4,116,2,124,3,124,1,124,4,131,3,1, +- 0,116,3,116,4,124,3,131,1,100,2,100,0,133,2,25, +- 0,124,1,124,2,100,3,141,3,83,0,41,4,78,114,183, +- 0,0,0,114,169,0,0,0,41,2,114,141,0,0,0,114, +- 132,0,0,0,41,5,114,203,0,0,0,114,255,0,0,0, +- 114,176,0,0,0,114,189,0,0,0,114,7,1,0,0,41, +- 5,114,143,0,0,0,114,163,0,0,0,114,65,0,0,0, +- 114,41,0,0,0,114,175,0,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,114,241,0,0,0,110,4, +- 0,0,115,22,0,0,0,10,1,10,1,2,4,2,1,6, +- 254,12,4,2,1,14,1,2,1,2,1,6,253,122,29,83, +- 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, +- 100,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, +- 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, +- 0,67,0,0,0,114,23,0,0,0,41,2,122,39,82,101, +- 116,117,114,110,32,78,111,110,101,32,97,115,32,116,104,101, +- 114,101,32,105,115,32,110,111,32,115,111,117,114,99,101,32, +- 99,111,100,101,46,78,114,7,0,0,0,114,247,0,0,0, +- 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, +- 1,1,0,0,126,4,0,0,114,24,0,0,0,122,31,83, +- 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, +- 100,101,114,46,103,101,116,95,115,111,117,114,99,101,78,41, +- 6,114,150,0,0,0,114,149,0,0,0,114,151,0,0,0, +- 114,152,0,0,0,114,241,0,0,0,114,1,1,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,114,41,1,0,0,106,4,0,0,115,8,0,0, +- 0,8,0,4,2,8,2,12,16,114,41,1,0,0,99,0, +- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, +- 0,0,0,64,0,0,0,115,92,0,0,0,101,0,90,1, +- 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, +- 100,4,100,5,132,0,90,5,100,6,100,7,132,0,90,6, +- 100,8,100,9,132,0,90,7,100,10,100,11,132,0,90,8, +- 100,12,100,13,132,0,90,9,100,14,100,15,132,0,90,10, +- 100,16,100,17,132,0,90,11,101,12,100,18,100,19,132,0, +- 131,1,90,13,100,20,83,0,41,21,114,30,1,0,0,122, +- 93,76,111,97,100,101,114,32,102,111,114,32,101,120,116,101, +- 110,115,105,111,110,32,109,111,100,117,108,101,115,46,10,10, +- 32,32,32,32,84,104,101,32,99,111,110,115,116,114,117,99, +- 116,111,114,32,105,115,32,100,101,115,105,103,110,101,100,32, +- 116,111,32,119,111,114,107,32,119,105,116,104,32,70,105,108, +- 101,70,105,110,100,101,114,46,10,10,32,32,32,32,99,3, +- 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, +- 0,0,0,67,0,0,0,115,16,0,0,0,124,1,124,0, +- 95,0,124,2,124,0,95,1,100,0,83,0,114,69,0,0, +- 0,114,183,0,0,0,41,3,114,143,0,0,0,114,141,0, +- 0,0,114,65,0,0,0,114,7,0,0,0,114,7,0,0, +- 0,114,8,0,0,0,114,236,0,0,0,139,4,0,0,115, +- 4,0,0,0,6,1,10,1,122,28,69,120,116,101,110,115, +- 105,111,110,70,105,108,101,76,111,97,100,101,114,46,95,95, +- 105,110,105,116,95,95,99,2,0,0,0,0,0,0,0,0, +- 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,114, +- 12,1,0,0,114,69,0,0,0,114,13,1,0,0,114,15, ++ 0,0,0,123,3,0,0,115,16,0,0,0,8,0,8,2, ++ 8,8,8,14,8,10,8,7,14,10,12,8,114,252,0,0, ++ 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,4,0,0,0,0,0,0,0,115,92,0,0,0,101, ++ 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, ++ 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, ++ 0,90,6,101,7,135,0,102,1,100,8,100,9,132,8,131, ++ 1,90,8,101,7,100,10,100,11,132,0,131,1,90,9,100, ++ 12,100,13,132,0,90,10,101,7,100,14,100,15,132,0,131, ++ 1,90,11,135,0,4,0,90,12,83,0,41,16,218,10,70, ++ 105,108,101,76,111,97,100,101,114,122,103,66,97,115,101,32, ++ 102,105,108,101,32,108,111,97,100,101,114,32,99,108,97,115, ++ 115,32,119,104,105,99,104,32,105,109,112,108,101,109,101,110, ++ 116,115,32,116,104,101,32,108,111,97,100,101,114,32,112,114, ++ 111,116,111,99,111,108,32,109,101,116,104,111,100,115,32,116, ++ 104,97,116,10,32,32,32,32,114,101,113,117,105,114,101,32, ++ 102,105,108,101,32,115,121,115,116,101,109,32,117,115,97,103, ++ 101,46,99,3,0,0,0,0,0,0,0,0,0,0,0,3, ++ 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, ++ 124,1,124,0,95,0,124,2,124,0,95,1,100,1,83,0, ++ 41,2,122,75,67,97,99,104,101,32,116,104,101,32,109,111, ++ 100,117,108,101,32,110,97,109,101,32,97,110,100,32,116,104, ++ 101,32,112,97,116,104,32,116,111,32,116,104,101,32,102,105, ++ 108,101,32,102,111,117,110,100,32,98,121,32,116,104,101,10, ++ 32,32,32,32,32,32,32,32,102,105,110,100,101,114,46,78, ++ 114,186,0,0,0,41,3,114,146,0,0,0,114,166,0,0, ++ 0,114,68,0,0,0,114,7,0,0,0,114,7,0,0,0, ++ 114,8,0,0,0,114,239,0,0,0,16,4,0,0,115,4, ++ 0,0,0,6,3,10,1,122,19,70,105,108,101,76,111,97, ++ 100,101,114,46,95,95,105,110,105,116,95,95,99,2,0,0, ++ 0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0, ++ 0,67,0,0,0,243,24,0,0,0,124,0,106,0,124,1, ++ 106,0,107,2,111,11,124,0,106,1,124,1,106,1,107,2, ++ 83,0,114,72,0,0,0,169,2,218,9,95,95,99,108,97, ++ 115,115,95,95,114,159,0,0,0,169,2,114,146,0,0,0, ++ 90,5,111,116,104,101,114,114,7,0,0,0,114,7,0,0, ++ 0,114,8,0,0,0,218,6,95,95,101,113,95,95,22,4, ++ 0,0,243,6,0,0,0,12,1,10,1,2,255,122,17,70, ++ 105,108,101,76,111,97,100,101,114,46,95,95,101,113,95,95, ++ 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, ++ 0,3,0,0,0,67,0,0,0,243,20,0,0,0,116,0, ++ 124,0,106,1,131,1,116,0,124,0,106,2,131,1,65,0, ++ 83,0,114,72,0,0,0,169,3,218,4,104,97,115,104,114, ++ 144,0,0,0,114,68,0,0,0,169,1,114,146,0,0,0, ++ 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, ++ 8,95,95,104,97,115,104,95,95,26,4,0,0,243,2,0, ++ 0,0,20,1,122,19,70,105,108,101,76,111,97,100,101,114, ++ 46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,0, ++ 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, ++ 0,0,115,16,0,0,0,116,0,116,1,124,0,131,2,160, ++ 2,124,1,161,1,83,0,41,1,122,100,76,111,97,100,32, ++ 97,32,109,111,100,117,108,101,32,102,114,111,109,32,97,32, ++ 102,105,108,101,46,10,10,32,32,32,32,32,32,32,32,84, ++ 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, ++ 112,114,101,99,97,116,101,100,46,32,32,85,115,101,32,101, ++ 120,101,99,95,109,111,100,117,108,101,40,41,32,105,110,115, ++ 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,41, ++ 3,218,5,115,117,112,101,114,114,14,1,0,0,114,251,0, ++ 0,0,114,250,0,0,0,169,1,114,17,1,0,0,114,7, ++ 0,0,0,114,8,0,0,0,114,251,0,0,0,29,4,0, ++ 0,115,2,0,0,0,16,10,122,22,70,105,108,101,76,111, ++ 97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101, ++ 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, ++ 0,1,0,0,0,67,0,0,0,243,6,0,0,0,124,0, ++ 106,0,83,0,169,1,122,58,82,101,116,117,114,110,32,116, ++ 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, ++ 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, ++ 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, ++ 114,46,114,74,0,0,0,114,250,0,0,0,114,7,0,0, ++ 0,114,7,0,0,0,114,8,0,0,0,114,206,0,0,0, ++ 41,4,0,0,243,2,0,0,0,6,3,122,23,70,105,108, ++ 101,76,111,97,100,101,114,46,103,101,116,95,102,105,108,101, ++ 110,97,109,101,99,2,0,0,0,0,0,0,0,0,0,0, ++ 0,3,0,0,0,8,0,0,0,67,0,0,0,115,128,0, ++ 0,0,116,0,124,0,116,1,116,2,102,2,131,2,114,36, ++ 116,3,160,4,116,5,124,1,131,1,161,1,143,12,125,2, ++ 124,2,160,6,161,0,87,0,2,0,100,1,4,0,4,0, ++ 131,3,1,0,83,0,49,0,115,29,119,1,1,0,1,0, ++ 1,0,89,0,1,0,100,1,83,0,116,3,160,7,124,1, ++ 100,2,161,2,143,12,125,2,124,2,160,6,161,0,87,0, ++ 2,0,100,1,4,0,4,0,131,3,1,0,83,0,49,0, ++ 115,57,119,1,1,0,1,0,1,0,89,0,1,0,100,1, ++ 83,0,41,3,122,39,82,101,116,117,114,110,32,116,104,101, ++ 32,100,97,116,97,32,102,114,111,109,32,112,97,116,104,32, ++ 97,115,32,114,97,119,32,98,121,116,101,115,46,78,218,1, ++ 114,41,8,114,188,0,0,0,114,252,0,0,0,218,19,69, ++ 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, ++ 101,114,114,94,0,0,0,90,9,111,112,101,110,95,99,111, ++ 100,101,114,112,0,0,0,218,4,114,101,97,100,114,95,0, ++ 0,0,41,3,114,146,0,0,0,114,68,0,0,0,114,97, ++ 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,114,2,1,0,0,46,4,0,0,115,14,0,0,0, ++ 14,2,16,1,6,1,36,255,14,3,6,1,36,255,122,19, ++ 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,100, ++ 97,116,97,99,2,0,0,0,0,0,0,0,0,0,0,0, ++ 3,0,0,0,2,0,0,0,67,0,0,0,115,20,0,0, ++ 0,100,1,100,2,108,0,109,1,125,2,1,0,124,2,124, ++ 0,131,1,83,0,41,3,78,114,0,0,0,0,41,1,218, ++ 10,70,105,108,101,82,101,97,100,101,114,41,2,218,17,105, ++ 109,112,111,114,116,108,105,98,46,114,101,97,100,101,114,115, ++ 114,35,1,0,0,41,3,114,146,0,0,0,114,247,0,0, ++ 0,114,35,1,0,0,114,7,0,0,0,114,7,0,0,0, ++ 114,8,0,0,0,218,19,103,101,116,95,114,101,115,111,117, ++ 114,99,101,95,114,101,97,100,101,114,55,4,0,0,115,4, ++ 0,0,0,12,2,8,1,122,30,70,105,108,101,76,111,97, ++ 100,101,114,46,103,101,116,95,114,101,115,111,117,114,99,101, ++ 95,114,101,97,100,101,114,41,13,114,153,0,0,0,114,152, ++ 0,0,0,114,154,0,0,0,114,155,0,0,0,114,239,0, ++ 0,0,114,19,1,0,0,114,25,1,0,0,114,163,0,0, ++ 0,114,251,0,0,0,114,206,0,0,0,114,2,1,0,0, ++ 114,37,1,0,0,90,13,95,95,99,108,97,115,115,99,101, ++ 108,108,95,95,114,7,0,0,0,114,7,0,0,0,114,28, ++ 1,0,0,114,8,0,0,0,114,14,1,0,0,11,4,0, ++ 0,115,24,0,0,0,8,0,4,2,8,3,8,6,8,4, ++ 2,3,14,1,2,11,10,1,8,4,2,9,18,1,114,14, ++ 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,3,0,0,0,64,0,0,0,115,46,0,0, ++ 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, ++ 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,100, ++ 7,156,1,100,8,100,9,132,2,90,6,100,10,83,0,41, ++ 11,218,16,83,111,117,114,99,101,70,105,108,101,76,111,97, ++ 100,101,114,122,62,67,111,110,99,114,101,116,101,32,105,109, ++ 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, ++ 83,111,117,114,99,101,76,111,97,100,101,114,32,117,115,105, ++ 110,103,32,116,104,101,32,102,105,108,101,32,115,121,115,116, ++ 101,109,46,99,2,0,0,0,0,0,0,0,0,0,0,0, ++ 3,0,0,0,3,0,0,0,67,0,0,0,115,22,0,0, ++ 0,116,0,124,1,131,1,125,2,124,2,106,1,124,2,106, ++ 2,100,1,156,2,83,0,41,2,122,33,82,101,116,117,114, ++ 110,32,116,104,101,32,109,101,116,97,100,97,116,97,32,102, ++ 111,114,32,116,104,101,32,112,97,116,104,46,41,2,114,196, ++ 0,0,0,114,9,1,0,0,41,3,114,78,0,0,0,218, ++ 8,115,116,95,109,116,105,109,101,90,7,115,116,95,115,105, ++ 122,101,41,3,114,146,0,0,0,114,68,0,0,0,114,13, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, +- 0,0,114,16,1,0,0,143,4,0,0,114,17,1,0,0, +- 122,26,69,120,116,101,110,115,105,111,110,70,105,108,101,76, +- 111,97,100,101,114,46,95,95,101,113,95,95,99,1,0,0, +- 0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0, +- 0,67,0,0,0,114,18,1,0,0,114,69,0,0,0,114, +- 19,1,0,0,114,21,1,0,0,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,114,22,1,0,0,147,4,0, +- 0,114,23,1,0,0,122,28,69,120,116,101,110,115,105,111, +- 110,70,105,108,101,76,111,97,100,101,114,46,95,95,104,97, +- 115,104,95,95,99,2,0,0,0,0,0,0,0,0,0,0, +- 0,3,0,0,0,5,0,0,0,67,0,0,0,115,36,0, +- 0,0,116,0,160,1,116,2,106,3,124,1,161,2,125,2, +- 116,0,160,4,100,1,124,1,106,5,124,0,106,6,161,3, +- 1,0,124,2,83,0,41,2,122,38,67,114,101,97,116,101, +- 32,97,110,32,117,110,105,116,105,97,108,105,122,101,100,32, ++ 0,0,114,255,0,0,0,65,4,0,0,115,4,0,0,0, ++ 8,2,14,1,122,27,83,111,117,114,99,101,70,105,108,101, ++ 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, ++ 115,99,4,0,0,0,0,0,0,0,0,0,0,0,5,0, ++ 0,0,5,0,0,0,67,0,0,0,115,24,0,0,0,116, ++ 0,124,1,131,1,125,4,124,0,106,1,124,2,124,3,124, ++ 4,100,1,141,3,83,0,41,2,78,169,1,218,5,95,109, ++ 111,100,101,41,2,114,142,0,0,0,114,0,1,0,0,41, ++ 5,114,146,0,0,0,114,137,0,0,0,114,135,0,0,0, ++ 114,44,0,0,0,114,81,0,0,0,114,7,0,0,0,114, ++ 7,0,0,0,114,8,0,0,0,114,1,1,0,0,70,4, ++ 0,0,115,4,0,0,0,8,2,16,1,122,32,83,111,117, ++ 114,99,101,70,105,108,101,76,111,97,100,101,114,46,95,99, ++ 97,99,104,101,95,98,121,116,101,99,111,100,101,114,90,0, ++ 0,0,114,40,1,0,0,99,3,0,0,0,0,0,0,0, ++ 1,0,0,0,9,0,0,0,11,0,0,0,67,0,0,0, ++ 115,254,0,0,0,116,0,124,1,131,1,92,2,125,4,125, ++ 5,103,0,125,6,124,4,114,31,116,1,124,4,131,1,115, ++ 31,116,0,124,4,131,1,92,2,125,4,125,7,124,6,160, ++ 2,124,7,161,1,1,0,124,4,114,31,116,1,124,4,131, ++ 1,114,14,116,3,124,6,131,1,68,0,93,49,125,7,116, ++ 4,124,4,124,7,131,2,125,4,122,7,116,5,160,6,124, ++ 4,161,1,1,0,87,0,113,35,4,0,116,7,121,58,1, ++ 0,1,0,1,0,89,0,113,35,4,0,116,8,121,84,1, ++ 0,125,8,1,0,122,15,116,9,160,10,100,1,124,4,124, ++ 8,161,3,1,0,87,0,89,0,100,2,125,8,126,8,1, ++ 0,100,2,83,0,100,2,125,8,126,8,119,1,119,0,122, ++ 15,116,11,124,1,124,2,124,3,131,3,1,0,116,9,160, ++ 10,100,3,124,1,161,2,1,0,87,0,100,2,83,0,4, ++ 0,116,8,121,126,1,0,125,8,1,0,122,14,116,9,160, ++ 10,100,1,124,1,124,8,161,3,1,0,87,0,89,0,100, ++ 2,125,8,126,8,100,2,83,0,100,2,125,8,126,8,119, ++ 1,119,0,41,4,122,27,87,114,105,116,101,32,98,121,116, ++ 101,115,32,100,97,116,97,32,116,111,32,97,32,102,105,108, ++ 101,46,122,27,99,111,117,108,100,32,110,111,116,32,99,114, ++ 101,97,116,101,32,123,33,114,125,58,32,123,33,114,125,78, ++ 122,12,99,114,101,97,116,101,100,32,123,33,114,125,41,12, ++ 114,77,0,0,0,114,86,0,0,0,114,64,0,0,0,218, ++ 8,114,101,118,101,114,115,101,100,114,70,0,0,0,114,21, ++ 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, ++ 69,120,105,115,116,115,69,114,114,111,114,114,79,0,0,0, ++ 114,162,0,0,0,114,176,0,0,0,114,98,0,0,0,41, ++ 9,114,146,0,0,0,114,68,0,0,0,114,44,0,0,0, ++ 114,41,1,0,0,218,6,112,97,114,101,110,116,114,123,0, ++ 0,0,114,66,0,0,0,114,71,0,0,0,114,3,1,0, ++ 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, ++ 114,0,1,0,0,75,4,0,0,115,56,0,0,0,12,2, ++ 4,1,12,2,12,1,10,1,12,254,12,4,10,1,2,1, ++ 14,1,12,1,4,2,14,1,6,3,4,1,4,255,16,2, ++ 8,128,2,251,2,6,12,1,18,1,14,1,8,2,2,1, ++ 18,255,8,128,2,254,122,25,83,111,117,114,99,101,70,105, ++ 108,101,76,111,97,100,101,114,46,115,101,116,95,100,97,116, ++ 97,78,41,7,114,153,0,0,0,114,152,0,0,0,114,154, ++ 0,0,0,114,155,0,0,0,114,255,0,0,0,114,1,1, ++ 0,0,114,0,1,0,0,114,7,0,0,0,114,7,0,0, ++ 0,114,7,0,0,0,114,8,0,0,0,114,38,1,0,0, ++ 61,4,0,0,115,10,0,0,0,8,0,4,2,8,2,8, ++ 5,18,5,114,38,1,0,0,99,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, ++ 0,115,32,0,0,0,101,0,90,1,100,0,90,2,100,1, ++ 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, ++ 90,5,100,6,83,0,41,7,218,20,83,111,117,114,99,101, ++ 108,101,115,115,70,105,108,101,76,111,97,100,101,114,122,45, ++ 76,111,97,100,101,114,32,119,104,105,99,104,32,104,97,110, ++ 100,108,101,115,32,115,111,117,114,99,101,108,101,115,115,32, ++ 102,105,108,101,32,105,109,112,111,114,116,115,46,99,2,0, ++ 0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0, ++ 0,0,67,0,0,0,115,68,0,0,0,124,0,160,0,124, ++ 1,161,1,125,2,124,0,160,1,124,2,161,1,125,3,124, ++ 1,124,2,100,1,156,2,125,4,116,2,124,3,124,1,124, ++ 4,131,3,1,0,116,3,116,4,124,3,131,1,100,2,100, ++ 0,133,2,25,0,124,1,124,2,100,3,141,3,83,0,41, ++ 4,78,114,186,0,0,0,114,172,0,0,0,41,2,114,144, ++ 0,0,0,114,135,0,0,0,41,5,114,206,0,0,0,114, ++ 2,1,0,0,114,179,0,0,0,114,192,0,0,0,114,10, ++ 1,0,0,41,5,114,146,0,0,0,114,166,0,0,0,114, ++ 68,0,0,0,114,44,0,0,0,114,178,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,114,244,0, ++ 0,0,110,4,0,0,115,22,0,0,0,10,1,10,1,2, ++ 4,2,1,6,254,12,4,2,1,14,1,2,1,2,1,6, ++ 253,122,29,83,111,117,114,99,101,108,101,115,115,70,105,108, ++ 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, ++ 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, ++ 0,1,0,0,0,67,0,0,0,114,26,0,0,0,41,2, ++ 122,39,82,101,116,117,114,110,32,78,111,110,101,32,97,115, ++ 32,116,104,101,114,101,32,105,115,32,110,111,32,115,111,117, ++ 114,99,101,32,99,111,100,101,46,78,114,7,0,0,0,114, ++ 250,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, ++ 0,0,0,114,4,1,0,0,126,4,0,0,114,27,0,0, ++ 0,122,31,83,111,117,114,99,101,108,101,115,115,70,105,108, ++ 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, ++ 99,101,78,41,6,114,153,0,0,0,114,152,0,0,0,114, ++ 154,0,0,0,114,155,0,0,0,114,244,0,0,0,114,4, ++ 1,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,114,45,1,0,0,106,4,0,0, ++ 115,8,0,0,0,8,0,4,2,8,2,12,16,114,45,1, ++ 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,3,0,0,0,64,0,0,0,115,92,0,0,0, ++ 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, ++ 132,0,90,4,100,4,100,5,132,0,90,5,100,6,100,7, ++ 132,0,90,6,100,8,100,9,132,0,90,7,100,10,100,11, ++ 132,0,90,8,100,12,100,13,132,0,90,9,100,14,100,15, ++ 132,0,90,10,100,16,100,17,132,0,90,11,101,12,100,18, ++ 100,19,132,0,131,1,90,13,100,20,83,0,41,21,114,33, ++ 1,0,0,122,93,76,111,97,100,101,114,32,102,111,114,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, +- 122,38,101,120,116,101,110,115,105,111,110,32,109,111,100,117, +- 108,101,32,123,33,114,125,32,108,111,97,100,101,100,32,102, +- 114,111,109,32,123,33,114,125,41,7,114,159,0,0,0,114, +- 242,0,0,0,114,187,0,0,0,90,14,99,114,101,97,116, +- 101,95,100,121,110,97,109,105,99,114,173,0,0,0,114,141, +- 0,0,0,114,65,0,0,0,41,3,114,143,0,0,0,114, +- 210,0,0,0,114,244,0,0,0,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,114,239,0,0,0,150,4,0, +- 0,115,14,0,0,0,4,2,6,1,4,255,6,2,8,1, +- 4,255,4,2,122,33,69,120,116,101,110,115,105,111,110,70, +- 105,108,101,76,111,97,100,101,114,46,99,114,101,97,116,101, +- 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, +- 0,0,0,0,2,0,0,0,5,0,0,0,67,0,0,0, +- 115,36,0,0,0,116,0,160,1,116,2,106,3,124,1,161, +- 2,1,0,116,0,160,4,100,1,124,0,106,5,124,0,106, +- 6,161,3,1,0,100,2,83,0,41,3,122,30,73,110,105, +- 116,105,97,108,105,122,101,32,97,110,32,101,120,116,101,110, +- 115,105,111,110,32,109,111,100,117,108,101,122,40,101,120,116, +- 101,110,115,105,111,110,32,109,111,100,117,108,101,32,123,33, +- 114,125,32,101,120,101,99,117,116,101,100,32,102,114,111,109, +- 32,123,33,114,125,78,41,7,114,159,0,0,0,114,242,0, +- 0,0,114,187,0,0,0,90,12,101,120,101,99,95,100,121, +- 110,97,109,105,99,114,173,0,0,0,114,141,0,0,0,114, +- 65,0,0,0,169,2,114,143,0,0,0,114,244,0,0,0, +- 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, +- 245,0,0,0,158,4,0,0,115,8,0,0,0,14,2,6, +- 1,8,1,8,255,122,31,69,120,116,101,110,115,105,111,110, +- 70,105,108,101,76,111,97,100,101,114,46,101,120,101,99,95, +- 109,111,100,117,108,101,99,2,0,0,0,0,0,0,0,0, +- 0,0,0,2,0,0,0,4,0,0,0,3,0,0,0,115, +- 36,0,0,0,116,0,124,0,106,1,131,1,100,1,25,0, +- 137,0,116,2,135,0,102,1,100,2,100,3,132,8,116,3, +- 68,0,131,1,131,1,83,0,41,4,122,49,82,101,116,117, +- 114,110,32,84,114,117,101,32,105,102,32,116,104,101,32,101, +- 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, +- 105,115,32,97,32,112,97,99,107,97,103,101,46,114,3,0, +- 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,2, +- 0,0,0,4,0,0,0,51,0,0,0,115,28,0,0,0, +- 129,0,124,0,93,9,125,1,136,0,100,0,124,1,23,0, +- 107,2,86,0,1,0,113,2,100,1,83,0,41,2,114,236, +- 0,0,0,78,114,7,0,0,0,169,2,114,5,0,0,0, +- 218,6,115,117,102,102,105,120,169,1,90,9,102,105,108,101, +- 95,110,97,109,101,114,7,0,0,0,114,8,0,0,0,114, +- 9,0,0,0,167,4,0,0,115,8,0,0,0,2,128,4, +- 0,2,1,20,255,122,49,69,120,116,101,110,115,105,111,110, +- 70,105,108,101,76,111,97,100,101,114,46,105,115,95,112,97, +- 99,107,97,103,101,46,60,108,111,99,97,108,115,62,46,60, +- 103,101,110,101,120,112,114,62,41,4,114,74,0,0,0,114, +- 65,0,0,0,218,3,97,110,121,114,232,0,0,0,114,247, +- 0,0,0,114,7,0,0,0,114,45,1,0,0,114,8,0, +- 0,0,114,206,0,0,0,164,4,0,0,115,8,0,0,0, +- 14,2,12,1,2,1,8,255,122,30,69,120,116,101,110,115, +- 105,111,110,70,105,108,101,76,111,97,100,101,114,46,105,115, +- 95,112,97,99,107,97,103,101,99,2,0,0,0,0,0,0, +- 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, +- 0,114,23,0,0,0,41,2,122,63,82,101,116,117,114,110, +- 32,78,111,110,101,32,97,115,32,97,110,32,101,120,116,101, +- 110,115,105,111,110,32,109,111,100,117,108,101,32,99,97,110, +- 110,111,116,32,99,114,101,97,116,101,32,97,32,99,111,100, +- 101,32,111,98,106,101,99,116,46,78,114,7,0,0,0,114, ++ 115,46,10,10,32,32,32,32,84,104,101,32,99,111,110,115, ++ 116,114,117,99,116,111,114,32,105,115,32,100,101,115,105,103, ++ 110,101,100,32,116,111,32,119,111,114,107,32,119,105,116,104, ++ 32,70,105,108,101,70,105,110,100,101,114,46,10,10,32,32, ++ 32,32,99,3,0,0,0,0,0,0,0,0,0,0,0,3, ++ 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, ++ 124,1,124,0,95,0,124,2,124,0,95,1,100,0,83,0, ++ 114,72,0,0,0,114,186,0,0,0,41,3,114,146,0,0, ++ 0,114,144,0,0,0,114,68,0,0,0,114,7,0,0,0, ++ 114,7,0,0,0,114,8,0,0,0,114,239,0,0,0,139, ++ 4,0,0,115,4,0,0,0,6,1,10,1,122,28,69,120, ++ 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, ++ 114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,0, ++ 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, ++ 0,0,0,114,15,1,0,0,114,72,0,0,0,114,16,1, ++ 0,0,114,18,1,0,0,114,7,0,0,0,114,7,0,0, ++ 0,114,8,0,0,0,114,19,1,0,0,143,4,0,0,114, ++ 20,1,0,0,122,26,69,120,116,101,110,115,105,111,110,70, ++ 105,108,101,76,111,97,100,101,114,46,95,95,101,113,95,95, ++ 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, ++ 0,3,0,0,0,67,0,0,0,114,21,1,0,0,114,72, ++ 0,0,0,114,22,1,0,0,114,24,1,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,114,25,1,0, ++ 0,147,4,0,0,114,26,1,0,0,122,28,69,120,116,101, ++ 110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,46, ++ 95,95,104,97,115,104,95,95,99,2,0,0,0,0,0,0, ++ 0,0,0,0,0,3,0,0,0,5,0,0,0,67,0,0, ++ 0,115,36,0,0,0,116,0,160,1,116,2,106,3,124,1, ++ 161,2,125,2,116,0,160,4,100,1,124,1,106,5,124,0, ++ 106,6,161,3,1,0,124,2,83,0,41,2,122,38,67,114, ++ 101,97,116,101,32,97,110,32,117,110,105,116,105,97,108,105, ++ 122,101,100,32,101,120,116,101,110,115,105,111,110,32,109,111, ++ 100,117,108,101,122,38,101,120,116,101,110,115,105,111,110,32, ++ 109,111,100,117,108,101,32,123,33,114,125,32,108,111,97,100, ++ 101,100,32,102,114,111,109,32,123,33,114,125,41,7,114,162, ++ 0,0,0,114,245,0,0,0,114,190,0,0,0,218,14,99, ++ 114,101,97,116,101,95,100,121,110,97,109,105,99,114,176,0, ++ 0,0,114,144,0,0,0,114,68,0,0,0,41,3,114,146, ++ 0,0,0,114,213,0,0,0,114,247,0,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,114,242,0,0, ++ 0,150,4,0,0,115,14,0,0,0,4,2,6,1,4,255, ++ 6,2,8,1,4,255,4,2,122,33,69,120,116,101,110,115, ++ 105,111,110,70,105,108,101,76,111,97,100,101,114,46,99,114, ++ 101,97,116,101,95,109,111,100,117,108,101,99,2,0,0,0, ++ 0,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0, ++ 67,0,0,0,115,36,0,0,0,116,0,160,1,116,2,106, ++ 3,124,1,161,2,1,0,116,0,160,4,100,1,124,0,106, ++ 5,124,0,106,6,161,3,1,0,100,2,83,0,41,3,122, ++ 30,73,110,105,116,105,97,108,105,122,101,32,97,110,32,101, ++ 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,122, ++ 40,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, ++ 101,32,123,33,114,125,32,101,120,101,99,117,116,101,100,32, ++ 102,114,111,109,32,123,33,114,125,78,41,7,114,162,0,0, ++ 0,114,245,0,0,0,114,190,0,0,0,90,12,101,120,101, ++ 99,95,100,121,110,97,109,105,99,114,176,0,0,0,114,144, ++ 0,0,0,114,68,0,0,0,169,2,114,146,0,0,0,114, + 247,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,114,241,0,0,0,170,4,0,0,114,24,0,0, +- 0,122,28,69,120,116,101,110,115,105,111,110,70,105,108,101, +- 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, +- 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, +- 1,0,0,0,67,0,0,0,114,23,0,0,0,41,2,122, +- 53,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, ++ 0,0,0,114,248,0,0,0,158,4,0,0,115,8,0,0, ++ 0,14,2,6,1,8,1,8,255,122,31,69,120,116,101,110, ++ 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,101, ++ 120,101,99,95,109,111,100,117,108,101,99,2,0,0,0,0, ++ 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,3, ++ 0,0,0,115,36,0,0,0,116,0,124,0,106,1,131,1, ++ 100,1,25,0,137,0,116,2,135,0,102,1,100,2,100,3, ++ 132,8,116,3,68,0,131,1,131,1,83,0,41,4,122,49, ++ 82,101,116,117,114,110,32,84,114,117,101,32,105,102,32,116, ++ 104,101,32,101,120,116,101,110,115,105,111,110,32,109,111,100, ++ 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, ++ 46,114,3,0,0,0,99,1,0,0,0,0,0,0,0,0, ++ 0,0,0,2,0,0,0,4,0,0,0,51,0,0,0,115, ++ 28,0,0,0,129,0,124,0,93,9,125,1,136,0,100,0, ++ 124,1,23,0,107,2,86,0,1,0,113,2,100,1,83,0, ++ 41,2,114,239,0,0,0,78,114,7,0,0,0,169,2,114, ++ 5,0,0,0,218,6,115,117,102,102,105,120,169,1,90,9, ++ 102,105,108,101,95,110,97,109,101,114,7,0,0,0,114,8, ++ 0,0,0,114,9,0,0,0,167,4,0,0,115,8,0,0, ++ 0,2,128,4,0,2,1,20,255,122,49,69,120,116,101,110, ++ 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,105, ++ 115,95,112,97,99,107,97,103,101,46,60,108,111,99,97,108, ++ 115,62,46,60,103,101,110,101,120,112,114,62,41,4,114,77, ++ 0,0,0,114,68,0,0,0,218,3,97,110,121,114,235,0, ++ 0,0,114,250,0,0,0,114,7,0,0,0,114,50,1,0, ++ 0,114,8,0,0,0,114,209,0,0,0,164,4,0,0,115, ++ 8,0,0,0,14,2,12,1,2,1,8,255,122,30,69,120, ++ 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, ++ 114,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, ++ 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, ++ 0,67,0,0,0,114,26,0,0,0,41,2,122,63,82,101, ++ 116,117,114,110,32,78,111,110,101,32,97,115,32,97,110,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, +- 115,32,104,97,118,101,32,110,111,32,115,111,117,114,99,101, +- 32,99,111,100,101,46,78,114,7,0,0,0,114,247,0,0, +- 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, +- 114,1,1,0,0,174,4,0,0,114,24,0,0,0,122,30, +- 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, +- 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, +- 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, +- 0,0,0,67,0,0,0,114,26,1,0,0,114,27,1,0, +- 0,114,71,0,0,0,114,247,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,114,203,0,0,0,178, +- 4,0,0,114,28,1,0,0,122,32,69,120,116,101,110,115, +- 105,111,110,70,105,108,101,76,111,97,100,101,114,46,103,101, +- 116,95,102,105,108,101,110,97,109,101,78,41,14,114,150,0, +- 0,0,114,149,0,0,0,114,151,0,0,0,114,152,0,0, +- 0,114,236,0,0,0,114,16,1,0,0,114,22,1,0,0, +- 114,239,0,0,0,114,245,0,0,0,114,206,0,0,0,114, +- 241,0,0,0,114,1,1,0,0,114,160,0,0,0,114,203, +- 0,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, +- 0,0,114,8,0,0,0,114,30,1,0,0,131,4,0,0, +- 115,24,0,0,0,8,0,4,2,8,6,8,4,8,4,8, +- 3,8,8,8,6,8,6,8,4,2,4,14,1,114,30,1, +- 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,2,0,0,0,64,0,0,0,115,108,0,0,0, +- 101,0,90,1,100,0,90,2,100,1,90,3,100,2,90,4, +- 100,3,100,4,132,0,90,5,100,5,100,6,132,0,90,6, +- 100,7,100,8,132,0,90,7,100,9,100,10,132,0,90,8, +- 100,11,100,12,132,0,90,9,100,13,100,14,132,0,90,10, +- 100,15,100,16,132,0,90,11,100,17,100,18,132,0,90,12, +- 100,19,100,20,132,0,90,13,100,21,100,22,132,0,90,14, +- 100,23,100,24,132,0,90,15,100,25,83,0,41,26,218,14, +- 95,78,97,109,101,115,112,97,99,101,80,97,116,104,97,38, +- 1,0,0,82,101,112,114,101,115,101,110,116,115,32,97,32, +- 110,97,109,101,115,112,97,99,101,32,112,97,99,107,97,103, +- 101,39,115,32,112,97,116,104,46,32,32,73,116,32,117,115, +- 101,115,32,116,104,101,32,109,111,100,117,108,101,32,110,97, +- 109,101,10,32,32,32,32,116,111,32,102,105,110,100,32,105, +- 116,115,32,112,97,114,101,110,116,32,109,111,100,117,108,101, +- 44,32,97,110,100,32,102,114,111,109,32,116,104,101,114,101, +- 32,105,116,32,108,111,111,107,115,32,117,112,32,116,104,101, +- 32,112,97,114,101,110,116,39,115,10,32,32,32,32,95,95, +- 112,97,116,104,95,95,46,32,32,87,104,101,110,32,116,104, +- 105,115,32,99,104,97,110,103,101,115,44,32,116,104,101,32, +- 109,111,100,117,108,101,39,115,32,111,119,110,32,112,97,116, +- 104,32,105,115,32,114,101,99,111,109,112,117,116,101,100,44, +- 10,32,32,32,32,117,115,105,110,103,32,112,97,116,104,95, +- 102,105,110,100,101,114,46,32,32,70,111,114,32,116,111,112, +- 45,108,101,118,101,108,32,109,111,100,117,108,101,115,44,32, +- 116,104,101,32,112,97,114,101,110,116,32,109,111,100,117,108, +- 101,39,115,32,112,97,116,104,10,32,32,32,32,105,115,32, +- 115,121,115,46,112,97,116,104,46,114,0,0,0,0,99,4, +- 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,3, +- 0,0,0,67,0,0,0,115,44,0,0,0,124,1,124,0, +- 95,0,124,2,124,0,95,1,116,2,124,0,160,3,161,0, +- 131,1,124,0,95,4,124,0,106,5,124,0,95,6,124,3, +- 124,0,95,7,100,0,83,0,114,69,0,0,0,41,8,218, +- 5,95,110,97,109,101,218,5,95,112,97,116,104,114,136,0, +- 0,0,218,16,95,103,101,116,95,112,97,114,101,110,116,95, +- 112,97,116,104,218,17,95,108,97,115,116,95,112,97,114,101, +- 110,116,95,112,97,116,104,218,6,95,101,112,111,99,104,218, +- 11,95,108,97,115,116,95,101,112,111,99,104,218,12,95,112, +- 97,116,104,95,102,105,110,100,101,114,169,4,114,143,0,0, +- 0,114,141,0,0,0,114,65,0,0,0,90,11,112,97,116, +- 104,95,102,105,110,100,101,114,114,7,0,0,0,114,7,0, +- 0,0,114,8,0,0,0,114,236,0,0,0,195,4,0,0, +- 115,10,0,0,0,6,1,6,1,14,1,8,1,10,1,122, +- 23,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, +- 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, +- 0,0,0,0,0,4,0,0,0,3,0,0,0,67,0,0, +- 0,115,38,0,0,0,124,0,106,0,160,1,100,1,161,1, +- 92,3,125,1,125,2,125,3,124,2,100,2,107,2,114,15, +- 100,3,83,0,124,1,100,4,102,2,83,0,41,5,122,62, +- 82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32, +- 111,102,32,40,112,97,114,101,110,116,45,109,111,100,117,108, +- 101,45,110,97,109,101,44,32,112,97,114,101,110,116,45,112, +- 97,116,104,45,97,116,116,114,45,110,97,109,101,41,114,97, +- 0,0,0,114,10,0,0,0,41,2,114,15,0,0,0,114, +- 65,0,0,0,90,8,95,95,112,97,116,104,95,95,41,2, +- 114,48,1,0,0,114,104,0,0,0,41,4,114,143,0,0, +- 0,114,40,1,0,0,218,3,100,111,116,90,2,109,101,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,23, +- 95,102,105,110,100,95,112,97,114,101,110,116,95,112,97,116, +- 104,95,110,97,109,101,115,202,4,0,0,115,8,0,0,0, +- 18,2,8,1,4,2,8,3,122,38,95,78,97,109,101,115, +- 112,97,99,101,80,97,116,104,46,95,102,105,110,100,95,112, +- 97,114,101,110,116,95,112,97,116,104,95,110,97,109,101,115, +- 99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0, +- 0,3,0,0,0,67,0,0,0,115,28,0,0,0,124,0, +- 160,0,161,0,92,2,125,1,125,2,116,1,116,2,106,3, +- 124,1,25,0,124,2,131,2,83,0,114,69,0,0,0,41, +- 4,114,57,1,0,0,114,155,0,0,0,114,15,0,0,0, +- 218,7,109,111,100,117,108,101,115,41,3,114,143,0,0,0, +- 90,18,112,97,114,101,110,116,95,109,111,100,117,108,101,95, +- 110,97,109,101,90,14,112,97,116,104,95,97,116,116,114,95, +- 110,97,109,101,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,114,50,1,0,0,212,4,0,0,115,4,0,0, +- 0,12,1,16,1,122,31,95,78,97,109,101,115,112,97,99, +- 101,80,97,116,104,46,95,103,101,116,95,112,97,114,101,110, +- 116,95,112,97,116,104,99,1,0,0,0,0,0,0,0,0, +- 0,0,0,3,0,0,0,4,0,0,0,67,0,0,0,115, +- 100,0,0,0,116,0,124,0,160,1,161,0,131,1,125,1, +- 124,1,124,0,106,2,107,3,115,17,124,0,106,3,124,0, +- 106,4,107,3,114,47,124,0,160,5,124,0,106,6,124,1, +- 161,2,125,2,124,2,100,0,117,1,114,40,124,2,106,7, +- 100,0,117,0,114,40,124,2,106,8,114,40,124,2,106,8, +- 124,0,95,9,124,1,124,0,95,2,124,0,106,3,124,0, +- 95,4,124,0,106,9,83,0,114,69,0,0,0,41,10,114, +- 136,0,0,0,114,50,1,0,0,114,51,1,0,0,114,52, +- 1,0,0,114,53,1,0,0,114,54,1,0,0,114,48,1, +- 0,0,114,164,0,0,0,114,202,0,0,0,114,49,1,0, +- 0,41,3,114,143,0,0,0,90,11,112,97,114,101,110,116, +- 95,112,97,116,104,114,210,0,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,218,12,95,114,101,99,97, +- 108,99,117,108,97,116,101,216,4,0,0,115,18,0,0,0, +- 12,2,22,1,14,1,18,3,6,1,8,1,6,1,8,1, +- 6,1,122,27,95,78,97,109,101,115,112,97,99,101,80,97, +- 116,104,46,95,114,101,99,97,108,99,117,108,97,116,101,99, ++ 32,99,97,110,110,111,116,32,99,114,101,97,116,101,32,97, ++ 32,99,111,100,101,32,111,98,106,101,99,116,46,78,114,7, ++ 0,0,0,114,250,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,114,244,0,0,0,170,4,0,0, ++ 114,27,0,0,0,122,28,69,120,116,101,110,115,105,111,110, ++ 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,99, ++ 111,100,101,99,2,0,0,0,0,0,0,0,0,0,0,0, ++ 2,0,0,0,1,0,0,0,67,0,0,0,114,26,0,0, ++ 0,41,2,122,53,82,101,116,117,114,110,32,78,111,110,101, ++ 32,97,115,32,101,120,116,101,110,115,105,111,110,32,109,111, ++ 100,117,108,101,115,32,104,97,118,101,32,110,111,32,115,111, ++ 117,114,99,101,32,99,111,100,101,46,78,114,7,0,0,0, ++ 114,250,0,0,0,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,114,4,1,0,0,174,4,0,0,114,27,0, ++ 0,0,122,30,69,120,116,101,110,115,105,111,110,70,105,108, ++ 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, ++ 99,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, ++ 0,0,0,1,0,0,0,67,0,0,0,114,29,1,0,0, ++ 114,30,1,0,0,114,74,0,0,0,114,250,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,206, ++ 0,0,0,178,4,0,0,114,31,1,0,0,122,32,69,120, ++ 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, ++ 114,46,103,101,116,95,102,105,108,101,110,97,109,101,78,41, ++ 14,114,153,0,0,0,114,152,0,0,0,114,154,0,0,0, ++ 114,155,0,0,0,114,239,0,0,0,114,19,1,0,0,114, ++ 25,1,0,0,114,242,0,0,0,114,248,0,0,0,114,209, ++ 0,0,0,114,244,0,0,0,114,4,1,0,0,114,163,0, ++ 0,0,114,206,0,0,0,114,7,0,0,0,114,7,0,0, ++ 0,114,7,0,0,0,114,8,0,0,0,114,33,1,0,0, ++ 131,4,0,0,115,24,0,0,0,8,0,4,2,8,6,8, ++ 4,8,4,8,3,8,8,8,6,8,6,8,4,2,4,14, ++ 1,114,33,1,0,0,99,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, ++ 108,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, ++ 100,2,90,4,100,3,100,4,132,0,90,5,100,5,100,6, ++ 132,0,90,6,100,7,100,8,132,0,90,7,100,9,100,10, ++ 132,0,90,8,100,11,100,12,132,0,90,9,100,13,100,14, ++ 132,0,90,10,100,15,100,16,132,0,90,11,100,17,100,18, ++ 132,0,90,12,100,19,100,20,132,0,90,13,100,21,100,22, ++ 132,0,90,14,100,23,100,24,132,0,90,15,100,25,83,0, ++ 41,26,218,14,95,78,97,109,101,115,112,97,99,101,80,97, ++ 116,104,97,38,1,0,0,82,101,112,114,101,115,101,110,116, ++ 115,32,97,32,110,97,109,101,115,112,97,99,101,32,112,97, ++ 99,107,97,103,101,39,115,32,112,97,116,104,46,32,32,73, ++ 116,32,117,115,101,115,32,116,104,101,32,109,111,100,117,108, ++ 101,32,110,97,109,101,10,32,32,32,32,116,111,32,102,105, ++ 110,100,32,105,116,115,32,112,97,114,101,110,116,32,109,111, ++ 100,117,108,101,44,32,97,110,100,32,102,114,111,109,32,116, ++ 104,101,114,101,32,105,116,32,108,111,111,107,115,32,117,112, ++ 32,116,104,101,32,112,97,114,101,110,116,39,115,10,32,32, ++ 32,32,95,95,112,97,116,104,95,95,46,32,32,87,104,101, ++ 110,32,116,104,105,115,32,99,104,97,110,103,101,115,44,32, ++ 116,104,101,32,109,111,100,117,108,101,39,115,32,111,119,110, ++ 32,112,97,116,104,32,105,115,32,114,101,99,111,109,112,117, ++ 116,101,100,44,10,32,32,32,32,117,115,105,110,103,32,112, ++ 97,116,104,95,102,105,110,100,101,114,46,32,32,70,111,114, ++ 32,116,111,112,45,108,101,118,101,108,32,109,111,100,117,108, ++ 101,115,44,32,116,104,101,32,112,97,114,101,110,116,32,109, ++ 111,100,117,108,101,39,115,32,112,97,116,104,10,32,32,32, ++ 32,105,115,32,115,121,115,46,112,97,116,104,46,114,0,0, ++ 0,0,99,4,0,0,0,0,0,0,0,0,0,0,0,4, ++ 0,0,0,3,0,0,0,67,0,0,0,115,44,0,0,0, ++ 124,1,124,0,95,0,124,2,124,0,95,1,116,2,124,0, ++ 160,3,161,0,131,1,124,0,95,4,124,0,106,5,124,0, ++ 95,6,124,3,124,0,95,7,100,0,83,0,114,72,0,0, ++ 0,41,8,218,5,95,110,97,109,101,218,5,95,112,97,116, ++ 104,114,139,0,0,0,218,16,95,103,101,116,95,112,97,114, ++ 101,110,116,95,112,97,116,104,218,17,95,108,97,115,116,95, ++ 112,97,114,101,110,116,95,112,97,116,104,218,6,95,101,112, ++ 111,99,104,218,11,95,108,97,115,116,95,101,112,111,99,104, ++ 218,12,95,112,97,116,104,95,102,105,110,100,101,114,169,4, ++ 114,146,0,0,0,114,144,0,0,0,114,68,0,0,0,90, ++ 11,112,97,116,104,95,102,105,110,100,101,114,114,7,0,0, ++ 0,114,7,0,0,0,114,8,0,0,0,114,239,0,0,0, ++ 195,4,0,0,115,10,0,0,0,6,1,6,1,14,1,8, ++ 1,10,1,122,23,95,78,97,109,101,115,112,97,99,101,80, ++ 97,116,104,46,95,95,105,110,105,116,95,95,99,1,0,0, ++ 0,0,0,0,0,0,0,0,0,4,0,0,0,3,0,0, ++ 0,67,0,0,0,115,38,0,0,0,124,0,106,0,160,1, ++ 100,1,161,1,92,3,125,1,125,2,125,3,124,2,100,2, ++ 107,2,114,15,100,3,83,0,124,1,100,4,102,2,83,0, ++ 41,5,122,62,82,101,116,117,114,110,115,32,97,32,116,117, ++ 112,108,101,32,111,102,32,40,112,97,114,101,110,116,45,109, ++ 111,100,117,108,101,45,110,97,109,101,44,32,112,97,114,101, ++ 110,116,45,112,97,116,104,45,97,116,116,114,45,110,97,109, ++ 101,41,114,100,0,0,0,114,10,0,0,0,41,2,114,18, ++ 0,0,0,114,68,0,0,0,90,8,95,95,112,97,116,104, ++ 95,95,41,2,114,53,1,0,0,114,107,0,0,0,41,4, ++ 114,146,0,0,0,114,44,1,0,0,218,3,100,111,116,90, ++ 2,109,101,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,218,23,95,102,105,110,100,95,112,97,114,101,110,116, ++ 95,112,97,116,104,95,110,97,109,101,115,202,4,0,0,115, ++ 8,0,0,0,18,2,8,1,4,2,8,3,122,38,95,78, ++ 97,109,101,115,112,97,99,101,80,97,116,104,46,95,102,105, ++ 110,100,95,112,97,114,101,110,116,95,112,97,116,104,95,110, ++ 97,109,101,115,99,1,0,0,0,0,0,0,0,0,0,0, ++ 0,3,0,0,0,3,0,0,0,67,0,0,0,115,28,0, ++ 0,0,124,0,160,0,161,0,92,2,125,1,125,2,116,1, ++ 116,2,106,3,124,1,25,0,124,2,131,2,83,0,114,72, ++ 0,0,0,41,4,114,62,1,0,0,114,158,0,0,0,114, ++ 18,0,0,0,218,7,109,111,100,117,108,101,115,41,3,114, ++ 146,0,0,0,90,18,112,97,114,101,110,116,95,109,111,100, ++ 117,108,101,95,110,97,109,101,90,14,112,97,116,104,95,97, ++ 116,116,114,95,110,97,109,101,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,114,55,1,0,0,212,4,0,0, ++ 115,4,0,0,0,12,1,16,1,122,31,95,78,97,109,101, ++ 115,112,97,99,101,80,97,116,104,46,95,103,101,116,95,112, ++ 97,114,101,110,116,95,112,97,116,104,99,1,0,0,0,0, ++ 0,0,0,0,0,0,0,3,0,0,0,4,0,0,0,67, ++ 0,0,0,115,100,0,0,0,116,0,124,0,160,1,161,0, ++ 131,1,125,1,124,1,124,0,106,2,107,3,115,17,124,0, ++ 106,3,124,0,106,4,107,3,114,47,124,0,160,5,124,0, ++ 106,6,124,1,161,2,125,2,124,2,100,0,117,1,114,40, ++ 124,2,106,7,100,0,117,0,114,40,124,2,106,8,114,40, ++ 124,2,106,8,124,0,95,9,124,1,124,0,95,2,124,0, ++ 106,3,124,0,95,4,124,0,106,9,83,0,114,72,0,0, ++ 0,41,10,114,139,0,0,0,114,55,1,0,0,114,56,1, ++ 0,0,114,57,1,0,0,114,58,1,0,0,114,59,1,0, ++ 0,114,53,1,0,0,114,167,0,0,0,114,205,0,0,0, ++ 114,54,1,0,0,41,3,114,146,0,0,0,90,11,112,97, ++ 114,101,110,116,95,112,97,116,104,114,213,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,218,12,95, ++ 114,101,99,97,108,99,117,108,97,116,101,216,4,0,0,115, ++ 18,0,0,0,12,2,22,1,14,1,18,3,6,1,8,1, ++ 6,1,8,1,6,1,122,27,95,78,97,109,101,115,112,97, ++ 99,101,80,97,116,104,46,95,114,101,99,97,108,99,117,108, ++ 97,116,101,99,1,0,0,0,0,0,0,0,0,0,0,0, ++ 1,0,0,0,3,0,0,0,67,0,0,0,243,12,0,0, ++ 0,116,0,124,0,160,1,161,0,131,1,83,0,114,72,0, ++ 0,0,41,2,218,4,105,116,101,114,114,64,1,0,0,114, ++ 24,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, ++ 0,0,0,218,8,95,95,105,116,101,114,95,95,230,4,0, ++ 0,243,2,0,0,0,12,1,122,23,95,78,97,109,101,115, ++ 112,97,99,101,80,97,116,104,46,95,95,105,116,101,114,95, ++ 95,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, ++ 0,0,2,0,0,0,67,0,0,0,115,12,0,0,0,124, ++ 0,160,0,161,0,124,1,25,0,83,0,114,72,0,0,0, ++ 169,1,114,64,1,0,0,41,2,114,146,0,0,0,218,5, ++ 105,110,100,101,120,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,218,11,95,95,103,101,116,105,116,101,109,95, ++ 95,233,4,0,0,114,68,1,0,0,122,26,95,78,97,109, ++ 101,115,112,97,99,101,80,97,116,104,46,95,95,103,101,116, ++ 105,116,101,109,95,95,99,3,0,0,0,0,0,0,0,0, ++ 0,0,0,3,0,0,0,3,0,0,0,67,0,0,0,115, ++ 14,0,0,0,124,2,124,0,106,0,124,1,60,0,100,0, ++ 83,0,114,72,0,0,0,41,1,114,54,1,0,0,41,3, ++ 114,146,0,0,0,114,70,1,0,0,114,68,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,11, ++ 95,95,115,101,116,105,116,101,109,95,95,236,4,0,0,115, ++ 2,0,0,0,14,1,122,26,95,78,97,109,101,115,112,97, ++ 99,101,80,97,116,104,46,95,95,115,101,116,105,116,101,109, ++ 95,95,99,1,0,0,0,0,0,0,0,0,0,0,0,1, ++ 0,0,0,3,0,0,0,67,0,0,0,114,65,1,0,0, ++ 114,72,0,0,0,41,2,114,4,0,0,0,114,64,1,0, ++ 0,114,24,1,0,0,114,7,0,0,0,114,7,0,0,0, ++ 114,8,0,0,0,218,7,95,95,108,101,110,95,95,239,4, ++ 0,0,114,68,1,0,0,122,22,95,78,97,109,101,115,112, ++ 97,99,101,80,97,116,104,46,95,95,108,101,110,95,95,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +- 3,0,0,0,67,0,0,0,243,12,0,0,0,116,0,124, +- 0,160,1,161,0,131,1,83,0,114,69,0,0,0,41,2, +- 218,4,105,116,101,114,114,59,1,0,0,114,21,1,0,0, +- 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, +- 8,95,95,105,116,101,114,95,95,230,4,0,0,243,2,0, +- 0,0,12,1,122,23,95,78,97,109,101,115,112,97,99,101, +- 80,97,116,104,46,95,95,105,116,101,114,95,95,99,2,0, +- 0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0, +- 0,0,67,0,0,0,115,12,0,0,0,124,0,160,0,161, +- 0,124,1,25,0,83,0,114,69,0,0,0,169,1,114,59, +- 1,0,0,41,2,114,143,0,0,0,218,5,105,110,100,101, +- 120,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, +- 218,11,95,95,103,101,116,105,116,101,109,95,95,233,4,0, +- 0,114,63,1,0,0,122,26,95,78,97,109,101,115,112,97, +- 99,101,80,97,116,104,46,95,95,103,101,116,105,116,101,109, +- 95,95,99,3,0,0,0,0,0,0,0,0,0,0,0,3, +- 0,0,0,3,0,0,0,67,0,0,0,115,14,0,0,0, +- 124,2,124,0,106,0,124,1,60,0,100,0,83,0,114,69, +- 0,0,0,41,1,114,49,1,0,0,41,3,114,143,0,0, +- 0,114,65,1,0,0,114,65,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,218,11,95,95,115,101, +- 116,105,116,101,109,95,95,236,4,0,0,115,2,0,0,0, +- 14,1,122,26,95,78,97,109,101,115,112,97,99,101,80,97, +- 116,104,46,95,95,115,101,116,105,116,101,109,95,95,99,1, +- 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3, +- 0,0,0,67,0,0,0,114,60,1,0,0,114,69,0,0, +- 0,41,2,114,4,0,0,0,114,59,1,0,0,114,21,1, +- 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, +- 0,218,7,95,95,108,101,110,95,95,239,4,0,0,114,63, +- 1,0,0,122,22,95,78,97,109,101,115,112,97,99,101,80, +- 97,116,104,46,95,95,108,101,110,95,95,99,1,0,0,0, +- 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, +- 67,0,0,0,243,12,0,0,0,100,1,160,0,124,0,106, +- 1,161,1,83,0,41,2,78,122,20,95,78,97,109,101,115, +- 112,97,99,101,80,97,116,104,40,123,33,114,125,41,41,2, +- 114,89,0,0,0,114,49,1,0,0,114,21,1,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,8, +- 95,95,114,101,112,114,95,95,242,4,0,0,114,63,1,0, +- 0,122,23,95,78,97,109,101,115,112,97,99,101,80,97,116, +- 104,46,95,95,114,101,112,114,95,95,99,2,0,0,0,0, +- 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, +- 0,0,0,115,12,0,0,0,124,1,124,0,160,0,161,0, +- 118,0,83,0,114,69,0,0,0,114,64,1,0,0,169,2, +- 114,143,0,0,0,218,4,105,116,101,109,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,218,12,95,95,99,111, +- 110,116,97,105,110,115,95,95,245,4,0,0,114,63,1,0, +- 0,122,27,95,78,97,109,101,115,112,97,99,101,80,97,116, +- 104,46,95,95,99,111,110,116,97,105,110,115,95,95,99,2, ++ 3,0,0,0,67,0,0,0,243,12,0,0,0,100,1,160, ++ 0,124,0,106,1,161,1,83,0,41,2,78,122,20,95,78, ++ 97,109,101,115,112,97,99,101,80,97,116,104,40,123,33,114, ++ 125,41,41,2,114,92,0,0,0,114,54,1,0,0,114,24, ++ 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,218,8,95,95,114,101,112,114,95,95,242,4,0,0, ++ 114,68,1,0,0,122,23,95,78,97,109,101,115,112,97,99, ++ 101,80,97,116,104,46,95,95,114,101,112,114,95,95,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3, +- 0,0,0,67,0,0,0,115,16,0,0,0,124,0,106,0, +- 160,1,124,1,161,1,1,0,100,0,83,0,114,69,0,0, +- 0,41,2,114,49,1,0,0,114,61,0,0,0,114,71,1, ++ 0,0,0,67,0,0,0,115,12,0,0,0,124,1,124,0, ++ 160,0,161,0,118,0,83,0,114,72,0,0,0,114,69,1, ++ 0,0,169,2,114,146,0,0,0,218,4,105,116,101,109,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,12, ++ 95,95,99,111,110,116,97,105,110,115,95,95,245,4,0,0, ++ 114,68,1,0,0,122,27,95,78,97,109,101,115,112,97,99, ++ 101,80,97,116,104,46,95,95,99,111,110,116,97,105,110,115, ++ 95,95,99,2,0,0,0,0,0,0,0,0,0,0,0,2, ++ 0,0,0,3,0,0,0,67,0,0,0,115,16,0,0,0, ++ 124,0,106,0,160,1,124,1,161,1,1,0,100,0,83,0, ++ 114,72,0,0,0,41,2,114,54,1,0,0,114,64,0,0, ++ 0,114,76,1,0,0,114,7,0,0,0,114,7,0,0,0, ++ 114,8,0,0,0,114,64,0,0,0,248,4,0,0,243,2, ++ 0,0,0,16,1,122,21,95,78,97,109,101,115,112,97,99, ++ 101,80,97,116,104,46,97,112,112,101,110,100,78,41,16,114, ++ 153,0,0,0,114,152,0,0,0,114,154,0,0,0,114,155, ++ 0,0,0,114,57,1,0,0,114,239,0,0,0,114,62,1, ++ 0,0,114,55,1,0,0,114,64,1,0,0,114,67,1,0, ++ 0,114,71,1,0,0,114,72,1,0,0,114,73,1,0,0, ++ 114,75,1,0,0,114,78,1,0,0,114,64,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, ++ 0,0,0,114,52,1,0,0,184,4,0,0,115,28,0,0, ++ 0,8,0,4,1,4,8,8,2,8,7,8,10,8,4,8, ++ 14,8,3,8,3,8,3,8,3,8,3,12,3,114,52,1, ++ 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,3,0,0,0,64,0,0,0,115,88,0,0,0, ++ 101,0,90,1,100,0,90,2,100,1,100,2,132,0,90,3, ++ 101,4,100,3,100,4,132,0,131,1,90,5,100,5,100,6, ++ 132,0,90,6,100,7,100,8,132,0,90,7,100,9,100,10, ++ 132,0,90,8,100,11,100,12,132,0,90,9,100,13,100,14, ++ 132,0,90,10,100,15,100,16,132,0,90,11,100,17,100,18, ++ 132,0,90,12,100,19,83,0,41,20,218,16,95,78,97,109, ++ 101,115,112,97,99,101,76,111,97,100,101,114,99,4,0,0, ++ 0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0, ++ 0,67,0,0,0,115,18,0,0,0,116,0,124,1,124,2, ++ 124,3,131,3,124,0,95,1,100,0,83,0,114,72,0,0, ++ 0,41,2,114,52,1,0,0,114,54,1,0,0,114,60,1, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, +- 0,114,61,0,0,0,248,4,0,0,243,2,0,0,0,16, +- 1,122,21,95,78,97,109,101,115,112,97,99,101,80,97,116, +- 104,46,97,112,112,101,110,100,78,41,16,114,150,0,0,0, +- 114,149,0,0,0,114,151,0,0,0,114,152,0,0,0,114, +- 52,1,0,0,114,236,0,0,0,114,57,1,0,0,114,50, +- 1,0,0,114,59,1,0,0,114,62,1,0,0,114,66,1, +- 0,0,114,67,1,0,0,114,68,1,0,0,114,70,1,0, +- 0,114,73,1,0,0,114,61,0,0,0,114,7,0,0,0, ++ 0,114,239,0,0,0,254,4,0,0,115,2,0,0,0,18, ++ 1,122,25,95,78,97,109,101,115,112,97,99,101,76,111,97, ++ 100,101,114,46,95,95,105,110,105,116,95,95,99,1,0,0, ++ 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, ++ 0,67,0,0,0,115,24,0,0,0,116,0,160,1,100,1, ++ 116,2,161,2,1,0,100,2,160,3,124,0,106,4,161,1, ++ 83,0,41,3,122,115,82,101,116,117,114,110,32,114,101,112, ++ 114,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, ++ 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,109, ++ 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, ++ 116,101,100,46,32,32,84,104,101,32,105,109,112,111,114,116, ++ 32,109,97,99,104,105,110,101,114,121,32,100,111,101,115,32, ++ 116,104,101,32,106,111,98,32,105,116,115,101,108,102,46,10, ++ 10,32,32,32,32,32,32,32,32,122,82,95,78,97,109,101, ++ 115,112,97,99,101,76,111,97,100,101,114,46,109,111,100,117, ++ 108,101,95,114,101,112,114,40,41,32,105,115,32,100,101,112, ++ 114,101,99,97,116,101,100,32,97,110,100,32,115,108,97,116, ++ 101,100,32,102,111,114,32,114,101,109,111,118,97,108,32,105, ++ 110,32,80,121,116,104,111,110,32,51,46,49,50,122,25,60, ++ 109,111,100,117,108,101,32,123,33,114,125,32,40,110,97,109, ++ 101,115,112,97,99,101,41,62,41,5,114,102,0,0,0,114, ++ 103,0,0,0,114,104,0,0,0,114,92,0,0,0,114,153, ++ 0,0,0,41,1,114,247,0,0,0,114,7,0,0,0,114, ++ 7,0,0,0,114,8,0,0,0,218,11,109,111,100,117,108, ++ 101,95,114,101,112,114,1,5,0,0,115,8,0,0,0,6, ++ 7,2,1,4,255,12,2,122,28,95,78,97,109,101,115,112, ++ 97,99,101,76,111,97,100,101,114,46,109,111,100,117,108,101, ++ 95,114,101,112,114,99,2,0,0,0,0,0,0,0,0,0, ++ 0,0,2,0,0,0,1,0,0,0,67,0,0,0,114,26, ++ 0,0,0,41,2,78,84,114,7,0,0,0,114,250,0,0, ++ 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, ++ 114,209,0,0,0,12,5,0,0,243,2,0,0,0,4,1, ++ 122,27,95,78,97,109,101,115,112,97,99,101,76,111,97,100, ++ 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, ++ 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0, ++ 0,0,67,0,0,0,114,26,0,0,0,41,2,78,114,10, ++ 0,0,0,114,7,0,0,0,114,250,0,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,114,4,1,0, ++ 0,15,5,0,0,114,82,1,0,0,122,27,95,78,97,109, ++ 101,115,112,97,99,101,76,111,97,100,101,114,46,103,101,116, ++ 95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0, ++ 0,0,0,0,2,0,0,0,6,0,0,0,67,0,0,0, ++ 115,16,0,0,0,116,0,100,1,100,2,100,3,100,4,100, ++ 5,141,4,83,0,41,6,78,114,10,0,0,0,122,8,60, ++ 115,116,114,105,110,103,62,114,246,0,0,0,84,41,1,114, ++ 6,1,0,0,41,1,114,7,1,0,0,114,250,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, +- 47,1,0,0,184,4,0,0,115,28,0,0,0,8,0,4, +- 1,4,8,8,2,8,7,8,10,8,4,8,14,8,3,8, +- 3,8,3,8,3,8,3,12,3,114,47,1,0,0,99,0, +- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, +- 0,0,0,64,0,0,0,115,88,0,0,0,101,0,90,1, +- 100,0,90,2,100,1,100,2,132,0,90,3,101,4,100,3, +- 100,4,132,0,131,1,90,5,100,5,100,6,132,0,90,6, +- 100,7,100,8,132,0,90,7,100,9,100,10,132,0,90,8, +- 100,11,100,12,132,0,90,9,100,13,100,14,132,0,90,10, +- 100,15,100,16,132,0,90,11,100,17,100,18,132,0,90,12, +- 100,19,83,0,41,20,218,16,95,78,97,109,101,115,112,97, +- 99,101,76,111,97,100,101,114,99,4,0,0,0,0,0,0, +- 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, +- 0,115,18,0,0,0,116,0,124,1,124,2,124,3,131,3, +- 124,0,95,1,100,0,83,0,114,69,0,0,0,41,2,114, +- 47,1,0,0,114,49,1,0,0,114,55,1,0,0,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,114,236,0, +- 0,0,254,4,0,0,115,2,0,0,0,18,1,122,25,95, ++ 244,0,0,0,18,5,0,0,114,79,1,0,0,122,25,95, + 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, +- 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, +- 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, +- 0,115,24,0,0,0,116,0,160,1,100,1,116,2,161,2, +- 1,0,100,2,160,3,124,0,106,4,161,1,83,0,41,3, +- 122,115,82,101,116,117,114,110,32,114,101,112,114,32,102,111, +- 114,32,116,104,101,32,109,111,100,117,108,101,46,10,10,32, +- 32,32,32,32,32,32,32,84,104,101,32,109,101,116,104,111, +- 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, +- 32,32,84,104,101,32,105,109,112,111,114,116,32,109,97,99, +- 104,105,110,101,114,121,32,100,111,101,115,32,116,104,101,32, +- 106,111,98,32,105,116,115,101,108,102,46,10,10,32,32,32, +- 32,32,32,32,32,122,82,95,78,97,109,101,115,112,97,99, +- 101,76,111,97,100,101,114,46,109,111,100,117,108,101,95,114, +- 101,112,114,40,41,32,105,115,32,100,101,112,114,101,99,97, +- 116,101,100,32,97,110,100,32,115,108,97,116,101,100,32,102, +- 111,114,32,114,101,109,111,118,97,108,32,105,110,32,80,121, +- 116,104,111,110,32,51,46,49,50,122,25,60,109,111,100,117, +- 108,101,32,123,33,114,125,32,40,110,97,109,101,115,112,97, +- 99,101,41,62,41,5,114,99,0,0,0,114,100,0,0,0, +- 114,101,0,0,0,114,89,0,0,0,114,150,0,0,0,41, +- 1,114,244,0,0,0,114,7,0,0,0,114,7,0,0,0, +- 114,8,0,0,0,218,11,109,111,100,117,108,101,95,114,101, +- 112,114,1,5,0,0,115,8,0,0,0,6,7,2,1,4, +- 255,12,2,122,28,95,78,97,109,101,115,112,97,99,101,76, +- 111,97,100,101,114,46,109,111,100,117,108,101,95,114,101,112, +- 114,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, +- 0,0,1,0,0,0,67,0,0,0,114,23,0,0,0,41, +- 2,78,84,114,7,0,0,0,114,247,0,0,0,114,7,0, +- 0,0,114,7,0,0,0,114,8,0,0,0,114,206,0,0, +- 0,12,5,0,0,243,2,0,0,0,4,1,122,27,95,78, +- 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,105, +- 115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0, +- 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, +- 0,0,114,23,0,0,0,41,2,78,114,10,0,0,0,114, +- 7,0,0,0,114,247,0,0,0,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,114,1,1,0,0,15,5,0, +- 0,114,77,1,0,0,122,27,95,78,97,109,101,115,112,97, +- 99,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, +- 114,99,101,99,2,0,0,0,0,0,0,0,0,0,0,0, +- 2,0,0,0,6,0,0,0,67,0,0,0,115,16,0,0, +- 0,116,0,100,1,100,2,100,3,100,4,100,5,141,4,83, +- 0,41,6,78,114,10,0,0,0,122,8,60,115,116,114,105, +- 110,103,62,114,243,0,0,0,84,41,1,114,3,1,0,0, +- 41,1,114,4,1,0,0,114,247,0,0,0,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,114,241,0,0,0, +- 18,5,0,0,114,74,1,0,0,122,25,95,78,97,109,101, +- 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, +- 99,111,100,101,99,2,0,0,0,0,0,0,0,0,0,0, +- 0,2,0,0,0,1,0,0,0,67,0,0,0,114,23,0, +- 0,0,114,237,0,0,0,114,7,0,0,0,114,238,0,0, +- 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, +- 114,239,0,0,0,21,5,0,0,114,240,0,0,0,122,30, +- 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, +- 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, +- 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, +- 0,0,0,67,0,0,0,115,4,0,0,0,100,0,83,0, +- 114,69,0,0,0,114,7,0,0,0,114,42,1,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,245, +- 0,0,0,24,5,0,0,114,77,1,0,0,122,28,95,78, +- 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,101, +- 120,101,99,95,109,111,100,117,108,101,99,2,0,0,0,0, +- 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, +- 0,0,0,115,26,0,0,0,116,0,160,1,100,1,124,0, +- 106,2,161,2,1,0,116,0,160,3,124,0,124,1,161,2, +- 83,0,41,2,122,98,76,111,97,100,32,97,32,110,97,109, +- 101,115,112,97,99,101,32,109,111,100,117,108,101,46,10,10, ++ 103,101,116,95,99,111,100,101,99,2,0,0,0,0,0,0, ++ 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, ++ 0,114,26,0,0,0,114,240,0,0,0,114,7,0,0,0, ++ 114,241,0,0,0,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,114,242,0,0,0,21,5,0,0,114,243,0, ++ 0,0,122,30,95,78,97,109,101,115,112,97,99,101,76,111, ++ 97,100,101,114,46,99,114,101,97,116,101,95,109,111,100,117, ++ 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, ++ 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, ++ 100,0,83,0,114,72,0,0,0,114,7,0,0,0,114,47, ++ 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,114,248,0,0,0,24,5,0,0,114,82,1,0,0, ++ 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, ++ 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, ++ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,4, ++ 0,0,0,67,0,0,0,115,26,0,0,0,116,0,160,1, ++ 100,1,124,0,106,2,161,2,1,0,116,0,160,3,124,0, ++ 124,1,161,2,83,0,41,2,122,98,76,111,97,100,32,97, ++ 32,110,97,109,101,115,112,97,99,101,32,109,111,100,117,108, ++ 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, ++ 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, ++ 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, ++ 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, ++ 100,46,10,10,32,32,32,32,32,32,32,32,122,38,110,97, ++ 109,101,115,112,97,99,101,32,109,111,100,117,108,101,32,108, ++ 111,97,100,101,100,32,119,105,116,104,32,112,97,116,104,32, ++ 123,33,114,125,41,4,114,162,0,0,0,114,176,0,0,0, ++ 114,54,1,0,0,114,249,0,0,0,114,250,0,0,0,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,251, ++ 0,0,0,27,5,0,0,115,8,0,0,0,6,7,4,1, ++ 4,255,12,3,122,28,95,78,97,109,101,115,112,97,99,101, ++ 76,111,97,100,101,114,46,108,111,97,100,95,109,111,100,117, ++ 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,3, ++ 0,0,0,2,0,0,0,67,0,0,0,115,22,0,0,0, ++ 100,1,100,2,108,0,109,1,125,2,1,0,124,2,124,0, ++ 106,2,131,1,83,0,41,3,78,114,0,0,0,0,41,1, ++ 218,15,78,97,109,101,115,112,97,99,101,82,101,97,100,101, ++ 114,41,3,114,36,1,0,0,114,83,1,0,0,114,54,1, ++ 0,0,41,3,114,146,0,0,0,114,247,0,0,0,114,83, ++ 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,114,37,1,0,0,39,5,0,0,115,4,0,0,0, ++ 12,1,10,1,122,36,95,78,97,109,101,115,112,97,99,101, ++ 76,111,97,100,101,114,46,103,101,116,95,114,101,115,111,117, ++ 114,99,101,95,114,101,97,100,101,114,78,41,13,114,153,0, ++ 0,0,114,152,0,0,0,114,154,0,0,0,114,239,0,0, ++ 0,114,236,0,0,0,114,81,1,0,0,114,209,0,0,0, ++ 114,4,1,0,0,114,244,0,0,0,114,242,0,0,0,114, ++ 248,0,0,0,114,251,0,0,0,114,37,1,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,114,80,1,0,0,253,4,0,0,115,22,0,0,0, ++ 8,0,8,1,2,3,10,1,8,10,8,3,8,3,8,3, ++ 8,3,8,3,12,12,114,80,1,0,0,99,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, ++ 64,0,0,0,115,118,0,0,0,101,0,90,1,100,0,90, ++ 2,100,1,90,3,101,4,100,2,100,3,132,0,131,1,90, ++ 5,101,4,100,4,100,5,132,0,131,1,90,6,101,7,100, ++ 6,100,7,132,0,131,1,90,8,101,7,100,8,100,9,132, ++ 0,131,1,90,9,101,7,100,19,100,11,100,12,132,1,131, ++ 1,90,10,101,7,100,20,100,13,100,14,132,1,131,1,90, ++ 11,101,7,100,19,100,15,100,16,132,1,131,1,90,12,101, ++ 4,100,17,100,18,132,0,131,1,90,13,100,10,83,0,41, ++ 21,218,10,80,97,116,104,70,105,110,100,101,114,122,62,77, ++ 101,116,97,32,112,97,116,104,32,102,105,110,100,101,114,32, ++ 102,111,114,32,115,121,115,46,112,97,116,104,32,97,110,100, ++ 32,112,97,99,107,97,103,101,32,95,95,112,97,116,104,95, ++ 95,32,97,116,116,114,105,98,117,116,101,115,46,99,0,0, ++ 0,0,0,0,0,0,0,0,0,0,2,0,0,0,4,0, ++ 0,0,67,0,0,0,115,78,0,0,0,116,0,116,1,106, ++ 2,160,3,161,0,131,1,68,0,93,22,92,2,125,0,125, ++ 1,124,1,100,1,117,0,114,20,116,1,106,2,124,0,61, ++ 0,113,7,116,4,124,1,100,2,131,2,114,29,124,1,160, ++ 5,161,0,1,0,113,7,116,6,4,0,106,7,100,3,55, ++ 0,2,0,95,7,100,1,83,0,41,4,122,125,67,97,108, ++ 108,32,116,104,101,32,105,110,118,97,108,105,100,97,116,101, ++ 95,99,97,99,104,101,115,40,41,32,109,101,116,104,111,100, ++ 32,111,110,32,97,108,108,32,112,97,116,104,32,101,110,116, ++ 114,121,32,102,105,110,100,101,114,115,10,32,32,32,32,32, ++ 32,32,32,115,116,111,114,101,100,32,105,110,32,115,121,115, ++ 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, ++ 97,99,104,101,115,32,40,119,104,101,114,101,32,105,109,112, ++ 108,101,109,101,110,116,101,100,41,46,78,218,17,105,110,118, ++ 97,108,105,100,97,116,101,95,99,97,99,104,101,115,114,3, ++ 0,0,0,41,8,218,4,108,105,115,116,114,18,0,0,0, ++ 218,19,112,97,116,104,95,105,109,112,111,114,116,101,114,95, ++ 99,97,99,104,101,218,5,105,116,101,109,115,114,156,0,0, ++ 0,114,85,1,0,0,114,52,1,0,0,114,57,1,0,0, ++ 41,2,114,144,0,0,0,218,6,102,105,110,100,101,114,114, ++ 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,85, ++ 1,0,0,50,5,0,0,115,14,0,0,0,22,4,8,1, ++ 10,1,10,1,8,1,2,128,18,3,122,28,80,97,116,104, ++ 70,105,110,100,101,114,46,105,110,118,97,108,105,100,97,116, ++ 101,95,99,97,99,104,101,115,99,1,0,0,0,0,0,0, ++ 0,0,0,0,0,2,0,0,0,9,0,0,0,67,0,0, ++ 0,115,76,0,0,0,116,0,106,1,100,1,117,1,114,14, ++ 116,0,106,1,115,14,116,2,160,3,100,2,116,4,161,2, ++ 1,0,116,0,106,1,68,0,93,18,125,1,122,7,124,1, ++ 124,0,131,1,87,0,2,0,1,0,83,0,4,0,116,5, ++ 121,35,1,0,1,0,1,0,89,0,113,17,119,0,100,1, ++ 83,0,41,3,122,46,83,101,97,114,99,104,32,115,121,115, ++ 46,112,97,116,104,95,104,111,111,107,115,32,102,111,114,32, ++ 97,32,102,105,110,100,101,114,32,102,111,114,32,39,112,97, ++ 116,104,39,46,78,122,23,115,121,115,46,112,97,116,104,95, ++ 104,111,111,107,115,32,105,115,32,101,109,112,116,121,41,6, ++ 114,18,0,0,0,218,10,112,97,116,104,95,104,111,111,107, ++ 115,114,102,0,0,0,114,103,0,0,0,114,165,0,0,0, ++ 114,145,0,0,0,41,2,114,68,0,0,0,90,4,104,111, ++ 111,107,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,218,11,95,112,97,116,104,95,104,111,111,107,115,63,5, ++ 0,0,115,18,0,0,0,16,3,12,1,10,1,2,1,14, ++ 1,12,1,4,1,2,255,4,3,122,22,80,97,116,104,70, ++ 105,110,100,101,114,46,95,112,97,116,104,95,104,111,111,107, ++ 115,99,2,0,0,0,0,0,0,0,0,0,0,0,3,0, ++ 0,0,8,0,0,0,67,0,0,0,115,100,0,0,0,124, ++ 1,100,1,107,2,114,21,122,6,116,0,160,1,161,0,125, ++ 1,87,0,110,10,4,0,116,2,121,20,1,0,1,0,1, ++ 0,89,0,100,2,83,0,119,0,122,8,116,3,106,4,124, ++ 1,25,0,125,2,87,0,124,2,83,0,4,0,116,5,121, ++ 49,1,0,1,0,1,0,124,0,160,6,124,1,161,1,125, ++ 2,124,2,116,3,106,4,124,1,60,0,89,0,124,2,83, ++ 0,119,0,41,3,122,210,71,101,116,32,116,104,101,32,102, ++ 105,110,100,101,114,32,102,111,114,32,116,104,101,32,112,97, ++ 116,104,32,101,110,116,114,121,32,102,114,111,109,32,115,121, ++ 115,46,112,97,116,104,95,105,109,112,111,114,116,101,114,95, ++ 99,97,99,104,101,46,10,10,32,32,32,32,32,32,32,32, ++ 73,102,32,116,104,101,32,112,97,116,104,32,101,110,116,114, ++ 121,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32, ++ 99,97,99,104,101,44,32,102,105,110,100,32,116,104,101,32, ++ 97,112,112,114,111,112,114,105,97,116,101,32,102,105,110,100, ++ 101,114,10,32,32,32,32,32,32,32,32,97,110,100,32,99, ++ 97,99,104,101,32,105,116,46,32,73,102,32,110,111,32,102, ++ 105,110,100,101,114,32,105,115,32,97,118,97,105,108,97,98, ++ 108,101,44,32,115,116,111,114,101,32,78,111,110,101,46,10, ++ 10,32,32,32,32,32,32,32,32,114,10,0,0,0,78,41, ++ 7,114,21,0,0,0,114,85,0,0,0,218,17,70,105,108, ++ 101,78,111,116,70,111,117,110,100,69,114,114,111,114,114,18, ++ 0,0,0,114,87,1,0,0,218,8,75,101,121,69,114,114, ++ 111,114,114,91,1,0,0,41,3,114,224,0,0,0,114,68, ++ 0,0,0,114,89,1,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,20,95,112,97,116,104,95,105, ++ 109,112,111,114,116,101,114,95,99,97,99,104,101,76,5,0, ++ 0,115,28,0,0,0,8,8,2,1,12,1,12,1,6,3, ++ 2,253,2,4,12,1,4,4,12,253,10,1,12,1,4,1, ++ 2,253,122,31,80,97,116,104,70,105,110,100,101,114,46,95, ++ 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, ++ 99,104,101,99,3,0,0,0,0,0,0,0,0,0,0,0, ++ 7,0,0,0,4,0,0,0,67,0,0,0,115,138,0,0, ++ 0,116,0,124,2,100,1,131,2,114,27,116,1,160,2,124, ++ 2,161,1,155,0,100,2,157,2,125,3,116,3,160,4,124, ++ 3,116,5,161,2,1,0,124,2,160,6,124,1,161,1,92, ++ 2,125,4,125,5,110,21,116,1,160,2,124,2,161,1,155, ++ 0,100,3,157,2,125,3,116,3,160,4,124,3,116,5,161, ++ 2,1,0,124,2,160,7,124,1,161,1,125,4,103,0,125, ++ 5,124,4,100,0,117,1,114,58,116,1,160,8,124,1,124, ++ 4,161,2,83,0,116,1,160,9,124,1,100,0,161,2,125, ++ 6,124,5,124,6,95,10,124,6,83,0,41,4,78,114,164, ++ 0,0,0,122,53,46,102,105,110,100,95,115,112,101,99,40, ++ 41,32,110,111,116,32,102,111,117,110,100,59,32,102,97,108, ++ 108,105,110,103,32,98,97,99,107,32,116,111,32,102,105,110, ++ 100,95,108,111,97,100,101,114,40,41,122,53,46,102,105,110, ++ 100,95,115,112,101,99,40,41,32,110,111,116,32,102,111,117, ++ 110,100,59,32,102,97,108,108,105,110,103,32,98,97,99,107, ++ 32,116,111,32,102,105,110,100,95,109,111,100,117,108,101,40, ++ 41,41,11,114,156,0,0,0,114,162,0,0,0,90,12,95, ++ 111,98,106,101,99,116,95,110,97,109,101,114,102,0,0,0, ++ 114,103,0,0,0,114,165,0,0,0,114,164,0,0,0,114, ++ 232,0,0,0,114,227,0,0,0,114,210,0,0,0,114,205, ++ 0,0,0,41,7,114,224,0,0,0,114,166,0,0,0,114, ++ 89,1,0,0,114,169,0,0,0,114,167,0,0,0,114,168, ++ 0,0,0,114,213,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,218,16,95,108,101,103,97,99,121, ++ 95,103,101,116,95,115,112,101,99,98,5,0,0,115,26,0, ++ 0,0,10,4,16,1,12,2,16,1,16,2,12,2,10,1, ++ 4,1,8,1,12,1,12,1,6,1,4,1,122,27,80,97, ++ 116,104,70,105,110,100,101,114,46,95,108,101,103,97,99,121, ++ 95,103,101,116,95,115,112,101,99,78,99,4,0,0,0,0, ++ 0,0,0,0,0,0,0,9,0,0,0,5,0,0,0,67, ++ 0,0,0,115,166,0,0,0,103,0,125,4,124,2,68,0, ++ 93,67,125,5,116,0,124,5,116,1,116,2,102,2,131,2, ++ 115,14,113,4,124,0,160,3,124,5,161,1,125,6,124,6, ++ 100,1,117,1,114,71,116,4,124,6,100,2,131,2,114,35, ++ 124,6,160,5,124,1,124,3,161,2,125,7,110,6,124,0, ++ 160,6,124,1,124,6,161,2,125,7,124,7,100,1,117,0, ++ 114,46,113,4,124,7,106,7,100,1,117,1,114,55,124,7, ++ 2,0,1,0,83,0,124,7,106,8,125,8,124,8,100,1, ++ 117,0,114,66,116,9,100,3,131,1,130,1,124,4,160,10, ++ 124,8,161,1,1,0,113,4,116,11,160,12,124,1,100,1, ++ 161,2,125,7,124,4,124,7,95,8,124,7,83,0,41,4, ++ 122,63,70,105,110,100,32,116,104,101,32,108,111,97,100,101, ++ 114,32,111,114,32,110,97,109,101,115,112,97,99,101,95,112, ++ 97,116,104,32,102,111,114,32,116,104,105,115,32,109,111,100, ++ 117,108,101,47,112,97,99,107,97,103,101,32,110,97,109,101, ++ 46,78,114,229,0,0,0,122,19,115,112,101,99,32,109,105, ++ 115,115,105,110,103,32,108,111,97,100,101,114,41,13,114,188, ++ 0,0,0,114,112,0,0,0,218,5,98,121,116,101,115,114, ++ 94,1,0,0,114,156,0,0,0,114,229,0,0,0,114,95, ++ 1,0,0,114,167,0,0,0,114,205,0,0,0,114,145,0, ++ 0,0,114,194,0,0,0,114,162,0,0,0,114,210,0,0, ++ 0,41,9,114,224,0,0,0,114,166,0,0,0,114,68,0, ++ 0,0,114,228,0,0,0,218,14,110,97,109,101,115,112,97, ++ 99,101,95,112,97,116,104,90,5,101,110,116,114,121,114,89, ++ 1,0,0,114,213,0,0,0,114,168,0,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,218,9,95,103, ++ 101,116,95,115,112,101,99,119,5,0,0,115,42,0,0,0, ++ 4,5,8,1,14,1,2,1,10,1,8,1,10,1,14,1, ++ 12,2,8,1,2,1,10,1,8,1,6,1,8,1,8,1, ++ 10,5,2,128,12,2,6,1,4,1,122,20,80,97,116,104, ++ 70,105,110,100,101,114,46,95,103,101,116,95,115,112,101,99, ++ 99,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0, ++ 0,5,0,0,0,67,0,0,0,115,94,0,0,0,124,2, ++ 100,1,117,0,114,7,116,0,106,1,125,2,124,0,160,2, ++ 124,1,124,2,124,3,161,3,125,4,124,4,100,1,117,0, ++ 114,20,100,1,83,0,124,4,106,3,100,1,117,0,114,45, ++ 124,4,106,4,125,5,124,5,114,43,100,1,124,4,95,5, ++ 116,6,124,1,124,5,124,0,106,2,131,3,124,4,95,4, ++ 124,4,83,0,100,1,83,0,124,4,83,0,41,2,122,141, ++ 84,114,121,32,116,111,32,102,105,110,100,32,97,32,115,112, ++ 101,99,32,102,111,114,32,39,102,117,108,108,110,97,109,101, ++ 39,32,111,110,32,115,121,115,46,112,97,116,104,32,111,114, ++ 32,39,112,97,116,104,39,46,10,10,32,32,32,32,32,32, ++ 32,32,84,104,101,32,115,101,97,114,99,104,32,105,115,32, ++ 98,97,115,101,100,32,111,110,32,115,121,115,46,112,97,116, ++ 104,95,104,111,111,107,115,32,97,110,100,32,115,121,115,46, ++ 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, ++ 99,104,101,46,10,32,32,32,32,32,32,32,32,78,41,7, ++ 114,18,0,0,0,114,68,0,0,0,114,98,1,0,0,114, ++ 167,0,0,0,114,205,0,0,0,114,208,0,0,0,114,52, ++ 1,0,0,41,6,114,224,0,0,0,114,166,0,0,0,114, ++ 68,0,0,0,114,228,0,0,0,114,213,0,0,0,114,97, ++ 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,114,229,0,0,0,151,5,0,0,115,26,0,0,0, ++ 8,6,6,1,14,1,8,1,4,1,10,1,6,1,4,1, ++ 6,3,16,1,4,1,4,2,4,2,122,20,80,97,116,104, ++ 70,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, ++ 99,3,0,0,0,0,0,0,0,0,0,0,0,4,0,0, ++ 0,4,0,0,0,67,0,0,0,115,42,0,0,0,116,0, ++ 160,1,100,1,116,2,161,2,1,0,124,0,160,3,124,1, ++ 124,2,161,2,125,3,124,3,100,2,117,0,114,18,100,2, ++ 83,0,124,3,106,4,83,0,41,3,122,170,102,105,110,100, ++ 32,116,104,101,32,109,111,100,117,108,101,32,111,110,32,115, ++ 121,115,46,112,97,116,104,32,111,114,32,39,112,97,116,104, ++ 39,32,98,97,115,101,100,32,111,110,32,115,121,115,46,112, ++ 97,116,104,95,104,111,111,107,115,32,97,110,100,10,32,32, ++ 32,32,32,32,32,32,115,121,115,46,112,97,116,104,95,105, ++ 109,112,111,114,116,101,114,95,99,97,99,104,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, +- 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, +- 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, +- 32,32,32,32,32,32,32,32,122,38,110,97,109,101,115,112, +- 97,99,101,32,109,111,100,117,108,101,32,108,111,97,100,101, +- 100,32,119,105,116,104,32,112,97,116,104,32,123,33,114,125, +- 41,4,114,159,0,0,0,114,173,0,0,0,114,49,1,0, +- 0,114,246,0,0,0,114,247,0,0,0,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,114,248,0,0,0,27, +- 5,0,0,115,8,0,0,0,6,7,4,1,4,255,12,3, +- 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, +- 101,114,46,108,111,97,100,95,109,111,100,117,108,101,99,2, +- 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, +- 0,0,0,67,0,0,0,115,22,0,0,0,100,1,100,2, +- 108,0,109,1,125,2,1,0,124,2,124,0,106,2,131,1, +- 83,0,41,3,78,114,0,0,0,0,41,1,218,15,78,97, +- 109,101,115,112,97,99,101,82,101,97,100,101,114,41,3,114, +- 32,1,0,0,114,78,1,0,0,114,49,1,0,0,41,3, +- 114,143,0,0,0,114,244,0,0,0,114,78,1,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,33, +- 1,0,0,39,5,0,0,115,4,0,0,0,12,1,10,1, +- 122,36,95,78,97,109,101,115,112,97,99,101,76,111,97,100, +- 101,114,46,103,101,116,95,114,101,115,111,117,114,99,101,95, +- 114,101,97,100,101,114,78,41,13,114,150,0,0,0,114,149, +- 0,0,0,114,151,0,0,0,114,236,0,0,0,114,233,0, +- 0,0,114,76,1,0,0,114,206,0,0,0,114,1,1,0, +- 0,114,241,0,0,0,114,239,0,0,0,114,245,0,0,0, +- 114,248,0,0,0,114,33,1,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,75, +- 1,0,0,253,4,0,0,115,22,0,0,0,8,0,8,1, +- 2,3,10,1,8,10,8,3,8,3,8,3,8,3,8,3, +- 12,12,114,75,1,0,0,99,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,4,0,0,0,64,0,0,0, +- 115,118,0,0,0,101,0,90,1,100,0,90,2,100,1,90, +- 3,101,4,100,2,100,3,132,0,131,1,90,5,101,4,100, +- 4,100,5,132,0,131,1,90,6,101,7,100,6,100,7,132, +- 0,131,1,90,8,101,7,100,8,100,9,132,0,131,1,90, +- 9,101,7,100,19,100,11,100,12,132,1,131,1,90,10,101, +- 7,100,20,100,13,100,14,132,1,131,1,90,11,101,7,100, +- 19,100,15,100,16,132,1,131,1,90,12,101,4,100,17,100, +- 18,132,0,131,1,90,13,100,10,83,0,41,21,218,10,80, +- 97,116,104,70,105,110,100,101,114,122,62,77,101,116,97,32, +- 112,97,116,104,32,102,105,110,100,101,114,32,102,111,114,32, +- 115,121,115,46,112,97,116,104,32,97,110,100,32,112,97,99, +- 107,97,103,101,32,95,95,112,97,116,104,95,95,32,97,116, +- 116,114,105,98,117,116,101,115,46,99,0,0,0,0,0,0, +- 0,0,0,0,0,0,2,0,0,0,4,0,0,0,67,0, +- 0,0,115,78,0,0,0,116,0,116,1,106,2,160,3,161, +- 0,131,1,68,0,93,22,92,2,125,0,125,1,124,1,100, +- 1,117,0,114,20,116,1,106,2,124,0,61,0,113,7,116, +- 4,124,1,100,2,131,2,114,29,124,1,160,5,161,0,1, +- 0,113,7,116,6,4,0,106,7,100,3,55,0,2,0,95, +- 7,100,1,83,0,41,4,122,125,67,97,108,108,32,116,104, +- 101,32,105,110,118,97,108,105,100,97,116,101,95,99,97,99, +- 104,101,115,40,41,32,109,101,116,104,111,100,32,111,110,32, +- 97,108,108,32,112,97,116,104,32,101,110,116,114,121,32,102, +- 105,110,100,101,114,115,10,32,32,32,32,32,32,32,32,115, +- 116,111,114,101,100,32,105,110,32,115,121,115,46,112,97,116, +- 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, +- 115,32,40,119,104,101,114,101,32,105,109,112,108,101,109,101, +- 110,116,101,100,41,46,78,218,17,105,110,118,97,108,105,100, +- 97,116,101,95,99,97,99,104,101,115,114,3,0,0,0,41, +- 8,218,4,108,105,115,116,114,15,0,0,0,218,19,112,97, +- 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, +- 101,218,5,105,116,101,109,115,114,153,0,0,0,114,80,1, +- 0,0,114,47,1,0,0,114,52,1,0,0,41,2,114,141, +- 0,0,0,218,6,102,105,110,100,101,114,114,7,0,0,0, +- 114,7,0,0,0,114,8,0,0,0,114,80,1,0,0,50, +- 5,0,0,115,14,0,0,0,22,4,8,1,10,1,10,1, +- 8,1,2,128,18,3,122,28,80,97,116,104,70,105,110,100, +- 101,114,46,105,110,118,97,108,105,100,97,116,101,95,99,97, +- 99,104,101,115,99,1,0,0,0,0,0,0,0,0,0,0, +- 0,2,0,0,0,9,0,0,0,67,0,0,0,115,76,0, +- 0,0,116,0,106,1,100,1,117,1,114,14,116,0,106,1, +- 115,14,116,2,160,3,100,2,116,4,161,2,1,0,116,0, +- 106,1,68,0,93,18,125,1,122,7,124,1,124,0,131,1, +- 87,0,2,0,1,0,83,0,4,0,116,5,121,35,1,0, +- 1,0,1,0,89,0,113,17,119,0,100,1,83,0,41,3, +- 122,46,83,101,97,114,99,104,32,115,121,115,46,112,97,116, +- 104,95,104,111,111,107,115,32,102,111,114,32,97,32,102,105, +- 110,100,101,114,32,102,111,114,32,39,112,97,116,104,39,46, +- 78,122,23,115,121,115,46,112,97,116,104,95,104,111,111,107, +- 115,32,105,115,32,101,109,112,116,121,41,6,114,15,0,0, +- 0,218,10,112,97,116,104,95,104,111,111,107,115,114,99,0, +- 0,0,114,100,0,0,0,114,162,0,0,0,114,142,0,0, +- 0,41,2,114,65,0,0,0,90,4,104,111,111,107,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,218,11,95, +- 112,97,116,104,95,104,111,111,107,115,63,5,0,0,115,18, +- 0,0,0,16,3,12,1,10,1,2,1,14,1,12,1,4, +- 1,2,255,4,3,122,22,80,97,116,104,70,105,110,100,101, +- 114,46,95,112,97,116,104,95,104,111,111,107,115,99,2,0, +- 0,0,0,0,0,0,0,0,0,0,3,0,0,0,8,0, +- 0,0,67,0,0,0,115,100,0,0,0,124,1,100,1,107, +- 2,114,21,122,6,116,0,160,1,161,0,125,1,87,0,110, +- 10,4,0,116,2,121,20,1,0,1,0,1,0,89,0,100, +- 2,83,0,119,0,122,8,116,3,106,4,124,1,25,0,125, +- 2,87,0,124,2,83,0,4,0,116,5,121,49,1,0,1, +- 0,1,0,124,0,160,6,124,1,161,1,125,2,124,2,116, +- 3,106,4,124,1,60,0,89,0,124,2,83,0,119,0,41, +- 3,122,210,71,101,116,32,116,104,101,32,102,105,110,100,101, +- 114,32,102,111,114,32,116,104,101,32,112,97,116,104,32,101, +- 110,116,114,121,32,102,114,111,109,32,115,121,115,46,112,97, +- 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, +- 101,46,10,10,32,32,32,32,32,32,32,32,73,102,32,116, +- 104,101,32,112,97,116,104,32,101,110,116,114,121,32,105,115, +- 32,110,111,116,32,105,110,32,116,104,101,32,99,97,99,104, +- 101,44,32,102,105,110,100,32,116,104,101,32,97,112,112,114, +- 111,112,114,105,97,116,101,32,102,105,110,100,101,114,10,32, +- 32,32,32,32,32,32,32,97,110,100,32,99,97,99,104,101, +- 32,105,116,46,32,73,102,32,110,111,32,102,105,110,100,101, +- 114,32,105,115,32,97,118,97,105,108,97,98,108,101,44,32, +- 115,116,111,114,101,32,78,111,110,101,46,10,10,32,32,32, +- 32,32,32,32,32,114,10,0,0,0,78,41,7,114,18,0, +- 0,0,114,82,0,0,0,218,17,70,105,108,101,78,111,116, +- 70,111,117,110,100,69,114,114,111,114,114,15,0,0,0,114, +- 82,1,0,0,218,8,75,101,121,69,114,114,111,114,114,86, +- 1,0,0,41,3,114,221,0,0,0,114,65,0,0,0,114, +- 84,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,20,95,112,97,116,104,95,105,109,112,111,114, +- 116,101,114,95,99,97,99,104,101,76,5,0,0,115,28,0, +- 0,0,8,8,2,1,12,1,12,1,6,3,2,253,2,4, +- 12,1,4,4,12,253,10,1,12,1,4,1,2,253,122,31, +- 80,97,116,104,70,105,110,100,101,114,46,95,112,97,116,104, +- 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,99, +- 3,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, +- 4,0,0,0,67,0,0,0,115,138,0,0,0,116,0,124, +- 2,100,1,131,2,114,27,116,1,160,2,124,2,161,1,155, +- 0,100,2,157,2,125,3,116,3,160,4,124,3,116,5,161, +- 2,1,0,124,2,160,6,124,1,161,1,92,2,125,4,125, +- 5,110,21,116,1,160,2,124,2,161,1,155,0,100,3,157, +- 2,125,3,116,3,160,4,124,3,116,5,161,2,1,0,124, +- 2,160,7,124,1,161,1,125,4,103,0,125,5,124,4,100, +- 0,117,1,114,58,116,1,160,8,124,1,124,4,161,2,83, +- 0,116,1,160,9,124,1,100,0,161,2,125,6,124,5,124, +- 6,95,10,124,6,83,0,41,4,78,114,161,0,0,0,122, +- 53,46,102,105,110,100,95,115,112,101,99,40,41,32,110,111, +- 116,32,102,111,117,110,100,59,32,102,97,108,108,105,110,103, +- 32,98,97,99,107,32,116,111,32,102,105,110,100,95,108,111, +- 97,100,101,114,40,41,122,53,46,102,105,110,100,95,115,112, +- 101,99,40,41,32,110,111,116,32,102,111,117,110,100,59,32, +- 102,97,108,108,105,110,103,32,98,97,99,107,32,116,111,32, +- 102,105,110,100,95,109,111,100,117,108,101,40,41,41,11,114, +- 153,0,0,0,114,159,0,0,0,90,12,95,111,98,106,101, +- 99,116,95,110,97,109,101,114,99,0,0,0,114,100,0,0, +- 0,114,162,0,0,0,114,161,0,0,0,114,229,0,0,0, +- 114,224,0,0,0,114,207,0,0,0,114,202,0,0,0,41, +- 7,114,221,0,0,0,114,163,0,0,0,114,84,1,0,0, +- 114,166,0,0,0,114,164,0,0,0,114,165,0,0,0,114, +- 210,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,218,16,95,108,101,103,97,99,121,95,103,101,116, +- 95,115,112,101,99,98,5,0,0,115,26,0,0,0,10,4, +- 16,1,12,2,16,1,16,2,12,2,10,1,4,1,8,1, +- 12,1,12,1,6,1,4,1,122,27,80,97,116,104,70,105, +- 110,100,101,114,46,95,108,101,103,97,99,121,95,103,101,116, +- 95,115,112,101,99,78,99,4,0,0,0,0,0,0,0,0, +- 0,0,0,9,0,0,0,5,0,0,0,67,0,0,0,115, +- 166,0,0,0,103,0,125,4,124,2,68,0,93,67,125,5, +- 116,0,124,5,116,1,116,2,102,2,131,2,115,14,113,4, +- 124,0,160,3,124,5,161,1,125,6,124,6,100,1,117,1, +- 114,71,116,4,124,6,100,2,131,2,114,35,124,6,160,5, +- 124,1,124,3,161,2,125,7,110,6,124,0,160,6,124,1, +- 124,6,161,2,125,7,124,7,100,1,117,0,114,46,113,4, +- 124,7,106,7,100,1,117,1,114,55,124,7,2,0,1,0, +- 83,0,124,7,106,8,125,8,124,8,100,1,117,0,114,66, +- 116,9,100,3,131,1,130,1,124,4,160,10,124,8,161,1, +- 1,0,113,4,116,11,160,12,124,1,100,1,161,2,125,7, +- 124,4,124,7,95,8,124,7,83,0,41,4,122,63,70,105, +- 110,100,32,116,104,101,32,108,111,97,100,101,114,32,111,114, +- 32,110,97,109,101,115,112,97,99,101,95,112,97,116,104,32, +- 102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,47, +- 112,97,99,107,97,103,101,32,110,97,109,101,46,78,114,226, +- 0,0,0,122,19,115,112,101,99,32,109,105,115,115,105,110, +- 103,32,108,111,97,100,101,114,41,13,114,185,0,0,0,114, +- 109,0,0,0,218,5,98,121,116,101,115,114,89,1,0,0, +- 114,153,0,0,0,114,226,0,0,0,114,90,1,0,0,114, +- 164,0,0,0,114,202,0,0,0,114,142,0,0,0,114,191, +- 0,0,0,114,159,0,0,0,114,207,0,0,0,41,9,114, +- 221,0,0,0,114,163,0,0,0,114,65,0,0,0,114,225, +- 0,0,0,218,14,110,97,109,101,115,112,97,99,101,95,112, +- 97,116,104,90,5,101,110,116,114,121,114,84,1,0,0,114, +- 210,0,0,0,114,165,0,0,0,114,7,0,0,0,114,7, +- 0,0,0,114,8,0,0,0,218,9,95,103,101,116,95,115, +- 112,101,99,119,5,0,0,115,42,0,0,0,4,5,8,1, +- 14,1,2,1,10,1,8,1,10,1,14,1,12,2,8,1, +- 2,1,10,1,8,1,6,1,8,1,8,1,10,5,2,128, +- 12,2,6,1,4,1,122,20,80,97,116,104,70,105,110,100, +- 101,114,46,95,103,101,116,95,115,112,101,99,99,4,0,0, +- 0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0, +- 0,67,0,0,0,115,94,0,0,0,124,2,100,1,117,0, +- 114,7,116,0,106,1,125,2,124,0,160,2,124,1,124,2, +- 124,3,161,3,125,4,124,4,100,1,117,0,114,20,100,1, +- 83,0,124,4,106,3,100,1,117,0,114,45,124,4,106,4, +- 125,5,124,5,114,43,100,1,124,4,95,5,116,6,124,1, +- 124,5,124,0,106,2,131,3,124,4,95,4,124,4,83,0, +- 100,1,83,0,124,4,83,0,41,2,122,141,84,114,121,32, +- 116,111,32,102,105,110,100,32,97,32,115,112,101,99,32,102, +- 111,114,32,39,102,117,108,108,110,97,109,101,39,32,111,110, +- 32,115,121,115,46,112,97,116,104,32,111,114,32,39,112,97, +- 116,104,39,46,10,10,32,32,32,32,32,32,32,32,84,104, +- 101,32,115,101,97,114,99,104,32,105,115,32,98,97,115,101, +- 100,32,111,110,32,115,121,115,46,112,97,116,104,95,104,111, +- 111,107,115,32,97,110,100,32,115,121,115,46,112,97,116,104, +- 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,46, +- 10,32,32,32,32,32,32,32,32,78,41,7,114,15,0,0, +- 0,114,65,0,0,0,114,93,1,0,0,114,164,0,0,0, +- 114,202,0,0,0,114,205,0,0,0,114,47,1,0,0,41, +- 6,114,221,0,0,0,114,163,0,0,0,114,65,0,0,0, +- 114,225,0,0,0,114,210,0,0,0,114,92,1,0,0,114, +- 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,226, +- 0,0,0,151,5,0,0,115,26,0,0,0,8,6,6,1, +- 14,1,8,1,4,1,10,1,6,1,4,1,6,3,16,1, +- 4,1,4,2,4,2,122,20,80,97,116,104,70,105,110,100, +- 101,114,46,102,105,110,100,95,115,112,101,99,99,3,0,0, +- 0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0, +- 0,67,0,0,0,115,42,0,0,0,116,0,160,1,100,1, +- 116,2,161,2,1,0,124,0,160,3,124,1,124,2,161,2, +- 125,3,124,3,100,2,117,0,114,18,100,2,83,0,124,3, +- 106,4,83,0,41,3,122,170,102,105,110,100,32,116,104,101, +- 32,109,111,100,117,108,101,32,111,110,32,115,121,115,46,112, +- 97,116,104,32,111,114,32,39,112,97,116,104,39,32,98,97, +- 115,101,100,32,111,110,32,115,121,115,46,112,97,116,104,95, +- 104,111,111,107,115,32,97,110,100,10,32,32,32,32,32,32, +- 32,32,115,121,115,46,112,97,116,104,95,105,109,112,111,114, +- 116,101,114,95,99,97,99,104,101,46,10,10,32,32,32,32, ++ 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, ++ 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, ++ 32,32,32,32,32,32,122,101,80,97,116,104,70,105,110,100, ++ 101,114,46,102,105,110,100,95,109,111,100,117,108,101,40,41, ++ 32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97, ++ 110,100,32,115,108,97,116,101,100,32,102,111,114,32,114,101, ++ 109,111,118,97,108,32,105,110,32,80,121,116,104,111,110,32, ++ 51,46,49,50,59,32,117,115,101,32,102,105,110,100,95,115, ++ 112,101,99,40,41,32,105,110,115,116,101,97,100,78,114,230, ++ 0,0,0,114,231,0,0,0,114,7,0,0,0,114,7,0, ++ 0,0,114,8,0,0,0,114,232,0,0,0,175,5,0,0, ++ 115,14,0,0,0,6,8,2,2,4,254,12,3,8,1,4, ++ 1,6,1,122,22,80,97,116,104,70,105,110,100,101,114,46, ++ 102,105,110,100,95,109,111,100,117,108,101,99,0,0,0,0, ++ 0,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0, ++ 79,0,0,0,115,28,0,0,0,100,1,100,2,108,0,109, ++ 1,125,2,1,0,124,2,106,2,124,0,105,0,124,1,164, ++ 1,142,1,83,0,41,3,97,32,1,0,0,10,32,32,32, ++ 32,32,32,32,32,70,105,110,100,32,100,105,115,116,114,105, ++ 98,117,116,105,111,110,115,46,10,10,32,32,32,32,32,32, ++ 32,32,82,101,116,117,114,110,32,97,110,32,105,116,101,114, ++ 97,98,108,101,32,111,102,32,97,108,108,32,68,105,115,116, ++ 114,105,98,117,116,105,111,110,32,105,110,115,116,97,110,99, ++ 101,115,32,99,97,112,97,98,108,101,32,111,102,10,32,32, ++ 32,32,32,32,32,32,108,111,97,100,105,110,103,32,116,104, ++ 101,32,109,101,116,97,100,97,116,97,32,102,111,114,32,112, ++ 97,99,107,97,103,101,115,32,109,97,116,99,104,105,110,103, ++ 32,96,96,99,111,110,116,101,120,116,46,110,97,109,101,96, ++ 96,10,32,32,32,32,32,32,32,32,40,111,114,32,97,108, ++ 108,32,110,97,109,101,115,32,105,102,32,96,96,78,111,110, ++ 101,96,96,32,105,110,100,105,99,97,116,101,100,41,32,97, ++ 108,111,110,103,32,116,104,101,32,112,97,116,104,115,32,105, ++ 110,32,116,104,101,32,108,105,115,116,10,32,32,32,32,32, ++ 32,32,32,111,102,32,100,105,114,101,99,116,111,114,105,101, ++ 115,32,96,96,99,111,110,116,101,120,116,46,112,97,116,104, ++ 96,96,46,10,32,32,32,32,32,32,32,32,114,0,0,0, ++ 0,41,1,218,18,77,101,116,97,100,97,116,97,80,97,116, ++ 104,70,105,110,100,101,114,41,3,90,18,105,109,112,111,114, ++ 116,108,105,98,46,109,101,116,97,100,97,116,97,114,99,1, ++ 0,0,218,18,102,105,110,100,95,100,105,115,116,114,105,98, ++ 117,116,105,111,110,115,41,3,114,147,0,0,0,114,148,0, ++ 0,0,114,99,1,0,0,114,7,0,0,0,114,7,0,0, ++ 0,114,8,0,0,0,114,100,1,0,0,191,5,0,0,115, ++ 4,0,0,0,12,10,16,1,122,29,80,97,116,104,70,105, ++ 110,100,101,114,46,102,105,110,100,95,100,105,115,116,114,105, ++ 98,117,116,105,111,110,115,114,72,0,0,0,114,233,0,0, ++ 0,41,14,114,153,0,0,0,114,152,0,0,0,114,154,0, ++ 0,0,114,155,0,0,0,114,236,0,0,0,114,85,1,0, ++ 0,114,91,1,0,0,114,237,0,0,0,114,94,1,0,0, ++ 114,95,1,0,0,114,98,1,0,0,114,229,0,0,0,114, ++ 232,0,0,0,114,100,1,0,0,114,7,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,114,84,1, ++ 0,0,46,5,0,0,115,36,0,0,0,8,0,4,2,2, ++ 2,10,1,2,12,10,1,2,12,10,1,2,21,10,1,2, ++ 20,12,1,2,31,12,1,2,23,12,1,2,15,14,1,114, ++ 84,1,0,0,99,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,3,0,0,0,64,0,0,0,115,90,0, ++ 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, ++ 100,3,132,0,90,4,100,4,100,5,132,0,90,5,101,6, ++ 90,7,100,6,100,7,132,0,90,8,100,8,100,9,132,0, ++ 90,9,100,19,100,11,100,12,132,1,90,10,100,13,100,14, ++ 132,0,90,11,101,12,100,15,100,16,132,0,131,1,90,13, ++ 100,17,100,18,132,0,90,14,100,10,83,0,41,20,218,10, ++ 70,105,108,101,70,105,110,100,101,114,122,172,70,105,108,101, ++ 45,98,97,115,101,100,32,102,105,110,100,101,114,46,10,10, ++ 32,32,32,32,73,110,116,101,114,97,99,116,105,111,110,115, ++ 32,119,105,116,104,32,116,104,101,32,102,105,108,101,32,115, ++ 121,115,116,101,109,32,97,114,101,32,99,97,99,104,101,100, ++ 32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101, ++ 44,32,98,101,105,110,103,10,32,32,32,32,114,101,102,114, ++ 101,115,104,101,100,32,119,104,101,110,32,116,104,101,32,100, ++ 105,114,101,99,116,111,114,121,32,116,104,101,32,102,105,110, ++ 100,101,114,32,105,115,32,104,97,110,100,108,105,110,103,32, ++ 104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101, ++ 100,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, ++ 0,0,0,0,0,5,0,0,0,6,0,0,0,7,0,0, ++ 0,115,112,0,0,0,103,0,125,3,124,2,68,0,93,16, ++ 92,2,137,0,125,4,124,3,160,0,135,0,102,1,100,1, ++ 100,2,132,8,124,4,68,0,131,1,161,1,1,0,113,4, ++ 124,3,124,0,95,1,124,1,112,27,100,3,124,0,95,2, ++ 116,3,124,0,106,2,131,1,115,43,116,4,116,5,160,6, ++ 161,0,124,0,106,2,131,2,124,0,95,2,100,4,124,0, ++ 95,7,116,8,131,0,124,0,95,9,116,8,131,0,124,0, ++ 95,10,100,5,83,0,41,6,122,154,73,110,105,116,105,97, ++ 108,105,122,101,32,119,105,116,104,32,116,104,101,32,112,97, ++ 116,104,32,116,111,32,115,101,97,114,99,104,32,111,110,32, ++ 97,110,100,32,97,32,118,97,114,105,97,98,108,101,32,110, ++ 117,109,98,101,114,32,111,102,10,32,32,32,32,32,32,32, ++ 32,50,45,116,117,112,108,101,115,32,99,111,110,116,97,105, ++ 110,105,110,103,32,116,104,101,32,108,111,97,100,101,114,32, ++ 97,110,100,32,116,104,101,32,102,105,108,101,32,115,117,102, ++ 102,105,120,101,115,32,116,104,101,32,108,111,97,100,101,114, ++ 10,32,32,32,32,32,32,32,32,114,101,99,111,103,110,105, ++ 122,101,115,46,99,1,0,0,0,0,0,0,0,0,0,0, ++ 0,2,0,0,0,3,0,0,0,51,0,0,0,115,24,0, ++ 0,0,129,0,124,0,93,7,125,1,124,1,136,0,102,2, ++ 86,0,1,0,113,2,100,0,83,0,114,72,0,0,0,114, ++ 7,0,0,0,114,48,1,0,0,169,1,114,167,0,0,0, ++ 114,7,0,0,0,114,8,0,0,0,114,9,0,0,0,220, ++ 5,0,0,115,4,0,0,0,2,128,22,0,122,38,70,105, ++ 108,101,70,105,110,100,101,114,46,95,95,105,110,105,116,95, ++ 95,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101, ++ 120,112,114,62,114,100,0,0,0,114,133,0,0,0,78,41, ++ 11,114,194,0,0,0,218,8,95,108,111,97,100,101,114,115, ++ 114,68,0,0,0,114,89,0,0,0,114,70,0,0,0,114, ++ 21,0,0,0,114,85,0,0,0,218,11,95,112,97,116,104, ++ 95,109,116,105,109,101,218,3,115,101,116,218,11,95,112,97, ++ 116,104,95,99,97,99,104,101,218,19,95,114,101,108,97,120, ++ 101,100,95,112,97,116,104,95,99,97,99,104,101,41,5,114, ++ 146,0,0,0,114,68,0,0,0,218,14,108,111,97,100,101, ++ 114,95,100,101,116,97,105,108,115,90,7,108,111,97,100,101, ++ 114,115,114,215,0,0,0,114,7,0,0,0,114,102,1,0, ++ 0,114,8,0,0,0,114,239,0,0,0,214,5,0,0,115, ++ 20,0,0,0,4,4,12,1,26,1,6,1,10,2,10,1, ++ 18,1,6,1,8,1,12,1,122,19,70,105,108,101,70,105, ++ 110,100,101,114,46,95,95,105,110,105,116,95,95,99,1,0, ++ 0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0, ++ 0,0,67,0,0,0,115,10,0,0,0,100,1,124,0,95, ++ 0,100,2,83,0,41,3,122,31,73,110,118,97,108,105,100, ++ 97,116,101,32,116,104,101,32,100,105,114,101,99,116,111,114, ++ 121,32,109,116,105,109,101,46,114,133,0,0,0,78,41,1, ++ 114,104,1,0,0,114,24,1,0,0,114,7,0,0,0,114, ++ 7,0,0,0,114,8,0,0,0,114,85,1,0,0,230,5, ++ 0,0,114,84,0,0,0,122,28,70,105,108,101,70,105,110, ++ 100,101,114,46,105,110,118,97,108,105,100,97,116,101,95,99, ++ 97,99,104,101,115,99,2,0,0,0,0,0,0,0,0,0, ++ 0,0,3,0,0,0,4,0,0,0,67,0,0,0,115,54, ++ 0,0,0,116,0,160,1,100,1,116,2,161,2,1,0,124, ++ 0,160,3,124,1,161,1,125,2,124,2,100,2,117,0,114, ++ 19,100,2,103,0,102,2,83,0,124,2,106,4,124,2,106, ++ 5,112,25,103,0,102,2,83,0,41,3,122,197,84,114,121, ++ 32,116,111,32,102,105,110,100,32,97,32,108,111,97,100,101, ++ 114,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102, ++ 105,101,100,32,109,111,100,117,108,101,44,32,111,114,32,116, ++ 104,101,32,110,97,109,101,115,112,97,99,101,10,32,32,32, ++ 32,32,32,32,32,112,97,99,107,97,103,101,32,112,111,114, ++ 116,105,111,110,115,46,32,82,101,116,117,114,110,115,32,40, ++ 108,111,97,100,101,114,44,32,108,105,115,116,45,111,102,45, ++ 112,111,114,116,105,111,110,115,41,46,10,10,32,32,32,32, + 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, + 85,115,101,32,102,105,110,100,95,115,112,101,99,40,41,32, + 105,110,115,116,101,97,100,46,10,10,32,32,32,32,32,32, +- 32,32,122,101,80,97,116,104,70,105,110,100,101,114,46,102, +- 105,110,100,95,109,111,100,117,108,101,40,41,32,105,115,32, ++ 32,32,122,101,70,105,108,101,70,105,110,100,101,114,46,102, ++ 105,110,100,95,108,111,97,100,101,114,40,41,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,32,97,110,100,32,115, + 108,97,116,101,100,32,102,111,114,32,114,101,109,111,118,97, + 108,32,105,110,32,80,121,116,104,111,110,32,51,46,49,50, + 59,32,117,115,101,32,102,105,110,100,95,115,112,101,99,40, +- 41,32,105,110,115,116,101,97,100,78,114,227,0,0,0,114, +- 228,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,114,229,0,0,0,175,5,0,0,115,14,0,0, +- 0,6,8,2,2,4,254,12,3,8,1,4,1,6,1,122, +- 22,80,97,116,104,70,105,110,100,101,114,46,102,105,110,100, +- 95,109,111,100,117,108,101,99,0,0,0,0,0,0,0,0, +- 0,0,0,0,3,0,0,0,4,0,0,0,79,0,0,0, +- 115,28,0,0,0,100,1,100,2,108,0,109,1,125,2,1, +- 0,124,2,106,2,124,0,105,0,124,1,164,1,142,1,83, +- 0,41,3,97,32,1,0,0,10,32,32,32,32,32,32,32, +- 32,70,105,110,100,32,100,105,115,116,114,105,98,117,116,105, +- 111,110,115,46,10,10,32,32,32,32,32,32,32,32,82,101, +- 116,117,114,110,32,97,110,32,105,116,101,114,97,98,108,101, +- 32,111,102,32,97,108,108,32,68,105,115,116,114,105,98,117, +- 116,105,111,110,32,105,110,115,116,97,110,99,101,115,32,99, +- 97,112,97,98,108,101,32,111,102,10,32,32,32,32,32,32, +- 32,32,108,111,97,100,105,110,103,32,116,104,101,32,109,101, +- 116,97,100,97,116,97,32,102,111,114,32,112,97,99,107,97, +- 103,101,115,32,109,97,116,99,104,105,110,103,32,96,96,99, +- 111,110,116,101,120,116,46,110,97,109,101,96,96,10,32,32, +- 32,32,32,32,32,32,40,111,114,32,97,108,108,32,110,97, +- 109,101,115,32,105,102,32,96,96,78,111,110,101,96,96,32, +- 105,110,100,105,99,97,116,101,100,41,32,97,108,111,110,103, +- 32,116,104,101,32,112,97,116,104,115,32,105,110,32,116,104, +- 101,32,108,105,115,116,10,32,32,32,32,32,32,32,32,111, +- 102,32,100,105,114,101,99,116,111,114,105,101,115,32,96,96, +- 99,111,110,116,101,120,116,46,112,97,116,104,96,96,46,10, +- 32,32,32,32,32,32,32,32,114,0,0,0,0,41,1,218, +- 18,77,101,116,97,100,97,116,97,80,97,116,104,70,105,110, +- 100,101,114,41,3,90,18,105,109,112,111,114,116,108,105,98, +- 46,109,101,116,97,100,97,116,97,114,94,1,0,0,218,18, +- 102,105,110,100,95,100,105,115,116,114,105,98,117,116,105,111, +- 110,115,41,3,114,144,0,0,0,114,145,0,0,0,114,94, +- 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, +- 0,0,114,95,1,0,0,191,5,0,0,115,4,0,0,0, +- 12,10,16,1,122,29,80,97,116,104,70,105,110,100,101,114, +- 46,102,105,110,100,95,100,105,115,116,114,105,98,117,116,105, +- 111,110,115,114,69,0,0,0,114,230,0,0,0,41,14,114, +- 150,0,0,0,114,149,0,0,0,114,151,0,0,0,114,152, +- 0,0,0,114,233,0,0,0,114,80,1,0,0,114,86,1, +- 0,0,114,234,0,0,0,114,89,1,0,0,114,90,1,0, +- 0,114,93,1,0,0,114,226,0,0,0,114,229,0,0,0, +- 114,95,1,0,0,114,7,0,0,0,114,7,0,0,0,114, +- 7,0,0,0,114,8,0,0,0,114,79,1,0,0,46,5, +- 0,0,115,36,0,0,0,8,0,4,2,2,2,10,1,2, +- 12,10,1,2,12,10,1,2,21,10,1,2,20,12,1,2, +- 31,12,1,2,23,12,1,2,15,14,1,114,79,1,0,0, +- 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +- 0,3,0,0,0,64,0,0,0,115,90,0,0,0,101,0, +- 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, +- 90,4,100,4,100,5,132,0,90,5,101,6,90,7,100,6, +- 100,7,132,0,90,8,100,8,100,9,132,0,90,9,100,19, +- 100,11,100,12,132,1,90,10,100,13,100,14,132,0,90,11, +- 101,12,100,15,100,16,132,0,131,1,90,13,100,17,100,18, +- 132,0,90,14,100,10,83,0,41,20,218,10,70,105,108,101, +- 70,105,110,100,101,114,122,172,70,105,108,101,45,98,97,115, +- 101,100,32,102,105,110,100,101,114,46,10,10,32,32,32,32, +- 73,110,116,101,114,97,99,116,105,111,110,115,32,119,105,116, +- 104,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101, +- 109,32,97,114,101,32,99,97,99,104,101,100,32,102,111,114, +- 32,112,101,114,102,111,114,109,97,110,99,101,44,32,98,101, +- 105,110,103,10,32,32,32,32,114,101,102,114,101,115,104,101, +- 100,32,119,104,101,110,32,116,104,101,32,100,105,114,101,99, +- 116,111,114,121,32,116,104,101,32,102,105,110,100,101,114,32, +- 105,115,32,104,97,110,100,108,105,110,103,32,104,97,115,32, +- 98,101,101,110,32,109,111,100,105,102,105,101,100,46,10,10, +- 32,32,32,32,99,2,0,0,0,0,0,0,0,0,0,0, +- 0,5,0,0,0,6,0,0,0,7,0,0,0,115,112,0, +- 0,0,103,0,125,3,124,2,68,0,93,16,92,2,137,0, +- 125,4,124,3,160,0,135,0,102,1,100,1,100,2,132,8, +- 124,4,68,0,131,1,161,1,1,0,113,4,124,3,124,0, +- 95,1,124,1,112,27,100,3,124,0,95,2,116,3,124,0, +- 106,2,131,1,115,43,116,4,116,5,160,6,161,0,124,0, +- 106,2,131,2,124,0,95,2,100,4,124,0,95,7,116,8, +- 131,0,124,0,95,9,116,8,131,0,124,0,95,10,100,5, +- 83,0,41,6,122,154,73,110,105,116,105,97,108,105,122,101, +- 32,119,105,116,104,32,116,104,101,32,112,97,116,104,32,116, +- 111,32,115,101,97,114,99,104,32,111,110,32,97,110,100,32, +- 97,32,118,97,114,105,97,98,108,101,32,110,117,109,98,101, +- 114,32,111,102,10,32,32,32,32,32,32,32,32,50,45,116, +- 117,112,108,101,115,32,99,111,110,116,97,105,110,105,110,103, +- 32,116,104,101,32,108,111,97,100,101,114,32,97,110,100,32, +- 116,104,101,32,102,105,108,101,32,115,117,102,102,105,120,101, +- 115,32,116,104,101,32,108,111,97,100,101,114,10,32,32,32, +- 32,32,32,32,32,114,101,99,111,103,110,105,122,101,115,46, ++ 41,32,105,110,115,116,101,97,100,78,41,6,114,102,0,0, ++ 0,114,103,0,0,0,114,104,0,0,0,114,229,0,0,0, ++ 114,167,0,0,0,114,205,0,0,0,41,3,114,146,0,0, ++ 0,114,166,0,0,0,114,213,0,0,0,114,7,0,0,0, ++ 114,7,0,0,0,114,8,0,0,0,114,164,0,0,0,236, ++ 5,0,0,115,14,0,0,0,6,7,2,2,4,254,10,3, ++ 8,1,8,1,16,1,122,22,70,105,108,101,70,105,110,100, ++ 101,114,46,102,105,110,100,95,108,111,97,100,101,114,99,6, ++ 0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,6, ++ 0,0,0,67,0,0,0,115,26,0,0,0,124,1,124,2, ++ 124,3,131,2,125,6,116,0,124,2,124,3,124,6,124,4, ++ 100,1,141,4,83,0,41,2,78,114,204,0,0,0,41,1, ++ 114,216,0,0,0,41,7,114,146,0,0,0,114,214,0,0, ++ 0,114,166,0,0,0,114,68,0,0,0,90,4,115,109,115, ++ 108,114,228,0,0,0,114,167,0,0,0,114,7,0,0,0, ++ 114,7,0,0,0,114,8,0,0,0,114,98,1,0,0,251, ++ 5,0,0,115,8,0,0,0,10,1,8,1,2,1,6,255, ++ 122,20,70,105,108,101,70,105,110,100,101,114,46,95,103,101, ++ 116,95,115,112,101,99,78,99,3,0,0,0,0,0,0,0, ++ 0,0,0,0,14,0,0,0,9,0,0,0,67,0,0,0, ++ 115,122,1,0,0,100,1,125,3,124,1,160,0,100,2,161, ++ 1,100,3,25,0,125,4,122,12,116,1,124,0,106,2,112, ++ 17,116,3,160,4,161,0,131,1,106,5,125,5,87,0,110, ++ 11,4,0,116,6,121,32,1,0,1,0,1,0,100,4,125, ++ 5,89,0,110,1,119,0,124,5,124,0,106,7,107,3,114, ++ 45,124,0,160,8,161,0,1,0,124,5,124,0,95,7,116, ++ 9,131,0,114,56,124,0,106,10,125,6,124,4,160,11,161, ++ 0,125,7,110,5,124,0,106,12,125,6,124,4,125,7,124, ++ 7,124,6,118,0,114,108,116,13,124,0,106,2,124,4,131, ++ 2,125,8,124,0,106,14,68,0,93,29,92,2,125,9,125, ++ 10,100,5,124,9,23,0,125,11,116,13,124,8,124,11,131, ++ 2,125,12,116,15,124,12,131,1,114,103,124,0,160,16,124, ++ 10,124,1,124,12,124,8,103,1,124,2,161,5,2,0,1, ++ 0,83,0,113,74,116,17,124,8,131,1,125,3,124,0,106, ++ 14,68,0,93,55,92,2,125,9,125,10,122,10,116,13,124, ++ 0,106,2,124,4,124,9,23,0,131,2,125,12,87,0,110, ++ 11,4,0,116,18,121,136,1,0,1,0,1,0,89,0,1, ++ 0,100,6,83,0,119,0,116,19,106,20,100,7,124,12,100, ++ 3,100,8,141,3,1,0,124,7,124,9,23,0,124,6,118, ++ 0,114,166,116,15,124,12,131,1,114,166,124,0,160,16,124, ++ 10,124,1,124,12,100,6,124,2,161,5,2,0,1,0,83, ++ 0,113,111,124,3,114,187,116,19,160,20,100,9,124,8,161, ++ 2,1,0,116,19,160,21,124,1,100,6,161,2,125,13,124, ++ 8,103,1,124,13,95,22,124,13,83,0,100,6,83,0,41, ++ 10,122,111,84,114,121,32,116,111,32,102,105,110,100,32,97, ++ 32,115,112,101,99,32,102,111,114,32,116,104,101,32,115,112, ++ 101,99,105,102,105,101,100,32,109,111,100,117,108,101,46,10, ++ 10,32,32,32,32,32,32,32,32,82,101,116,117,114,110,115, ++ 32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,112, ++ 101,99,44,32,111,114,32,78,111,110,101,32,105,102,32,110, ++ 111,116,32,102,111,117,110,100,46,10,32,32,32,32,32,32, ++ 32,32,70,114,100,0,0,0,114,47,0,0,0,114,133,0, ++ 0,0,114,239,0,0,0,78,122,9,116,114,121,105,110,103, ++ 32,123,125,41,1,90,9,118,101,114,98,111,115,105,116,121, ++ 122,25,112,111,115,115,105,98,108,101,32,110,97,109,101,115, ++ 112,97,99,101,32,102,111,114,32,123,125,41,23,114,107,0, ++ 0,0,114,78,0,0,0,114,68,0,0,0,114,21,0,0, ++ 0,114,85,0,0,0,114,39,1,0,0,114,79,0,0,0, ++ 114,104,1,0,0,218,11,95,102,105,108,108,95,99,97,99, ++ 104,101,114,24,0,0,0,114,107,1,0,0,114,134,0,0, ++ 0,114,106,1,0,0,114,70,0,0,0,114,103,1,0,0, ++ 114,83,0,0,0,114,98,1,0,0,114,86,0,0,0,114, ++ 114,0,0,0,114,162,0,0,0,114,176,0,0,0,114,210, ++ 0,0,0,114,205,0,0,0,41,14,114,146,0,0,0,114, ++ 166,0,0,0,114,228,0,0,0,90,12,105,115,95,110,97, ++ 109,101,115,112,97,99,101,90,11,116,97,105,108,95,109,111, ++ 100,117,108,101,114,196,0,0,0,90,5,99,97,99,104,101, ++ 90,12,99,97,99,104,101,95,109,111,100,117,108,101,90,9, ++ 98,97,115,101,95,112,97,116,104,114,49,1,0,0,114,214, ++ 0,0,0,90,13,105,110,105,116,95,102,105,108,101,110,97, ++ 109,101,90,9,102,117,108,108,95,112,97,116,104,114,213,0, ++ 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,114,229,0,0,0,0,6,0,0,115,86,0,0,0,4, ++ 5,14,1,2,1,24,1,12,1,8,1,2,255,10,2,8, ++ 1,6,1,6,2,6,1,10,1,6,2,4,1,8,2,12, ++ 1,14,1,8,1,10,1,8,1,24,1,2,255,8,5,14, ++ 2,2,1,20,1,12,1,8,1,2,255,16,2,12,1,8, ++ 1,10,1,4,1,8,255,2,128,4,2,12,1,12,1,8, ++ 1,4,1,4,1,122,20,70,105,108,101,70,105,110,100,101, ++ 114,46,102,105,110,100,95,115,112,101,99,99,1,0,0,0, ++ 0,0,0,0,0,0,0,0,9,0,0,0,10,0,0,0, ++ 67,0,0,0,115,192,0,0,0,124,0,106,0,125,1,122, ++ 11,116,1,160,2,124,1,112,11,116,1,160,3,161,0,161, ++ 1,125,2,87,0,110,14,4,0,116,4,116,5,116,6,102, ++ 3,121,28,1,0,1,0,1,0,103,0,125,2,89,0,110, ++ 1,119,0,116,7,106,8,160,9,100,1,161,1,115,41,116, ++ 10,124,2,131,1,124,0,95,11,110,37,116,10,131,0,125, ++ 3,124,2,68,0,93,28,125,4,124,4,160,12,100,2,161, ++ 1,92,3,125,5,125,6,125,7,124,6,114,67,100,3,160, ++ 13,124,5,124,7,160,14,161,0,161,2,125,8,110,2,124, ++ 5,125,8,124,3,160,15,124,8,161,1,1,0,113,46,124, ++ 3,124,0,95,11,116,7,106,8,160,9,116,16,161,1,114, ++ 94,100,4,100,5,132,0,124,2,68,0,131,1,124,0,95, ++ 17,100,6,83,0,100,6,83,0,41,7,122,68,70,105,108, ++ 108,32,116,104,101,32,99,97,99,104,101,32,111,102,32,112, ++ 111,116,101,110,116,105,97,108,32,109,111,100,117,108,101,115, ++ 32,97,110,100,32,112,97,99,107,97,103,101,115,32,102,111, ++ 114,32,116,104,105,115,32,100,105,114,101,99,116,111,114,121, ++ 46,114,14,0,0,0,114,100,0,0,0,114,91,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, +- 0,3,0,0,0,51,0,0,0,115,24,0,0,0,129,0, +- 124,0,93,7,125,1,124,1,136,0,102,2,86,0,1,0, +- 113,2,100,0,83,0,114,69,0,0,0,114,7,0,0,0, +- 114,43,1,0,0,169,1,114,164,0,0,0,114,7,0,0, +- 0,114,8,0,0,0,114,9,0,0,0,220,5,0,0,115, +- 4,0,0,0,2,128,22,0,122,38,70,105,108,101,70,105, +- 110,100,101,114,46,95,95,105,110,105,116,95,95,46,60,108, +- 111,99,97,108,115,62,46,60,103,101,110,101,120,112,114,62, +- 114,97,0,0,0,114,130,0,0,0,78,41,11,114,191,0, +- 0,0,218,8,95,108,111,97,100,101,114,115,114,65,0,0, +- 0,114,86,0,0,0,114,67,0,0,0,114,18,0,0,0, +- 114,82,0,0,0,218,11,95,112,97,116,104,95,109,116,105, +- 109,101,218,3,115,101,116,218,11,95,112,97,116,104,95,99, +- 97,99,104,101,218,19,95,114,101,108,97,120,101,100,95,112, +- 97,116,104,95,99,97,99,104,101,41,5,114,143,0,0,0, +- 114,65,0,0,0,218,14,108,111,97,100,101,114,95,100,101, +- 116,97,105,108,115,90,7,108,111,97,100,101,114,115,114,212, +- 0,0,0,114,7,0,0,0,114,97,1,0,0,114,8,0, +- 0,0,114,236,0,0,0,214,5,0,0,115,20,0,0,0, +- 4,4,12,1,26,1,6,1,10,2,10,1,18,1,6,1, +- 8,1,12,1,122,19,70,105,108,101,70,105,110,100,101,114, +- 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, +- 0,0,0,0,0,0,1,0,0,0,2,0,0,0,67,0, +- 0,0,115,10,0,0,0,100,1,124,0,95,0,100,2,83, +- 0,41,3,122,31,73,110,118,97,108,105,100,97,116,101,32, +- 116,104,101,32,100,105,114,101,99,116,111,114,121,32,109,116, +- 105,109,101,46,114,130,0,0,0,78,41,1,114,99,1,0, +- 0,114,21,1,0,0,114,7,0,0,0,114,7,0,0,0, +- 114,8,0,0,0,114,80,1,0,0,230,5,0,0,114,81, +- 0,0,0,122,28,70,105,108,101,70,105,110,100,101,114,46, +- 105,110,118,97,108,105,100,97,116,101,95,99,97,99,104,101, +- 115,99,2,0,0,0,0,0,0,0,0,0,0,0,3,0, +- 0,0,4,0,0,0,67,0,0,0,115,54,0,0,0,116, +- 0,160,1,100,1,116,2,161,2,1,0,124,0,160,3,124, +- 1,161,1,125,2,124,2,100,2,117,0,114,19,100,2,103, +- 0,102,2,83,0,124,2,106,4,124,2,106,5,112,25,103, +- 0,102,2,83,0,41,3,122,197,84,114,121,32,116,111,32, +- 102,105,110,100,32,97,32,108,111,97,100,101,114,32,102,111, +- 114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, +- 109,111,100,117,108,101,44,32,111,114,32,116,104,101,32,110, +- 97,109,101,115,112,97,99,101,10,32,32,32,32,32,32,32, +- 32,112,97,99,107,97,103,101,32,112,111,114,116,105,111,110, +- 115,46,32,82,101,116,117,114,110,115,32,40,108,111,97,100, +- 101,114,44,32,108,105,115,116,45,111,102,45,112,111,114,116, +- 105,111,110,115,41,46,10,10,32,32,32,32,32,32,32,32, +- 84,104,105,115,32,109,101,116,104,111,100,32,105,115,32,100, +- 101,112,114,101,99,97,116,101,100,46,32,32,85,115,101,32, +- 102,105,110,100,95,115,112,101,99,40,41,32,105,110,115,116, +- 101,97,100,46,10,10,32,32,32,32,32,32,32,32,122,101, +- 70,105,108,101,70,105,110,100,101,114,46,102,105,110,100,95, +- 108,111,97,100,101,114,40,41,32,105,115,32,100,101,112,114, +- 101,99,97,116,101,100,32,97,110,100,32,115,108,97,116,101, +- 100,32,102,111,114,32,114,101,109,111,118,97,108,32,105,110, +- 32,80,121,116,104,111,110,32,51,46,49,50,59,32,117,115, +- 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, +- 115,116,101,97,100,78,41,6,114,99,0,0,0,114,100,0, +- 0,0,114,101,0,0,0,114,226,0,0,0,114,164,0,0, +- 0,114,202,0,0,0,41,3,114,143,0,0,0,114,163,0, +- 0,0,114,210,0,0,0,114,7,0,0,0,114,7,0,0, +- 0,114,8,0,0,0,114,161,0,0,0,236,5,0,0,115, +- 14,0,0,0,6,7,2,2,4,254,10,3,8,1,8,1, +- 16,1,122,22,70,105,108,101,70,105,110,100,101,114,46,102, +- 105,110,100,95,108,111,97,100,101,114,99,6,0,0,0,0, +- 0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,67, +- 0,0,0,115,26,0,0,0,124,1,124,2,124,3,131,2, +- 125,6,116,0,124,2,124,3,124,6,124,4,100,1,141,4, +- 83,0,41,2,78,114,201,0,0,0,41,1,114,213,0,0, +- 0,41,7,114,143,0,0,0,114,211,0,0,0,114,163,0, +- 0,0,114,65,0,0,0,90,4,115,109,115,108,114,225,0, +- 0,0,114,164,0,0,0,114,7,0,0,0,114,7,0,0, +- 0,114,8,0,0,0,114,93,1,0,0,251,5,0,0,115, +- 8,0,0,0,10,1,8,1,2,1,6,255,122,20,70,105, +- 108,101,70,105,110,100,101,114,46,95,103,101,116,95,115,112, +- 101,99,78,99,3,0,0,0,0,0,0,0,0,0,0,0, +- 14,0,0,0,9,0,0,0,67,0,0,0,115,122,1,0, +- 0,100,1,125,3,124,1,160,0,100,2,161,1,100,3,25, +- 0,125,4,122,12,116,1,124,0,106,2,112,17,116,3,160, +- 4,161,0,131,1,106,5,125,5,87,0,110,11,4,0,116, +- 6,121,32,1,0,1,0,1,0,100,4,125,5,89,0,110, +- 1,119,0,124,5,124,0,106,7,107,3,114,45,124,0,160, +- 8,161,0,1,0,124,5,124,0,95,7,116,9,131,0,114, +- 56,124,0,106,10,125,6,124,4,160,11,161,0,125,7,110, +- 5,124,0,106,12,125,6,124,4,125,7,124,7,124,6,118, +- 0,114,108,116,13,124,0,106,2,124,4,131,2,125,8,124, +- 0,106,14,68,0,93,29,92,2,125,9,125,10,100,5,124, +- 9,23,0,125,11,116,13,124,8,124,11,131,2,125,12,116, +- 15,124,12,131,1,114,103,124,0,160,16,124,10,124,1,124, +- 12,124,8,103,1,124,2,161,5,2,0,1,0,83,0,113, +- 74,116,17,124,8,131,1,125,3,124,0,106,14,68,0,93, +- 55,92,2,125,9,125,10,122,10,116,13,124,0,106,2,124, +- 4,124,9,23,0,131,2,125,12,87,0,110,11,4,0,116, +- 18,121,136,1,0,1,0,1,0,89,0,1,0,100,6,83, +- 0,119,0,116,19,106,20,100,7,124,12,100,3,100,8,141, +- 3,1,0,124,7,124,9,23,0,124,6,118,0,114,166,116, +- 15,124,12,131,1,114,166,124,0,160,16,124,10,124,1,124, +- 12,100,6,124,2,161,5,2,0,1,0,83,0,113,111,124, +- 3,114,187,116,19,160,20,100,9,124,8,161,2,1,0,116, +- 19,160,21,124,1,100,6,161,2,125,13,124,8,103,1,124, +- 13,95,22,124,13,83,0,100,6,83,0,41,10,122,111,84, +- 114,121,32,116,111,32,102,105,110,100,32,97,32,115,112,101, +- 99,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102, +- 105,101,100,32,109,111,100,117,108,101,46,10,10,32,32,32, +- 32,32,32,32,32,82,101,116,117,114,110,115,32,116,104,101, +- 32,109,97,116,99,104,105,110,103,32,115,112,101,99,44,32, +- 111,114,32,78,111,110,101,32,105,102,32,110,111,116,32,102, +- 111,117,110,100,46,10,32,32,32,32,32,32,32,32,70,114, +- 97,0,0,0,114,44,0,0,0,114,130,0,0,0,114,236, +- 0,0,0,78,122,9,116,114,121,105,110,103,32,123,125,41, +- 1,90,9,118,101,114,98,111,115,105,116,121,122,25,112,111, +- 115,115,105,98,108,101,32,110,97,109,101,115,112,97,99,101, +- 32,102,111,114,32,123,125,41,23,114,104,0,0,0,114,75, +- 0,0,0,114,65,0,0,0,114,18,0,0,0,114,82,0, +- 0,0,114,35,1,0,0,114,76,0,0,0,114,99,1,0, +- 0,218,11,95,102,105,108,108,95,99,97,99,104,101,114,21, +- 0,0,0,114,102,1,0,0,114,131,0,0,0,114,101,1, +- 0,0,114,67,0,0,0,114,98,1,0,0,114,80,0,0, +- 0,114,93,1,0,0,114,83,0,0,0,114,111,0,0,0, +- 114,159,0,0,0,114,173,0,0,0,114,207,0,0,0,114, +- 202,0,0,0,41,14,114,143,0,0,0,114,163,0,0,0, +- 114,225,0,0,0,90,12,105,115,95,110,97,109,101,115,112, +- 97,99,101,90,11,116,97,105,108,95,109,111,100,117,108,101, +- 114,193,0,0,0,90,5,99,97,99,104,101,90,12,99,97, +- 99,104,101,95,109,111,100,117,108,101,90,9,98,97,115,101, +- 95,112,97,116,104,114,44,1,0,0,114,211,0,0,0,90, +- 13,105,110,105,116,95,102,105,108,101,110,97,109,101,90,9, +- 102,117,108,108,95,112,97,116,104,114,210,0,0,0,114,7, +- 0,0,0,114,7,0,0,0,114,8,0,0,0,114,226,0, +- 0,0,0,6,0,0,115,86,0,0,0,4,5,14,1,2, +- 1,24,1,12,1,8,1,2,255,10,2,8,1,6,1,6, +- 2,6,1,10,1,6,2,4,1,8,2,12,1,14,1,8, +- 1,10,1,8,1,24,1,2,255,8,5,14,2,2,1,20, +- 1,12,1,8,1,2,255,16,2,12,1,8,1,10,1,4, +- 1,8,255,2,128,4,2,12,1,12,1,8,1,4,1,4, +- 1,122,20,70,105,108,101,70,105,110,100,101,114,46,102,105, +- 110,100,95,115,112,101,99,99,1,0,0,0,0,0,0,0, +- 0,0,0,0,9,0,0,0,10,0,0,0,67,0,0,0, +- 115,192,0,0,0,124,0,106,0,125,1,122,11,116,1,160, +- 2,124,1,112,11,116,1,160,3,161,0,161,1,125,2,87, +- 0,110,14,4,0,116,4,116,5,116,6,102,3,121,28,1, +- 0,1,0,1,0,103,0,125,2,89,0,110,1,119,0,116, +- 7,106,8,160,9,100,1,161,1,115,41,116,10,124,2,131, +- 1,124,0,95,11,110,37,116,10,131,0,125,3,124,2,68, +- 0,93,28,125,4,124,4,160,12,100,2,161,1,92,3,125, +- 5,125,6,125,7,124,6,114,67,100,3,160,13,124,5,124, +- 7,160,14,161,0,161,2,125,8,110,2,124,5,125,8,124, +- 3,160,15,124,8,161,1,1,0,113,46,124,3,124,0,95, +- 11,116,7,106,8,160,9,116,16,161,1,114,94,100,4,100, +- 5,132,0,124,2,68,0,131,1,124,0,95,17,100,6,83, +- 0,100,6,83,0,41,7,122,68,70,105,108,108,32,116,104, +- 101,32,99,97,99,104,101,32,111,102,32,112,111,116,101,110, +- 116,105,97,108,32,109,111,100,117,108,101,115,32,97,110,100, +- 32,112,97,99,107,97,103,101,115,32,102,111,114,32,116,104, +- 105,115,32,100,105,114,101,99,116,111,114,121,46,114,14,0, +- 0,0,114,97,0,0,0,114,88,0,0,0,99,1,0,0, +- 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, +- 0,83,0,0,0,115,20,0,0,0,104,0,124,0,93,6, +- 125,1,124,1,160,0,161,0,146,2,113,2,83,0,114,7, +- 0,0,0,41,1,114,131,0,0,0,41,2,114,5,0,0, +- 0,90,2,102,110,114,7,0,0,0,114,7,0,0,0,114, +- 8,0,0,0,114,13,0,0,0,80,6,0,0,115,2,0, +- 0,0,20,0,122,41,70,105,108,101,70,105,110,100,101,114, +- 46,95,102,105,108,108,95,99,97,99,104,101,46,60,108,111, +- 99,97,108,115,62,46,60,115,101,116,99,111,109,112,62,78, +- 41,18,114,65,0,0,0,114,18,0,0,0,90,7,108,105, +- 115,116,100,105,114,114,82,0,0,0,114,87,1,0,0,218, +- 15,80,101,114,109,105,115,115,105,111,110,69,114,114,111,114, +- 218,18,78,111,116,65,68,105,114,101,99,116,111,114,121,69, +- 114,114,111,114,114,15,0,0,0,114,25,0,0,0,114,26, +- 0,0,0,114,100,1,0,0,114,101,1,0,0,114,126,0, +- 0,0,114,89,0,0,0,114,131,0,0,0,218,3,97,100, +- 100,114,27,0,0,0,114,102,1,0,0,41,9,114,143,0, +- 0,0,114,65,0,0,0,90,8,99,111,110,116,101,110,116, +- 115,90,21,108,111,119,101,114,95,115,117,102,102,105,120,95, +- 99,111,110,116,101,110,116,115,114,72,1,0,0,114,141,0, +- 0,0,114,56,1,0,0,114,44,1,0,0,90,8,110,101, +- 119,95,110,97,109,101,114,7,0,0,0,114,7,0,0,0, +- 114,8,0,0,0,114,104,1,0,0,51,6,0,0,115,38, +- 0,0,0,6,2,2,1,22,1,18,1,8,3,2,253,12, +- 6,12,1,6,7,8,1,16,1,4,1,18,1,4,2,12, +- 1,6,1,12,1,20,1,4,255,122,22,70,105,108,101,70, +- 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, +- 101,99,1,0,0,0,0,0,0,0,0,0,0,0,3,0, +- 0,0,3,0,0,0,7,0,0,0,115,18,0,0,0,135, +- 0,135,1,102,2,100,1,100,2,132,8,125,2,124,2,83, +- 0,41,3,97,20,1,0,0,65,32,99,108,97,115,115,32, +- 109,101,116,104,111,100,32,119,104,105,99,104,32,114,101,116, +- 117,114,110,115,32,97,32,99,108,111,115,117,114,101,32,116, +- 111,32,117,115,101,32,111,110,32,115,121,115,46,112,97,116, +- 104,95,104,111,111,107,10,32,32,32,32,32,32,32,32,119, +- 104,105,99,104,32,119,105,108,108,32,114,101,116,117,114,110, +- 32,97,110,32,105,110,115,116,97,110,99,101,32,117,115,105, +- 110,103,32,116,104,101,32,115,112,101,99,105,102,105,101,100, +- 32,108,111,97,100,101,114,115,32,97,110,100,32,116,104,101, +- 32,112,97,116,104,10,32,32,32,32,32,32,32,32,99,97, ++ 0,4,0,0,0,83,0,0,0,115,20,0,0,0,104,0, ++ 124,0,93,6,125,1,124,1,160,0,161,0,146,2,113,2, ++ 83,0,114,7,0,0,0,41,1,114,134,0,0,0,41,2, ++ 114,5,0,0,0,90,2,102,110,114,7,0,0,0,114,7, ++ 0,0,0,114,8,0,0,0,114,13,0,0,0,80,6,0, ++ 0,115,2,0,0,0,20,0,122,41,70,105,108,101,70,105, ++ 110,100,101,114,46,95,102,105,108,108,95,99,97,99,104,101, ++ 46,60,108,111,99,97,108,115,62,46,60,115,101,116,99,111, ++ 109,112,62,78,41,18,114,68,0,0,0,114,21,0,0,0, ++ 90,7,108,105,115,116,100,105,114,114,85,0,0,0,114,92, ++ 1,0,0,218,15,80,101,114,109,105,115,115,105,111,110,69, ++ 114,114,111,114,218,18,78,111,116,65,68,105,114,101,99,116, ++ 111,114,121,69,114,114,111,114,114,18,0,0,0,114,28,0, ++ 0,0,114,29,0,0,0,114,105,1,0,0,114,106,1,0, ++ 0,114,129,0,0,0,114,92,0,0,0,114,134,0,0,0, ++ 218,3,97,100,100,114,30,0,0,0,114,107,1,0,0,41, ++ 9,114,146,0,0,0,114,68,0,0,0,90,8,99,111,110, ++ 116,101,110,116,115,90,21,108,111,119,101,114,95,115,117,102, ++ 102,105,120,95,99,111,110,116,101,110,116,115,114,77,1,0, ++ 0,114,144,0,0,0,114,61,1,0,0,114,49,1,0,0, ++ 90,8,110,101,119,95,110,97,109,101,114,7,0,0,0,114, ++ 7,0,0,0,114,8,0,0,0,114,109,1,0,0,51,6, ++ 0,0,115,38,0,0,0,6,2,2,1,22,1,18,1,8, ++ 3,2,253,12,6,12,1,6,7,8,1,16,1,4,1,18, ++ 1,4,2,12,1,6,1,12,1,20,1,4,255,122,22,70, ++ 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, ++ 99,97,99,104,101,99,1,0,0,0,0,0,0,0,0,0, ++ 0,0,3,0,0,0,3,0,0,0,7,0,0,0,115,18, ++ 0,0,0,135,0,135,1,102,2,100,1,100,2,132,8,125, ++ 2,124,2,83,0,41,3,97,20,1,0,0,65,32,99,108, ++ 97,115,115,32,109,101,116,104,111,100,32,119,104,105,99,104, ++ 32,114,101,116,117,114,110,115,32,97,32,99,108,111,115,117, ++ 114,101,32,116,111,32,117,115,101,32,111,110,32,115,121,115, ++ 46,112,97,116,104,95,104,111,111,107,10,32,32,32,32,32, ++ 32,32,32,119,104,105,99,104,32,119,105,108,108,32,114,101, ++ 116,117,114,110,32,97,110,32,105,110,115,116,97,110,99,101, ++ 32,117,115,105,110,103,32,116,104,101,32,115,112,101,99,105, ++ 102,105,101,100,32,108,111,97,100,101,114,115,32,97,110,100, ++ 32,116,104,101,32,112,97,116,104,10,32,32,32,32,32,32, ++ 32,32,99,97,108,108,101,100,32,111,110,32,116,104,101,32, ++ 99,108,111,115,117,114,101,46,10,10,32,32,32,32,32,32, ++ 32,32,73,102,32,116,104,101,32,112,97,116,104,32,99,97, + 108,108,101,100,32,111,110,32,116,104,101,32,99,108,111,115, +- 117,114,101,46,10,10,32,32,32,32,32,32,32,32,73,102, +- 32,116,104,101,32,112,97,116,104,32,99,97,108,108,101,100, +- 32,111,110,32,116,104,101,32,99,108,111,115,117,114,101,32, +- 105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111, +- 114,121,44,32,73,109,112,111,114,116,69,114,114,111,114,32, +- 105,115,10,32,32,32,32,32,32,32,32,114,97,105,115,101, +- 100,46,10,10,32,32,32,32,32,32,32,32,99,1,0,0, +- 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, +- 0,19,0,0,0,115,36,0,0,0,116,0,124,0,131,1, +- 115,10,116,1,100,1,124,0,100,2,141,2,130,1,136,0, +- 124,0,103,1,136,1,162,1,82,0,142,0,83,0,41,3, +- 122,45,80,97,116,104,32,104,111,111,107,32,102,111,114,32, +- 105,109,112,111,114,116,108,105,98,46,109,97,99,104,105,110, +- 101,114,121,46,70,105,108,101,70,105,110,100,101,114,46,122, +- 30,111,110,108,121,32,100,105,114,101,99,116,111,114,105,101, +- 115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,114, +- 71,0,0,0,41,2,114,83,0,0,0,114,142,0,0,0, +- 114,71,0,0,0,169,2,114,221,0,0,0,114,103,1,0, +- 0,114,7,0,0,0,114,8,0,0,0,218,24,112,97,116, +- 104,95,104,111,111,107,95,102,111,114,95,70,105,108,101,70, +- 105,110,100,101,114,92,6,0,0,115,6,0,0,0,8,2, +- 12,1,16,1,122,54,70,105,108,101,70,105,110,100,101,114, +- 46,112,97,116,104,95,104,111,111,107,46,60,108,111,99,97, +- 108,115,62,46,112,97,116,104,95,104,111,111,107,95,102,111, +- 114,95,70,105,108,101,70,105,110,100,101,114,114,7,0,0, +- 0,41,3,114,221,0,0,0,114,103,1,0,0,114,109,1, +- 0,0,114,7,0,0,0,114,108,1,0,0,114,8,0,0, +- 0,218,9,112,97,116,104,95,104,111,111,107,82,6,0,0, +- 115,4,0,0,0,14,10,4,6,122,20,70,105,108,101,70, +- 105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,99, +- 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +- 3,0,0,0,67,0,0,0,114,69,1,0,0,41,2,78, +- 122,16,70,105,108,101,70,105,110,100,101,114,40,123,33,114, +- 125,41,41,2,114,89,0,0,0,114,65,0,0,0,114,21, +- 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, +- 0,0,114,70,1,0,0,100,6,0,0,114,63,1,0,0, +- 122,19,70,105,108,101,70,105,110,100,101,114,46,95,95,114, +- 101,112,114,95,95,114,69,0,0,0,41,15,114,150,0,0, +- 0,114,149,0,0,0,114,151,0,0,0,114,152,0,0,0, +- 114,236,0,0,0,114,80,1,0,0,114,167,0,0,0,114, +- 229,0,0,0,114,161,0,0,0,114,93,1,0,0,114,226, +- 0,0,0,114,104,1,0,0,114,234,0,0,0,114,110,1, +- 0,0,114,70,1,0,0,114,7,0,0,0,114,7,0,0, +- 0,114,7,0,0,0,114,8,0,0,0,114,96,1,0,0, +- 205,5,0,0,115,24,0,0,0,8,0,4,2,8,7,8, +- 16,4,4,8,2,8,15,10,5,8,51,2,31,10,1,12, +- 17,114,96,1,0,0,99,4,0,0,0,0,0,0,0,0, ++ 117,114,101,32,105,115,32,110,111,116,32,97,32,100,105,114, ++ 101,99,116,111,114,121,44,32,73,109,112,111,114,116,69,114, ++ 114,111,114,32,105,115,10,32,32,32,32,32,32,32,32,114, ++ 97,105,115,101,100,46,10,10,32,32,32,32,32,32,32,32, ++ 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, ++ 0,4,0,0,0,19,0,0,0,115,36,0,0,0,116,0, ++ 124,0,131,1,115,10,116,1,100,1,124,0,100,2,141,2, ++ 130,1,136,0,124,0,103,1,136,1,162,1,82,0,142,0, ++ 83,0,41,3,122,45,80,97,116,104,32,104,111,111,107,32, ++ 102,111,114,32,105,109,112,111,114,116,108,105,98,46,109,97, ++ 99,104,105,110,101,114,121,46,70,105,108,101,70,105,110,100, ++ 101,114,46,122,30,111,110,108,121,32,100,105,114,101,99,116, ++ 111,114,105,101,115,32,97,114,101,32,115,117,112,112,111,114, ++ 116,101,100,114,74,0,0,0,41,2,114,86,0,0,0,114, ++ 145,0,0,0,114,74,0,0,0,169,2,114,224,0,0,0, ++ 114,108,1,0,0,114,7,0,0,0,114,8,0,0,0,218, ++ 24,112,97,116,104,95,104,111,111,107,95,102,111,114,95,70, ++ 105,108,101,70,105,110,100,101,114,92,6,0,0,115,6,0, ++ 0,0,8,2,12,1,16,1,122,54,70,105,108,101,70,105, ++ 110,100,101,114,46,112,97,116,104,95,104,111,111,107,46,60, ++ 108,111,99,97,108,115,62,46,112,97,116,104,95,104,111,111, ++ 107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,114, ++ 114,7,0,0,0,41,3,114,224,0,0,0,114,108,1,0, ++ 0,114,114,1,0,0,114,7,0,0,0,114,113,1,0,0, ++ 114,8,0,0,0,218,9,112,97,116,104,95,104,111,111,107, ++ 82,6,0,0,115,4,0,0,0,14,10,4,6,122,20,70, ++ 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, ++ 111,111,107,99,1,0,0,0,0,0,0,0,0,0,0,0, ++ 1,0,0,0,3,0,0,0,67,0,0,0,114,74,1,0, ++ 0,41,2,78,122,16,70,105,108,101,70,105,110,100,101,114, ++ 40,123,33,114,125,41,41,2,114,92,0,0,0,114,68,0, ++ 0,0,114,24,1,0,0,114,7,0,0,0,114,7,0,0, ++ 0,114,8,0,0,0,114,75,1,0,0,100,6,0,0,114, ++ 68,1,0,0,122,19,70,105,108,101,70,105,110,100,101,114, ++ 46,95,95,114,101,112,114,95,95,114,72,0,0,0,41,15, ++ 114,153,0,0,0,114,152,0,0,0,114,154,0,0,0,114, ++ 155,0,0,0,114,239,0,0,0,114,85,1,0,0,114,170, ++ 0,0,0,114,232,0,0,0,114,164,0,0,0,114,98,1, ++ 0,0,114,229,0,0,0,114,109,1,0,0,114,237,0,0, ++ 0,114,115,1,0,0,114,75,1,0,0,114,7,0,0,0, ++ 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, ++ 101,1,0,0,205,5,0,0,115,24,0,0,0,8,0,4, ++ 2,8,7,8,16,4,4,8,2,8,15,10,5,8,51,2, ++ 31,10,1,12,17,114,101,1,0,0,99,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,64, ++ 0,0,0,115,24,0,0,0,101,0,90,1,100,0,90,2, ++ 100,1,90,3,100,2,100,3,132,0,90,4,100,4,83,0, ++ 41,5,218,20,65,112,112,108,101,70,114,97,109,101,119,111, ++ 114,107,76,111,97,100,101,114,122,122,65,32,108,111,97,100, ++ 101,114,32,102,111,114,32,109,111,100,117,108,101,115,32,116, ++ 104,97,116,32,104,97,118,101,32,98,101,101,110,32,112,97, ++ 99,107,97,103,101,100,32,97,115,32,102,114,97,109,101,119, ++ 111,114,107,115,32,102,111,114,10,32,32,32,32,99,111,109, ++ 112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32, ++ 65,112,112,108,101,39,115,32,105,79,83,32,65,112,112,32, ++ 83,116,111,114,101,32,112,111,108,105,99,105,101,115,46,10, ++ 32,32,32,32,99,2,0,0,0,0,0,0,0,0,0,0, ++ 0,8,0,0,0,8,0,0,0,67,0,0,0,115,254,0, ++ 0,0,124,1,106,0,160,1,100,1,161,1,114,50,116,2, ++ 160,3,124,1,106,0,100,2,161,2,143,16,125,2,124,2, ++ 160,4,161,0,160,5,161,0,160,6,161,0,125,3,87,0, ++ 100,0,4,0,4,0,131,3,1,0,110,8,49,0,115,32, ++ 119,1,1,0,1,0,1,0,89,0,1,0,116,7,116,8, ++ 106,9,131,1,100,3,25,0,125,4,116,10,124,4,124,3, ++ 131,2,124,1,95,0,124,0,106,11,160,1,100,1,161,1, ++ 114,60,124,0,106,11,125,5,110,45,116,2,160,3,124,0, ++ 106,11,100,4,23,0,100,2,161,2,143,28,125,2,124,2, ++ 160,4,161,0,160,5,161,0,160,6,161,0,125,6,116,7, ++ 116,8,106,9,131,1,100,3,25,0,125,4,116,10,124,4, ++ 124,6,131,2,125,5,87,0,100,0,4,0,4,0,131,3, ++ 1,0,110,8,49,0,115,100,119,1,1,0,1,0,1,0, ++ 89,0,1,0,116,12,160,13,116,14,106,15,124,1,161,2, ++ 125,7,116,12,160,16,100,5,124,1,106,17,124,1,106,0, ++ 124,5,161,4,1,0,124,5,124,7,95,18,124,7,83,0, ++ 41,6,78,250,6,46,102,119,111,114,107,114,32,1,0,0, ++ 114,0,0,0,0,122,7,46,111,114,105,103,105,110,122,66, ++ 65,112,112,108,101,32,102,114,97,109,101,119,111,114,107,32, ++ 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, ++ 32,123,33,114,125,32,108,111,97,100,101,100,32,102,114,111, ++ 109,32,123,33,114,125,32,40,112,97,116,104,32,123,33,114, ++ 125,41,41,19,114,208,0,0,0,114,61,0,0,0,114,94, ++ 0,0,0,114,95,0,0,0,114,34,1,0,0,114,200,0, ++ 0,0,218,5,115,116,114,105,112,114,77,0,0,0,114,18, ++ 0,0,0,90,10,101,120,101,99,117,116,97,98,108,101,114, ++ 70,0,0,0,114,68,0,0,0,114,162,0,0,0,114,245, ++ 0,0,0,114,190,0,0,0,114,46,1,0,0,114,176,0, ++ 0,0,114,144,0,0,0,218,8,95,95,102,105,108,101,95, ++ 95,41,8,114,146,0,0,0,114,213,0,0,0,114,97,0, ++ 0,0,90,16,102,114,97,109,101,119,111,114,107,95,98,105, ++ 110,97,114,121,90,11,98,117,110,100,108,101,95,112,97,116, ++ 104,114,68,0,0,0,114,208,0,0,0,114,247,0,0,0, ++ 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, ++ 242,0,0,0,108,6,0,0,115,44,0,0,0,12,5,16, ++ 1,18,1,28,255,14,2,12,1,12,5,8,1,20,2,16, ++ 1,14,1,12,1,28,253,14,5,4,2,2,1,4,1,4, ++ 1,2,1,4,252,6,8,4,2,122,34,65,112,112,108,101, ++ 70,114,97,109,101,119,111,114,107,76,111,97,100,101,114,46, ++ 99,114,101,97,116,101,95,109,111,100,117,108,101,78,41,5, ++ 114,153,0,0,0,114,152,0,0,0,114,154,0,0,0,114, ++ 155,0,0,0,114,242,0,0,0,114,7,0,0,0,114,7, ++ 0,0,0,114,7,0,0,0,114,8,0,0,0,114,116,1, ++ 0,0,104,6,0,0,115,6,0,0,0,8,0,4,1,12, ++ 3,114,116,1,0,0,99,4,0,0,0,0,0,0,0,0, + 0,0,0,6,0,0,0,8,0,0,0,67,0,0,0,115, + 144,0,0,0,124,0,160,0,100,1,161,1,125,4,124,0, + 160,0,100,2,161,1,125,5,124,4,115,33,124,5,114,18, +@@ -2664,108 +2725,125 @@ + 60,0,124,3,124,0,100,5,60,0,87,0,100,0,83,0, + 4,0,116,5,121,71,1,0,1,0,1,0,89,0,100,0, + 83,0,119,0,41,6,78,218,10,95,95,108,111,97,100,101, +- 114,95,95,218,8,95,95,115,112,101,99,95,95,114,97,1, +- 0,0,90,8,95,95,102,105,108,101,95,95,90,10,95,95, +- 99,97,99,104,101,100,95,95,41,6,218,3,103,101,116,114, +- 164,0,0,0,114,41,1,0,0,114,34,1,0,0,114,213, +- 0,0,0,218,9,69,120,99,101,112,116,105,111,110,41,6, +- 90,2,110,115,114,141,0,0,0,90,8,112,97,116,104,110, +- 97,109,101,90,9,99,112,97,116,104,110,97,109,101,114,164, +- 0,0,0,114,210,0,0,0,114,7,0,0,0,114,7,0, +- 0,0,114,8,0,0,0,218,14,95,102,105,120,95,117,112, +- 95,109,111,100,117,108,101,106,6,0,0,115,36,0,0,0, +- 10,2,10,1,4,1,4,1,8,1,8,1,12,1,10,2, +- 4,1,14,1,2,1,8,1,8,1,8,1,14,1,12,1, +- 6,2,2,254,114,115,1,0,0,99,0,0,0,0,0,0, +- 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, +- 0,0,115,38,0,0,0,116,0,116,1,160,2,161,0,102, +- 2,125,0,116,3,116,4,102,2,125,1,116,5,116,6,102, +- 2,125,2,124,0,124,1,124,2,103,3,83,0,41,1,122, +- 95,82,101,116,117,114,110,115,32,97,32,108,105,115,116,32, +- 111,102,32,102,105,108,101,45,98,97,115,101,100,32,109,111, +- 100,117,108,101,32,108,111,97,100,101,114,115,46,10,10,32, +- 32,32,32,69,97,99,104,32,105,116,101,109,32,105,115,32, +- 97,32,116,117,112,108,101,32,40,108,111,97,100,101,114,44, +- 32,115,117,102,102,105,120,101,115,41,46,10,32,32,32,32, +- 41,7,114,30,1,0,0,114,187,0,0,0,218,18,101,120, +- 116,101,110,115,105,111,110,95,115,117,102,102,105,120,101,115, +- 114,34,1,0,0,114,127,0,0,0,114,41,1,0,0,114, +- 113,0,0,0,41,3,90,10,101,120,116,101,110,115,105,111, +- 110,115,90,6,115,111,117,114,99,101,90,8,98,121,116,101, +- 99,111,100,101,114,7,0,0,0,114,7,0,0,0,114,8, +- 0,0,0,114,208,0,0,0,129,6,0,0,115,8,0,0, +- 0,12,5,8,1,8,1,10,1,114,208,0,0,0,99,1, +- 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1, +- 0,0,0,67,0,0,0,115,8,0,0,0,124,0,97,0, +- 100,0,83,0,114,69,0,0,0,41,1,114,159,0,0,0, +- 41,1,218,17,95,98,111,111,116,115,116,114,97,112,95,109, +- 111,100,117,108,101,114,7,0,0,0,114,7,0,0,0,114, +- 8,0,0,0,218,21,95,115,101,116,95,98,111,111,116,115, +- 116,114,97,112,95,109,111,100,117,108,101,140,6,0,0,115, +- 2,0,0,0,8,2,114,118,1,0,0,99,1,0,0,0, +- 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, +- 67,0,0,0,115,50,0,0,0,116,0,124,0,131,1,1, +- 0,116,1,131,0,125,1,116,2,106,3,160,4,116,5,106, +- 6,124,1,142,0,103,1,161,1,1,0,116,2,106,7,160, +- 8,116,9,161,1,1,0,100,1,83,0,41,2,122,41,73, +- 110,115,116,97,108,108,32,116,104,101,32,112,97,116,104,45, +- 98,97,115,101,100,32,105,109,112,111,114,116,32,99,111,109, +- 112,111,110,101,110,116,115,46,78,41,10,114,118,1,0,0, +- 114,208,0,0,0,114,15,0,0,0,114,85,1,0,0,114, +- 191,0,0,0,114,96,1,0,0,114,110,1,0,0,218,9, +- 109,101,116,97,95,112,97,116,104,114,61,0,0,0,114,79, +- 1,0,0,41,2,114,117,1,0,0,90,17,115,117,112,112, +- 111,114,116,101,100,95,108,111,97,100,101,114,115,114,7,0, +- 0,0,114,7,0,0,0,114,8,0,0,0,218,8,95,105, +- 110,115,116,97,108,108,145,6,0,0,115,8,0,0,0,8, +- 2,6,1,20,1,16,1,114,120,1,0,0,41,1,114,87, +- 0,0,0,114,69,0,0,0,41,3,78,78,78,41,2,114, +- 0,0,0,0,114,0,0,0,0,41,1,84,41,85,114,152, +- 0,0,0,114,159,0,0,0,114,187,0,0,0,114,91,0, +- 0,0,114,15,0,0,0,114,99,0,0,0,114,184,0,0, +- 0,114,25,0,0,0,114,231,0,0,0,90,2,110,116,114, +- 18,0,0,0,114,215,0,0,0,90,5,112,111,115,105,120, +- 114,50,0,0,0,218,3,97,108,108,114,59,0,0,0,114, +- 136,0,0,0,114,57,0,0,0,114,62,0,0,0,90,20, +- 95,112,97,116,104,115,101,112,115,95,119,105,116,104,95,99, +- 111,108,111,110,114,28,0,0,0,90,37,95,67,65,83,69, +- 95,73,78,83,69,78,83,73,84,73,86,69,95,80,76,65, +- 84,70,79,82,77,83,95,66,89,84,69,83,95,75,69,89, +- 114,27,0,0,0,114,29,0,0,0,114,21,0,0,0,114, +- 36,0,0,0,114,42,0,0,0,114,45,0,0,0,114,67, +- 0,0,0,114,74,0,0,0,114,75,0,0,0,114,79,0, +- 0,0,114,80,0,0,0,114,83,0,0,0,114,86,0,0, +- 0,114,95,0,0,0,218,4,116,121,112,101,218,8,95,95, +- 99,111,100,101,95,95,114,186,0,0,0,114,34,0,0,0, +- 114,172,0,0,0,114,33,0,0,0,114,39,0,0,0,114, +- 8,1,0,0,114,116,0,0,0,114,112,0,0,0,114,127, +- 0,0,0,114,61,0,0,0,114,116,1,0,0,114,232,0, +- 0,0,114,113,0,0,0,90,23,68,69,66,85,71,95,66, +- 89,84,69,67,79,68,69,95,83,85,70,70,73,88,69,83, +- 90,27,79,80,84,73,77,73,90,69,68,95,66,89,84,69, +- 67,79,68,69,95,83,85,70,70,73,88,69,83,114,121,0, +- 0,0,114,128,0,0,0,114,135,0,0,0,114,137,0,0, +- 0,114,139,0,0,0,114,160,0,0,0,114,167,0,0,0, +- 114,176,0,0,0,114,180,0,0,0,114,182,0,0,0,114, +- 189,0,0,0,114,194,0,0,0,114,195,0,0,0,114,200, +- 0,0,0,218,6,111,98,106,101,99,116,114,209,0,0,0, +- 114,213,0,0,0,114,214,0,0,0,114,235,0,0,0,114, +- 249,0,0,0,114,11,1,0,0,114,34,1,0,0,114,41, +- 1,0,0,114,30,1,0,0,114,47,1,0,0,114,75,1, +- 0,0,114,79,1,0,0,114,96,1,0,0,114,115,1,0, +- 0,114,208,0,0,0,114,118,1,0,0,114,120,1,0,0, +- 114,7,0,0,0,114,7,0,0,0,114,7,0,0,0,114, +- 8,0,0,0,218,8,60,109,111,100,117,108,101,62,1,0, +- 0,0,115,180,0,0,0,4,0,4,22,8,3,8,1,8, +- 1,8,1,8,1,10,3,4,1,8,1,10,1,8,2,4, +- 3,10,1,6,2,22,2,8,1,8,1,10,1,14,1,4, +- 4,4,1,2,1,2,1,4,255,8,4,6,16,8,3,8, +- 5,8,5,4,6,10,1,8,30,8,6,8,8,8,10,8, +- 9,8,5,4,7,10,1,8,8,10,5,10,22,0,127,16, +- 30,12,1,4,2,4,1,6,2,4,1,10,1,8,2,6, +- 2,8,2,16,2,8,71,8,40,8,19,8,12,8,12,8, +- 31,8,20,8,33,8,28,10,24,10,13,10,10,8,11,6, +- 14,4,3,2,1,12,255,14,73,14,67,16,30,0,127,14, +- 17,18,50,18,45,18,25,14,53,14,69,14,49,0,127,14, +- 32,0,127,10,30,8,23,8,11,12,5, ++ 114,95,95,218,8,95,95,115,112,101,99,95,95,114,102,1, ++ 0,0,114,119,1,0,0,90,10,95,95,99,97,99,104,101, ++ 100,95,95,41,6,218,3,103,101,116,114,167,0,0,0,114, ++ 45,1,0,0,114,38,1,0,0,114,216,0,0,0,218,9, ++ 69,120,99,101,112,116,105,111,110,41,6,90,2,110,115,114, ++ 144,0,0,0,90,8,112,97,116,104,110,97,109,101,90,9, ++ 99,112,97,116,104,110,97,109,101,114,167,0,0,0,114,213, ++ 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, ++ 0,0,218,14,95,102,105,120,95,117,112,95,109,111,100,117, ++ 108,101,146,6,0,0,115,36,0,0,0,10,2,10,1,4, ++ 1,4,1,8,1,8,1,12,1,10,2,4,1,14,1,2, ++ 1,8,1,8,1,8,1,14,1,12,1,6,2,2,254,114, ++ 124,1,0,0,99,0,0,0,0,0,0,0,0,0,0,0, ++ 0,3,0,0,0,5,0,0,0,67,0,0,0,115,86,0, ++ 0,0,116,0,106,1,100,1,118,0,114,18,116,2,100,2, ++ 100,3,132,0,116,3,160,4,161,0,68,0,131,1,102,2, ++ 103,1,125,0,110,2,103,0,125,0,124,0,160,5,116,6, ++ 116,3,160,4,161,0,102,2,161,1,1,0,116,7,116,8, ++ 102,2,125,1,116,9,116,10,102,2,125,2,124,0,124,1, ++ 124,2,103,2,23,0,83,0,41,4,122,95,82,101,116,117, ++ 114,110,115,32,97,32,108,105,115,116,32,111,102,32,102,105, ++ 108,101,45,98,97,115,101,100,32,109,111,100,117,108,101,32, ++ 108,111,97,100,101,114,115,46,10,10,32,32,32,32,69,97, ++ 99,104,32,105,116,101,109,32,105,115,32,97,32,116,117,112, ++ 108,101,32,40,108,111,97,100,101,114,44,32,115,117,102,102, ++ 105,120,101,115,41,46,10,32,32,32,32,62,3,0,0,0, ++ 114,15,0,0,0,114,17,0,0,0,114,16,0,0,0,99, ++ 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, ++ 6,0,0,0,83,0,0,0,115,24,0,0,0,103,0,124, ++ 0,93,8,125,1,124,1,160,0,100,0,100,1,161,2,145, ++ 2,113,2,83,0,41,2,122,3,46,115,111,114,117,1,0, ++ 0,41,1,114,88,0,0,0,114,48,1,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,114,56,0,0, ++ 0,175,6,0,0,115,8,0,0,0,6,0,2,2,10,255, ++ 6,255,122,47,95,103,101,116,95,115,117,112,112,111,114,116, ++ 101,100,95,102,105,108,101,95,108,111,97,100,101,114,115,46, ++ 60,108,111,99,97,108,115,62,46,60,108,105,115,116,99,111, ++ 109,112,62,41,11,114,18,0,0,0,114,28,0,0,0,114, ++ 116,1,0,0,114,190,0,0,0,218,18,101,120,116,101,110, ++ 115,105,111,110,95,115,117,102,102,105,120,101,115,114,64,0, ++ 0,0,114,33,1,0,0,114,38,1,0,0,114,130,0,0, ++ 0,114,45,1,0,0,114,116,0,0,0,41,3,90,17,101, ++ 120,116,101,110,115,105,111,110,95,108,111,97,100,101,114,115, ++ 90,6,115,111,117,114,99,101,90,8,98,121,116,101,99,111, ++ 100,101,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,114,211,0,0,0,169,6,0,0,115,18,0,0,0,10, ++ 5,8,1,6,2,12,254,4,5,18,1,8,1,8,1,12, ++ 1,114,211,0,0,0,99,1,0,0,0,0,0,0,0,0, ++ 0,0,0,1,0,0,0,1,0,0,0,67,0,0,0,115, ++ 8,0,0,0,124,0,97,0,100,0,83,0,114,72,0,0, ++ 0,41,1,114,162,0,0,0,41,1,218,17,95,98,111,111, ++ 116,115,116,114,97,112,95,109,111,100,117,108,101,114,7,0, ++ 0,0,114,7,0,0,0,114,8,0,0,0,218,21,95,115, ++ 101,116,95,98,111,111,116,115,116,114,97,112,95,109,111,100, ++ 117,108,101,187,6,0,0,115,2,0,0,0,8,2,114,127, ++ 1,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, ++ 2,0,0,0,4,0,0,0,67,0,0,0,115,50,0,0, ++ 0,116,0,124,0,131,1,1,0,116,1,131,0,125,1,116, ++ 2,106,3,160,4,116,5,106,6,124,1,142,0,103,1,161, ++ 1,1,0,116,2,106,7,160,8,116,9,161,1,1,0,100, ++ 1,83,0,41,2,122,41,73,110,115,116,97,108,108,32,116, ++ 104,101,32,112,97,116,104,45,98,97,115,101,100,32,105,109, ++ 112,111,114,116,32,99,111,109,112,111,110,101,110,116,115,46, ++ 78,41,10,114,127,1,0,0,114,211,0,0,0,114,18,0, ++ 0,0,114,90,1,0,0,114,194,0,0,0,114,101,1,0, ++ 0,114,115,1,0,0,218,9,109,101,116,97,95,112,97,116, ++ 104,114,64,0,0,0,114,84,1,0,0,41,2,114,126,1, ++ 0,0,90,17,115,117,112,112,111,114,116,101,100,95,108,111, ++ 97,100,101,114,115,114,7,0,0,0,114,7,0,0,0,114, ++ 8,0,0,0,218,8,95,105,110,115,116,97,108,108,192,6, ++ 0,0,115,8,0,0,0,8,2,6,1,20,1,16,1,114, ++ 129,1,0,0,41,1,114,90,0,0,0,114,72,0,0,0, ++ 41,3,78,78,78,41,2,114,0,0,0,0,114,0,0,0, ++ 0,41,1,84,41,86,114,155,0,0,0,114,162,0,0,0, ++ 114,190,0,0,0,114,94,0,0,0,114,18,0,0,0,114, ++ 102,0,0,0,114,187,0,0,0,114,28,0,0,0,114,234, ++ 0,0,0,90,2,110,116,114,21,0,0,0,114,218,0,0, ++ 0,90,5,112,111,115,105,120,114,53,0,0,0,218,3,97, ++ 108,108,114,62,0,0,0,114,139,0,0,0,114,60,0,0, ++ 0,114,65,0,0,0,90,20,95,112,97,116,104,115,101,112, ++ 115,95,119,105,116,104,95,99,111,108,111,110,114,31,0,0, ++ 0,90,37,95,67,65,83,69,95,73,78,83,69,78,83,73, ++ 84,73,86,69,95,80,76,65,84,70,79,82,77,83,95,66, ++ 89,84,69,83,95,75,69,89,114,30,0,0,0,114,32,0, ++ 0,0,114,24,0,0,0,114,39,0,0,0,114,45,0,0, ++ 0,114,48,0,0,0,114,70,0,0,0,114,77,0,0,0, ++ 114,78,0,0,0,114,82,0,0,0,114,83,0,0,0,114, ++ 86,0,0,0,114,89,0,0,0,114,98,0,0,0,218,4, ++ 116,121,112,101,218,8,95,95,99,111,100,101,95,95,114,189, ++ 0,0,0,114,37,0,0,0,114,175,0,0,0,114,36,0, ++ 0,0,114,42,0,0,0,114,11,1,0,0,114,119,0,0, ++ 0,114,115,0,0,0,114,130,0,0,0,114,64,0,0,0, ++ 114,125,1,0,0,114,235,0,0,0,114,116,0,0,0,90, ++ 23,68,69,66,85,71,95,66,89,84,69,67,79,68,69,95, ++ 83,85,70,70,73,88,69,83,90,27,79,80,84,73,77,73, ++ 90,69,68,95,66,89,84,69,67,79,68,69,95,83,85,70, ++ 70,73,88,69,83,114,124,0,0,0,114,131,0,0,0,114, ++ 138,0,0,0,114,140,0,0,0,114,142,0,0,0,114,163, ++ 0,0,0,114,170,0,0,0,114,179,0,0,0,114,183,0, ++ 0,0,114,185,0,0,0,114,192,0,0,0,114,197,0,0, ++ 0,114,198,0,0,0,114,203,0,0,0,218,6,111,98,106, ++ 101,99,116,114,212,0,0,0,114,216,0,0,0,114,217,0, ++ 0,0,114,238,0,0,0,114,252,0,0,0,114,14,1,0, ++ 0,114,38,1,0,0,114,45,1,0,0,114,33,1,0,0, ++ 114,52,1,0,0,114,80,1,0,0,114,84,1,0,0,114, ++ 101,1,0,0,114,116,1,0,0,114,124,1,0,0,114,211, ++ 0,0,0,114,127,1,0,0,114,129,1,0,0,114,7,0, ++ 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, ++ 0,218,8,60,109,111,100,117,108,101,62,1,0,0,0,115, ++ 182,0,0,0,4,0,4,22,8,3,8,1,8,1,8,1, ++ 8,1,10,3,4,1,8,1,10,1,8,2,4,3,10,1, ++ 6,2,22,2,8,1,8,1,10,1,14,1,4,4,4,1, ++ 2,1,2,1,4,255,8,4,6,16,8,3,8,5,8,5, ++ 4,6,10,1,8,30,8,6,8,8,8,10,8,9,8,5, ++ 4,7,10,1,8,8,10,5,10,22,0,127,16,30,12,1, ++ 4,2,4,1,6,2,4,1,10,1,8,2,6,2,8,2, ++ 16,2,8,71,8,40,8,19,8,12,8,12,8,31,8,20, ++ 8,33,8,28,10,24,10,13,10,10,8,11,6,14,4,3, ++ 2,1,12,255,14,73,14,67,16,30,0,127,14,17,18,50, ++ 18,45,18,25,14,53,14,69,14,49,0,127,14,32,0,127, ++ 16,28,10,42,8,23,8,18,12,5, + }; +diff --git a/Python/marshal.c b/Python/marshal.c +index 67540e08ed9..062e3047fb8 100644 +--- a/Python/marshal.c ++++ b/Python/marshal.c +@@ -14,6 +14,10 @@ + #include "marshal.h" + #include "pycore_hashtable.h" + ++#ifdef __APPLE__ ++# include "TargetConditionals.h" ++#endif /* __APPLE__ */ ++ + /*[clinic input] + module marshal + [clinic start generated code]*/ +@@ -33,9 +37,12 @@ + * #if defined(MS_WINDOWS) && defined(_DEBUG) + */ + #if defined(MS_WINDOWS) +-#define MAX_MARSHAL_STACK_DEPTH 1000 ++# define MAX_MARSHAL_STACK_DEPTH 1000 ++// TARGET_OS_IPHONE covers any non-macOS Apple platform. ++#elif defined(__APPLE__) && TARGET_OS_IPHONE ++# define MAX_MARSHAL_STACK_DEPTH 1500 + #else +-#define MAX_MARSHAL_STACK_DEPTH 2000 ++# define MAX_MARSHAL_STACK_DEPTH 2000 + #endif + + #define TYPE_NULL '0' +diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c +index b0c5da56c4f..c2c45c62ed2 100644 +--- a/Python/pylifecycle.c ++++ b/Python/pylifecycle.c +@@ -18,7 +18,21 @@ + #include // setlocale() + + #if defined(__APPLE__) +-#include ++# include ++# include ++# include ++// The os_log unified logging APIs were introduced in macOS 10.12, iOS 10.0, ++// tvOS 10.0, and watchOS 3.0; we enable the use of the system logger ++// automatically on non-macOS platforms. ++# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE ++# define USE_APPLE_SYSTEM_LOG 1 ++# else ++# define USE_APPLE_SYSTEM_LOG 0 ++# endif ++ ++# if USE_APPLE_SYSTEM_LOG ++# include ++# endif + #endif + + #ifdef HAVE_SIGNAL_H +@@ -58,6 +72,9 @@ + static PyStatus init_import_site(void); + static PyStatus init_set_builtins_open(void); + static PyStatus init_sys_streams(PyThreadState *tstate); ++#if defined(__APPLE__) && USE_APPLE_SYSTEM_LOG ++static PyStatus init_apple_streams(PyThreadState *tstate); ++#endif + static void wait_for_thread_shutdown(PyThreadState *tstate); + static void call_ll_exitfuncs(_PyRuntimeState *runtime); + +@@ -1126,6 +1143,17 @@ + return status; + } + ++#if defined(__APPLE__) && USE_APPLE_SYSTEM_LOG ++ status = init_apple_streams(tstate); ++ if (_PyStatus_EXCEPTION(status)) { ++ return status; ++ } ++#endif ++ ++#ifdef Py_DEBUG ++ run_presite(tstate); ++#endif ++ + status = add_main_module(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; +@@ -2408,6 +2436,71 @@ + return res; + } + ++#if defined(__APPLE__) && USE_APPLE_SYSTEM_LOG ++ ++static PyObject * ++apple_log_write_impl(PyObject *self, PyObject *args) ++{ ++ int logtype = 0; ++ const char *text = NULL; ++ if (!PyArg_ParseTuple(args, "iy", &logtype, &text)) { ++ return NULL; ++ } ++ ++ // Pass the user-provided text through explicit %s formatting ++ // to avoid % literals being interpreted as a formatting directive. ++ // Using {public} ensures "dynamic" string messages are visible ++ // in the log without special configuration. ++ os_log_with_type(OS_LOG_DEFAULT, logtype, "%{public}s", text); ++ Py_RETURN_NONE; ++} ++ ++ ++static PyMethodDef apple_log_write_method = { ++ "apple_log_write", apple_log_write_impl, METH_VARARGS ++}; ++ ++ ++static PyStatus ++init_apple_streams(PyThreadState *tstate) ++{ ++ PyStatus status = _PyStatus_OK(); ++ PyObject *_apple_support = NULL; ++ PyObject *apple_log_write = NULL; ++ PyObject *result = NULL; ++ ++ _apple_support = PyImport_ImportModule("_apple_support"); ++ if (_apple_support == NULL) { ++ goto error; ++ } ++ ++ apple_log_write = PyCFunction_New(&apple_log_write_method, NULL); ++ if (apple_log_write == NULL) { ++ goto error; ++ } ++ ++ // Initialize the logging streams, sending stdout -> Default; stderr -> Error ++ result = PyObject_CallMethod( ++ _apple_support, "init_streams", "Oii", ++ apple_log_write, OS_LOG_TYPE_DEFAULT, OS_LOG_TYPE_ERROR); ++ if (result == NULL) { ++ goto error; ++ } ++ goto done; ++ ++error: ++ _PyErr_Print(tstate); ++ status = _PyStatus_ERR("failed to initialize Apple log streams"); ++ ++done: ++ Py_XDECREF(result); ++ Py_XDECREF(apple_log_write); ++ Py_XDECREF(_apple_support); ++ return status; ++} ++ ++#endif // __APPLE__ && USE_APPLE_SYSTEM_LOG ++ + + static void + _Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp, +diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h +index 50cf340e543..c1d391e5229 100644 +--- a/Python/stdlib_module_names.h ++++ b/Python/stdlib_module_names.h +@@ -5,6 +5,7 @@ + "__future__", + "_abc", + "_aix_support", ++"_apple_support", + "_ast", + "_asyncio", + "_bisect", +@@ -40,6 +41,7 @@ + "_heapq", + "_imp", + "_io", ++"_ios_support", + "_json", + "_locale", + "_lsprof", +diff --git a/config.sub b/config.sub +index d74fb6deac9..1bb6a05dc11 100755 +--- a/config.sub ++++ b/config.sub +@@ -1,14 +1,15 @@ + #! /bin/sh + # Configuration validation subroutine script. +-# Copyright 1992-2021 Free Software Foundation, Inc. ++# Copyright 1992-2024 Free Software Foundation, Inc. + + # shellcheck disable=SC2006,SC2268 # see below for rationale + +-timestamp='2021-08-14' ++# Patched 2024-02-03 to include support for arm64_32 and iOS/tvOS/watchOS simulators ++timestamp='2024-01-01' + + # This file is free software; you can redistribute it and/or modify it + # under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 3 of the License, or ++# the Free Software Foundation, either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, but +@@ -76,13 +77,13 @@ + version="\ + GNU config.sub ($timestamp) + +-Copyright 1992-2021 Free Software Foundation, Inc. ++Copyright 1992-2024 Free Software Foundation, Inc. + + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + + help=" +-Try \`$me --help' for more information." ++Try '$me --help' for more information." + + # Parse command line + while test $# -gt 0 ; do +@@ -130,7 +131,7 @@ + # Separate into logical components for further validation + case $1 in + *-*-*-*-*) +- echo Invalid configuration \`"$1"\': more than four components >&2 ++ echo "Invalid configuration '$1': more than four components" >&2 + exit 1 + ;; + *-*-*-*) +@@ -145,7 +146,8 @@ + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ +- | storm-chaos* | os2-emx* | rtmk-nova*) ++ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ ++ | windows-* ) + basic_machine=$field1 + basic_os=$maybe_os + ;; +@@ -943,7 +945,7 @@ + EOF + IFS=$saved_IFS + ;; +- # We use `pc' rather than `unknown' ++ # We use 'pc' rather than 'unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) +@@ -1020,6 +1022,11 @@ + ;; + + # Here we normalize CPU types with a missing or matching vendor ++ armh-unknown | armh-alt) ++ cpu=armv7l ++ vendor=alt ++ basic_os=${basic_os:-linux-gnueabihf} ++ ;; + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull +@@ -1070,7 +1077,7 @@ + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 + ;; +- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) ++ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) + cpu=i686 + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) +@@ -1121,7 +1128,7 @@ + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` + ;; +- arm64-*) ++ arm64-* | aarch64le-* | arm64_32-*) + cpu=aarch64 + ;; + +@@ -1175,7 +1182,7 @@ + case $cpu in + 1750a | 580 \ + | a29k \ +- | aarch64 | aarch64_be \ ++ | aarch64 | aarch64_be | aarch64c | arm64ec \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ +@@ -1194,50 +1201,29 @@ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ ++ | javascript \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ ++ | kvx \ + | le32 | le64 \ + | lm32 \ +- | loongarch32 | loongarch64 | loongarchx32 \ ++ | loongarch32 | loongarch64 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ +- | mips | mipsbe | mipseb | mipsel | mipsle \ +- | mips16 \ +- | mips64 | mips64eb | mips64el \ +- | mips64octeon | mips64octeonel \ +- | mips64orion | mips64orionel \ +- | mips64r5900 | mips64r5900el \ +- | mips64vr | mips64vrel \ +- | mips64vr4100 | mips64vr4100el \ +- | mips64vr4300 | mips64vr4300el \ +- | mips64vr5000 | mips64vr5000el \ +- | mips64vr5900 | mips64vr5900el \ +- | mipsisa32 | mipsisa32el \ +- | mipsisa32r2 | mipsisa32r2el \ +- | mipsisa32r3 | mipsisa32r3el \ +- | mipsisa32r5 | mipsisa32r5el \ +- | mipsisa32r6 | mipsisa32r6el \ +- | mipsisa64 | mipsisa64el \ +- | mipsisa64r2 | mipsisa64r2el \ +- | mipsisa64r3 | mipsisa64r3el \ +- | mipsisa64r5 | mipsisa64r5el \ +- | mipsisa64r6 | mipsisa64r6el \ +- | mipsisa64sb1 | mipsisa64sb1el \ +- | mipsisa64sr71k | mipsisa64sr71kel \ +- | mipsr5900 | mipsr5900el \ +- | mipstx39 | mipstx39el \ ++ | mips* \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ ++ | nanomips* \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ +@@ -1269,6 +1255,7 @@ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ ++ | vc4 \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ +@@ -1280,7 +1267,7 @@ + ;; + + *) +- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 ++ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2 + exit 1 + ;; + esac +@@ -1301,11 +1288,12 @@ + + # Decode manufacturer-specific aliases for certain operating systems. + +-if test x$basic_os != x ++if test x"$basic_os" != x + then + +-# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just ++# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just + # set os. ++obj= + case $basic_os in + gnu/linux*) + kernel=linux +@@ -1336,6 +1324,10 @@ + kernel=linux + os=`echo "$basic_os" | sed -e 's|linux|gnu|'` + ;; ++ managarm*) ++ kernel=managarm ++ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'` ++ ;; + *) + kernel= + os=$basic_os +@@ -1501,10 +1493,16 @@ + os=eabi + ;; + *) +- os=elf ++ os= ++ obj=elf + ;; + esac + ;; ++ aout* | coff* | elf* | pe*) ++ # These are machine code file formats, not OSes ++ obj=$os ++ os= ++ ;; + *) + # No normalization, but not necessarily accepted, that comes below. + ;; +@@ -1523,12 +1521,15 @@ + # system, and we'll never get to this point. + + kernel= ++obj= + case $cpu-$vendor in + score-*) +- os=elf ++ os= ++ obj=elf + ;; + spu-*) +- os=elf ++ os= ++ obj=elf + ;; + *-acorn) + os=riscix1.2 +@@ -1538,28 +1539,35 @@ + os=gnu + ;; + arm*-semi) +- os=aout ++ os= ++ obj=aout + ;; + c4x-* | tic4x-*) +- os=coff ++ os= ++ obj=coff + ;; + c8051-*) +- os=elf ++ os= ++ obj=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) +- os=elf ++ os= ++ obj=elf + ;; + tic54x-*) +- os=coff ++ os= ++ obj=coff + ;; + tic55x-*) +- os=coff ++ os= ++ obj=coff + ;; + tic6x-*) +- os=coff ++ os= ++ obj=coff + ;; + # This must come before the *-dec entry. + pdp10-*) +@@ -1581,19 +1589,24 @@ + os=sunos3 + ;; + m68*-cisco) +- os=aout ++ os= ++ obj=aout + ;; + mep-*) +- os=elf ++ os= ++ obj=elf + ;; + mips*-cisco) +- os=elf ++ os= ++ obj=elf + ;; +- mips*-*) +- os=elf ++ mips*-*|nanomips*-*) ++ os= ++ obj=elf + ;; + or32-*) +- os=coff ++ os= ++ obj=coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=sysv3 +@@ -1602,7 +1615,8 @@ + os=sunos4.1.1 + ;; + pru-*) +- os=elf ++ os= ++ obj=elf + ;; + *-be) + os=beos +@@ -1683,10 +1697,12 @@ + os=uxpv + ;; + *-rom68k) +- os=coff ++ os= ++ obj=coff + ;; + *-*bug) +- os=coff ++ os= ++ obj=coff + ;; + *-apple) + os=macos +@@ -1704,10 +1720,11 @@ + + fi + +-# Now, validate our (potentially fixed-up) OS. ++# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ). ++ + case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. +- musl* | newlib* | relibc* | uclibc*) ++ llvm* | musl* | newlib* | relibc* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) +@@ -1715,6 +1732,9 @@ + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; ++ # See `case $cpu-$os` validation below ++ ghcjs) ++ ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. +@@ -1723,7 +1743,7 @@ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ +- | os9* | macos* | osx* | ios* \ ++ | os9* | macos* | osx* | ios* | tvos* | watchos* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ +@@ -1732,11 +1752,11 @@ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ +- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ +- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ ++ | bosx* | nextstep* | cxux* | oabi* \ ++ | ptx* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ +- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ ++ | cygwin* | msys* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ +@@ -1748,49 +1768,119 @@ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ +- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*) ++ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ ++ | fiwix* | mlibc* | cos* | mbr* | ironclad* ) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; ++ # This refers to builds using the UEFI calling convention ++ # (which depends on the architecture) and PE file format. ++ # Note that this is both a different calling convention and ++ # different file format than that of GNU-EFI ++ # (x86_64-w64-mingw32). ++ uefi) ++ ;; + none) + ;; ++ kernel* | msvc* ) ++ # Restricted further below ++ ;; ++ '') ++ if test x"$obj" = x ++ then ++ echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2 ++ fi ++ ;; + *) +- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 ++ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 ++ exit 1 ++ ;; ++esac ++ ++case $obj in ++ aout* | coff* | elf* | pe*) ++ ;; ++ '') ++ # empty is fine ++ ;; ++ *) ++ echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2 ++ exit 1 ++ ;; ++esac ++ ++# Here we handle the constraint that a (synthetic) cpu and os are ++# valid only in combination with each other and nowhere else. ++case $cpu-$os in ++ # The "javascript-unknown-ghcjs" triple is used by GHC; we ++ # accept it here in order to tolerate that, but reject any ++ # variations. ++ javascript-ghcjs) ++ ;; ++ javascript-* | *-ghcjs) ++ echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2 + exit 1 + ;; + esac + + # As a final step for OS-related things, validate the OS-kernel combination + # (given a valid OS), if there is a kernel. +-case $kernel-$os in +- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ +- | linux-musl* | linux-relibc* | linux-uclibc* ) ++case $kernel-$os-$obj in ++ linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \ ++ | linux-mlibc*- | linux-musl*- | linux-newlib*- \ ++ | linux-relibc*- | linux-uclibc*- ) ++ ;; ++ uclinux-uclibc*- ) + ;; +- uclinux-uclibc* ) ++ managarm-mlibc*- | managarm-kernel*- ) + ;; +- -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) ++ windows*-msvc*-) ++ ;; ++ -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \ ++ | -uclibc*- ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. +- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 ++ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 + exit 1 + ;; +- kfreebsd*-gnu* | kopensolaris*-gnu*) ++ -kernel*- ) ++ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 ++ exit 1 + ;; +- vxworks-simlinux | vxworks-simwindows | vxworks-spe) ++ *-kernel*- ) ++ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 ++ exit 1 + ;; +- nto-qnx*) ++ *-msvc*- ) ++ echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 ++ exit 1 + ;; +- os2-emx) ++ kfreebsd*-gnu*- | kopensolaris*-gnu*-) + ;; +- *-eabi* | *-gnueabi*) ++ vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-) + ;; +- -*) ++ nto-qnx*-) ++ ;; ++ os2-emx-) ++ ;; ++ *-eabi*- | *-gnueabi*-) ++ ;; ++ ios*-simulator- | tvos*-simulator- | watchos*-simulator- ) ++ ;; ++ none--*) ++ # None (no kernel, i.e. freestanding / bare metal), ++ # can be paired with an machine code file format ++ ;; ++ -*-) + # Blank kernel with real OS is always fine. + ;; +- *-*) +- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 ++ --*) ++ # Blank kernel and OS with real machine code file format is always fine. ++ ;; ++ *-*-*) ++ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 + exit 1 + ;; + esac +@@ -1873,7 +1963,7 @@ + ;; + esac + +-echo "$cpu-$vendor-${kernel:+$kernel-}$os" ++echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}" + exit + + # Local variables: +diff --git a/configure b/configure +index 4b71c4e00f8..94e8960cd9d 100755 +--- a/configure ++++ b/configure +@@ -660,6 +660,8 @@ + DTRACE + TCLTK_LIBS + TCLTK_INCLUDES ++LIBFFI_LIB ++LIBFFI_LIBDIR + LIBFFI_INCLUDEDIR + PKG_CONFIG_LIBDIR + PKG_CONFIG_PATH +@@ -736,10 +738,14 @@ + LDFLAGS + CFLAGS + CC ++WATCHOS_DEPLOYMENT_TARGET ++TVOS_DEPLOYMENT_TARGET ++IPHONEOS_DEPLOYMENT_TARGET + EXPORT_MACOSX_DEPLOYMENT_TARGET + CONFIGURE_MACOSX_DEPLOYMENT_TARGET + _PYTHON_HOST_PLATFORM +-MACHDEP ++APP_STORE_COMPLIANCE_PATCH ++INSTALLTARGETS + FRAMEWORKINSTALLAPPSPREFIX + FRAMEWORKUNIXTOOLSPREFIX + FRAMEWORKPYTHONW +@@ -747,6 +753,8 @@ + FRAMEWORKALTINSTALLFIRST + FRAMEWORKINSTALLLAST + FRAMEWORKINSTALLFIRST ++RESSRCDIR ++PYTHONFRAMEWORKINSTALLNAMEPREFIX + PYTHONFRAMEWORKINSTALLDIR + PYTHONFRAMEWORKPREFIX + PYTHONFRAMEWORKDIR +@@ -756,6 +764,7 @@ + LIPO_32BIT_FLAGS + ARCH_RUN_32BIT + UNIVERSALSDK ++MACHDEP + CONFIG_ARGS + SOVERSION + VERSION +@@ -793,7 +802,6 @@ + docdir + oldincludedir + includedir +-runstatedir + localstatedir + sharedstatedir + sysconfdir +@@ -820,6 +828,7 @@ + with_universal_archs + with_framework_name + enable_framework ++with_app_store_compliance + with_cxx_main + with_suffix + enable_shared +@@ -917,7 +926,6 @@ + sysconfdir='${prefix}/etc' + sharedstatedir='${prefix}/com' + localstatedir='${prefix}/var' +-runstatedir='${localstatedir}/run' + includedir='${prefix}/include' + oldincludedir='/usr/include' + docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +@@ -1170,15 +1178,6 @@ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + +- -runstatedir | --runstatedir | --runstatedi | --runstated \ +- | --runstate | --runstat | --runsta | --runst | --runs \ +- | --run | --ru | --r) +- ac_prev=runstatedir ;; +- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ +- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ +- | --run=* | --ru=* | --r=*) +- runstatedir=$ac_optarg ;; +- + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ +@@ -1316,7 +1315,7 @@ + for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ +- libdir localedir mandir runstatedir ++ libdir localedir mandir + do + eval ac_val=\$$ac_var + # Remove trailing slashes. +@@ -1469,7 +1468,6 @@ + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] +- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] +@@ -1542,6 +1540,10 @@ + specify the name for the python framework on macOS + only valid when --enable-framework is set. see + Mac/README.rst (default is 'Python') ++ --with-app-store-compliance=[PATCH-FILE] ++ Enable any patches required for compiliance with app ++ stores. Optional PATCH-FILE specifies the custom ++ patch to apply. + --with-cxx-main[=COMPILER] + compile main() and link Python executable with C++ + compiler specified in COMPILER (default is $CXX) +@@ -3007,7 +3009,7 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python interpreter for cross build" >&5 + $as_echo_n "checking for python interpreter for cross build... " >&6; } + if test -z "$PYTHON_FOR_BUILD"; then +- for interp in python$PACKAGE_VERSION python3 python; do ++ for interp in $PYTHON_FOR_REGEN python$PACKAGE_VERSION python3 python; do + which $interp >/dev/null 2>&1 || continue + if $interp -c "import sys;sys.exit(not '.'.join(str(n) for n in sys.version_info[:2]) == '$PACKAGE_VERSION')"; then + break +@@ -3025,6 +3027,8 @@ + as_fn_error $? "Cross compiling required --host=HOST-TUPLE and --build=ARCH" "$LINENO" 5 + else + PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $interp" >&5 ++$as_echo "$interp" >&6; } + fi + + +@@ -3083,6 +3087,166 @@ + + CONFIG_ARGS="$ac_configure_args" + ++# Set name for machine-dependent library files ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking MACHDEP" >&5 ++$as_echo_n "checking MACHDEP... " >&6; } ++if test -z "$MACHDEP" ++then ++ # avoid using uname for cross builds ++ if test "$cross_compiling" = yes; then ++ # ac_sys_system and ac_sys_release are used for setting ++ # a lot of different things including 'define_xopen_source' ++ # in the case statement below. ++ case "$host" in ++ *-*-linux-android*) ++ ac_sys_system=Linux-android ++ ;; ++ *-*-linux*) ++ ac_sys_system=Linux ++ ;; ++ *-*-cygwin*) ++ ac_sys_system=Cygwin ++ ;; ++ *-apple-ios*) ++ ac_sys_system=iOS ++ ;; ++ *-apple-tvos*) ++ ac_sys_system=tvOS ++ ;; ++ *-apple-watchos*) ++ ac_sys_system=watchOS ++ ;; ++ *-*-vxworks*) ++ ac_sys_system=VxWorks ++ ;; ++ *-*-emscripten) ++ ac_sys_system=Emscripten ++ ;; ++ *-*-wasi) ++ ac_sys_system=WASI ++ ;; ++ *) ++ # for now, limit cross builds to known configurations ++ MACHDEP="unknown" ++ as_fn_error $? "cross build not supported for $host" "$LINENO" 5 ++ esac ++ ac_sys_release= ++ else ++ ac_sys_system=`uname -s` ++ if test "$ac_sys_system" = "AIX" \ ++ -o "$ac_sys_system" = "UnixWare" -o "$ac_sys_system" = "OpenUNIX"; then ++ ac_sys_release=`uname -v` ++ else ++ ac_sys_release=`uname -r` ++ fi ++ fi ++ ac_md_system=`echo $ac_sys_system | ++ tr -d '/ ' | tr '[A-Z]' '[a-z]'` ++ ac_md_release=`echo $ac_sys_release | ++ tr -d '/ ' | sed 's/^[A-Z]\.//' | sed 's/\..*//'` ++ MACHDEP="$ac_md_system$ac_md_release" ++ ++ case $MACHDEP in ++ aix*) MACHDEP="aix";; ++ linux*) MACHDEP="linux";; ++ cygwin*) MACHDEP="cygwin";; ++ darwin*) MACHDEP="darwin";; ++ '') MACHDEP="unknown";; ++ esac ++ ++ if test "$ac_sys_system" = "SunOS"; then ++ # For Solaris, there isn't an OS version specific macro defined ++ # in most compilers, so we define one here. ++ SUNOS_VERSION=`echo $ac_sys_release | sed -e 's!\.\(0-9\)$!.0\1!g' | tr -d '.'` ++ ++cat >>confdefs.h <<_ACEOF ++#define Py_SUNOS_VERSION $SUNOS_VERSION ++_ACEOF ++ ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$MACHDEP\"" >&5 ++$as_echo "\"$MACHDEP\"" >&6; } ++ ++# On cross-compile builds, configure will look for a host-specific compiler by ++# prepending the user-provided host triple to the required binary name. ++# ++# On iOS/tvOS/watchOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", ++# which isn't a binary that exists, and isn't very convenient, as it contains the ++# iOS version. As the default cross-compiler name won't exist, configure falls ++# back to gcc, which *definitely* won't work. We're providing wrapper scripts for ++# these tools; the binary names of these scripts are better defaults than "gcc". ++# This only requires that the user put the platform scripts folder (e.g., ++# "iOS/Resources/bin") in their path, rather than defining platform-specific ++# names/paths for AR, CC, CPP, and CXX explicitly; and if the user forgets to ++# either put the platform scripts folder in the path, or specify CC etc, ++# configure will fail. ++if test -z "$AR"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;; ++ aarch64-apple-ios*) AR=arm64-apple-ios-ar ;; ++ x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; ++ ++ aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;; ++ aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;; ++ x86_64-apple-tvos*-simulator) AR=x86_64-apple-tvos-simulator-ar ;; ++ ++ aarch64-apple-watchos*-simulator) AR=arm64-apple-watchos-simulator-ar ;; ++ aarch64-apple-watchos*) AR=arm64_32-apple-watchos-ar ;; ++ x86_64-apple-watchos*-simulator) AR=x86_64-apple-watchos-simulator-ar ;; ++ *) ++ esac ++fi ++if test -z "$CC"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;; ++ aarch64-apple-ios*) CC=arm64-apple-ios-clang ;; ++ x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; ++ ++ aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;; ++ aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;; ++ x86_64-apple-tvos*-simulator) CC=x86_64-apple-tvos-simulator-clang ;; ++ ++ aarch64-apple-watchos*-simulator) CC=arm64-apple-watchos-simulator-clang ;; ++ aarch64-apple-watchos*) CC=arm64_32-apple-watchos-clang ;; ++ x86_64-apple-watchos*-simulator) CC=x86_64-apple-watchos-simulator-clang ;; ++ *) ++ esac ++fi ++if test -z "$CPP"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;; ++ aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;; ++ x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; ++ ++ aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;; ++ aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;; ++ x86_64-apple-tvos*-simulator) CPP=x86_64-apple-tvos-simulator-cpp ;; ++ ++ aarch64-apple-watchos*-simulator) CPP=arm64-apple-watchos-simulator-cpp ;; ++ aarch64-apple-watchos*) CPP=arm64_32-apple-watchos-cpp ;; ++ x86_64-apple-watchos*-simulator) CPP=x86_64-apple-watchos-simulator-cpp ;; ++ *) ++ esac ++fi ++if test -z "$CXX"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;; ++ aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;; ++ x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; ++ ++ aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;; ++ aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;; ++ x86_64-apple-tvos*-simulator) CXX=x86_64-apple-tvos-simulator-clang++ ;; ++ ++ aarch64-apple-watchos*-simulator) CXX=arm64-apple-watchos-simulator-clang++ ;; ++ aarch64-apple-watchos*) CXX=arm64_32-apple-watchos-clang++ ;; ++ x86_64-apple-watchos*-simulator) CXX=x86_64-apple-watchos-simulator-clang++ ;; ++ *) ++ esac ++fi ++ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-universalsdk" >&5 + $as_echo_n "checking for --enable-universalsdk... " >&6; } + # Check whether --enable-universalsdk was given. +@@ -3194,111 +3358,201 @@ + enableval=$enable_framework; + case $enableval in + yes) +- enableval=/Library/Frameworks ++ case $ac_sys_system in ++ Darwin) enableval=/Library/Frameworks ;; ++ iOS) enableval=Apple/iOS/Frameworks/\$\(MULTIARCH\) ;; ++ tvOS) enableval=Apple/tvOS/Frameworks/\$\(MULTIARCH\) ;; ++ watchOS) enableval=Apple/watchOS/Frameworks/\$\(MULTIARCH\) ;; ++ *) as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 ++ esac + esac ++ + case $enableval in + no) +- PYTHONFRAMEWORK= +- PYTHONFRAMEWORKDIR=no-framework +- PYTHONFRAMEWORKPREFIX= +- PYTHONFRAMEWORKINSTALLDIR= +- FRAMEWORKINSTALLFIRST= +- FRAMEWORKINSTALLLAST= +- FRAMEWORKALTINSTALLFIRST= +- FRAMEWORKALTINSTALLLAST= +- FRAMEWORKPYTHONW= +- if test "x${prefix}" = "xNONE"; then +- FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" +- else +- FRAMEWORKUNIXTOOLSPREFIX="${prefix}" +- fi +- enable_framework= ++ case $ac_sys_system in ++ iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; ++ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; ++ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; ++ *) ++ PYTHONFRAMEWORK= ++ PYTHONFRAMEWORKDIR=no-framework ++ PYTHONFRAMEWORKPREFIX= ++ PYTHONFRAMEWORKINSTALLDIR= ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX= ++ RESSRCDIR= ++ FRAMEWORKINSTALLFIRST= ++ FRAMEWORKINSTALLLAST= ++ FRAMEWORKALTINSTALLFIRST= ++ FRAMEWORKALTINSTALLLAST= ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="commoninstall bininstall maninstall" ++ ++ if test "x${prefix}" = "xNONE"; then ++ FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ else ++ FRAMEWORKUNIXTOOLSPREFIX="${prefix}" ++ fi ++ enable_framework= ++ esac + ;; + *) + PYTHONFRAMEWORKPREFIX="${enableval}" + PYTHONFRAMEWORKINSTALLDIR=$PYTHONFRAMEWORKPREFIX/$PYTHONFRAMEWORKDIR +- FRAMEWORKINSTALLFIRST="frameworkinstallstructure" +- FRAMEWORKALTINSTALLFIRST="frameworkinstallstructure " +- FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" +- FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" +- FRAMEWORKPYTHONW="frameworkpythonw" +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" + +- if test "x${prefix}" = "xNONE" ; then +- FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ case $ac_sys_system in #( ++ Darwin) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" ++ FRAMEWORKPYTHONW="frameworkpythonw" ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ INSTALLTARGETS="commoninstall bininstall maninstall" ++ ++ if test "x${prefix}" = "xNONE" ; then ++ FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ ++ else ++ FRAMEWORKUNIXTOOLSPREFIX="${prefix}" ++ fi + +- else +- FRAMEWORKUNIXTOOLSPREFIX="${prefix}" +- fi ++ case "${enableval}" in ++ /System*) ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ if test "${prefix}" = "NONE" ; then ++ # See below ++ FRAMEWORKUNIXTOOLSPREFIX="/usr" ++ fi ++ ;; ++ ++ /Library*) ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ ;; ++ ++ */Library/Frameworks) ++ MDIR="`dirname "${enableval}"`" ++ MDIR="`dirname "${MDIR}"`" ++ FRAMEWORKINSTALLAPPSPREFIX="${MDIR}/Applications" ++ ++ if test "${prefix}" = "NONE"; then ++ # User hasn't specified the ++ # --prefix option, but wants to install ++ # the framework in a non-default location, ++ # ensure that the compatibility links get ++ # installed relative to that prefix as well ++ # instead of in /usr/local. ++ FRAMEWORKUNIXTOOLSPREFIX="${MDIR}" ++ fi ++ ;; + +- case "${enableval}" in +- /System*) +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- if test "${prefix}" = "NONE" ; then +- # See below +- FRAMEWORKUNIXTOOLSPREFIX="/usr" +- fi +- ;; ++ *) ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ ;; ++ esac + +- /Library*) +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- ;; ++ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX=${prefix} ++ RESSRCDIR=Mac/Resources/framework ++ ++ # Add files for Mac specific code to the list of output ++ # files: ++ ac_config_files="$ac_config_files Mac/Makefile" ++ ++ ac_config_files="$ac_config_files Mac/PythonLauncher/Makefile" ++ ++ ac_config_files="$ac_config_files Mac/Resources/framework/Info.plist" ++ ++ ac_config_files="$ac_config_files Mac/Resources/app/Info.plist" ++ ++ ;; ++ iOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/iOS/Resources ++ ++ ac_config_files="$ac_config_files Apple/iOS/Resources/Info.plist" ++ ++ ;; ++ tvOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/tvOS/Resources ++ ++ ac_config_files="$ac_config_files Apple/tvOS/Resources/Info.plist" ++ ++ ;; ++ watchOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" ++ ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/watchOS/Resources ++ ++ ac_config_files="$ac_config_files Apple/watchOS/Resources/Info.plist" ++ ++ ;; ++ *) ++ as_fn_error $? "Unknown platform for framework build" "$LINENO" 5 ++ ;; ++ esac ++ esac + +- */Library/Frameworks) +- MDIR="`dirname "${enableval}"`" +- MDIR="`dirname "${MDIR}"`" +- FRAMEWORKINSTALLAPPSPREFIX="${MDIR}/Applications" +- +- if test "${prefix}" = "NONE"; then +- # User hasn't specified the +- # --prefix option, but wants to install +- # the framework in a non-default location, +- # ensure that the compatibility links get +- # installed relative to that prefix as well +- # instead of in /usr/local. +- FRAMEWORKUNIXTOOLSPREFIX="${MDIR}" +- fi +- ;; ++else + ++ case $ac_sys_system in ++ iOS) as_fn_error $? "iOS builds must use --enable-framework" "$LINENO" 5 ;; ++ tvOS) as_fn_error $? "tvOS builds must use --enable-framework" "$LINENO" 5 ;; ++ watchOS) as_fn_error $? "watchOS builds must use --enable-framework" "$LINENO" 5 ;; + *) +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- ;; +- esac ++ PYTHONFRAMEWORK= ++ PYTHONFRAMEWORKDIR=no-framework ++ PYTHONFRAMEWORKPREFIX= ++ PYTHONFRAMEWORKINSTALLDIR= ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX= ++ RESSRCDIR= ++ FRAMEWORKINSTALLFIRST= ++ FRAMEWORKINSTALLLAST= ++ FRAMEWORKALTINSTALLFIRST= ++ FRAMEWORKALTINSTALLLAST= ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="commoninstall bininstall maninstall" ++ if test "x${prefix}" = "xNONE" ; then ++ FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ else ++ FRAMEWORKUNIXTOOLSPREFIX="${prefix}" ++ fi ++ enable_framework= ++ esac + +- prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++fi + +- # Add files for Mac specific code to the list of output +- # files: +- ac_config_files="$ac_config_files Mac/Makefile" + +- ac_config_files="$ac_config_files Mac/PythonLauncher/Makefile" + +- ac_config_files="$ac_config_files Mac/Resources/framework/Info.plist" + +- ac_config_files="$ac_config_files Mac/Resources/app/Info.plist" + +- esac + +-else + +- PYTHONFRAMEWORK= +- PYTHONFRAMEWORKDIR=no-framework +- PYTHONFRAMEWORKPREFIX= +- PYTHONFRAMEWORKINSTALLDIR= +- FRAMEWORKINSTALLFIRST= +- FRAMEWORKINSTALLLAST= +- FRAMEWORKALTINSTALLFIRST= +- FRAMEWORKALTINSTALLLAST= +- FRAMEWORKPYTHONW= +- if test "x${prefix}" = "xNONE" ; then +- FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" +- else +- FRAMEWORKUNIXTOOLSPREFIX="${prefix}" +- fi +- enable_framework= + + +-fi + + + +@@ -3308,21 +3562,59 @@ + + + ++cat >>confdefs.h <<_ACEOF ++#define _PYTHONFRAMEWORK "${PYTHONFRAMEWORK}" ++_ACEOF ++ + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-app-store-compliance" >&5 ++$as_echo_n "checking for --with-app-store-compliance... " >&6; } ++ ++# Check whether --with-app_store_compliance was given. ++if test "${with_app_store_compliance+set}" = set; then : ++ withval=$with_app_store_compliance; ++ case "$withval" in ++ yes) ++ case $ac_sys_system in ++ Darwin|iOS|tvOS|watchOS) ++ # iOS/tvOS/watchOS is able to share the macOS patch ++ APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ++ ;; ++ *) as_fn_error $? "no default app store compliance patch available for $ac_sys_system" "$LINENO" 5 ;; ++ esac ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 ++$as_echo "applying default app store compliance patch" >&6; } ++ ;; ++ *) ++ APP_STORE_COMPLIANCE_PATCH="${withval}" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: applying custom app store compliance patch" >&5 ++$as_echo "applying custom app store compliance patch" >&6; } ++ ;; ++ esac + ++else + ++ case $ac_sys_system in ++ iOS|tvOS|watchOS) ++ # Always apply the compliance patch on iOS/tvOS/watchOS; we can use the macOS patch ++ APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: applying default app store compliance patch" >&5 ++$as_echo "applying default app store compliance patch" >&6; } ++ ;; ++ *) ++ # No default app compliance patching on any other platform ++ APP_STORE_COMPLIANCE_PATCH= ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not patching for app store compliance" >&5 ++$as_echo "not patching for app store compliance" >&6; } ++ ;; ++ esac ++ ++fi + + + +-cat >>confdefs.h <<_ACEOF +-#define _PYTHONFRAMEWORK "${PYTHONFRAMEWORK}" +-_ACEOF + + +-##AC_ARG_WITH(dyld, +-## AS_HELP_STRING([--with-dyld], +-## [use (OpenStep|Rhapsody) dynamic linker])) +-## + # Set name for machine-dependent library files + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking MACHDEP" >&5 +@@ -3347,6 +3639,12 @@ + *-*-vxworks*) + ac_sys_system=VxWorks + ;; ++ *-*-emscripten) ++ ac_sys_system=Emscripten ++ ;; ++ *-*-wasi) ++ ac_sys_system=WASI ++ ;; + *) + # for now, limit cross builds to known configurations + MACHDEP="unknown" +@@ -3375,34 +3673,110 @@ + darwin*) MACHDEP="darwin";; + '') MACHDEP="unknown";; + esac ++ ++ if test "$ac_sys_system" = "SunOS"; then ++ # For Solaris, there isn't an OS version specific macro defined ++ # in most compilers, so we define one here. ++ SUNOS_VERSION=`echo $ac_sys_release | sed -e 's!\.\(0-9\)$!.0\1!g' | tr -d '.'` ++ ++cat >>confdefs.h <<_ACEOF ++#define Py_SUNOS_VERSION $SUNOS_VERSION ++_ACEOF ++ ++ fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$MACHDEP\"" >&5 + $as_echo "\"$MACHDEP\"" >&6; } + +- + if test "$cross_compiling" = yes; then + case "$host" in + *-*-linux*) + case "$host_cpu" in + arm*) +- _host_cpu=arm ++ _host_ident=arm + ;; + *) +- _host_cpu=$host_cpu ++ _host_ident=$host_cpu + esac + ;; + *-*-cygwin*) +- _host_cpu= ++ _host_ident= ++ ;; ++ *-apple-ios*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} ++ ++ # IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking iOS deployment target" >&5 ++$as_echo_n "checking iOS deployment target... " >&6; } ++ IPHONEOS_DEPLOYMENT_TARGET=${_host_os:3} ++ IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=13.0} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IPHONEOS_DEPLOYMENT_TARGET" >&5 ++$as_echo "$IPHONEOS_DEPLOYMENT_TARGET" >&6; } ++ ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-arm64-iphone${_host_device} ++ ;; ++ *) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-$host_cpu-iphone${_host_device} ++ ;; ++ esac ++ ;; ++ *-apple-tvos*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} ++ ++ # TVOS_DEPLOYMENT_TARGET is the minimum supported tvOS version ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking tvOS deployment target" >&5 ++$as_echo_n "checking tvOS deployment target... " >&6; } ++ TVOS_DEPLOYMENT_TARGET=${_host_os:4} ++ TVOS_DEPLOYMENT_TARGET=${TVOS_DEPLOYMENT_TARGET:=12.0} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TVOS_DEPLOYMENT_TARGET" >&5 ++$as_echo "$TVOS_DEPLOYMENT_TARGET" >&6; } ++ ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${TVOS_DEPLOYMENT_TARGET}-arm64-appletv${_host_device} ++ ;; ++ *) ++ _host_ident=${TVOS_DEPLOYMENT_TARGET}-$host_cpu-appletv${_host_device} ++ ;; ++ esac ++ ;; ++ *-apple-watchos*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} ++ ++ # WATCHOS_DEPLOYMENT_TARGET is the minimum supported watchOS version ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking watchOS deployment target" >&5 ++$as_echo_n "checking watchOS deployment target... " >&6; } ++ WATCHOS_DEPLOYMENT_TARGET=${_host_os:7} ++ WATCHOS_DEPLOYMENT_TARGET=${WATCHOS_DEPLOYMENT_TARGET:=4.0} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WATCHOS_DEPLOYMENT_TARGET" >&5 ++$as_echo "$WATCHOS_DEPLOYMENT_TARGET" >&6; } ++ ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-arm64-watch${_host_device} ++ ;; ++ *) ++ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-$host_cpu-watch${_host_device} ++ ;; ++ esac + ;; + *-*-vxworks*) +- _host_cpu=$host_cpu ++ _host_ident=$host_cpu + ;; + *) + # for now, limit cross builds to known configurations + MACHDEP="unknown" + as_fn_error $? "cross build not supported for $host" "$LINENO" 5 + esac +- _PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}" ++ _PYTHON_HOST_PLATFORM="$MACHDEP${_host_ident:+-$_host_ident}" + fi + + # Some systems cannot stand _XOPEN_SOURCE being defined at all; they +@@ -3469,6 +3843,13 @@ + define_xopen_source=no;; + Darwin/[12][0-9].*) + define_xopen_source=no;; ++ # On iOS/tvOS/watchOS, defining _POSIX_C_SOURCE also disables platform specific features. ++ iOS/*) ++ define_xopen_source=no;; ++ tvOS/*) ++ define_xopen_source=no;; ++ watchOS/*) ++ define_xopen_source=no;; + # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from + # defining NI_NUMERICHOST. + QNX/6.3.2) +@@ -3531,6 +3912,12 @@ + CONFIGURE_MACOSX_DEPLOYMENT_TARGET= + EXPORT_MACOSX_DEPLOYMENT_TARGET='#' + ++# Record the value of IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET / ++# WATCHOS_DEPLOYMENT_TARGET enforced by the selected host triple. ++ ++ ++ ++ + # checks for alternative programs + + # compiler flags are generated in two sets, BASECFLAGS and OPT. OPT is just +@@ -3553,6 +3940,26 @@ + CFLAGS= + fi + ++case $ac_sys_system in #( ++ iOS) : ++ ++ as_fn_append CFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" ++ as_fn_append LDFLAGS " -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}" ++ ;; #( ++ tvOS) : ++ ++ as_fn_append CFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" ++ as_fn_append LDFLAGS " -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}" ++ ;; #( ++ watchOS) : ++ ++ as_fn_append CFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" ++ as_fn_append LDFLAGS " -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}" ++ ;; #( ++ *) : ++ ;; ++esac ++ + if test "$ac_sys_system" = "Darwin" + then + # Compiler selection on MacOSX is more complicated than +@@ -5365,7 +5772,42 @@ + #elif defined(__gnu_hurd__) + i386-gnu + #elif defined(__APPLE__) ++# include "TargetConditionals.h" ++# if TARGET_OS_IOS ++# if TARGET_OS_SIMULATOR ++# if __x86_64__ ++ x86_64-iphonesimulator ++# else ++ arm64-iphonesimulator ++# endif ++# else ++ arm64-iphoneos ++# endif ++# elif TARGET_OS_TV ++# if TARGET_OS_SIMULATOR ++# if __x86_64__ ++ x86_64-appletvsimulator ++# else ++ arm64-appletvsimulator ++# endif ++# else ++ arm64-appletvos ++# endif ++# elif TARGET_OS_WATCH ++# if TARGET_OS_SIMULATOR ++# if __x86_64__ ++ x86_64-watchsimulator ++# else ++ arm64-watchsimulator ++# endif ++# else ++ arm64_32-watchos ++# endif ++# elif TARGET_OS_OSX + darwin ++# else ++# error unknown Apple platform ++# endif + #elif defined(__VXWORKS__) + vxworks + #else +@@ -5389,6 +5831,12 @@ + case $ac_sys_system in #( + Darwin*) : + MULTIARCH="" ;; #( ++ iOS) : ++ MULTIARCH="" ;; #( ++ tvOS) : ++ MULTIARCH="" ;; #( ++ watchOS) : ++ MULTIARCH="" ;; #( + FreeBSD*) : + MULTIARCH="" ;; #( + *) : +@@ -5396,8 +5844,6 @@ + ;; + esac + +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MULTIARCH" >&5 +-$as_echo "$MULTIARCH" >&6; } + + if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then + if test x$PLATFORM_TRIPLET != x$MULTIARCH; then +@@ -5407,6 +5853,16 @@ + MULTIARCH=$PLATFORM_TRIPLET + fi + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MULTIARCH" >&5 ++$as_echo "$MULTIARCH" >&6; } ++ ++case $ac_sys_system in #( ++ iOS|tvOS|watchOS) : ++ SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2` ;; #( ++ *) : ++ SOABI_PLATFORM=$PLATFORM_TRIPLET ++ ;; ++esac + + if test x$MULTIARCH != x; then + MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\"" +@@ -5953,17 +6409,25 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking LDLIBRARY" >&5 + $as_echo_n "checking LDLIBRARY... " >&6; } + +-# MacOSX framework builds need more magic. LDLIBRARY is the dynamic ++# Apple framework builds need more magic. LDLIBRARY is the dynamic + # library that we build, but we do not want to link against it (we + # will find it with a -framework option). For this reason there is an + # extra variable BLDLIBRARY against which Python and the extension + # modules are linked, BLDLIBRARY. This is normally the same as +-# LDLIBRARY, but empty for MacOSX framework builds. ++# LDLIBRARY, but empty for MacOSX framework builds. iOS does the same, ++# but uses a non-versioned framework layout. + if test "$enable_framework" + then +- LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' +- RUNSHARED=DYLD_FRAMEWORK_PATH=`pwd`${DYLD_FRAMEWORK_PATH:+:${DYLD_FRAMEWORK_PATH}} ++ case $ac_sys_system in ++ Darwin) ++ LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; ++ iOS|tvOS|watchOS) ++ LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; ++ *) ++ as_fn_error $? "Unknown platform for framework build" "$LINENO" 5;; ++ esac + BLDLIBRARY='' ++ RUNSHARED=DYLD_FRAMEWORK_PATH=`pwd`${DYLD_FRAMEWORK_PATH:+:${DYLD_FRAMEWORK_PATH}} + else + BLDLIBRARY='$(LDLIBRARY)' + fi +@@ -5976,64 +6440,67 @@ + + case $ac_sys_system in + CYGWIN*) +- LDLIBRARY='libpython$(LDVERSION).dll.a' +- DLLLIBRARY='libpython$(LDVERSION).dll' +- ;; ++ LDLIBRARY='libpython$(LDVERSION).dll.a' ++ DLLLIBRARY='libpython$(LDVERSION).dll' ++ ;; + SunOS*) +- LDLIBRARY='libpython$(LDVERSION).so' +- BLDLIBRARY='-Wl,-R,$(LIBDIR) -L. -lpython$(LDVERSION)' +- RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} +- INSTSONAME="$LDLIBRARY".$SOVERSION +- if test "$with_pydebug" != yes +- then +- PY3LIBRARY=libpython3.so +- fi +- ;; ++ LDLIBRARY='libpython$(LDVERSION).so' ++ BLDLIBRARY='-Wl,-R,$(LIBDIR) -L. -lpython$(LDVERSION)' ++ RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} ++ INSTSONAME="$LDLIBRARY".$SOVERSION ++ if test "$with_pydebug" != yes ++ then ++ PY3LIBRARY=libpython3.so ++ fi ++ ;; + Linux*|GNU*|NetBSD*|FreeBSD*|DragonFly*|OpenBSD*|VxWorks*) +- LDLIBRARY='libpython$(LDVERSION).so' +- BLDLIBRARY='-L. -lpython$(LDVERSION)' +- RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} +- INSTSONAME="$LDLIBRARY".$SOVERSION +- if test "$with_pydebug" != yes +- then +- PY3LIBRARY=libpython3.so +- fi +- ;; ++ LDLIBRARY='libpython$(LDVERSION).so' ++ BLDLIBRARY='-L. -lpython$(LDVERSION)' ++ RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} ++ INSTSONAME="$LDLIBRARY".$SOVERSION ++ if test "$with_pydebug" != yes ++ then ++ PY3LIBRARY=libpython3.so ++ fi ++ ;; + hp*|HP*) +- case `uname -m` in +- ia64) +- LDLIBRARY='libpython$(LDVERSION).so' +- ;; +- *) +- LDLIBRARY='libpython$(LDVERSION).sl' +- ;; +- esac +- BLDLIBRARY='-Wl,+b,$(LIBDIR) -L. -lpython$(LDVERSION)' +- RUNSHARED=SHLIB_PATH=`pwd`${SHLIB_PATH:+:${SHLIB_PATH}} +- ;; ++ case `uname -m` in ++ ia64) ++ LDLIBRARY='libpython$(LDVERSION).so' ++ ;; ++ *) ++ LDLIBRARY='libpython$(LDVERSION).sl' ++ ;; ++ esac ++ BLDLIBRARY='-Wl,+b,$(LIBDIR) -L. -lpython$(LDVERSION)' ++ RUNSHARED=SHLIB_PATH=`pwd`${SHLIB_PATH:+:${SHLIB_PATH}} ++ ;; + Darwin*) +- LDLIBRARY='libpython$(LDVERSION).dylib' +- BLDLIBRARY='-L. -lpython$(LDVERSION)' +- RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} +- ;; ++ LDLIBRARY='libpython$(LDVERSION).dylib' ++ BLDLIBRARY='-L. -lpython$(LDVERSION)' ++ RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} ++ ;; ++ iOS|tvOS|watchOS) ++ LDLIBRARY='libpython$(LDVERSION).dylib' ++ ;; + AIX*) +- LDLIBRARY='libpython$(LDVERSION).so' +- RUNSHARED=LIBPATH=`pwd`${LIBPATH:+:${LIBPATH}} +- ;; ++ LDLIBRARY='libpython$(LDVERSION).so' ++ RUNSHARED=LIBPATH=`pwd`${LIBPATH:+:${LIBPATH}} ++ ;; + + esac + else # shared is disabled + PY_ENABLE_SHARED=0 + case $ac_sys_system in + CYGWIN*) +- BLDLIBRARY='$(LIBRARY)' +- LDLIBRARY='libpython$(LDVERSION).dll.a' +- ;; ++ BLDLIBRARY='$(LIBRARY)' ++ LDLIBRARY='libpython$(LDVERSION).dll.a' ++ ;; + esac + fi + + if test "$cross_compiling" = yes; then +- RUNSHARED= ++ RUNSHARED= + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDLIBRARY" >&5 +@@ -6249,11 +6716,16 @@ + fi + + if test "$cross_compiling" = yes; then +- case "$READELF" in +- readelf|:) +- as_fn_error $? "readelf for the host is required for cross builds" "$LINENO" 5 +- ;; +- esac ++ case "$ac_sys_system" in ++ iOS|tvOS|watchOS) ;; ++ *) ++ case "$READELF" in ++ readelf|:) ++ as_fn_error $? "readelf for the host is required for cross builds" "$LINENO" 5 ++ ;; ++ esac ++ ;; ++ esac + fi + + +@@ -9787,6 +10259,11 @@ + BLDSHARED="$LDSHARED" + fi + ;; ++ iOS/*|tvOS/*|watchOS/*) ++ LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' ++ LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' ++ BLDSHARED="$LDSHARED" ++ ;; + Linux*|GNU*|QNX*|VxWorks*) + LDSHARED='$(CC) -shared' + LDCXXSHARED='$(CXX) -shared';; +@@ -9888,20 +10365,18 @@ + Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; + Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; + # -u libsys_s pulls in all symbols in libsys +- Darwin/*) ++ Darwin/*|iOS/*|tvOS/*|watchOS/*) + LINKFORSHARED="$extra_undefs -framework CoreFoundation" + + # Issue #18075: the default maximum stack size (8MBytes) is too + # small for the default recursion limit. Increase the stack size + # to ensure that tests don't crash +- stack_size="1000000" # 16 MB +- if test "$with_ubsan" = "yes" +- then +- # Undefined behavior sanitizer requires an even deeper stack +- stack_size="4000000" # 64 MB +- fi +- +- LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED" ++ stack_size="1000000" # 16 MB ++ if test "$with_ubsan" = "yes" ++ then ++ # Undefined behavior sanitizer requires an even deeper stack ++ stack_size="4000000" # 64 MB ++ fi + + + cat >>confdefs.h <<_ACEOF +@@ -9909,11 +10384,17 @@ + _ACEOF + + +- if test "$enable_framework" +- then +- LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' ++ if test $ac_sys_system = "Darwin"; then ++ LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED" ++ ++ if test "$enable_framework"; then ++ LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' ++ fi ++ LINKFORSHARED="$LINKFORSHARED" ++ elif test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS"; then ++ LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' + fi +- LINKFORSHARED="$LINKFORSHARED";; ++ ;; + OpenUNIX*|UnixWare*) LINKFORSHARED="-Wl,-Bexport";; + SCO_SV*) LINKFORSHARED="-Wl,-Bexport";; + ReliantUNIX*) LINKFORSHARED="-W1 -Blargedynsym";; +@@ -10796,7 +11277,7 @@ + fi + + +-if test "$ac_sys_system" = "Darwin" ++if test "$ac_sys_system" = "Darwin" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS" + then + case "$with_system_ffi" in + "") +@@ -10824,10 +11305,12 @@ + if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then + LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`" + else +- LIBFFI_INCLUDEDIR="" ++ LIBFFI_INCLUDEDIR="${LIBFFI_INCLUDEDIR}" + fi + + ++ ++ + # Check for use of the system libmpdec library + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-libmpdec" >&5 + $as_echo_n "checking for --with-system-libmpdec... " >&6; } +@@ -11952,18 +12435,18 @@ + + # checks for library functions + for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ +- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \ ++ clock confstr close_range copy_file_range ctermid explicit_bzero \ + explicit_memset faccessat fchmod fchmodat fchown fchownat \ +- fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ +- futimens futimes gai_strerror getentropy \ ++ fdwalk fexecve fdopendir fpathconf fstatat ftime ftruncate futimesat \ ++ futimens futimes gai_strerror \ + getgrgid_r getgrnam_r \ +- getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ ++ getgrouplist getlogin getloadavg getpeername getpgid getpid \ + getpriority getresuid getresgid getpwent getpwnam_r getpwuid_r getspnam getspent getsid getwd \ + if_nameindex \ + initgroups kill killpg lchown lockf linkat lstat lutimes mmap \ + memrchr mbrtowc mkdirat mkfifo \ +- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ +- posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \ ++ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \ ++ posix_fallocate posix_fadvise pread preadv preadv2 \ + pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \ + readlink readlinkat readv realpath renameat \ + sem_open sem_timedwait sem_clockwait sem_getvalue sem_unlink sendfile setegid seteuid \ +@@ -11971,7 +12454,7 @@ + setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ + sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ + sched_rr_get_interval \ +- sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ ++ sigaction sigfillset siginterrupt sigpending sigrelse \ + sigtimedwait sigwait sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ + sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ + truncate uname unlinkat utimensat utimes vfork waitid waitpid wait3 wait4 \ +@@ -12005,6 +12488,44 @@ + + fi + ++# iOS/tvOS/watchOS define some system methods that can be linked (so they are ++# found by configure), but either raise a compilation error (because the ++# header definition prevents usage - autoconf doesn't use the headers), or ++# raise an error if used at runtime. Force these symbols off. ++if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then ++ for ac_func in dup3 getentropy getgroups pipe2 system ++do : ++ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ++ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ++if eval test \"x\$"$as_ac_var"\" = x"yes"; then : ++ cat >>confdefs.h <<_ACEOF ++#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++done ++ ++fi ++ ++# tvOS/watchOS have some additional methods that can be found, but not used. ++if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then ++ for ac_func in \ ++ execv fork posix_spawn posix_spawnp \ ++ sigaltstack \ ++ ++do : ++ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ++ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ++if eval test \"x\$"$as_ac_var"\" = x"yes"; then : ++ cat >>confdefs.h <<_ACEOF ++#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++done ++ ++fi ++ + ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include + #include + " +@@ -12956,9 +13477,10 @@ + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +-# check for openpty and forkpty +- +-for ac_func in openpty ++# check for openpty, login_tty, and forkpty ++# tvOS/watchOS have functions for tty, but can't use them ++if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then ++ for ac_func in openpty + do : + ac_fn_c_check_func "$LINENO" "openpty" "ac_cv_func_openpty" + if test "x$ac_cv_func_openpty" = xyes; then : +@@ -13048,14 +13570,71 @@ + LIBS="$LIBS -lbsd" + fi + ++fi + + fi ++done + ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing login_tty" >&5 ++$as_echo_n "checking for library containing login_tty... " >&6; } ++if ${ac_cv_search_login_tty+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_func_search_save_LIBS=$LIBS ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ + ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char login_tty (); ++int ++main () ++{ ++return login_tty (); ++ ; ++ return 0; ++} ++_ACEOF ++for ac_lib in '' util; do ++ if test -z "$ac_lib"; then ++ ac_res="none required" ++ else ++ ac_res=-l$ac_lib ++ LIBS="-l$ac_lib $ac_func_search_save_LIBS" ++ fi ++ if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_search_login_tty=$ac_res ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext ++ if ${ac_cv_search_login_tty+:} false; then : ++ break + fi + done ++if ${ac_cv_search_login_tty+:} false; then : + +-for ac_func in forkpty ++else ++ ac_cv_search_login_tty=no ++fi ++rm conftest.$ac_ext ++LIBS=$ac_func_search_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_login_tty" >&5 ++$as_echo "$ac_cv_search_login_tty" >&6; } ++ac_res=$ac_cv_search_login_tty ++if test "$ac_res" != no; then : ++ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ++ ++$as_echo "#define HAVE_LOGIN_TTY 1" >>confdefs.h ++ ++ ++fi ++ ++ for ac_func in forkpty + do : + ac_fn_c_check_func "$LINENO" "forkpty" "ac_cv_func_forkpty" + if test "x$ac_cv_func_forkpty" = xyes; then : +@@ -13145,13 +13724,12 @@ + LIBS="$LIBS -lbsd" + fi + +- + fi + +- + fi + done + ++fi + + # check for long file support functions + for ac_func in fseek64 fseeko fstatvfs ftell64 ftello statvfs +@@ -13502,7 +14080,12 @@ + done + + +-for ac_func in clock_settime ++# On iOS, tvOS and watchOS, clock_settime can be linked (so it is found by ++# configure), but when used in an unprivileged process, it crashes rather than ++# returning an error. Force the symbol off. ++if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ++then ++ for ac_func in clock_settime + do : + ac_fn_c_check_func "$LINENO" "clock_settime" "ac_cv_func_clock_settime" + if test "x$ac_cv_func_clock_settime" = xyes; then : +@@ -13512,7 +14095,7 @@ + + else + +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_settime in -lrt" >&5 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_settime in -lrt" >&5 + $as_echo_n "checking for clock_settime in -lrt... " >&6; } + if ${ac_cv_lib_rt_clock_settime+:} false; then : + $as_echo_n "(cached) " >&6 +@@ -13550,7 +14133,7 @@ + $as_echo "$ac_cv_lib_rt_clock_settime" >&6; } + if test "x$ac_cv_lib_rt_clock_settime" = xyes; then : + +- $as_echo "#define HAVE_CLOCK_SETTIME 1" >>confdefs.h ++ $as_echo "#define HAVE_CLOCK_SETTIME 1" >>confdefs.h + + + fi +@@ -13559,6 +14142,7 @@ + fi + done + ++fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for major" >&5 + $as_echo_n "checking for major... " >&6; } +@@ -13638,7 +14222,9 @@ + else + if test "$cross_compiling" = yes; then : + +-if test "${enable_ipv6+set}" = set; then ++if test "$ac_sys_system" = "Linux-android" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS"; then ++ ac_cv_buggy_getaddrinfo="no" ++elif test "${enable_ipv6+set}" = set; then + ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" + else + ac_cv_buggy_getaddrinfo=yes +@@ -15617,7 +16203,7 @@ + $as_echo "$ABIFLAGS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking SOABI" >&5 + $as_echo_n "checking SOABI... " >&6; } +-SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} ++SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${SOABI_PLATFORM:+-$SOABI_PLATFORM} + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SOABI" >&5 + $as_echo "$SOABI" >&6; } + +@@ -15625,7 +16211,7 @@ + if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then + # Similar to SOABI but remove "d" flag from ABIFLAGS + +- ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} ++ ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${SOABI_PLATFORM:+-$SOABI_PLATFORM} + + cat >>confdefs.h <<_ACEOF + #define ALT_SOABI "${ALT_SOABI}" +@@ -16875,24 +17461,28 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for device files" >&5 + $as_echo "$as_me: checking for device files" >&6;} + +-if test "x$cross_compiling" = xyes; then +- if test "${ac_cv_file__dev_ptmx+set}" != set; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptmx" >&5 ++if test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS" ; then ++ ac_cv_file__dev_ptmx=no ++ ac_cv_file__dev_ptc=no ++else ++ if test "x$cross_compiling" = xyes; then ++ if test "${ac_cv_file__dev_ptmx+set}" != set; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptmx" >&5 + $as_echo_n "checking for /dev/ptmx... " >&6; } +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not set" >&5 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not set" >&5 + $as_echo "not set" >&6; } +- as_fn_error $? "set ac_cv_file__dev_ptmx to yes/no in your CONFIG_SITE file when cross compiling" "$LINENO" 5 +- fi +- if test "${ac_cv_file__dev_ptc+set}" != set; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptc" >&5 ++ as_fn_error $? "set ac_cv_file__dev_ptmx to yes/no in your CONFIG_SITE file when cross compiling" "$LINENO" 5 ++ fi ++ if test "${ac_cv_file__dev_ptc+set}" != set; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptc" >&5 + $as_echo_n "checking for /dev/ptc... " >&6; } +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not set" >&5 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not set" >&5 + $as_echo "not set" >&6; } +- as_fn_error $? "set ac_cv_file__dev_ptc to yes/no in your CONFIG_SITE file when cross compiling" "$LINENO" 5 ++ as_fn_error $? "set ac_cv_file__dev_ptc to yes/no in your CONFIG_SITE file when cross compiling" "$LINENO" 5 ++ fi + fi +-fi + +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptmx" >&5 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptmx" >&5 + $as_echo_n "checking for /dev/ptmx... " >&6; } + if ${ac_cv_file__dev_ptmx+:} false; then : + $as_echo_n "(cached) " >&6 +@@ -16911,12 +17501,12 @@ + + fi + +-if test "x$ac_cv_file__dev_ptmx" = xyes; then ++ if test "x$ac_cv_file__dev_ptmx" = xyes; then + + $as_echo "#define HAVE_DEV_PTMX 1" >>confdefs.h + +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptc" >&5 ++ fi ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptc" >&5 + $as_echo_n "checking for /dev/ptc... " >&6; } + if ${ac_cv_file__dev_ptc+:} false; then : + $as_echo_n "(cached) " >&6 +@@ -16935,10 +17525,11 @@ + + fi + +-if test "x$ac_cv_file__dev_ptc" = xyes; then ++ if test "x$ac_cv_file__dev_ptc" = xyes; then + + $as_echo "#define HAVE_DEV_PTC 1" >>confdefs.h + ++ fi + fi + + if test $ac_sys_system = Darwin +@@ -17382,7 +17973,15 @@ + if test "${with_ensurepip+set}" = set; then : + withval=$with_ensurepip; + else +- with_ensurepip=upgrade ++ ++ case $ac_sys_system in #( ++ iOS|tvOS|watchOS) : ++ with_ensurepip=no ;; #( ++ *) : ++ with_ensurepip=upgrade ++ ;; ++esac ++ + fi + + case $with_ensurepip in #( +@@ -18765,6 +19364,9 @@ + "Mac/PythonLauncher/Makefile") CONFIG_FILES="$CONFIG_FILES Mac/PythonLauncher/Makefile" ;; + "Mac/Resources/framework/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/framework/Info.plist" ;; + "Mac/Resources/app/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/app/Info.plist" ;; ++ "Apple/iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Apple/iOS/Resources/Info.plist" ;; ++ "Apple/tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Apple/tvOS/Resources/Info.plist" ;; ++ "Apple/watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES Apple/watchOS/Resources/Info.plist" ;; + "Makefile.pre") CONFIG_FILES="$CONFIG_FILES Makefile.pre" ;; + "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; + "Misc/python-embed.pc") CONFIG_FILES="$CONFIG_FILES Misc/python-embed.pc" ;; +diff --git a/configure.ac b/configure.ac +index ac3be3850a9..5f9e4a4a3e2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -71,7 +71,7 @@ + if test "$cross_compiling" = yes; then + AC_MSG_CHECKING([for python interpreter for cross build]) + if test -z "$PYTHON_FOR_BUILD"; then +- for interp in python$PACKAGE_VERSION python3 python; do ++ for interp in $PYTHON_FOR_REGEN python$PACKAGE_VERSION python3 python; do + which $interp >/dev/null 2>&1 || continue + if $interp -c "import sys;sys.exit(not '.'.join(str(n) for n in sys.version_info@<:@:2@:>@) == '$PACKAGE_VERSION')"; then + break +@@ -88,6 +88,7 @@ + AC_MSG_ERROR([Cross compiling required --host=HOST-TUPLE and --build=ARCH]) + else + PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' ++ AC_MSG_RESULT($interp) + fi + AC_SUBST(PYTHON_FOR_BUILD) + +@@ -154,6 +155,161 @@ + AC_SUBST(CONFIG_ARGS) + CONFIG_ARGS="$ac_configure_args" + ++# Set name for machine-dependent library files ++AC_ARG_VAR([MACHDEP], [name for machine-dependent library files]) ++AC_MSG_CHECKING([MACHDEP]) ++if test -z "$MACHDEP" ++then ++ # avoid using uname for cross builds ++ if test "$cross_compiling" = yes; then ++ # ac_sys_system and ac_sys_release are used for setting ++ # a lot of different things including 'define_xopen_source' ++ # in the case statement below. ++ case "$host" in ++ *-*-linux-android*) ++ ac_sys_system=Linux-android ++ ;; ++ *-*-linux*) ++ ac_sys_system=Linux ++ ;; ++ *-*-cygwin*) ++ ac_sys_system=Cygwin ++ ;; ++ *-apple-ios*) ++ ac_sys_system=iOS ++ ;; ++ *-apple-tvos*) ++ ac_sys_system=tvOS ++ ;; ++ *-apple-watchos*) ++ ac_sys_system=watchOS ++ ;; ++ *-*-vxworks*) ++ ac_sys_system=VxWorks ++ ;; ++ *-*-emscripten) ++ ac_sys_system=Emscripten ++ ;; ++ *-*-wasi) ++ ac_sys_system=WASI ++ ;; ++ *) ++ # for now, limit cross builds to known configurations ++ MACHDEP="unknown" ++ AC_MSG_ERROR([cross build not supported for $host]) ++ esac ++ ac_sys_release= ++ else ++ ac_sys_system=`uname -s` ++ if test "$ac_sys_system" = "AIX" \ ++ -o "$ac_sys_system" = "UnixWare" -o "$ac_sys_system" = "OpenUNIX"; then ++ ac_sys_release=`uname -v` ++ else ++ ac_sys_release=`uname -r` ++ fi ++ fi ++ ac_md_system=`echo $ac_sys_system | ++ tr -d '[/ ]' | tr '[[A-Z]]' '[[a-z]]'` ++ ac_md_release=`echo $ac_sys_release | ++ tr -d '[/ ]' | sed 's/^[[A-Z]]\.//' | sed 's/\..*//'` ++ MACHDEP="$ac_md_system$ac_md_release" ++ ++ case $MACHDEP in ++ aix*) MACHDEP="aix";; ++ linux*) MACHDEP="linux";; ++ cygwin*) MACHDEP="cygwin";; ++ darwin*) MACHDEP="darwin";; ++ '') MACHDEP="unknown";; ++ esac ++ ++ if test "$ac_sys_system" = "SunOS"; then ++ # For Solaris, there isn't an OS version specific macro defined ++ # in most compilers, so we define one here. ++ SUNOS_VERSION=`echo $ac_sys_release | sed -e 's!\.\([0-9]\)$!.0\1!g' | tr -d '.'` ++ AC_DEFINE_UNQUOTED([Py_SUNOS_VERSION], [$SUNOS_VERSION], ++ [The version of SunOS/Solaris as reported by `uname -r' without the dot.]) ++ fi ++fi ++AC_MSG_RESULT(["$MACHDEP"]) ++ ++# On cross-compile builds, configure will look for a host-specific compiler by ++# prepending the user-provided host triple to the required binary name. ++# ++# On iOS/tvOS/watchOS, this results in binaries like "arm64-apple-ios13.0-simulator-gcc", ++# which isn't a binary that exists, and isn't very convenient, as it contains the ++# iOS version. As the default cross-compiler name won't exist, configure falls ++# back to gcc, which *definitely* won't work. We're providing wrapper scripts for ++# these tools; the binary names of these scripts are better defaults than "gcc". ++# This only requires that the user put the platform scripts folder (e.g., ++# "iOS/Resources/bin") in their path, rather than defining platform-specific ++# names/paths for AR, CC, CPP, and CXX explicitly; and if the user forgets to ++# either put the platform scripts folder in the path, or specify CC etc, ++# configure will fail. ++if test -z "$AR"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;; ++ aarch64-apple-ios*) AR=arm64-apple-ios-ar ;; ++ x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;; ++ ++ aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;; ++ aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;; ++ x86_64-apple-tvos*-simulator) AR=x86_64-apple-tvos-simulator-ar ;; ++ ++ aarch64-apple-watchos*-simulator) AR=arm64-apple-watchos-simulator-ar ;; ++ aarch64-apple-watchos*) AR=arm64_32-apple-watchos-ar ;; ++ x86_64-apple-watchos*-simulator) AR=x86_64-apple-watchos-simulator-ar ;; ++ *) ++ esac ++fi ++if test -z "$CC"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;; ++ aarch64-apple-ios*) CC=arm64-apple-ios-clang ;; ++ x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;; + -+watchOS specific arguments to configure -+======================================= ++ aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;; ++ aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;; ++ x86_64-apple-tvos*-simulator) CC=x86_64-apple-tvos-simulator-clang ;; + -+* ``--enable-framework[=DIR]`` ++ aarch64-apple-watchos*-simulator) CC=arm64-apple-watchos-simulator-clang ;; ++ aarch64-apple-watchos*) CC=arm64_32-apple-watchos-clang ;; ++ x86_64-apple-watchos*-simulator) CC=x86_64-apple-watchos-simulator-clang ;; ++ *) ++ esac ++fi ++if test -z "$CPP"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;; ++ aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;; ++ x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;; + -+ This argument specifies the location where the Python.framework will -+ be installed. ++ aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;; ++ aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;; ++ x86_64-apple-tvos*-simulator) CPP=x86_64-apple-tvos-simulator-cpp ;; + -+* ``--with-framework-name=NAME`` ++ aarch64-apple-watchos*-simulator) CPP=arm64-apple-watchos-simulator-cpp ;; ++ aarch64-apple-watchos*) CPP=arm64_32-apple-watchos-cpp ;; ++ x86_64-apple-watchos*-simulator) CPP=x86_64-apple-watchos-simulator-cpp ;; ++ *) ++ esac ++fi ++if test -z "$CXX"; then ++ case "$host" in ++ aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;; ++ aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;; ++ x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;; + -+ Specify the name for the python framework, defaults to ``Python``. ++ aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;; ++ aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;; ++ x86_64-apple-tvos*-simulator) CXX=x86_64-apple-tvos-simulator-clang++ ;; + ++ aarch64-apple-watchos*-simulator) CXX=arm64-apple-watchos-simulator-clang++ ;; ++ aarch64-apple-watchos*) CXX=arm64_32-apple-watchos-clang++ ;; ++ x86_64-apple-watchos*-simulator) CXX=x86_64-apple-watchos-simulator-clang++ ;; ++ *) ++ esac ++fi + -+Building and using Python on watchOS -+==================================== + AC_MSG_CHECKING([for --enable-universalsdk]) + AC_ARG_ENABLE(universalsdk, + AS_HELP_STRING([--enable-universalsdk@<:@=SDKDIR@:>@], +@@ -263,123 +419,243 @@ + [ + case $enableval in + yes) +- enableval=/Library/Frameworks ++ case $ac_sys_system in ++ Darwin) enableval=/Library/Frameworks ;; ++ iOS) enableval=Apple/iOS/Frameworks/\$\(MULTIARCH\) ;; ++ tvOS) enableval=Apple/tvOS/Frameworks/\$\(MULTIARCH\) ;; ++ watchOS) enableval=Apple/watchOS/Frameworks/\$\(MULTIARCH\) ;; ++ *) AC_MSG_ERROR([Unknown platform for framework build]) ++ esac + esac + -+ABIs and Architectures -+---------------------- + case $enableval in + no) +- PYTHONFRAMEWORK= +- PYTHONFRAMEWORKDIR=no-framework +- PYTHONFRAMEWORKPREFIX= +- PYTHONFRAMEWORKINSTALLDIR= +- FRAMEWORKINSTALLFIRST= +- FRAMEWORKINSTALLLAST= +- FRAMEWORKALTINSTALLFIRST= +- FRAMEWORKALTINSTALLLAST= +- FRAMEWORKPYTHONW= +- if test "x${prefix}" = "xNONE"; then +- FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" +- else +- FRAMEWORKUNIXTOOLSPREFIX="${prefix}" +- fi +- enable_framework= ++ case $ac_sys_system in ++ iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; ++ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; ++ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; ++ *) ++ PYTHONFRAMEWORK= ++ PYTHONFRAMEWORKDIR=no-framework ++ PYTHONFRAMEWORKPREFIX= ++ PYTHONFRAMEWORKINSTALLDIR= ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX= ++ RESSRCDIR= ++ FRAMEWORKINSTALLFIRST= ++ FRAMEWORKINSTALLLAST= ++ FRAMEWORKALTINSTALLFIRST= ++ FRAMEWORKALTINSTALLLAST= ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="commoninstall bininstall maninstall" ++ ++ if test "x${prefix}" = "xNONE"; then ++ FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ else ++ FRAMEWORKUNIXTOOLSPREFIX="${prefix}" ++ fi ++ enable_framework= ++ esac + ;; + *) + PYTHONFRAMEWORKPREFIX="${enableval}" + PYTHONFRAMEWORKINSTALLDIR=$PYTHONFRAMEWORKPREFIX/$PYTHONFRAMEWORKDIR +- FRAMEWORKINSTALLFIRST="frameworkinstallstructure" +- FRAMEWORKALTINSTALLFIRST="frameworkinstallstructure " +- FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" +- FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" +- FRAMEWORKPYTHONW="frameworkpythonw" +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- +- if test "x${prefix}" = "xNONE" ; then +- FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" + +- else +- FRAMEWORKUNIXTOOLSPREFIX="${prefix}" +- fi ++ case $ac_sys_system in #( ++ Darwin) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" ++ FRAMEWORKPYTHONW="frameworkpythonw" ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ INSTALLTARGETS="commoninstall bininstall maninstall" ++ ++ if test "x${prefix}" = "xNONE" ; then ++ FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ ++ else ++ FRAMEWORKUNIXTOOLSPREFIX="${prefix}" ++ fi + +- case "${enableval}" in +- /System*) +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- if test "${prefix}" = "NONE" ; then +- # See below +- FRAMEWORKUNIXTOOLSPREFIX="/usr" +- fi +- ;; ++ case "${enableval}" in ++ /System*) ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ if test "${prefix}" = "NONE" ; then ++ # See below ++ FRAMEWORKUNIXTOOLSPREFIX="/usr" ++ fi ++ ;; ++ ++ /Library*) ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ ;; ++ ++ */Library/Frameworks) ++ MDIR="`dirname "${enableval}"`" ++ MDIR="`dirname "${MDIR}"`" ++ FRAMEWORKINSTALLAPPSPREFIX="${MDIR}/Applications" ++ ++ if test "${prefix}" = "NONE"; then ++ # User hasn't specified the ++ # --prefix option, but wants to install ++ # the framework in a non-default location, ++ # ensure that the compatibility links get ++ # installed relative to that prefix as well ++ # instead of in /usr/local. ++ FRAMEWORKUNIXTOOLSPREFIX="${MDIR}" ++ fi ++ ;; + +- /Library*) +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- ;; +- +- */Library/Frameworks) +- MDIR="`dirname "${enableval}"`" +- MDIR="`dirname "${MDIR}"`" +- FRAMEWORKINSTALLAPPSPREFIX="${MDIR}/Applications" +- +- if test "${prefix}" = "NONE"; then +- # User hasn't specified the +- # --prefix option, but wants to install +- # the framework in a non-default location, +- # ensure that the compatibility links get +- # installed relative to that prefix as well +- # instead of in /usr/local. +- FRAMEWORKUNIXTOOLSPREFIX="${MDIR}" +- fi +- ;; ++ *) ++ FRAMEWORKINSTALLAPPSPREFIX="/Applications" ++ ;; ++ esac + +- *) +- FRAMEWORKINSTALLAPPSPREFIX="/Applications" +- ;; ++ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX=${prefix} ++ RESSRCDIR=Mac/Resources/framework ++ ++ # Add files for Mac specific code to the list of output ++ # files: ++ AC_CONFIG_FILES([Mac/Makefile]) ++ AC_CONFIG_FILES([Mac/PythonLauncher/Makefile]) ++ AC_CONFIG_FILES([Mac/Resources/framework/Info.plist]) ++ AC_CONFIG_FILES([Mac/Resources/app/Info.plist]) ++ ;; ++ iOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+watchOS apps can be deployed on physical devices, and on the watchOS simulator. -+Although the API used on these devices is identical, the ABI is different - you -+need to link against different libraries for an watchOS device build -+(``watchos``) or an watchOS simulator build (``watchsimulator``). Apple uses the -+XCframework format to allow specifying a single dependency that supports -+multiple ABIs. An XCframework is a wrapper around multiple ABI-specific -+frameworks. ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/iOS/Resources + -+watchOS can also support different CPU architectures within each ABI. At present, -+there is only a single support ed architecture on physical devices - ARM64. -+However, the *simulator* supports 2 architectures - ARM64 (for running on Apple -+Silicon machines), and x86_64 (for running on older Intel-based machines.) ++ AC_CONFIG_FILES([Apple/iOS/Resources/Info.plist]) ++ ;; ++ tvOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+To support multiple CPU architectures on a single platform, Apple uses a "fat -+binary" format - a single physical file that contains support for multiple -+architectures. ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/tvOS/Resources + -+How do I build Python for watchOS? -+------------------------------- ++ AC_CONFIG_FILES([Apple/tvOS/Resources/Info.plist]) ++ ;; ++ watchOS) : ++ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure" ++ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure " ++ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders" ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="libinstall inclinstall sharedinstall" + -+The Python build system will build a ``Python.framework`` that supports a -+*single* ABI with a *single* architecture. If you want to use Python in an watchOS -+project, you need to: ++ prefix=$PYTHONFRAMEWORKPREFIX ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR" ++ RESSRCDIR=Apple/watchOS/Resources + -+1. Produce multiple ``Python.framework`` builds, one for each ABI and architecture; -+2. Merge the binaries for each architecture on a given ABI into a single "fat" binary; -+3. Merge the "fat" frameworks for each ABI into a single XCframework. ++ AC_CONFIG_FILES([Apple/watchOS/Resources/Info.plist]) ++ ;; ++ *) ++ AC_MSG_ERROR([Unknown platform for framework build]) ++ ;; ++ esac + esac +- +- prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION +- +- # Add files for Mac specific code to the list of output +- # files: +- AC_CONFIG_FILES(Mac/Makefile) +- AC_CONFIG_FILES(Mac/PythonLauncher/Makefile) +- AC_CONFIG_FILES(Mac/Resources/framework/Info.plist) +- AC_CONFIG_FILES(Mac/Resources/app/Info.plist) +- esac + ],[ +- PYTHONFRAMEWORK= +- PYTHONFRAMEWORKDIR=no-framework +- PYTHONFRAMEWORKPREFIX= +- PYTHONFRAMEWORKINSTALLDIR= +- FRAMEWORKINSTALLFIRST= +- FRAMEWORKINSTALLLAST= +- FRAMEWORKALTINSTALLFIRST= +- FRAMEWORKALTINSTALLLAST= +- FRAMEWORKPYTHONW= +- if test "x${prefix}" = "xNONE" ; then +- FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" +- else +- FRAMEWORKUNIXTOOLSPREFIX="${prefix}" +- fi +- enable_framework= +- ++ case $ac_sys_system in ++ iOS) AC_MSG_ERROR([iOS builds must use --enable-framework]) ;; ++ tvOS) AC_MSG_ERROR([tvOS builds must use --enable-framework]) ;; ++ watchOS) AC_MSG_ERROR([watchOS builds must use --enable-framework]) ;; ++ *) ++ PYTHONFRAMEWORK= ++ PYTHONFRAMEWORKDIR=no-framework ++ PYTHONFRAMEWORKPREFIX= ++ PYTHONFRAMEWORKINSTALLDIR= ++ PYTHONFRAMEWORKINSTALLNAMEPREFIX= ++ RESSRCDIR= ++ FRAMEWORKINSTALLFIRST= ++ FRAMEWORKINSTALLLAST= ++ FRAMEWORKALTINSTALLFIRST= ++ FRAMEWORKALTINSTALLLAST= ++ FRAMEWORKPYTHONW= ++ INSTALLTARGETS="commoninstall bininstall maninstall" ++ if test "x${prefix}" = "xNONE" ; then ++ FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}" ++ else ++ FRAMEWORKUNIXTOOLSPREFIX="${prefix}" ++ fi ++ enable_framework= ++ esac + ]) +-AC_SUBST(PYTHONFRAMEWORK) +-AC_SUBST(PYTHONFRAMEWORKIDENTIFIER) +-AC_SUBST(PYTHONFRAMEWORKDIR) +-AC_SUBST(PYTHONFRAMEWORKPREFIX) +-AC_SUBST(PYTHONFRAMEWORKINSTALLDIR) +-AC_SUBST(FRAMEWORKINSTALLFIRST) +-AC_SUBST(FRAMEWORKINSTALLLAST) +-AC_SUBST(FRAMEWORKALTINSTALLFIRST) +-AC_SUBST(FRAMEWORKALTINSTALLLAST) +-AC_SUBST(FRAMEWORKPYTHONW) +-AC_SUBST(FRAMEWORKUNIXTOOLSPREFIX) +-AC_SUBST(FRAMEWORKINSTALLAPPSPREFIX) ++AC_SUBST([PYTHONFRAMEWORK]) ++AC_SUBST([PYTHONFRAMEWORKIDENTIFIER]) ++AC_SUBST([PYTHONFRAMEWORKDIR]) ++AC_SUBST([PYTHONFRAMEWORKPREFIX]) ++AC_SUBST([PYTHONFRAMEWORKINSTALLDIR]) ++AC_SUBST([PYTHONFRAMEWORKINSTALLNAMEPREFIX]) ++AC_SUBST([RESSRCDIR]) ++AC_SUBST([FRAMEWORKINSTALLFIRST]) ++AC_SUBST([FRAMEWORKINSTALLLAST]) ++AC_SUBST([FRAMEWORKALTINSTALLFIRST]) ++AC_SUBST([FRAMEWORKALTINSTALLLAST]) ++AC_SUBST([FRAMEWORKPYTHONW]) ++AC_SUBST([FRAMEWORKUNIXTOOLSPREFIX]) ++AC_SUBST([FRAMEWORKINSTALLAPPSPREFIX]) ++AC_SUBST([INSTALLTARGETS]) + + AC_DEFINE_UNQUOTED(_PYTHONFRAMEWORK, "${PYTHONFRAMEWORK}", [framework name]) + +-##AC_ARG_WITH(dyld, +-## AS_HELP_STRING([--with-dyld], +-## [use (OpenStep|Rhapsody) dynamic linker])) +-## ++dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output ++AC_MSG_CHECKING([for --with-app-store-compliance]) ++AC_ARG_WITH( ++ [app_store_compliance], ++ [AS_HELP_STRING( ++ [--with-app-store-compliance=@<:@PATCH-FILE@:>@], ++ [Enable any patches required for compiliance with app stores. ++ Optional PATCH-FILE specifies the custom patch to apply.] ++ )],[ ++ case "$withval" in ++ yes) ++ case $ac_sys_system in ++ Darwin|iOS|tvOS|watchOS) ++ # iOS/tvOS/watchOS is able to share the macOS patch ++ APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ++ ;; ++ *) AC_MSG_ERROR([no default app store compliance patch available for $ac_sys_system]) ;; ++ esac ++ AC_MSG_RESULT([applying default app store compliance patch]) ++ ;; ++ *) ++ APP_STORE_COMPLIANCE_PATCH="${withval}" ++ AC_MSG_RESULT([applying custom app store compliance patch]) ++ ;; ++ esac ++ ],[ ++ case $ac_sys_system in ++ iOS|tvOS|watchOS) ++ # Always apply the compliance patch on iOS/tvOS/watchOS; we can use the macOS patch ++ APP_STORE_COMPLIANCE_PATCH="Mac/Resources/app-store-compliance.patch" ++ AC_MSG_RESULT([applying default app store compliance patch]) ++ ;; ++ *) ++ # No default app compliance patching on any other platform ++ APP_STORE_COMPLIANCE_PATCH= ++ AC_MSG_RESULT([not patching for app store compliance]) ++ ;; ++ esac ++]) ++AC_SUBST([APP_STORE_COMPLIANCE_PATCH]) ++ ++AC_SUBST([_PYTHON_HOST_PLATFORM]) ++ + # Set name for machine-dependent library files + AC_ARG_VAR([MACHDEP], [name for machine-dependent library files]) + AC_MSG_CHECKING(MACHDEP) +@@ -403,6 +679,12 @@ + *-*-vxworks*) + ac_sys_system=VxWorks + ;; ++ *-*-emscripten) ++ ac_sys_system=Emscripten ++ ;; ++ *-*-wasi) ++ ac_sys_system=WASI ++ ;; + *) + # for now, limit cross builds to known configurations + MACHDEP="unknown" +@@ -431,33 +713,100 @@ + darwin*) MACHDEP="darwin";; + '') MACHDEP="unknown";; + esac + -+watchOS builds of Python *must* be constructed as framework builds. To support this, -+you must provide the ``--enable-framework`` flag when configuring the build. ++ if test "$ac_sys_system" = "SunOS"; then ++ # For Solaris, there isn't an OS version specific macro defined ++ # in most compilers, so we define one here. ++ SUNOS_VERSION=`echo $ac_sys_release | sed -e 's!\.\([0-9]\)$!.0\1!g' | tr -d '.'` ++ AC_DEFINE_UNQUOTED([Py_SUNOS_VERSION], [$SUNOS_VERSION], ++ [The version of SunOS/Solaris as reported by `uname -r' without the dot.]) ++ fi + fi + AC_MSG_RESULT("$MACHDEP") + +-AC_SUBST(_PYTHON_HOST_PLATFORM) + if test "$cross_compiling" = yes; then + case "$host" in + *-*-linux*) + case "$host_cpu" in + arm*) +- _host_cpu=arm ++ _host_ident=arm + ;; + *) +- _host_cpu=$host_cpu ++ _host_ident=$host_cpu + esac + ;; + *-*-cygwin*) +- _host_cpu= ++ _host_ident= ++ ;; ++ *-apple-ios*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} + -+The build also requires the use of cross-compilation. The commands for building -+Python for watchOS will look somethign like:: ++ # IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version ++ AC_MSG_CHECKING([iOS deployment target]) ++ IPHONEOS_DEPLOYMENT_TARGET=${_host_os:3} ++ IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=13.0} ++ AC_MSG_RESULT([$IPHONEOS_DEPLOYMENT_TARGET]) + -+ $ ./configure \ -+ --enable-framework=/path/to/install \ -+ --host=aarch64-apple-watchos \ -+ --build=aarch64-apple-darwin \ -+ --with-build-python=/path/to/python.exe -+ $ make -+ $ make install ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-arm64-iphone${_host_device} ++ ;; ++ *) ++ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-$host_cpu-iphone${_host_device} ++ ;; ++ esac ++ ;; ++ *-apple-tvos*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} + -+In this invocation: ++ # TVOS_DEPLOYMENT_TARGET is the minimum supported tvOS version ++ AC_MSG_CHECKING([tvOS deployment target]) ++ TVOS_DEPLOYMENT_TARGET=${_host_os:4} ++ TVOS_DEPLOYMENT_TARGET=${TVOS_DEPLOYMENT_TARGET:=12.0} ++ AC_MSG_RESULT([$TVOS_DEPLOYMENT_TARGET]) + -+* ``/path/to/install`` is the location where the final Python.framework will be -+ output. ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${TVOS_DEPLOYMENT_TARGET}-arm64-appletv${_host_device} ++ ;; ++ *) ++ _host_ident=${TVOS_DEPLOYMENT_TARGET}-$host_cpu-appletv${_host_device} ++ ;; ++ esac ++ ;; ++ *-apple-watchos*) ++ _host_os=`echo $host | cut -d '-' -f3` ++ _host_device=`echo $host | cut -d '-' -f4` ++ _host_device=${_host_device:=os} + -+* ``--host`` is the architecture and ABI that you want to build, in GNU compiler -+ triple format. This will be one of: ++ # WATCHOS_DEPLOYMENT_TARGET is the minimum supported watchOS version ++ AC_MSG_CHECKING([watchOS deployment target]) ++ WATCHOS_DEPLOYMENT_TARGET=${_host_os:7} ++ WATCHOS_DEPLOYMENT_TARGET=${WATCHOS_DEPLOYMENT_TARGET:=4.0} ++ AC_MSG_RESULT([$WATCHOS_DEPLOYMENT_TARGET]) + -+ - ``arm64_32-apple-watchos`` for ARM64-32 watchOS devices. -+ - ``aarch64-apple-watchos-simulator`` for the watchOS simulator running on Apple -+ Silicon devices. -+ - ``x86_64-apple-watchos-simulator`` for the watchOS simulator running on Intel -+ devices. ++ case "$host_cpu" in ++ aarch64) ++ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-arm64-watch${_host_device} ++ ;; ++ *) ++ _host_ident=${WATCHOS_DEPLOYMENT_TARGET}-$host_cpu-watch${_host_device} ++ ;; ++ esac + ;; + *-*-vxworks*) +- _host_cpu=$host_cpu ++ _host_ident=$host_cpu + ;; + *) + # for now, limit cross builds to known configurations + MACHDEP="unknown" + AC_MSG_ERROR([cross build not supported for $host]) + esac +- _PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}" ++ _PYTHON_HOST_PLATFORM="$MACHDEP${_host_ident:+-$_host_ident}" + fi + + # Some systems cannot stand _XOPEN_SOURCE being defined at all; they +@@ -521,6 +870,13 @@ + define_xopen_source=no;; + Darwin/@<:@[12]@:>@@<:@0-9@:>@.*) + define_xopen_source=no;; ++ # On iOS/tvOS/watchOS, defining _POSIX_C_SOURCE also disables platform specific features. ++ iOS/*) ++ define_xopen_source=no;; ++ tvOS/*) ++ define_xopen_source=no;; ++ watchOS/*) ++ define_xopen_source=no;; + # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from + # defining NI_NUMERICHOST. + QNX/6.3.2) +@@ -577,6 +933,12 @@ + CONFIGURE_MACOSX_DEPLOYMENT_TARGET= + EXPORT_MACOSX_DEPLOYMENT_TARGET='#' + ++# Record the value of IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET / ++# WATCHOS_DEPLOYMENT_TARGET enforced by the selected host triple. ++AC_SUBST([IPHONEOS_DEPLOYMENT_TARGET]) ++AC_SUBST([TVOS_DEPLOYMENT_TARGET]) ++AC_SUBST([WATCHOS_DEPLOYMENT_TARGET]) + -+* ``--build`` is the GNU compiler triple for the machine that will be running -+ the compiler. This is one of: + # checks for alternative programs + + # compiler flags are generated in two sets, BASECFLAGS and OPT. OPT is just +@@ -599,6 +961,20 @@ + CFLAGS= + fi + ++dnl Add the compiler flag for the iOS/tvOS/watchOS minimum supported OS version. ++AS_CASE([$ac_sys_system], ++ [iOS], [ ++ AS_VAR_APPEND([CFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) ++ AS_VAR_APPEND([LDFLAGS], [" -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}"]) ++ ],[tvOS], [ ++ AS_VAR_APPEND([CFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) ++ AS_VAR_APPEND([LDFLAGS], [" -mtvos-version-min=${TVOS_DEPLOYMENT_TARGET}"]) ++ ],[watchOS], [ ++ AS_VAR_APPEND([CFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) ++ AS_VAR_APPEND([LDFLAGS], [" -mwatchos-version-min=${WATCHOS_DEPLOYMENT_TARGET}"]) ++ ], ++) + -+ - ``aarch64-apple-darwin`` for Apple Silicon devices. -+ - ``x86_64-apple-darwin`` for Intel devices. + if test "$ac_sys_system" = "Darwin" + then + # Compiler selection on MacOSX is more complicated than +@@ -855,7 +1231,42 @@ + #elif defined(__gnu_hurd__) + i386-gnu + #elif defined(__APPLE__) ++# include "TargetConditionals.h" ++# if TARGET_OS_IOS ++# if TARGET_OS_SIMULATOR ++# if __x86_64__ ++ x86_64-iphonesimulator ++# else ++ arm64-iphonesimulator ++# endif ++# else ++ arm64-iphoneos ++# endif ++# elif TARGET_OS_TV ++# if TARGET_OS_SIMULATOR ++# if __x86_64__ ++ x86_64-appletvsimulator ++# else ++ arm64-appletvsimulator ++# endif ++# else ++ arm64-appletvos ++# endif ++# elif TARGET_OS_WATCH ++# if TARGET_OS_SIMULATOR ++# if __x86_64__ ++ x86_64-watchsimulator ++# else ++ arm64-watchsimulator ++# endif ++# else ++ arm64_32-watchos ++# endif ++# elif TARGET_OS_OSX + darwin ++# else ++# error unknown Apple platform ++# endif + #elif defined(__VXWORKS__) + vxworks + #else +@@ -872,14 +1283,24 @@ + fi + rm -f conftest.c conftest.out + ++dnl On some platforms, using a true "triplet" for MULTIARCH would be redundant. ++dnl For example, `arm64-apple-darwin` is redundant, because there isn't a ++dnl non-Apple Darwin. Including the CPU architecture can also be potentially ++dnl redundant - on macOS, for example, it's possible to do a single compile ++dnl pass that includes multiple architectures, so it would be misleading for ++dnl MULTIARCH (and thus the sysconfigdata module name) to include a single CPU ++dnl architecture. PLATFORM_TRIPLET will be a pair or single value for these ++dnl platforms. + AC_MSG_CHECKING([for multiarch]) + AS_CASE([$ac_sys_system], + [Darwin*], [MULTIARCH=""], ++ [iOS], [MULTIARCH=""], ++ [tvOS], [MULTIARCH=""], ++ [watchOS], [MULTIARCH=""], + [FreeBSD*], [MULTIARCH=""], + [MULTIARCH=$($CC --print-multiarch 2>/dev/null)] + ) + AC_SUBST([MULTIARCH]) +-AC_MSG_RESULT([$MULTIARCH]) + + if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then + if test x$PLATFORM_TRIPLET != x$MULTIARCH; then +@@ -888,7 +1309,18 @@ + elif test x$PLATFORM_TRIPLET != x && test x$MULTIARCH = x; then + MULTIARCH=$PLATFORM_TRIPLET + fi +-AC_SUBST(PLATFORM_TRIPLET) ++AC_SUBST([PLATFORM_TRIPLET]) ++AC_MSG_RESULT([$MULTIARCH]) ++ ++dnl Even if we *do* include the CPU architecture in the MULTIARCH value, some ++dnl platforms don't need the CPU architecture in the SOABI tag. These platforms ++dnl will have multiple sysconfig modules (one for each CPU architecture), but ++dnl use a single "fat" binary at runtime. SOABI_PLATFORM is the component of ++dnl the PLATFORM_TRIPLET that will be used in binary module extensions. ++AS_CASE([$ac_sys_system], ++ [iOS|tvOS|watchOS], [SOABI_PLATFORM=`echo "$PLATFORM_TRIPLET" | cut -d '-' -f2`], ++ [SOABI_PLATFORM=$PLATFORM_TRIPLET] ++) + + if test x$MULTIARCH != x; then + MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\"" +@@ -1115,17 +1547,25 @@ + + AC_MSG_CHECKING(LDLIBRARY) + +-# MacOSX framework builds need more magic. LDLIBRARY is the dynamic ++# Apple framework builds need more magic. LDLIBRARY is the dynamic + # library that we build, but we do not want to link against it (we + # will find it with a -framework option). For this reason there is an + # extra variable BLDLIBRARY against which Python and the extension + # modules are linked, BLDLIBRARY. This is normally the same as +-# LDLIBRARY, but empty for MacOSX framework builds. ++# LDLIBRARY, but empty for MacOSX framework builds. iOS does the same, ++# but uses a non-versioned framework layout. + if test "$enable_framework" + then +- LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' +- RUNSHARED=DYLD_FRAMEWORK_PATH=`pwd`${DYLD_FRAMEWORK_PATH:+:${DYLD_FRAMEWORK_PATH}} ++ case $ac_sys_system in ++ Darwin) ++ LDLIBRARY='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)';; ++ iOS|tvOS|watchOS) ++ LDLIBRARY='$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)';; ++ *) ++ AC_MSG_ERROR([Unknown platform for framework build]);; ++ esac + BLDLIBRARY='' ++ RUNSHARED=DYLD_FRAMEWORK_PATH=`pwd`${DYLD_FRAMEWORK_PATH:+:${DYLD_FRAMEWORK_PATH}} + else + BLDLIBRARY='$(LDLIBRARY)' + fi +@@ -1136,64 +1576,67 @@ + AC_DEFINE(Py_ENABLE_SHARED, 1, [Defined if Python is built as a shared library.]) + case $ac_sys_system in + CYGWIN*) +- LDLIBRARY='libpython$(LDVERSION).dll.a' +- DLLLIBRARY='libpython$(LDVERSION).dll' +- ;; ++ LDLIBRARY='libpython$(LDVERSION).dll.a' ++ DLLLIBRARY='libpython$(LDVERSION).dll' ++ ;; + SunOS*) +- LDLIBRARY='libpython$(LDVERSION).so' +- BLDLIBRARY='-Wl,-R,$(LIBDIR) -L. -lpython$(LDVERSION)' +- RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} +- INSTSONAME="$LDLIBRARY".$SOVERSION +- if test "$with_pydebug" != yes +- then +- PY3LIBRARY=libpython3.so +- fi +- ;; ++ LDLIBRARY='libpython$(LDVERSION).so' ++ BLDLIBRARY='-Wl,-R,$(LIBDIR) -L. -lpython$(LDVERSION)' ++ RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} ++ INSTSONAME="$LDLIBRARY".$SOVERSION ++ if test "$with_pydebug" != yes ++ then ++ PY3LIBRARY=libpython3.so ++ fi ++ ;; + Linux*|GNU*|NetBSD*|FreeBSD*|DragonFly*|OpenBSD*|VxWorks*) +- LDLIBRARY='libpython$(LDVERSION).so' +- BLDLIBRARY='-L. -lpython$(LDVERSION)' +- RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} +- INSTSONAME="$LDLIBRARY".$SOVERSION +- if test "$with_pydebug" != yes +- then +- PY3LIBRARY=libpython3.so +- fi +- ;; ++ LDLIBRARY='libpython$(LDVERSION).so' ++ BLDLIBRARY='-L. -lpython$(LDVERSION)' ++ RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} ++ INSTSONAME="$LDLIBRARY".$SOVERSION ++ if test "$with_pydebug" != yes ++ then ++ PY3LIBRARY=libpython3.so ++ fi ++ ;; + hp*|HP*) +- case `uname -m` in +- ia64) +- LDLIBRARY='libpython$(LDVERSION).so' +- ;; +- *) +- LDLIBRARY='libpython$(LDVERSION).sl' +- ;; +- esac +- BLDLIBRARY='-Wl,+b,$(LIBDIR) -L. -lpython$(LDVERSION)' +- RUNSHARED=SHLIB_PATH=`pwd`${SHLIB_PATH:+:${SHLIB_PATH}} +- ;; ++ case `uname -m` in ++ ia64) ++ LDLIBRARY='libpython$(LDVERSION).so' ++ ;; ++ *) ++ LDLIBRARY='libpython$(LDVERSION).sl' ++ ;; ++ esac ++ BLDLIBRARY='-Wl,+b,$(LIBDIR) -L. -lpython$(LDVERSION)' ++ RUNSHARED=SHLIB_PATH=`pwd`${SHLIB_PATH:+:${SHLIB_PATH}} ++ ;; + Darwin*) +- LDLIBRARY='libpython$(LDVERSION).dylib' +- BLDLIBRARY='-L. -lpython$(LDVERSION)' +- RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} +- ;; ++ LDLIBRARY='libpython$(LDVERSION).dylib' ++ BLDLIBRARY='-L. -lpython$(LDVERSION)' ++ RUNSHARED=DYLD_LIBRARY_PATH=`pwd`${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}} ++ ;; ++ iOS|tvOS|watchOS) ++ LDLIBRARY='libpython$(LDVERSION).dylib' ++ ;; + AIX*) +- LDLIBRARY='libpython$(LDVERSION).so' +- RUNSHARED=LIBPATH=`pwd`${LIBPATH:+:${LIBPATH}} +- ;; ++ LDLIBRARY='libpython$(LDVERSION).so' ++ RUNSHARED=LIBPATH=`pwd`${LIBPATH:+:${LIBPATH}} ++ ;; + + esac + else # shared is disabled + PY_ENABLE_SHARED=0 + case $ac_sys_system in + CYGWIN*) +- BLDLIBRARY='$(LIBRARY)' +- LDLIBRARY='libpython$(LDVERSION).dll.a' +- ;; ++ BLDLIBRARY='$(LIBRARY)' ++ LDLIBRARY='libpython$(LDVERSION).dll.a' ++ ;; + esac + fi + + if test "$cross_compiling" = yes; then +- RUNSHARED= ++ RUNSHARED= + fi + + AC_MSG_RESULT($LDLIBRARY) +@@ -1210,11 +1653,16 @@ + + AC_CHECK_TOOLS([READELF], [readelf], [:]) + if test "$cross_compiling" = yes; then +- case "$READELF" in +- readelf|:) +- AC_MSG_ERROR([readelf for the host is required for cross builds]) +- ;; +- esac ++ case "$ac_sys_system" in ++ iOS|tvOS|watchOS) ;; ++ *) ++ case "$READELF" in ++ readelf|:) ++ AC_MSG_ERROR([readelf for the host is required for cross builds]) ++ ;; ++ esac ++ ;; ++ esac + fi + AC_SUBST(READELF) + +@@ -2712,6 +3160,11 @@ + BLDSHARED="$LDSHARED" + fi + ;; ++ iOS/*|tvOS/*|watchOS/*) ++ LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' ++ LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' ++ BLDSHARED="$LDSHARED" ++ ;; + Linux*|GNU*|QNX*|VxWorks*) + LDSHARED='$(CC) -shared' + LDCXXSHARED='$(CXX) -shared';; +@@ -2809,30 +3262,34 @@ + Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; + Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; + # -u libsys_s pulls in all symbols in libsys +- Darwin/*) ++ Darwin/*|iOS/*|tvOS/*|watchOS/*) + LINKFORSHARED="$extra_undefs -framework CoreFoundation" + + # Issue #18075: the default maximum stack size (8MBytes) is too + # small for the default recursion limit. Increase the stack size + # to ensure that tests don't crash +- stack_size="1000000" # 16 MB +- if test "$with_ubsan" = "yes" +- then +- # Undefined behavior sanitizer requires an even deeper stack +- stack_size="4000000" # 64 MB +- fi ++ stack_size="1000000" # 16 MB ++ if test "$with_ubsan" = "yes" ++ then ++ # Undefined behavior sanitizer requires an even deeper stack ++ stack_size="4000000" # 64 MB ++ fi + +- LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED" ++ AC_DEFINE_UNQUOTED([THREAD_STACK_SIZE], ++ [0x$stack_size], ++ [Custom thread stack size depending on chosen sanitizer runtimes.]) + +- AC_DEFINE_UNQUOTED(THREAD_STACK_SIZE, +- 0x$stack_size, +- [Custom thread stack size depending on chosen sanitizer runtimes.]) ++ if test $ac_sys_system = "Darwin"; then ++ LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED" + +- if test "$enable_framework" +- then +- LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' ++ if test "$enable_framework"; then ++ LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' ++ fi ++ LINKFORSHARED="$LINKFORSHARED" ++ elif test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS"; then ++ LINKFORSHARED="-Wl,-stack_size,$stack_size $LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)' + fi +- LINKFORSHARED="$LINKFORSHARED";; ++ ;; + OpenUNIX*|UnixWare*) LINKFORSHARED="-Wl,-Bexport";; + SCO_SV*) LINKFORSHARED="-Wl,-Bexport";; + ReliantUNIX*) LINKFORSHARED="-W1 -Blargedynsym";; +@@ -3104,7 +3561,7 @@ + AC_ARG_WITH(system_ffi, + AS_HELP_STRING([--with-system-ffi], [build _ctypes module using an installed ffi library, see Doc/library/ctypes.rst (default is system-dependent)]),,,) + +-if test "$ac_sys_system" = "Darwin" ++if test "$ac_sys_system" = "Darwin" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS" + then + case "$with_system_ffi" in + "") +@@ -3129,9 +3586,11 @@ + if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then + LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`" + else +- LIBFFI_INCLUDEDIR="" ++ LIBFFI_INCLUDEDIR="${LIBFFI_INCLUDEDIR}" + fi + AC_SUBST(LIBFFI_INCLUDEDIR) ++AC_SUBST(LIBFFI_LIBDIR) ++AC_SUBST(LIBFFI_LIB) + + # Check for use of the system libmpdec library + AC_MSG_CHECKING(for --with-system-libmpdec) +@@ -3708,18 +4167,18 @@ + + # checks for library functions + AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ +- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \ ++ clock confstr close_range copy_file_range ctermid explicit_bzero \ + explicit_memset faccessat fchmod fchmodat fchown fchownat \ +- fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ +- futimens futimes gai_strerror getentropy \ ++ fdwalk fexecve fdopendir fpathconf fstatat ftime ftruncate futimesat \ ++ futimens futimes gai_strerror \ + getgrgid_r getgrnam_r \ +- getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ ++ getgrouplist getlogin getloadavg getpeername getpgid getpid \ + getpriority getresuid getresgid getpwent getpwnam_r getpwuid_r getspnam getspent getsid getwd \ + if_nameindex \ + initgroups kill killpg lchown lockf linkat lstat lutimes mmap \ + memrchr mbrtowc mkdirat mkfifo \ +- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ +- posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \ ++ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \ ++ posix_fallocate posix_fadvise pread preadv preadv2 \ + pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \ + readlink readlinkat readv realpath renameat \ + sem_open sem_timedwait sem_clockwait sem_getvalue sem_unlink sendfile setegid seteuid \ +@@ -3727,7 +4186,7 @@ + setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ + sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ + sched_rr_get_interval \ +- sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ ++ sigaction sigfillset siginterrupt sigpending sigrelse \ + sigtimedwait sigwait sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ + sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ + truncate uname unlinkat utimensat utimes vfork waitid waitpid wait3 wait4 \ +@@ -3740,6 +4199,22 @@ + AC_CHECK_FUNCS(lchmod) + fi + ++# iOS/tvOS/watchOS define some system methods that can be linked (so they are ++# found by configure), but either raise a compilation error (because the ++# header definition prevents usage - autoconf doesn't use the headers), or ++# raise an error if used at runtime. Force these symbols off. ++if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then ++ AC_CHECK_FUNCS([dup3 getentropy getgroups pipe2 system ]) ++fi + -+* ``/path/to/python.exe`` is the path to a Python binary on the machine that -+ will be running the compiler. This is needed because the Python compilation -+ process involves running some Python code. On a normal desktop build of -+ Python, you can compile a python interpreter and then use that interpreter to -+ run Python code. However, the binaries produced for watchOS won't run on macOS, so -+ you need to provide an external Python interpreter. This interpreter must be -+ the version as the Python that is being compiled. ++# tvOS/watchOS have some additional methods that can be found, but not used. ++if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then ++ AC_CHECK_FUNCS([ \ ++ execv fork posix_spawn posix_spawnp \ ++ sigaltstack \ ++ ]) ++fi + -+Using a framework-based Python on watchOS -+====================================== + AC_CHECK_DECL(dirfd, + AC_DEFINE(HAVE_DIRFD, 1, + Define if you have the 'dirfd' function or macro.), , +@@ -4025,20 +4500,23 @@ + [AC_MSG_RESULT(no) + ]) + +-# check for openpty and forkpty +- +-AC_CHECK_FUNCS(openpty,, +- AC_CHECK_LIB(util,openpty, +- [AC_DEFINE(HAVE_OPENPTY) LIBS="$LIBS -lutil"], +- AC_CHECK_LIB(bsd,openpty, [AC_DEFINE(HAVE_OPENPTY) LIBS="$LIBS -lbsd"]) +- ) +-) +-AC_CHECK_FUNCS(forkpty,, +- AC_CHECK_LIB(util,forkpty, +- [AC_DEFINE(HAVE_FORKPTY) LIBS="$LIBS -lutil"], +- AC_CHECK_LIB(bsd,forkpty, [AC_DEFINE(HAVE_FORKPTY) LIBS="$LIBS -lbsd"]) +- ) +-) ++# check for openpty, login_tty, and forkpty ++# tvOS/watchOS have functions for tty, but can't use them ++if test "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ; then ++ AC_CHECK_FUNCS([openpty], [], ++ [AC_CHECK_LIB([util], [openpty], ++ [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lutil"], ++ [AC_CHECK_LIB([bsd], [openpty], ++ [AC_DEFINE([HAVE_OPENPTY]) LIBS="$LIBS -lbsd"])])]) ++ AC_SEARCH_LIBS([login_tty], [util], ++ [AC_DEFINE([HAVE_LOGIN_TTY], [1], [Define to 1 if you have the `login_tty' function.])] ++ ) ++ AC_CHECK_FUNCS([forkpty], [], ++ [AC_CHECK_LIB([util], [forkpty], ++ [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lutil"], ++ [AC_CHECK_LIB([bsd], [forkpty], ++ [AC_DEFINE([HAVE_FORKPTY]) LIBS="$LIBS -lbsd"])])]) ++fi + + # check for long file support functions + AC_CHECK_FUNCS(fseek64 fseeko fstatvfs ftell64 ftello statvfs) +@@ -4087,11 +4565,17 @@ + ]) + ]) + +-AC_CHECK_FUNCS(clock_settime, [], [ +- AC_CHECK_LIB(rt, clock_settime, [ +- AC_DEFINE(HAVE_CLOCK_SETTIME, 1) +- ]) +-]) ++# On iOS, tvOS and watchOS, clock_settime can be linked (so it is found by ++# configure), but when used in an unprivileged process, it crashes rather than ++# returning an error. Force the symbol off. ++if test "$ac_sys_system" != "iOS" -a "$ac_sys_system" != "tvOS" -a "$ac_sys_system" != "watchOS" ++then ++ AC_CHECK_FUNCS([clock_settime], [], [ ++ AC_CHECK_LIB([rt], [clock_settime], [ ++ AC_DEFINE([HAVE_CLOCK_SETTIME], [1]) ++ ]) ++ ]) ++fi + + AC_MSG_CHECKING(for major, minor, and makedev) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +@@ -4221,7 +4705,9 @@ + [ac_cv_buggy_getaddrinfo=no], + [ac_cv_buggy_getaddrinfo=yes], + [ +-if test "${enable_ipv6+set}" = set; then ++if test "$ac_sys_system" = "Linux-android" -o "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS"; then ++ ac_cv_buggy_getaddrinfo="no" ++elif test "${enable_ipv6+set}" = set; then + ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6" + else + ac_cv_buggy_getaddrinfo=yes +@@ -4821,19 +5307,19 @@ + # + # In Python 3.2 and older, --with-wide-unicode added a 'u' flag. + # In Python 3.7 and older, --with-pymalloc added a 'm' flag. +-AC_SUBST(SOABI) +-AC_MSG_CHECKING(ABIFLAGS) +-AC_MSG_RESULT($ABIFLAGS) +-AC_MSG_CHECKING(SOABI) +-SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} +-AC_MSG_RESULT($SOABI) ++AC_SUBST([SOABI]) ++AC_MSG_CHECKING([ABIFLAGS]) ++AC_MSG_RESULT([$ABIFLAGS]) ++AC_MSG_CHECKING([SOABI]) ++SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${SOABI_PLATFORM:+-$SOABI_PLATFORM} ++AC_MSG_RESULT([$SOABI]) + + # Release and debug (Py_DEBUG) ABI are compatible, but not Py_TRACE_REFS ABI + if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then + # Similar to SOABI but remove "d" flag from ABIFLAGS +- AC_SUBST(ALT_SOABI) +- ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} +- AC_DEFINE_UNQUOTED(ALT_SOABI, "${ALT_SOABI}", ++ AC_SUBST([ALT_SOABI]) ++ ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${SOABI_PLATFORM:+-$SOABI_PLATFORM} ++ AC_DEFINE_UNQUOTED([ALT_SOABI], ["${ALT_SOABI}"], + [Alternative SOABI used in debug build to load C extensions built in release mode]) + fi + +@@ -5399,28 +5885,35 @@ + AC_MSG_NOTICE([checking for device files]) + + dnl NOTE: Inform user how to proceed with files when cross compiling. +-if test "x$cross_compiling" = xyes; then +- if test "${ac_cv_file__dev_ptmx+set}" != set; then +- AC_MSG_CHECKING([for /dev/ptmx]) +- AC_MSG_RESULT([not set]) +- AC_MSG_ERROR([set ac_cv_file__dev_ptmx to yes/no in your CONFIG_SITE file when cross compiling]) +- fi +- if test "${ac_cv_file__dev_ptc+set}" != set; then +- AC_MSG_CHECKING([for /dev/ptc]) +- AC_MSG_RESULT([not set]) +- AC_MSG_ERROR([set ac_cv_file__dev_ptc to yes/no in your CONFIG_SITE file when cross compiling]) ++dnl iOS cross-compile builds are predictable; they won't ever ++dnl have /dev/ptmx or /dev/ptc, so we can set them explicitly. ++if test "$ac_sys_system" = "iOS" -o "$ac_sys_system" = "tvOS" -o "$ac_sys_system" = "watchOS" ; then ++ ac_cv_file__dev_ptmx=no ++ ac_cv_file__dev_ptc=no ++else ++ if test "x$cross_compiling" = xyes; then ++ if test "${ac_cv_file__dev_ptmx+set}" != set; then ++ AC_MSG_CHECKING([for /dev/ptmx]) ++ AC_MSG_RESULT([not set]) ++ AC_MSG_ERROR([set ac_cv_file__dev_ptmx to yes/no in your CONFIG_SITE file when cross compiling]) ++ fi ++ if test "${ac_cv_file__dev_ptc+set}" != set; then ++ AC_MSG_CHECKING([for /dev/ptc]) ++ AC_MSG_RESULT([not set]) ++ AC_MSG_ERROR([set ac_cv_file__dev_ptc to yes/no in your CONFIG_SITE file when cross compiling]) ++ fi + fi +-fi + +-AC_CHECK_FILE(/dev/ptmx, [], []) +-if test "x$ac_cv_file__dev_ptmx" = xyes; then +- AC_DEFINE(HAVE_DEV_PTMX, 1, +- [Define to 1 if you have the /dev/ptmx device file.]) +-fi +-AC_CHECK_FILE(/dev/ptc, [], []) +-if test "x$ac_cv_file__dev_ptc" = xyes; then +- AC_DEFINE(HAVE_DEV_PTC, 1, +- [Define to 1 if you have the /dev/ptc device file.]) ++ AC_CHECK_FILE([/dev/ptmx], [], []) ++ if test "x$ac_cv_file__dev_ptmx" = xyes; then ++ AC_DEFINE([HAVE_DEV_PTMX], [1], ++ [Define to 1 if you have the /dev/ptmx device file.]) ++ fi ++ AC_CHECK_FILE([/dev/ptc], [], []) ++ if test "x$ac_cv_file__dev_ptc" = xyes; then ++ AC_DEFINE([HAVE_DEV_PTC], [1], ++ [Define to 1 if you have the /dev/ptc device file.]) ++ fi + fi + + if test $ac_sys_system = Darwin +@@ -5713,7 +6206,12 @@ + [AS_HELP_STRING([--with-ensurepip@<:@=install|upgrade|no@:>@], + ["install" or "upgrade" using bundled pip (default is upgrade)])], + [], +- [with_ensurepip=upgrade]) ++ [ ++ AS_CASE([$ac_sys_system], ++ [iOS|tvOS|watchOS], [with_ensurepip=no], ++ [with_ensurepip=upgrade] ++ ) ++ ]) + AS_CASE($with_ensurepip, + [yes|upgrade],[ENSUREPIP=upgrade], + [install],[ENSUREPIP=install], +diff --git a/iOS/Resources/bin/arm64-apple-ios-ar b/iOS/Resources/bin/arm64-apple-ios-ar +new file mode 100755 +index 00000000000..3cf3eb21874 --- /dev/null -+++ b/watchOS/Resources/Info.plist.in -@@ -0,0 +1,34 @@ -+ -+ -+ -+ -+ CFBundleDevelopmentRegion -+ en -+ CFBundleExecutable -+ Python -+ CFBundleGetInfoString -+ Python Runtime and Library -+ CFBundleIdentifier -+ @PYTHONFRAMEWORKIDENTIFIER@ -+ CFBundleInfoDictionaryVersion -+ 6.0 -+ CFBundleName -+ Python -+ CFBundlePackageType -+ FMWK -+ CFBundleShortVersionString -+ %VERSION% -+ CFBundleLongVersionString -+ %VERSION%, (c) 2001-2023 Python Software Foundation. -+ CFBundleSignature -+ ???? -+ CFBundleVersion -+ %VERSION% -+ CFBundleSupportedPlatforms -+ -+ watchOS -+ -+ MinimumOSVersion -+ @WATCHOS_DEPLOYMENT_TARGET@ -+ -+ ++++ b/iOS/Resources/bin/arm64-apple-ios-ar +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} ar "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-clang b/iOS/Resources/bin/arm64-apple-ios-clang +new file mode 100755 +index 00000000000..f50d5b5142f --- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-ar ++++ b/iOS/Resources/bin/arm64-apple-ios-clang @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-clang++ b/iOS/Resources/bin/arm64-apple-ios-clang++ +new file mode 100755 +index 00000000000..0794731d7dc --- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang ++++ b/iOS/Resources/bin/arm64-apple-ios-clang++ @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target arm64-apple-watchos-simulator "$@" ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-cpp b/iOS/Resources/bin/arm64-apple-ios-cpp +new file mode 100755 +index 00000000000..24fa1506bab --- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-clang++ ++++ b/iOS/Resources/bin/arm64-apple-ios-cpp @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target arm64-apple-watchos-simulator "$@" ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} -E "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/iOS/Resources/bin/arm64-apple-ios-simulator-ar +new file mode 100755 +index 00000000000..b836b6db902 --- /dev/null -+++ b/watchOS/Resources/bin/arm64-apple-watchos-simulator-cpp ++++ b/iOS/Resources/bin/arm64-apple-ios-simulator-ar @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator clang -target arm64-apple-watchos-simulator -E "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/iOS/Resources/bin/arm64-apple-ios-simulator-clang +new file mode 100755 +index 00000000000..4891a00876e --- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-ar ++++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} ar "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ +new file mode 100755 +index 00000000000..58b2a5f6f18 --- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-clang ++++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp +new file mode 100755 +index 00000000000..c9df94e8b7c --- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-clang++ ++++ b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang++ -target arm64_32-apple-watchos "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-strip b/iOS/Resources/bin/arm64-apple-ios-simulator-strip +new file mode 100755 +index 00000000000..fd59d309b73 --- /dev/null -+++ b/watchOS/Resources/bin/arm64_32-apple-watchos-cpp ++++ b/iOS/Resources/bin/arm64-apple-ios-simulator-strip @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchos${WATCHOS_SDK_VERSION} clang -target arm64_32-apple-watchos -E "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/iOS/Resources/bin/arm64-apple-ios-strip b/iOS/Resources/bin/arm64-apple-ios-strip +new file mode 100755 +index 00000000000..75e823a3d02 --- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-ar ++++ b/iOS/Resources/bin/arm64-apple-ios-strip @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} ar "$@" ++#!/bin/sh ++xcrun --sdk iphoneos${IOS_SDK_VERSION} strip -arch arm64 "$@" +diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar +new file mode 100755 +index 00000000000..b836b6db902 --- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang ++++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos-simulator "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar "$@" +diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang +new file mode 100755 +index 00000000000..f4739a7b945 --- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-clang++ ++++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang++ -target x86_64-apple-watchos-simulator "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ +new file mode 100755 +index 00000000000..c348ae4c103 --- /dev/null -+++ b/watchOS/Resources/bin/x86_64-apple-watchos-simulator-cpp ++++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ @@ -0,0 +1,2 @@ -+#!/bin/bash -+xcrun --sdk watchsimulator${WATCHOS_SDK_VERSION} clang -target x86_64-apple-watchos-simulator -E "$@" ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" +diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp +new file mode 100755 +index 00000000000..6d7f8084c9f --- /dev/null -+++ b/watchOS/Resources/dylib-Info-template.plist -@@ -0,0 +1,26 @@ -+ -+ -+ -+ -+ CFBundleDevelopmentRegion -+ en -+ CFBundleExecutable -+ -+ CFBundleIdentifier -+ -+ CFBundleInfoDictionaryVersion -+ 6.0 -+ CFBundlePackageType -+ APPL -+ CFBundleShortVersionString -+ 1.0 -+ CFBundleSupportedPlatforms -+ -+ watchOS -+ -+ MinimumOSVersion -+ 4.0 -+ CFBundleVersion -+ 1 -+ -+ ++++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator -E "$@" +diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-strip b/iOS/Resources/bin/x86_64-apple-ios-simulator-strip +new file mode 100755 +index 00000000000..c5cfb289291 --- /dev/null -+++ b/watchOS/Resources/pyconfig.h -@@ -0,0 +1,11 @@ -+#ifdef __arm64__ -+# ifdef __LP64__ -+#include "pyconfig-arm64.h" -+# else -+#include "pyconfig-arm64_32.h" -+# endif -+#endif ++++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-strip +@@ -0,0 +1,2 @@ ++#!/bin/sh ++xcrun --sdk iphonesimulator${IOS_SDK_VERSION} strip -arch x86_64 "$@" +diff --git a/pyconfig.h.in b/pyconfig.h.in +index 57c84e5f8fa..b40023b5f61 100644 +--- a/pyconfig.h.in ++++ b/pyconfig.h.in +@@ -1122,6 +1122,9 @@ + /* Define to 1 if you have the `sysconf' function. */ + #undef HAVE_SYSCONF + ++/* Define to 1 if you have the `system' function. */ ++#undef HAVE_SYSTEM + -+#ifdef __x86_64__ -+#include "pyconfig-x86_64.h" -+#endif + /* Define to 1 if you have the header file. */ + #undef HAVE_SYSEXITS_H + +@@ -1699,4 +1702,3 @@ + #endif + + #endif /*Py_PYCONFIG_H*/ +- +diff --git a/setup.py b/setup.py +index a39610a1c7c..09ea06965e9 100644 +--- a/setup.py ++++ b/setup.py +@@ -84,6 +84,9 @@ + MS_WINDOWS = (HOST_PLATFORM == 'win32') + CYGWIN = (HOST_PLATFORM == 'cygwin') + MACOS = (HOST_PLATFORM == 'darwin') ++IOS = HOST_PLATFORM.startswith('ios-') ++TVOS = HOST_PLATFORM.startswith('tvos-') ++WATCHOS = HOST_PLATFORM.startswith('watchos-') + AIX = (HOST_PLATFORM.startswith('aix')) + VXWORKS = ('vxworks' in HOST_PLATFORM) + CC = os.environ.get("CC") +@@ -163,16 +166,20 @@ + for var_name in make_vars: + var = sysconfig.get_config_var(var_name) + if var is not None: +- m = re.search(r'--sysroot=([^"]\S*|"[^"]+")', var) +- if m is not None: +- sysroot = m.group(1).strip('"') +- for subdir in subdirs: +- if os.path.isabs(subdir): +- subdir = subdir[1:] +- path = os.path.join(sysroot, subdir) +- if os.path.isdir(path): +- dirs.append(path) +- break ++ for pattern in [ ++ r'-isysroot\s*([^"]\S*|"[^"]+")', ++ r'--sysroot=([^"]\S*|"[^"]+")', ++ ]: ++ m = re.search(pattern, var) ++ if m is not None: ++ sysroot = m.group(1).strip('"') ++ for subdir in subdirs: ++ if os.path.isabs(subdir): ++ subdir = subdir[1:] ++ path = os.path.join(sysroot, subdir) ++ if os.path.isdir(path): ++ dirs.append(path) ++ break + return dirs + + +@@ -1035,8 +1042,10 @@ + self.add(Extension('_csv', ['_csv.c'])) + + # POSIX subprocess module helper. +- self.add(Extension('_posixsubprocess', ['_posixsubprocess.c'], +- extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) ++ # iOS/tvOS/watchOS doesn't have this. ++ if not (IOS or TVOS or WATCHOS): ++ self.add(Extension('_posixsubprocess', ['_posixsubprocess.c'], ++ extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) + + def detect_test_extensions(self): + # Python C API test module +@@ -1526,6 +1535,15 @@ + ], + libraries=dblibs) + break ++ ++ # iOS, tvOS and watchOS have DBM in the system libraries. ++ if IOS or TVOS or WATCHOS: ++ dbmext = Extension('_dbm', ['_dbmmodule.c'], ++ define_macros=[ ++ ('HAVE_NDBM_H',None), ++ ], ++ libraries=['dbm']) ++ + if dbmext is not None: + self.add(dbmext) + else: +@@ -1605,7 +1623,8 @@ + if sqlite_libfile: + sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))] + +- if sqlite_incdir and sqlite_libdir: ++ # iOS, tvOS and watchOS provide SQLITE as part of the system libraries. ++ if (sqlite_incdir and sqlite_libdir) or IOS or TVOS or WATCHOS: + sqlite_srcs = ['_sqlite/cache.c', + '_sqlite/connection.c', + '_sqlite/cursor.c', +@@ -1638,7 +1657,7 @@ + # Only include the directory where sqlite was found if it does + # not already exist in set include directories, otherwise you + # can end up with a bad search path order. +- if sqlite_incdir not in self.compiler.include_dirs: ++ if sqlite_incdir and sqlite_incdir not in self.compiler.include_dirs: + include_dirs.append(sqlite_incdir) + # avoid a runtime library path for a system library dir + if sqlite_libdir and sqlite_libdir[0] in self.lib_dirs: +@@ -1721,6 +1740,9 @@ + self.missing.append('zlib') + else: + self.missing.append('zlib') ++ elif IOS or TVOS or WATCHOS: ++ # iOS/tvOS/watchOS include zlib in the system libraries. ++ self.add(Extension('zlib', ['zlibmodule.c'], libraries=['z'])) + else: + self.missing.append('zlib') + +@@ -2246,6 +2268,11 @@ + extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + ++ elif IOS or TVOS or WATCHOS: ++ sources.append('_ctypes/malloc_closure.c') ++ extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C') ++ include_dirs.append('_ctypes/darwin') ++ + elif HOST_PLATFORM == 'sunos5': + # XXX This shouldn't be necessary; it appears that some + # of the assembler code is non-PIC (i.e. it has relocations +@@ -2275,7 +2302,8 @@ + libraries=['m'])) + + ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") +- ffi_lib = None ++ ffi_lib_dir = sysconfig.get_config_var("LIBFFI_LIBDIR") ++ ffi_lib = sysconfig.get_config_var("LIBFFI_LIB") + + ffi_inc_dirs = self.inc_dirs.copy() + if MACOS: +@@ -2304,6 +2332,7 @@ + for lib_name in ('ffi', 'ffi_pic'): + if (self.compiler.find_library_file(self.lib_dirs, lib_name)): + ffi_lib = lib_name ++ self.use_system_libffi = True + break + + if ffi_inc and ffi_lib: +@@ -2317,7 +2346,8 @@ + + ext.include_dirs.append(ffi_inc) + ext.libraries.append(ffi_lib) +- self.use_system_libffi = True ++ if ffi_lib_dir: ++ ext.library_dirs.append(ffi_lib_dir) + + if sysconfig.get_config_var('HAVE_LIBDL'): + # for dlopen, see bpo-32647 diff --git a/patch/Python/_cross_target.py.tmpl b/patch/Python/_cross_target.py.tmpl new file mode 100644 index 00000000..6b75958a --- /dev/null +++ b/patch/Python/_cross_target.py.tmpl @@ -0,0 +1,85 @@ +# A site package that turns a macOS virtual environment +# into an {{arch}} {{sdk}} cross-platform virtual environment +import collections +import platform +import subprocess +import sys +import sysconfig + +########################################################################### +# sys module patches +########################################################################### +sys.cross_compiling = True +sys.platform = "{{platform}}" +sys.implementation._multiarch = "{{arch}}-{{sdk}}" +sys.base_prefix = sysconfig.get_config_var("prefix") +sys.base_exec_prefix = sysconfig.get_config_var("prefix") + +########################################################################### +# subprocess module patches +########################################################################### +subprocess._can_fork_exec = True + + +########################################################################### +# platform module patches +########################################################################### + +def cross_system(): + return "{{os}}" + + +def cross_uname(): + return platform.uname_result( + system="{{os}}", + node="build", + release="{{version_min}}", + version="", + machine="{{arch}}", + ) + + +platform.IOSVersionInfo = collections.namedtuple( + "IOSVersionInfo", + ["system", "release", "model", "is_simulator"] +) + + +def cross_ios_ver(system="", release="", model="", is_simulator=False): + if system == "": + system = "{{os}}" + if release == "": + release = "{{version_min}}" + if model == "": + model = "{{sdk}}" + + return platform.IOSVersionInfo(system, release, model, {{is_simulator}}) + + +platform.system = cross_system +platform.uname = cross_uname +platform.ios_ver = cross_ios_ver + + +########################################################################### +# sysconfig module patches +########################################################################### + +def cross_get_platform(): + return "{{platform}}-{{version_min}}-{{arch}}-{{sdk}}" + + +def cross_get_sysconfigdata_name(): + return "_sysconfigdata__{{platform}}_{{arch}}-{{sdk}}" + + +sysconfig.get_platform = cross_get_platform +sysconfig._get_sysconfigdata_name = cross_get_sysconfigdata_name + +# Ensure module-level values cached at time of import are updated. +sysconfig._BASE_PREFIX = sys.base_prefix +sysconfig._BASE_EXEC_PREFIX = sys.base_exec_prefix + +# Force sysconfig data to be loaded (and cached). +sysconfig._CONFIG_VARS = None +sysconfig.get_config_vars() diff --git a/patch/Python/_cross_venv.py b/patch/Python/_cross_venv.py new file mode 100644 index 00000000..a51e5cbe --- /dev/null +++ b/patch/Python/_cross_venv.py @@ -0,0 +1,103 @@ +import shutil +import sys +import sysconfig +from pathlib import Path + +SITE_PACKAGE_PATH = Path(__file__).parent + +########################################################################### +# importlib module patches +########################################################################### + + +def patch_env_create(env): + """ + Patch the process of creating virtual environments to ensure that the cross + environment modification files are also copied as part of environment + creation. + """ + old_pip_env_create = env._PipBackend.create + + def pip_env_create(self, path, *args, **kwargs): + result = old_pip_env_create(self, path, *args, **kwargs) + # Copy any _cross_*.pth or _cross_*.py file, plus the cross-platform + # sysconfigdata module to the new environment. + data_name = sysconfig._get_sysconfigdata_name() + for filename in [ + "_cross_venv.pth", + "_cross_venv.py", + f"_cross_{sys.implementation._multiarch.replace('-', '_')}.py", + f"{data_name}.py", + ]: + src = SITE_PACKAGE_PATH / filename + target = Path(path) / src.relative_to( + SITE_PACKAGE_PATH.parent.parent.parent + ) + if not target.exists(): + shutil.copy(src, target) + return result + + env._PipBackend.create = pip_env_create + + +# Import hook that patches the creation of virtual environments by `build` +# +# The approach used here is the same as the one used by virtualenv to patch +# distutils (but without support for the older load_module API). +# https://docs.python.org/3/library/importlib.html#setting-up-an-importer +_BUILD_PATCH = ("build.env",) + + +class _Finder: + """A meta path finder that allows patching the imported build modules.""" + + fullname = None + + # lock[0] is threading.Lock(), but initialized lazily to avoid importing + # threading very early at startup, because there are gevent-based + # applications that need to be first to import threading by themselves. + # See https://github.com/pypa/virtualenv/issues/1895 for details. + lock = [] # noqa: RUF012 + + def find_spec(self, fullname, path, target=None): + if fullname in _BUILD_PATCH and self.fullname is None: + # initialize lock[0] lazily + if len(self.lock) == 0: + import threading + + lock = threading.Lock() + # there is possibility that two threads T1 and T2 are + # simultaneously running into find_spec, observing .lock as + # empty, and further going into hereby initialization. However + # due to the GIL, list.append() operation is atomic and this + # way only one of the threads will "win" to put the lock + # - that every thread will use - into .lock[0]. + # https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe + self.lock.append(lock) + + from functools import partial + from importlib.util import find_spec + + with self.lock[0]: + self.fullname = fullname + try: + spec = find_spec(fullname, path) + if spec is not None: + # https://www.python.org/dev/peps/pep-0451/#how-loading-will-work + old = spec.loader.exec_module + func = self.exec_module + if old is not func: + spec.loader.exec_module = partial(func, old) + return spec + finally: + self.fullname = None + return None + + @staticmethod + def exec_module(old, module): + old(module) + if module.__name__ in _BUILD_PATCH: + patch_env_create(module) + + +sys.meta_path.insert(0, _Finder()) diff --git a/patch/Python/app-store-compliance.patch b/patch/Python/app-store-compliance.patch deleted file mode 100644 index f4b7decc..00000000 --- a/patch/Python/app-store-compliance.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py -index d6c83a75c1c..19ed4e01091 100644 ---- a/Lib/test/test_urlparse.py -+++ b/Lib/test/test_urlparse.py -@@ -237,11 +237,6 @@ def test_roundtrips(self): - '','',''), - ('git+ssh', 'git@github.com','/user/project.git', - '', '')), -- ('itms-services://?action=download-manifest&url=https://example.com/app', -- ('itms-services', '', '', '', -- 'action=download-manifest&url=https://example.com/app', ''), -- ('itms-services', '', '', -- 'action=download-manifest&url=https://example.com/app', '')), - ('+scheme:path/to/file', - ('', '', '+scheme:path/to/file', '', '', ''), - ('', '', '+scheme:path/to/file', '', '')), -diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py -index 8f724f907d4..148caf742c9 100644 ---- a/Lib/urllib/parse.py -+++ b/Lib/urllib/parse.py -@@ -59,7 +59,7 @@ - 'imap', 'wais', 'file', 'mms', 'https', 'shttp', - 'snews', 'prospero', 'rtsp', 'rtsps', 'rtspu', 'rsync', - 'svn', 'svn+ssh', 'sftp', 'nfs', 'git', 'git+ssh', -- 'ws', 'wss', 'itms-services'] -+ 'ws', 'wss'] - - uses_params = ['', 'ftp', 'hdl', 'prospero', 'http', 'imap', - 'https', 'shttp', 'rtsp', 'rtsps', 'rtspu', 'sip', diff --git a/patch/Python/make_cross_venv.py b/patch/Python/make_cross_venv.py new file mode 100644 index 00000000..7eb9da21 --- /dev/null +++ b/patch/Python/make_cross_venv.py @@ -0,0 +1,123 @@ +import pprint +import shutil +import sys +from pathlib import Path +from importlib import util as importlib_util + + +def localized_vars(orig_vars, slice_path): + """Update (where possible) any references to build-time variables with the + best guess of the installed location. + """ + # The host's sysconfigdata will include references to build-time variables. + # Update these to refer to the current known install location. + orig_prefix = orig_vars["prefix"] + localized_vars = {} + for key, value in orig_vars.items(): + final = value + if isinstance(value, str): + # Replace any reference to the build installation prefix + final = final.replace(orig_prefix, str(slice_path)) + # Replace any reference to the build-time Framework location + final = final.replace("-F .", f"-F {slice_path}") + localized_vars[key] = final + + return localized_vars + + +def localize_sysconfigdata(platform_config_path, venv_site_packages): + """Localize a sysconfigdata python module. + + :param platform_config_path: The platform config that contains the + sysconfigdata module to localize. + :param venv_site_packages: The site packages folder where the localized + sysconfigdata module should be output. + """ + # Find the "_sysconfigdata_*.py" file in the platform config + sysconfigdata_path = next(platform_config_path.glob("_sysconfigdata_*.py")) + + # Import the sysconfigdata module + spec = importlib_util.spec_from_file_location( + sysconfigdata_path.stem, + sysconfigdata_path + ) + if spec is None: + msg = f"Unable to load spec for {sysconfigdata_path}" + raise ValueError(msg) + if spec.loader is None: + msg = f"Spec for {sysconfigdata_path} does not define a loader" + raise ValueError(msg) + sysconfigdata = importlib_util.module_from_spec(spec) + spec.loader.exec_module(sysconfigdata) + + # Write the updated sysconfigdata module into the cross-platform site. + slice_path = sysconfigdata_path.parent.parent.parent + with (venv_site_packages / sysconfigdata_path.name).open("w") as f: + f.write(f"# Generated from {sysconfigdata_path}\n") + f.write("build_time_vars = ") + pprint.pprint( + localized_vars(sysconfigdata.build_time_vars, slice_path), + stream=f, + compact=True + ) + + +def make_cross_venv(venv_path: Path, platform_config_path: Path): + """Convert a virtual environment into a cross-platform environment. + + :param venv_path: The path to the root of the venv. + :param platform_config_path: The path containing the platform config. + """ + if not venv_path.exists(): + raise ValueError(f"Virtual environment {venv_path} does not exist.") + if not (venv_path / "bin/python3").exists(): + raise ValueError(f"{venv_path} does not appear to be a virtual environment.") + + print( + f"Converting {venv_path} into a {platform_config_path.name} environment... ", + end="", + ) + + LIB_PATH = f"lib/python{sys.version_info[0]}.{sys.version_info[1]}" + + # Update path references in the sysconfigdata to reflect local conditions. + venv_site_packages = venv_path / LIB_PATH / "site-packages" + localize_sysconfigdata(platform_config_path, venv_site_packages) + + # Copy in the site-package environment modifications. + cross_multiarch = f"_cross_{platform_config_path.name.replace('-', '_')}" + shutil.copy( + platform_config_path / f"{cross_multiarch}.py", + venv_site_packages / f"{cross_multiarch}.py", + ) + shutil.copy( + platform_config_path / "_cross_venv.py", + venv_site_packages / "_cross_venv.py", + ) + # Write the .pth file that will enable the cross-env modifications + (venv_site_packages / "_cross_venv.pth").write_text( + f"import {cross_multiarch}; import _cross_venv\n" + ) + + print("done.") + + +if __name__ == "__main__": + try: + platform_config_path = Path(sys.argv[2]).resolve() + except IndexError: + platform_config_path = Path(__file__).parent + + try: + venv_path = Path(sys.argv[1]).resolve() + make_cross_venv(venv_path, platform_config_path) + except IndexError: + print(""" +Convert a virtual environment in to a cross-platform environment. + +Usage: + make_cross_venv () + +If an explicit platform config isn't provided, it is assumed the directory +containing the make_cross_venv script *is* a platform config. +""") diff --git a/patch/Python/module.modulemap.prefix b/patch/Python/module.modulemap.prefix new file mode 100644 index 00000000..e6e73127 --- /dev/null +++ b/patch/Python/module.modulemap.prefix @@ -0,0 +1,23 @@ +module Python { + umbrella header "Python.h" + export * + link "Python" + + exclude header "datetime.h" + exclude header "dynamic_annotations.h" + exclude header "errcode.h" + exclude header "frameobject.h" + exclude header "interpreteridobject.h" + exclude header "marshal.h" + exclude header "opcode_ids.h" + exclude header "opcode.h" + exclude header "osdefs.h" + exclude header "py_curses.h" + exclude header "pyconfig-arm32_64.h" + exclude header "pyconfig-arm64.h" + exclude header "pyconfig-x86_64.h" + exclude header "pydtrace.h" + exclude header "pyexpat.h" + exclude header "pystrhex.h" + exclude header "structmember.h" + exclude header "token.h" diff --git a/patch/Python/sitecustomize.iOS.py b/patch/Python/sitecustomize.iOS.py deleted file mode 100644 index ccc291f3..00000000 --- a/patch/Python/sitecustomize.iOS.py +++ /dev/null @@ -1,114 +0,0 @@ -# A site customization that can be used to trick pip into installing -# packages cross-platform. If the folder containing this file is on -# your PYTHONPATH when you invoke pip, pip will behave as if it were -# running on {{os}}. -import collections -import distutils.ccompiler -import distutils.unixccompiler -import os -import platform -import sys -import sysconfig -import types - -# Make platform.system() return "{{os}}" -def custom_system(): - return "{{os}}" - -platform.system = custom_system - -# Make platform.ios_ver() return an appropriate namedtuple -IOSVersionInfo = collections.namedtuple( - "IOSVersionInfo", - ["system", "release", "model", "is_simulator"] -) - -def custom_ios_ver(system="", release="", model="", is_simulator=False): - return IOSVersionInfo("{{os}}", "{{version_min}}", "iPhone", {{is_simulator}}) - -platform.ios_ver = custom_ios_ver - -# Make sys.implementation._multiarch return the multiarch description -sys.implementation._multiarch = "{{multiarch}}" - -# Make sysconfig.get_platform() return the platform tag -def custom_get_platform(): - return "{{tag}}" - -sysconfig.get_platform = custom_get_platform - -# Make distutils raise errors if you try to use it to build modules. -DISABLED_COMPILER_ERROR = "Cannot compile native modules" - -distutils.ccompiler.get_default_compiler = lambda *args, **kwargs: "disabled" -distutils.ccompiler.compiler_class["disabled"] = ( - "disabledcompiler", - "DisabledCompiler", - "Compiler disabled ({})".format(DISABLED_COMPILER_ERROR), -) - - -def disabled_compiler(prefix): - # No need to give any more advice here: that will come from the higher-level code in pip. - from distutils.errors import DistutilsPlatformError - - raise DistutilsPlatformError("{}: {}".format(prefix, DISABLED_COMPILER_ERROR)) - - -class DisabledCompiler(distutils.ccompiler.CCompiler): - compiler_type = "disabled" - - def preprocess(*args, **kwargs): - disabled_compiler("CCompiler.preprocess") - - def compile(*args, **kwargs): - disabled_compiler("CCompiler.compile") - - def create_static_lib(*args, **kwargs): - disabled_compiler("CCompiler.create_static_lib") - - def link(*args, **kwargs): - disabled_compiler("CCompiler.link") - - -# To maximize the chance of the build getting as far as actually calling compile(), make -# sure the class has all of the expected attributes. -for name in [ - "src_extensions", - "obj_extension", - "static_lib_extension", - "shared_lib_extension", - "static_lib_format", - "shared_lib_format", - "exe_extension", -]: - setattr( - DisabledCompiler, name, getattr(distutils.unixccompiler.UnixCCompiler, name) - ) - -DisabledCompiler.executables = { - name: [DISABLED_COMPILER_ERROR.replace(" ", "_")] - for name in distutils.unixccompiler.UnixCCompiler.executables -} - -disabled_mod = types.ModuleType("distutils.disabledcompiler") -disabled_mod.DisabledCompiler = DisabledCompiler -sys.modules["distutils.disabledcompiler"] = disabled_mod - - -# Try to disable native builds for packages which don't use the distutils native build -# system at all (e.g. uwsgi), or only use it to wrap an external build script (e.g. pynacl). -for tool in ["ar", "as", "cc", "cxx", "ld"]: - os.environ[tool.upper()] = DISABLED_COMPILER_ERROR.replace(" ", "_") - - -# Call the next sitecustomize script if there is one -# (https://nedbatchelder.com/blog/201001/running_code_at_python_startup.html). -del sys.modules["sitecustomize"] -this_dir = os.path.dirname(__file__) -path_index = sys.path.index(this_dir) -del sys.path[path_index] -try: - import sitecustomize # noqa: F401 -finally: - sys.path.insert(path_index, this_dir) diff --git a/patch/Python/sitecustomize.macOS.py b/patch/Python/sitecustomize.macOS.py deleted file mode 100644 index 500714da..00000000 --- a/patch/Python/sitecustomize.macOS.py +++ /dev/null @@ -1,14 +0,0 @@ -# A site customization that can be used to trick pip into installing -# packages cross-platform. If the folder containing this file is on -# your PYTHONPATH when you invoke pip, pip will behave as if it were -# running on {{arch}}. -import platform - -# Make platform.mac_ver() return {{arch}} -orig_mac_ver = platform.mac_ver - -def custom_mac_ver(): - orig = orig_mac_ver() - return orig[0], orig[1], "{{arch}}" - -platform.mac_ver = custom_mac_ver diff --git a/patch/Python/sitecustomize.py.tmpl b/patch/Python/sitecustomize.py.tmpl new file mode 100644 index 00000000..0330575a --- /dev/null +++ b/patch/Python/sitecustomize.py.tmpl @@ -0,0 +1,22 @@ +# A site customization that can be used to trick pip into installing packages +# cross-platform. If the folder containing this file is on your PYTHONPATH when +# you invoke python, the interpreter will behave as if it were running on +# {{arch}} {{sdk}}. +import sys +import os + +# Apply the cross-platform patch +import _cross_{{arch}}_{{sdk}} +import _cross_venv + + +# Call the next sitecustomize script if there is one +# (https://nedbatchelder.com/blog/201001/running_code_at_python_startup.html). +del sys.modules["sitecustomize"] +this_dir = os.path.dirname(__file__) +path_index = sys.path.index(this_dir) +del sys.path[path_index] +try: + import sitecustomize # noqa: F401 +finally: + sys.path.insert(path_index, this_dir) diff --git a/patch/Python/sitecustomize.tvOS.py b/patch/Python/sitecustomize.tvOS.py deleted file mode 100644 index d7d86e36..00000000 --- a/patch/Python/sitecustomize.tvOS.py +++ /dev/null @@ -1,99 +0,0 @@ -# A site customization that can be used to trick pip into installing -# packages cross-platform. If the folder containing this file is on -# your PYTHONPATH when you invoke pip, pip will behave as if it were -# running on {{os}}. -import distutils.ccompiler -import distutils.unixccompiler -import os -import platform -import sys -import sysconfig -import types - -# Make platform.system() return "{{os}}" -def custom_system(): - return "{{os}}" - -platform.system = custom_system - -# Make sysconfig.get_platform() return "{{tag}}" -def custom_get_platform(): - return "{{tag}}" - -sysconfig.get_platform = custom_get_platform - -# Make distutils raise errors if you try to use it to build modules. -DISABLED_COMPILER_ERROR = "Cannot compile native modules" - -distutils.ccompiler.get_default_compiler = lambda *args, **kwargs: "disabled" -distutils.ccompiler.compiler_class["disabled"] = ( - "disabledcompiler", - "DisabledCompiler", - "Compiler disabled ({})".format(DISABLED_COMPILER_ERROR), -) - - -def disabled_compiler(prefix): - # No need to give any more advice here: that will come from the higher-level code in pip. - from distutils.errors import DistutilsPlatformError - - raise DistutilsPlatformError("{}: {}".format(prefix, DISABLED_COMPILER_ERROR)) - - -class DisabledCompiler(distutils.ccompiler.CCompiler): - compiler_type = "disabled" - - def preprocess(*args, **kwargs): - disabled_compiler("CCompiler.preprocess") - - def compile(*args, **kwargs): - disabled_compiler("CCompiler.compile") - - def create_static_lib(*args, **kwargs): - disabled_compiler("CCompiler.create_static_lib") - - def link(*args, **kwargs): - disabled_compiler("CCompiler.link") - - -# To maximize the chance of the build getting as far as actually calling compile(), make -# sure the class has all of the expected attributes. -for name in [ - "src_extensions", - "obj_extension", - "static_lib_extension", - "shared_lib_extension", - "static_lib_format", - "shared_lib_format", - "exe_extension", -]: - setattr( - DisabledCompiler, name, getattr(distutils.unixccompiler.UnixCCompiler, name) - ) - -DisabledCompiler.executables = { - name: [DISABLED_COMPILER_ERROR.replace(" ", "_")] - for name in distutils.unixccompiler.UnixCCompiler.executables -} - -disabled_mod = types.ModuleType("distutils.disabledcompiler") -disabled_mod.DisabledCompiler = DisabledCompiler -sys.modules["distutils.disabledcompiler"] = disabled_mod - - -# Try to disable native builds for packages which don't use the distutils native build -# system at all (e.g. uwsgi), or only use it to wrap an external build script (e.g. pynacl). -for tool in ["ar", "as", "cc", "cxx", "ld"]: - os.environ[tool.upper()] = DISABLED_COMPILER_ERROR.replace(" ", "_") - - -# Call the next sitecustomize script if there is one -# (https://nedbatchelder.com/blog/201001/running_code_at_python_startup.html). -del sys.modules["sitecustomize"] -this_dir = os.path.dirname(__file__) -path_index = sys.path.index(this_dir) -del sys.path[path_index] -try: - import sitecustomize # noqa: F401 -finally: - sys.path.insert(path_index, this_dir) diff --git a/patch/Python/sitecustomize.watchOS.py b/patch/Python/sitecustomize.watchOS.py deleted file mode 100644 index d7d86e36..00000000 --- a/patch/Python/sitecustomize.watchOS.py +++ /dev/null @@ -1,99 +0,0 @@ -# A site customization that can be used to trick pip into installing -# packages cross-platform. If the folder containing this file is on -# your PYTHONPATH when you invoke pip, pip will behave as if it were -# running on {{os}}. -import distutils.ccompiler -import distutils.unixccompiler -import os -import platform -import sys -import sysconfig -import types - -# Make platform.system() return "{{os}}" -def custom_system(): - return "{{os}}" - -platform.system = custom_system - -# Make sysconfig.get_platform() return "{{tag}}" -def custom_get_platform(): - return "{{tag}}" - -sysconfig.get_platform = custom_get_platform - -# Make distutils raise errors if you try to use it to build modules. -DISABLED_COMPILER_ERROR = "Cannot compile native modules" - -distutils.ccompiler.get_default_compiler = lambda *args, **kwargs: "disabled" -distutils.ccompiler.compiler_class["disabled"] = ( - "disabledcompiler", - "DisabledCompiler", - "Compiler disabled ({})".format(DISABLED_COMPILER_ERROR), -) - - -def disabled_compiler(prefix): - # No need to give any more advice here: that will come from the higher-level code in pip. - from distutils.errors import DistutilsPlatformError - - raise DistutilsPlatformError("{}: {}".format(prefix, DISABLED_COMPILER_ERROR)) - - -class DisabledCompiler(distutils.ccompiler.CCompiler): - compiler_type = "disabled" - - def preprocess(*args, **kwargs): - disabled_compiler("CCompiler.preprocess") - - def compile(*args, **kwargs): - disabled_compiler("CCompiler.compile") - - def create_static_lib(*args, **kwargs): - disabled_compiler("CCompiler.create_static_lib") - - def link(*args, **kwargs): - disabled_compiler("CCompiler.link") - - -# To maximize the chance of the build getting as far as actually calling compile(), make -# sure the class has all of the expected attributes. -for name in [ - "src_extensions", - "obj_extension", - "static_lib_extension", - "shared_lib_extension", - "static_lib_format", - "shared_lib_format", - "exe_extension", -]: - setattr( - DisabledCompiler, name, getattr(distutils.unixccompiler.UnixCCompiler, name) - ) - -DisabledCompiler.executables = { - name: [DISABLED_COMPILER_ERROR.replace(" ", "_")] - for name in distutils.unixccompiler.UnixCCompiler.executables -} - -disabled_mod = types.ModuleType("distutils.disabledcompiler") -disabled_mod.DisabledCompiler = DisabledCompiler -sys.modules["distutils.disabledcompiler"] = disabled_mod - - -# Try to disable native builds for packages which don't use the distutils native build -# system at all (e.g. uwsgi), or only use it to wrap an external build script (e.g. pynacl). -for tool in ["ar", "as", "cc", "cxx", "ld"]: - os.environ[tool.upper()] = DISABLED_COMPILER_ERROR.replace(" ", "_") - - -# Call the next sitecustomize script if there is one -# (https://nedbatchelder.com/blog/201001/running_code_at_python_startup.html). -del sys.modules["sitecustomize"] -this_dir = os.path.dirname(__file__) -path_index = sys.path.index(this_dir) -del sys.path[path_index] -try: - import sitecustomize # noqa: F401 -finally: - sys.path.insert(path_index, this_dir) diff --git a/tests/test_cross_env.py b/tests/test_cross_env.py new file mode 100644 index 00000000..24b90457 --- /dev/null +++ b/tests/test_cross_env.py @@ -0,0 +1,98 @@ +import os +import platform +import sys +import sysconfig +from pathlib import Path + +import pytest + +# To run these tests, the following three environment variables must be set, +# reflecting the cross-platform environment that is in effect.' +PYTHON_CROSS_PLATFORM = os.getenv("PYTHON_CROSS_PLATFORM", "unknown") +PYTHON_CROSS_SLICE = os.getenv("PYTHON_CROSS_SLICE", "unknown") +PYTHON_CROSS_MULTIARCH = os.getenv("PYTHON_CROSS_MULTIARCH", "unknown") + +# Determine some file system anchor points for the tests +# Assumes that the tests are run in a virtual environment named +# `cross-venv`, +VENV_PREFIX = os.getenv("VIRTUAL_ENV", Path(__file__).parent.parent / "cross-venv") +default_support_base = ( + f"support/{sys.version_info.major}.{sys.version_info.minor}/{PYTHON_CROSS_PLATFORM}" +) +SUPPORT_PREFIX = ( + Path(__file__).parent.parent + / os.getenv("PYTHON_SUPPORT_BASE", default_support_base) + / "Python.xcframework" + / PYTHON_CROSS_SLICE +) + + +########################################################################### +# sys +########################################################################### + + +def test_sys_platform(): + assert sys.platform == PYTHON_CROSS_PLATFORM.lower() + + +def test_sys_cross_compiling(): + assert sys.cross_compiling + + +def test_sys_multiarch(): + assert sys.implementation._multiarch == PYTHON_CROSS_MULTIARCH + + +def test_sys_base_prefix(): + assert Path(sys.base_prefix) == SUPPORT_PREFIX + + +def test_sys_base_exec_prefix(): + assert Path(sys.base_exec_prefix) == SUPPORT_PREFIX + + +########################################################################### +# platform +########################################################################### + + +def test_platform_system(): + assert platform.system() == PYTHON_CROSS_PLATFORM + + +########################################################################### +# sysconfig +########################################################################### + + +def test_sysconfig_get_platform(): + parts = sysconfig.get_platform().split("-", 2) + assert parts[0] == PYTHON_CROSS_PLATFORM.lower() + assert parts[2] == PYTHON_CROSS_MULTIARCH + + +def test_sysconfig_get_sysconfigdata_name(): + parts = sysconfig._get_sysconfigdata_name().split("_", 4) + assert parts[3] == PYTHON_CROSS_PLATFORM.lower() + assert parts[4] == PYTHON_CROSS_MULTIARCH + + +@pytest.mark.parametrize( + "name, prefix", + [ + # Paths that should be relative to the support folder + ("stdlib", SUPPORT_PREFIX), + ("include", SUPPORT_PREFIX), + ("platinclude", SUPPORT_PREFIX), + ("stdlib", SUPPORT_PREFIX), + # paths that should be relative to the venv + ("platstdlib", VENV_PREFIX), + ("purelib", VENV_PREFIX), + ("platlib", VENV_PREFIX), + ("scripts", VENV_PREFIX), + ("data", VENV_PREFIX), + ], +) +def test_sysconfig_get_paths(name, prefix): + assert sysconfig.get_paths()[name].startswith(str(prefix))