├── .github └── workflows │ ├── build.yml │ ├── release.yml │ └── update.yml ├── .gitignore ├── LICENSE ├── README.md ├── default.nix ├── devenv.lock ├── devenv.nix ├── flake.lock ├── flake.nix ├── patches ├── 2.6-no-ldconfig.patch ├── 2.7-no-ldconfig.patch ├── 2.7.10-no-ldconfig.patch ├── 2.7.11-no-ldconfig.patch ├── 2.7.17-distutils-C++.patch ├── 3.10-no-ldconfig.patch ├── 3.11-no-ldconfig.patch ├── 3.12-no-ldconfig.patch ├── 3.13-no-ldconfig.patch ├── 3.4-no-ldconfig.patch ├── 3.5-no-ldconfig.patch ├── 3.6-no-ldconfig.patch ├── 3.7-no-ldconfig.patch ├── 3.7.9-no-ldconfig.patch ├── 3.8-no-ldconfig.patch ├── 3.8.6-no-ldconfig.patch ├── 3.9-no-ldconfig.patch ├── python-3.7.3-distutils-C++.patch └── segfault.patch ├── renovate.json ├── update.py └── versions.json /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build & Test" 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | build: 11 | name: Build 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [[self-hosted, linux, X64], [macos-13], [self-hosted, macOS, ARM64], [self-hosted, linux, ARM64]] 16 | runs-on: ${{ matrix.os }} 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: cachix/install-nix-action@526118121621777ccd86f79b04685a9319637641 # v31 20 | - uses: cachix/cachix-action@v16 21 | with: 22 | name: nixpkgs-python 23 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 24 | - run: nix flake check -L --keep-going --accept-flake-config --show-trace 25 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Publish a flake to flakestry" 2 | on: 3 | push: 4 | tags: 5 | - "v?[0-9]+.[0-9]+.[0-9]+" 6 | - "v?[0-9]+.[0-9]+" 7 | workflow_dispatch: 8 | inputs: 9 | tag: 10 | description: "The existing tag to publish" 11 | type: "string" 12 | required: true 13 | jobs: 14 | publish-flake: 15 | runs-on: ubuntu-latest 16 | permissions: 17 | id-token: "write" 18 | contents: "read" 19 | steps: 20 | - uses: flakestry/flakestry-publish@main 21 | with: 22 | version: "${{ inputs.tag || github.ref_name }}" 23 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Update Python versions 2 | 3 | on: 4 | schedule: 5 | - cron: "5 * * * *" 6 | permissions: 7 | pull-requests: write 8 | contents: write 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | ref: main 16 | - name: Install Nix 17 | uses: cachix/install-nix-action@526118121621777ccd86f79b04685a9319637641 # v31 18 | - name: Install Cachix 19 | uses: cachix/cachix-action@v16 20 | with: 21 | name: nixpkgs-python 22 | extraPullNames: devenv 23 | - name: Install devenv.sh 24 | run: nix profile install github:cachix/devenv/latest 25 | - run: devenv shell python update.py 26 | - run: nix flake check --keep-going --accept-flake-config --show-trace 27 | - name: Create Pull Request 28 | id: create-pull-request 29 | uses: peter-evans/create-pull-request@v7 30 | with: 31 | commit-message: Update Python versions 32 | title: Update Python versions 33 | body: | 34 | Automatically created pull-request to update Python versions. 35 | 36 | This is the result of running: 37 | 38 | ``` 39 | devenv shell python update.py 40 | ``` 41 | delete-branch: true 42 | - if: ${{ steps.create-pull-request.outputs.pull-request-operation == 'created' }} 43 | uses: peter-evans/enable-pull-request-automerge@v3 44 | with: 45 | pull-request-number: ${{ steps.create-pull-request.outputs.pull-request-number }} 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .direnv* 2 | 3 | # Devenv 4 | .devenv* 5 | devenv.local.nix 6 | 7 | result* 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nixpkgs-python 2 | 3 | All Python versions, kept up-to-date on hourly basis using Nix. 4 | 5 | ## Supported Python Versions 6 | 7 | This project supports the following Python versions: 8 | 9 | - 2.7.6+ 10 | - 3.3.1+ (up to the latest release) 11 | 12 | ## Cachix (optional) 13 | 14 | If you'd like to avoid compilation [install Cachix](https://docs.cachix.org/installation) and: 15 | 16 | $ cachix use nixpkgs-python 17 | 18 | Using the following platforms: 19 | 20 | - x86_64-darwin 21 | - x86_64-linux 22 | - aarch64-linux 23 | - aarch64-darwin 24 | 25 | ## Usage 26 | 27 | ### [devenv.sh](https://devenv.sh) 28 | 29 | Create `devenv.nix`: 30 | 31 | ```nix 32 | { pkgs, ... }: 33 | 34 | { 35 | languages.python.enable = true; 36 | languages.python.version = "3.11"; 37 | # languages.python.version = "3.11.3"; 38 | } 39 | ``` 40 | 41 | Create `devenv.yaml`: 42 | 43 | ```yaml 44 | inputs: 45 | nixpkgs-python: 46 | url: github:cachix/nixpkgs-python 47 | ``` 48 | 49 | Then run: 50 | 51 | $ devenv shell 52 | ... 53 | 54 | ### flake.nix 55 | 56 | ```nix 57 | { 58 | inputs = { 59 | nixpkgs-python.url = "github:cachix/nixpkgs-python"; 60 | }; 61 | 62 | outputs = { self, nixpkgs-python }: { 63 | # You can now refer to packages like: 64 | # nixpkgs-python.packages.x86_64-linux."2.7" 65 | }; 66 | } 67 | ``` 68 | 69 | ### nix shell 70 | 71 | You can run this package ad-hoc using the following command: 72 | 73 | $ nix shell github:cachix/nixpkgs-python#'"2.7"' 74 | 75 | Or specify a minor version: 76 | 77 | $ nix shell github:cachix/nixpkgs-python#'"2.7.16"' 78 | 79 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in 4 | fetchTarball { 5 | url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 6 | sha256 = lock.nodes.flake-compat.locked.narHash; 7 | } 8 | ) 9 | { src = ./.; } 10 | ).defaultNix 11 | -------------------------------------------------------------------------------- /devenv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "devenv": { 4 | "locked": { 5 | "dir": "src/modules", 6 | "lastModified": 1746101600, 7 | "owner": "cachix", 8 | "repo": "devenv", 9 | "rev": "86dbb4b05ac23147bcc468e7ed77567bae11e418", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "dir": "src/modules", 14 | "owner": "cachix", 15 | "repo": "devenv", 16 | "type": "github" 17 | } 18 | }, 19 | "flake-compat": { 20 | "flake": false, 21 | "locked": { 22 | "lastModified": 1733328505, 23 | "owner": "edolstra", 24 | "repo": "flake-compat", 25 | "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "edolstra", 30 | "repo": "flake-compat", 31 | "type": "github" 32 | } 33 | }, 34 | "git-hooks": { 35 | "inputs": { 36 | "flake-compat": "flake-compat", 37 | "gitignore": "gitignore", 38 | "nixpkgs": [ 39 | "nixpkgs" 40 | ] 41 | }, 42 | "locked": { 43 | "lastModified": 1742649964, 44 | "owner": "cachix", 45 | "repo": "git-hooks.nix", 46 | "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", 47 | "type": "github" 48 | }, 49 | "original": { 50 | "owner": "cachix", 51 | "repo": "git-hooks.nix", 52 | "type": "github" 53 | } 54 | }, 55 | "gitignore": { 56 | "inputs": { 57 | "nixpkgs": [ 58 | "git-hooks", 59 | "nixpkgs" 60 | ] 61 | }, 62 | "locked": { 63 | "lastModified": 1709087332, 64 | "owner": "hercules-ci", 65 | "repo": "gitignore.nix", 66 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 67 | "type": "github" 68 | }, 69 | "original": { 70 | "owner": "hercules-ci", 71 | "repo": "gitignore.nix", 72 | "type": "github" 73 | } 74 | }, 75 | "nixpkgs": { 76 | "locked": { 77 | "lastModified": 1733477122, 78 | "owner": "cachix", 79 | "repo": "devenv-nixpkgs", 80 | "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", 81 | "type": "github" 82 | }, 83 | "original": { 84 | "owner": "cachix", 85 | "ref": "rolling", 86 | "repo": "devenv-nixpkgs", 87 | "type": "github" 88 | } 89 | }, 90 | "root": { 91 | "inputs": { 92 | "devenv": "devenv", 93 | "git-hooks": "git-hooks", 94 | "nixpkgs": "nixpkgs", 95 | "pre-commit-hooks": [ 96 | "git-hooks" 97 | ] 98 | } 99 | } 100 | }, 101 | "root": "root", 102 | "version": 7 103 | } 104 | -------------------------------------------------------------------------------- /devenv.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | languages.python.enable = true; 3 | languages.python.venv.enable = true; 4 | 5 | packages = [ pkgs.jq ]; 6 | 7 | enterShell = '' 8 | pip install requests 9 | ''; 10 | } -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-compat": { 4 | "flake": false, 5 | "locked": { 6 | "lastModified": 1733328505, 7 | "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", 8 | "owner": "edolstra", 9 | "repo": "flake-compat", 10 | "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", 11 | "type": "github" 12 | }, 13 | "original": { 14 | "owner": "edolstra", 15 | "repo": "flake-compat", 16 | "type": "github" 17 | } 18 | }, 19 | "nixpkgs": { 20 | "locked": { 21 | "lastModified": 1743367904, 22 | "narHash": "sha256-sOos1jZGKmT6xxPvxGQyPTApOunXvScV4lNjBCXd/CI=", 23 | "owner": "NixOS", 24 | "repo": "nixpkgs", 25 | "rev": "7ffe0edc685f14b8c635e3d6591b0bbb97365e6c", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "NixOS", 30 | "ref": "nixos-24.11", 31 | "repo": "nixpkgs", 32 | "type": "github" 33 | } 34 | }, 35 | "root": { 36 | "inputs": { 37 | "flake-compat": "flake-compat", 38 | "nixpkgs": "nixpkgs" 39 | } 40 | } 41 | }, 42 | "root": "root", 43 | "version": 7 44 | } 45 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "All Python versions packages in Nix."; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; 6 | flake-compat.url = "github:edolstra/flake-compat"; 7 | flake-compat.flake = false; 8 | }; 9 | 10 | nixConfig = { 11 | extra-substituters = "https://nixpkgs-python.cachix.org"; 12 | extra-trusted-public-keys = "nixpkgs-python.cachix.org-1:hxjI7pFxTyuTHn2NkvWCrAUcNZLNS3ZAvfYNuYifcEU="; 13 | }; 14 | 15 | outputs = { self, nixpkgs, ... }: 16 | let 17 | systems = [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; 18 | forAllSystems = f: builtins.listToAttrs (map (name: { inherit name; value = f name; }) systems); 19 | lib = nixpkgs.lib; 20 | versionInBetween = version: upper: lower: 21 | lib.versionAtLeast version lower && lib.versionOlder version upper; 22 | in { 23 | lib.applyOverrides = overrides: pkg: 24 | let 25 | matching = builtins.filter ({ condition, ... }: condition pkg.version) overrides; 26 | apply = pkg: { override, ... }: override pkg; 27 | in lib.foldl apply pkg matching; 28 | lib.mkPython = 29 | { pkgs 30 | , version 31 | , hash 32 | , url 33 | , packages 34 | }: 35 | let 36 | versionList = builtins.splitVersion version; 37 | versionSuffixList = builtins.concatLists [[""] (lib.drop 3 versionList)]; 38 | sourceVersion = { 39 | major = builtins.elemAt versionList 0; 40 | minor = builtins.elemAt versionList 1; 41 | patch = builtins.elemAt versionList 2; 42 | suffix = builtins.concatStringsSep "." versionSuffixList; 43 | }; 44 | infix = if sourceVersion.major == "2" then "2.7/" else ""; 45 | overrideLDConfigPatch = path: pkg: pkg.override { 46 | noldconfigPatch = path; 47 | }; 48 | replacePatch = name: patch: pkg: pkg.overrideAttrs (old: { 49 | patches = (lib.filter (elem: if builtins.isNull elem then true else !lib.hasSuffix name elem) old.patches) ++ [ patch ]; 50 | }); 51 | filterOutPatch = name: pkg: replacePatch name null pkg; 52 | overrides = [ 53 | # py2 54 | { condition = version: versionInBetween version "2.7.3" "2.6"; 55 | # patch not available 56 | override = pkg: filterOutPatch "deterministic-build.patch" (filterOutPatch "no-win64-workaround.patch" pkg); 57 | } 58 | { condition = version: versionInBetween version "2.7.4" "2.6"; 59 | # patch not available 60 | override = filterOutPatch "atomic_pyc.patch"; 61 | } 62 | { condition = version: versionInBetween version "3.7" "3.3"; 63 | # patch not available 64 | override = filterOutPatch "loongarch-support.patch"; 65 | } 66 | { condition = version: versionInBetween version "2.7.13" "2.6"; 67 | override = pkg: filterOutPatch "find_library-gcc10.patch" (filterOutPatch "profile-task.patch" pkg); 68 | } 69 | # patch not available before 2.7.11 70 | { condition = version: versionInBetween version "2.7.11" "2.6"; 71 | override = filterOutPatch "no-ldconfig.patch"; 72 | } 73 | { condition = version: versionInBetween version "2.7.12" "2.7.11"; 74 | override = replacePatch "no-ldconfig.patch" ./patches/2.7.10-no-ldconfig.patch; 75 | } 76 | { condition = version: versionInBetween version "2.7.13" "2.7.12"; 77 | override = replacePatch "no-ldconfig.patch" ./patches/2.7.11-no-ldconfig.patch; 78 | } 79 | { condition = version: versionInBetween version "2.7.17" "2.7.6"; 80 | override = replacePatch "python-2.7-distutils-C++.patch" ./patches/2.7.17-distutils-C++.patch; 81 | } 82 | # this patch reverts an ActiveState change that was introduced in 2.7.18.8 83 | { condition = version: versionInBetween version "2.7.18.8" "2.7"; 84 | override = pkg: filterOutPatch "20ea5b46aaf1e7bdf9d6905ba8bece2cc73b05b0.patch" pkg; 85 | } 86 | # py3 87 | { condition = version: versionInBetween version "3.8.7" "3.8"; 88 | override = overrideLDConfigPatch ./patches/3.8.6-no-ldconfig.patch; 89 | } 90 | { condition = version: versionInBetween version "3.7.10" "3.7"; 91 | override = overrideLDConfigPatch ./patches/3.7.9-no-ldconfig.patch; 92 | } 93 | { condition = version: versionInBetween version "3.7.3" "3.7"; 94 | override = filterOutPatch "fix-finding-headers-when-cross-compiling.patch"; 95 | } 96 | { condition = version: versionInBetween version "3.7.3" "3.7.1"; 97 | override = replacePatch "python-3.x-distutils-C++.patch" (pkgs.fetchpatch { 98 | url = "https://bugs.python.org/file48016/python-3.x-distutils-C++.patch"; 99 | sha256 = "1h18lnpx539h5lfxyk379dxwr8m2raigcjixkf133l4xy3f4bzi2"; 100 | }); 101 | } 102 | { condition = version: versionInBetween version "3.7.4" "3.7.3"; 103 | override = replacePatch "python-3.x-distutils-C++.patch" ./patches/python-3.7.3-distutils-C++.patch; 104 | } 105 | { 106 | condition = version: versionInBetween version "3.7.2" "3.7" || versionInBetween version "3.6.8" "3.6.6"; 107 | override = replacePatch "python-3.x-distutils-C++.patch" (pkgs.fetchpatch { 108 | url = "https://bugs.python.org/file47669/python-3.8-distutils-C++.patch"; 109 | sha256 = "0s801d7ww9yrk6ys053jvdhl0wicbznx08idy36f1nrrxsghb3ii"; 110 | }); 111 | } 112 | { condition = version: versionInBetween version "3.5.3" "3.5"; 113 | # no existing patch available 114 | override = overrideLDConfigPatch null; 115 | } 116 | { condition = version: versionInBetween version "3.6.6" "3.4"; 117 | override = replacePatch "python-3.x-distutils-C++.patch" (pkgs.fetchpatch { 118 | url = "https://bugs.python.org/file47046/python-3.x-distutils-C++.patch"; 119 | sha256 = "0dgdn9k2kmw4wh90vdnjcrnn97ylxgx7mbn9l87fwz6j501jqvk8"; 120 | extraPrefix = ""; 121 | }); 122 | } 123 | # no C++ patch for 3.3 124 | { condition = version: versionInBetween version "3.4" "3.0"; 125 | override = filterOutPatch "python-3.x-distutils-C++.patch"; 126 | } 127 | # fix darwin compilation 128 | { condition = version: versionInBetween version "3.8.4" "3.8" || versionInBetween version "3.7.8" "3.0"; 129 | override = pkg: pkg.overrideAttrs (old: { 130 | patches = old.patches ++ [(pkgs.fetchpatch { 131 | url = "https://github.com/python/cpython/commit/8ea6353.patch"; 132 | sha256 = "xXRDwtMMhb66J4Lis0rtTNxARgPqLAqR2y3YtkJOt2g="; 133 | })]; 134 | }); 135 | } 136 | # Fix ensurepip for 3.6: https://bugs.python.org/issue45700 137 | { condition = version: versionInBetween version "3.6.15" "3.6"; 138 | override = pkg: pkg.overrideAttrs (old: { 139 | patches = old.patches ++ [(pkgs.fetchpatch { 140 | url = "https://github.com/python/cpython/commit/8766cb74e186d3820db0a855.patch"; 141 | sha256 = "IzAp3M6hpSNcbVRttzvXNDyAVK7vLesKZDEDkdYbuww="; 142 | }) 143 | (pkgs.fetchpatch { 144 | url = "https://github.com/python/cpython/commit/f0be4bbb9b3cee876249c23f.patch"; 145 | sha256 = "FUF7ZkkatS4ON4++pR9XJQFQLW1kKSVzSs8NAS19bDY="; 146 | })]; 147 | }); 148 | } 149 | { condition = version: versionInBetween version "3.4" "3.0"; 150 | override = pkg: (pkg.override { 151 | # no existing patch available 152 | noldconfigPatch = null; 153 | # otherwise it segfaults 154 | stdenv = 155 | if pkgs.stdenv.isLinux 156 | then pkgs.overrideCC pkgs.stdenv pkgs.gcc8 157 | else pkgs.stdenv; 158 | }); 159 | } 160 | # compatibility with substitutions done by the nixpkgs derivation 161 | { condition = version: versionInBetween version "3.7" "3.0"; 162 | override = pkg: pkg.overrideAttrs (old: { 163 | prePatch = '' 164 | substituteInPlace Lib/subprocess.py --replace-fail '"/bin/sh"' "'/bin/sh'" 165 | '' + old.prePatch; 166 | }); 167 | } 168 | # fill in the missing pc file 169 | { condition = version: versionInBetween version "3.5.2" "3.0" && pkgs.stdenv.isLinux; 170 | override = pkg: pkg.overrideAttrs (old: { 171 | postInstall = '' 172 | ln -s "$out/lib/pkgconfig/python-${pkg.passthru.sourceVersion.major}.${pkg.passthru.sourceVersion.minor}.pc" "$out/lib/pkgconfig/python3.pc" 173 | ''+ old.postInstall; 174 | }); 175 | } 176 | # https://www.cve.org/CVERecord?id=CVE-2024-12254 177 | # Applied to: 178 | # * 3.12.0-3.13.1 179 | { condition = version: 180 | versionInBetween version "3.14" "3.13.2" || 181 | versionInBetween version "3.13" "3.12.9"; 182 | override = filterOutPatch "CVE-2024-12254.patch"; 183 | } 184 | # https://www.cve.org/CVERecord?id=CVE-2025-0938 185 | # https://github.com/python/cpython/pull/129418 186 | # Applied to: 187 | # * 3.11.4-3.11.11,3.11.16 188 | # * 3.12.0-3.12.8 189 | # * 3.13.0-3.13.1 190 | { condition = version: 191 | lib.versionAtLeast version "3.14" || 192 | versionInBetween version "3.14" "3.13.2" || 193 | versionInBetween version "3.13" "3.12.9" || 194 | versionInBetween version "3.11.4" "3.11.0" || versionInBetween version "3.12" "3.11.12" || 195 | versionInBetween version "3.11" "3.10.17" || versionInBetween version "3.10.16" "3.10" || 196 | lib.versionOlder version "3.10"; 197 | override = filterOutPatch "CVE-2025-0938.patch"; 198 | } 199 | { condition = version: versionInBetween version "3.11.5" "2.0" || versionInBetween version "3.12" "3.11.12"; 200 | override = filterOutPatch "f4b31edf2d9d72878dab1f66a36913b5bcc848ec.patch"; 201 | } 202 | { condition = version: versionInBetween version "3.10.11" "3.10.0" || versionInBetween version "3.11" "3.10.17" ; 203 | override = filterOutPatch "raise-OSError-for-ERR_LIB_SYS.patch"; 204 | } 205 | ]; 206 | callPackage = pkgs.newScope { 207 | inherit python; 208 | pkgsBuildHost = pkgs.pkgsBuildHost // { 209 | "python${sourceVersion.major}${sourceVersion.minor}" = python; 210 | }; 211 | }; 212 | 213 | pythonFun = import "${toString pkgs.path}/pkgs/development/interpreters/python/cpython/${infix}default.nix"; 214 | python = (self.lib.applyOverrides overrides (callPackage pythonFun ({ 215 | inherit sourceVersion; 216 | hash = null; 217 | self = packages.${version}; 218 | passthruFun = callPackage "${pkgs.path}/pkgs/development/interpreters/python/passthrufun.nix" { }; 219 | } // lib.optionalAttrs (sourceVersion.major == "3") { 220 | noldconfigPatch = ./patches + "/${sourceVersion.major}.${sourceVersion.minor}-no-ldconfig.patch"; 221 | } // lib.optionalAttrs (lib.functionArgs pythonFun ? configd) { 222 | # Nixpkgs had a Darwin SDK refactor in 24.11 which removed configd from the Python derivation 223 | # Only inject configd for older Nixpkgs where it's required. 224 | inherit (pkgs.darwin) configd; 225 | }))).overrideAttrs (old: { 226 | src = pkgs.fetchurl { 227 | inherit url; 228 | sha256 = hash; 229 | }; 230 | meta = old.meta // { 231 | knownVulnerabilities = []; 232 | }; 233 | }); 234 | in python; 235 | 236 | lib.versions = builtins.fromJSON (builtins.readFile ./versions.json); 237 | 238 | packages = forAllSystems (system: 239 | let 240 | pkgs = nixpkgs.legacyPackages.${system}; 241 | getRelease = version: source: self.lib.mkPython { 242 | inherit pkgs version packages; 243 | inherit (source) hash url; 244 | }; 245 | getLatest = version: latest: 246 | getRelease latest self.lib.versions.releases.${latest}; 247 | packages = pkgs.lib.mapAttrs getRelease self.lib.versions.releases 248 | // pkgs.lib.mapAttrs getLatest self.lib.versions.latest; 249 | in packages 250 | ); 251 | 252 | checks = forAllSystems (system: 253 | let 254 | pkgs = nixpkgs.legacyPackages.${system}; 255 | in 256 | pkgs.lib.concatMapAttrs (version: python: { 257 | ${version} = python; 258 | } // lib.optionalAttrs (versionInBetween version "3" "2.7.18") { 259 | ${version + "-ssl"} = pkgs.runCommand "${version}-test-ssl" { } '' 260 | set -x 261 | 262 | mkdir $out 263 | ${python}/bin/python -c 'import ssl; print(ssl.OPENSSL_VERSION)' | tee $out/openssl-version 264 | ''; 265 | } // lib.optionalAttrs (versionInBetween version "3.12" "3.6") { 266 | ${version + "-ensurepip"} = pkgs.runCommand "${version}-test-ensurepip" { } '' 267 | set -x 268 | 269 | mkdir $out 270 | ${python}/bin/python -m ensurepip --help | tee $out/ensurepip-help 271 | ''; 272 | }) self.packages.${system}); 273 | }; 274 | } 275 | -------------------------------------------------------------------------------- /patches/2.6-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | --- a/Lib/ctypes/util.py 2023-05-29 14:05:36.312398701 +0100 2 | +++ b/Lib/ctypes/util.py 2023-05-29 14:07:20.235686728 +0100 3 | @@ -159,17 +159,7 @@ 4 | else: 5 | 6 | def _findLib_ldconfig(name): 7 | - # XXX assuming GLIBC's ldconfig (with option -p) 8 | - expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) 9 | - res = re.search(expr, 10 | - os.popen('/sbin/ldconfig -p 2>/dev/null').read()) 11 | - if not res: 12 | - # Hm, this works only for libs needed by the python executable. 13 | - cmd = 'ldd %s 2>/dev/null' % sys.executable 14 | - res = re.search(expr, os.popen(cmd).read()) 15 | - if not res: 16 | - return None 17 | - return res.group(0) 18 | + return None 19 | 20 | def find_library(name): 21 | return _get_soname(_findLib_ldconfig(name) or _findLib_gcc(name)) 22 | --- a/Lib/uuid.py 23 | +++ b/Lib/uuid.py 24 | @@ -387,54 +387,7 @@ 25 | return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + 26 | (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) 27 | 28 | -# Thanks to Thomas Heller for ctypes and for his help with its use here. 29 | - 30 | -# If ctypes is available, use it to find system routines for UUID generation. 31 | _uuid_generate_random = _uuid_generate_time = _UuidCreate = None 32 | -try: 33 | - import ctypes, ctypes.util 34 | - 35 | - # The uuid_generate_* routines are provided by libuuid on at least 36 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 37 | - for libname in ['uuid', 'c']: 38 | - try: 39 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 40 | - except: 41 | - continue 42 | - if hasattr(lib, 'uuid_generate_random'): 43 | - _uuid_generate_random = lib.uuid_generate_random 44 | - if hasattr(lib, 'uuid_generate_time'): 45 | - _uuid_generate_time = lib.uuid_generate_time 46 | - 47 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 48 | - # in issue #8621 the function generates the same sequence of values 49 | - # in the parent process and all children created using fork (unless 50 | - # those children use exec as well). 51 | - # 52 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 53 | - # the test can be adjusted when a later version is fixed. 54 | - import sys 55 | - if sys.platform == 'darwin': 56 | - import os 57 | - if int(os.uname()[2].split('.')[0]) >= 9: 58 | - _uuid_generate_random = _uuid_generate_time = None 59 | - 60 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 61 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 62 | - # random UUID and UuidCreateSequential gives a UUID containing the 63 | - # hardware address. These routines are provided by the RPC runtime. 64 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 65 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 66 | - # to bear any relationship to the MAC address of any network device 67 | - # on the box. 68 | - try: 69 | - lib = ctypes.windll.rpcrt4 70 | - except: 71 | - lib = None 72 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 73 | - getattr(lib, 'UuidCreate', None)) 74 | -except: 75 | - pass 76 | 77 | def _unixdll_getnode(): 78 | """Get the hardware address on Unix using ctypes.""" 79 | 80 | -------------------------------------------------------------------------------- /patches/2.7-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 6b0f329a9f37110020ca02b35c8125391ef282b7 Mon Sep 17 00:00:00 2001 2 | From: Frederik Rietdijk 3 | Date: Sat, 24 Dec 2016 15:56:10 +0100 4 | Subject: [PATCH] no ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 35 +---------------------------------- 8 | Lib/uuid.py | 47 ----------------------------------------------- 9 | 2 files changed, 1 insertion(+), 81 deletions(-) 10 | 11 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 12 | index ab10ec5..f253e34 100644 13 | --- a/Lib/ctypes/util.py 14 | +++ b/Lib/ctypes/util.py 15 | @@ -235,40 +235,7 @@ elif os.name == "posix": 16 | else: 17 | 18 | def _findSoname_ldconfig(name): 19 | - import struct 20 | - if struct.calcsize('l') == 4: 21 | - machine = os.uname()[4] + '-32' 22 | - else: 23 | - machine = os.uname()[4] + '-64' 24 | - mach_map = { 25 | - 'x86_64-64': 'libc6,x86-64', 26 | - 'ppc64-64': 'libc6,64bit', 27 | - 'sparc64-64': 'libc6,64bit', 28 | - 's390x-64': 'libc6,64bit', 29 | - 'ia64-64': 'libc6,IA-64', 30 | - } 31 | - abi_type = mach_map.get(machine, 'libc6') 32 | - 33 | - # XXX assuming GLIBC's ldconfig (with option -p) 34 | - expr = r'\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type) 35 | - 36 | - env = dict(os.environ) 37 | - env['LC_ALL'] = 'C' 38 | - env['LANG'] = 'C' 39 | - null = open(os.devnull, 'wb') 40 | - try: 41 | - with null: 42 | - p = subprocess.Popen(['/sbin/ldconfig', '-p'], 43 | - stderr=null, 44 | - stdout=subprocess.PIPE, 45 | - env=env) 46 | - except OSError: # E.g. command not found 47 | - return None 48 | - [data, _] = p.communicate() 49 | - res = re.search(expr, data) 50 | - if not res: 51 | - return None 52 | - return res.group(1) 53 | + return None 54 | 55 | def find_library(name): 56 | return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) 57 | diff --git a/Lib/uuid.py b/Lib/uuid.py 58 | index 7432032..05eeee5 100644 59 | --- a/Lib/uuid.py 60 | +++ b/Lib/uuid.py 61 | @@ -441,53 +441,6 @@ def _netbios_getnode(): 62 | 63 | # If ctypes is available, use it to find system routines for UUID generation. 64 | _uuid_generate_time = _UuidCreate = None 65 | -try: 66 | - import ctypes, ctypes.util 67 | - import sys 68 | - 69 | - # The uuid_generate_* routines are provided by libuuid on at least 70 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 71 | - _libnames = ['uuid'] 72 | - if not sys.platform.startswith('win'): 73 | - _libnames.append('c') 74 | - for libname in _libnames: 75 | - try: 76 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 77 | - except: 78 | - continue 79 | - if hasattr(lib, 'uuid_generate_time'): 80 | - _uuid_generate_time = lib.uuid_generate_time 81 | - break 82 | - del _libnames 83 | - 84 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 85 | - # in issue #8621 the function generates the same sequence of values 86 | - # in the parent process and all children created using fork (unless 87 | - # those children use exec as well). 88 | - # 89 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 90 | - # the test can be adjusted when a later version is fixed. 91 | - if sys.platform == 'darwin': 92 | - import os 93 | - if int(os.uname()[2].split('.')[0]) >= 9: 94 | - _uuid_generate_time = None 95 | - 96 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 97 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 98 | - # random UUID and UuidCreateSequential gives a UUID containing the 99 | - # hardware address. These routines are provided by the RPC runtime. 100 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 101 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 102 | - # to bear any relationship to the MAC address of any network device 103 | - # on the box. 104 | - try: 105 | - lib = ctypes.windll.rpcrt4 106 | - except: 107 | - lib = None 108 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 109 | - getattr(lib, 'UuidCreate', None)) 110 | -except: 111 | - pass 112 | 113 | def _unixdll_getnode(): 114 | """Get the hardware address on Unix using ctypes.""" 115 | -- 116 | 2.11.0 117 | 118 | -------------------------------------------------------------------------------- /patches/2.7.10-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | diff -ru -x '*~' Python-2.7.11-orig/Lib/ctypes/util.py Python-2.7.11/Lib/ctypes/util.py 2 | --- Python-2.7.11-orig/Lib/ctypes/util.py 2015-12-05 20:46:56.000000000 +0100 3 | +++ Python-2.7.11/Lib/ctypes/util.py 2016-07-01 14:24:50.714223450 +0200 4 | @@ -212,31 +212,7 @@ 5 | else: 6 | 7 | def _findSoname_ldconfig(name): 8 | - import struct 9 | - if struct.calcsize('l') == 4: 10 | - machine = os.uname()[4] + '-32' 11 | - else: 12 | - machine = os.uname()[4] + '-64' 13 | - mach_map = { 14 | - 'x86_64-64': 'libc6,x86-64', 15 | - 'ppc64-64': 'libc6,64bit', 16 | - 'sparc64-64': 'libc6,64bit', 17 | - 's390x-64': 'libc6,64bit', 18 | - 'ia64-64': 'libc6,IA-64', 19 | - } 20 | - abi_type = mach_map.get(machine, 'libc6') 21 | - 22 | - # XXX assuming GLIBC's ldconfig (with option -p) 23 | - expr = r'\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type) 24 | - f = os.popen('/sbin/ldconfig -p 2>/dev/null') 25 | - try: 26 | - data = f.read() 27 | - finally: 28 | - f.close() 29 | - res = re.search(expr, data) 30 | - if not res: 31 | - return None 32 | - return res.group(1) 33 | + return None 34 | 35 | def find_library(name): 36 | return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) 37 | diff -ru -x '*~' Python-2.7.11-orig/Lib/uuid.py Python-2.7.11/Lib/uuid.py 38 | --- Python-2.7.11-orig/Lib/uuid.py 2015-12-05 20:47:09.000000000 +0100 39 | +++ Python-2.7.11/Lib/uuid.py 2016-07-01 14:33:14.360446897 +0200 40 | @@ -437,57 +437,7 @@ 41 | return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + 42 | (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) 43 | 44 | -# Thanks to Thomas Heller for ctypes and for his help with its use here. 45 | - 46 | -# If ctypes is available, use it to find system routines for UUID generation. 47 | _uuid_generate_time = _UuidCreate = None 48 | -try: 49 | - import ctypes, ctypes.util 50 | - import sys 51 | - 52 | - # The uuid_generate_* routines are provided by libuuid on at least 53 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 54 | - _libnames = ['uuid'] 55 | - if not sys.platform.startswith('win'): 56 | - _libnames.append('c') 57 | - for libname in _libnames: 58 | - try: 59 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 60 | - except: 61 | - continue 62 | - if hasattr(lib, 'uuid_generate_time'): 63 | - _uuid_generate_time = lib.uuid_generate_time 64 | - break 65 | - del _libnames 66 | - 67 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 68 | - # in issue #8621 the function generates the same sequence of values 69 | - # in the parent process and all children created using fork (unless 70 | - # those children use exec as well). 71 | - # 72 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 73 | - # the test can be adjusted when a later version is fixed. 74 | - if sys.platform == 'darwin': 75 | - import os 76 | - if int(os.uname()[2].split('.')[0]) >= 9: 77 | - _uuid_generate_time = None 78 | - 79 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 80 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 81 | - # random UUID and UuidCreateSequential gives a UUID containing the 82 | - # hardware address. These routines are provided by the RPC runtime. 83 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 84 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 85 | - # to bear any relationship to the MAC address of any network device 86 | - # on the box. 87 | - try: 88 | - lib = ctypes.windll.rpcrt4 89 | - except: 90 | - lib = None 91 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 92 | - getattr(lib, 'UuidCreate', None)) 93 | -except: 94 | - pass 95 | 96 | def _unixdll_getnode(): 97 | """Get the hardware address on Unix using ctypes.""" 98 | -------------------------------------------------------------------------------- /patches/2.7.11-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 2 | index b2c514d..a6eca81 100644 3 | --- a/Lib/ctypes/util.py 4 | +++ b/Lib/ctypes/util.py 5 | @@ -207,31 +207,7 @@ elif os.name == "posix": 6 | else: 7 | 8 | def _findSoname_ldconfig(name): 9 | - import struct 10 | - if struct.calcsize('l') == 4: 11 | - machine = os.uname()[4] + '-32' 12 | - else: 13 | - machine = os.uname()[4] + '-64' 14 | - mach_map = { 15 | - 'x86_64-64': 'libc6,x86-64', 16 | - 'ppc64-64': 'libc6,64bit', 17 | - 'sparc64-64': 'libc6,64bit', 18 | - 's390x-64': 'libc6,64bit', 19 | - 'ia64-64': 'libc6,IA-64', 20 | - } 21 | - abi_type = mach_map.get(machine, 'libc6') 22 | - 23 | - # XXX assuming GLIBC's ldconfig (with option -p) 24 | - expr = r'\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type) 25 | - f = os.popen('LC_ALL=C LANG=C /sbin/ldconfig -p 2>/dev/null') 26 | - try: 27 | - data = f.read() 28 | - finally: 29 | - f.close() 30 | - res = re.search(expr, data) 31 | - if not res: 32 | - return None 33 | - return res.group(1) 34 | + return None 35 | 36 | def find_library(name): 37 | return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) 38 | diff --git a/Lib/uuid.py b/Lib/uuid.py 39 | index 7432032..9829d18 100644 40 | --- a/Lib/uuid.py 41 | +++ b/Lib/uuid.py 42 | @@ -437,57 +437,7 @@ def _netbios_getnode(): 43 | return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + 44 | (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) 45 | 46 | -# Thanks to Thomas Heller for ctypes and for his help with its use here. 47 | - 48 | -# If ctypes is available, use it to find system routines for UUID generation. 49 | _uuid_generate_time = _UuidCreate = None 50 | -try: 51 | - import ctypes, ctypes.util 52 | - import sys 53 | - 54 | - # The uuid_generate_* routines are provided by libuuid on at least 55 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 56 | - _libnames = ['uuid'] 57 | - if not sys.platform.startswith('win'): 58 | - _libnames.append('c') 59 | - for libname in _libnames: 60 | - try: 61 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 62 | - except: 63 | - continue 64 | - if hasattr(lib, 'uuid_generate_time'): 65 | - _uuid_generate_time = lib.uuid_generate_time 66 | - break 67 | - del _libnames 68 | - 69 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 70 | - # in issue #8621 the function generates the same sequence of values 71 | - # in the parent process and all children created using fork (unless 72 | - # those children use exec as well). 73 | - # 74 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 75 | - # the test can be adjusted when a later version is fixed. 76 | - if sys.platform == 'darwin': 77 | - import os 78 | - if int(os.uname()[2].split('.')[0]) >= 9: 79 | - _uuid_generate_time = None 80 | - 81 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 82 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 83 | - # random UUID and UuidCreateSequential gives a UUID containing the 84 | - # hardware address. These routines are provided by the RPC runtime. 85 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 86 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 87 | - # to bear any relationship to the MAC address of any network device 88 | - # on the box. 89 | - try: 90 | - lib = ctypes.windll.rpcrt4 91 | - except: 92 | - lib = None 93 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 94 | - getattr(lib, 'UuidCreate', None)) 95 | -except: 96 | - pass 97 | 98 | def _unixdll_getnode(): 99 | """Get the hardware address on Unix using ctypes.""" 100 | -------------------------------------------------------------------------------- /patches/2.7.17-distutils-C++.patch: -------------------------------------------------------------------------------- 1 | --- a/Lib/distutils/cygwinccompiler.py 2 | +++ b/Lib/distutils/cygwinccompiler.py 3 | @@ -117,8 +117,10 @@ 4 | # dllwrap 2.10.90 is buggy 5 | if self.ld_version >= "2.10.90": 6 | self.linker_dll = "gcc" 7 | + self.linker_dll_cxx = "g++" 8 | else: 9 | self.linker_dll = "dllwrap" 10 | + self.linker_dll_cxx = "dllwrap" 11 | 12 | # ld_version >= "2.13" support -shared so use it instead of 13 | # -mdll -static 14 | @@ -132,9 +134,13 @@ 15 | self.set_executables(compiler='gcc -mcygwin -O -Wall', 16 | compiler_so='gcc -mcygwin -mdll -O -Wall', 17 | compiler_cxx='g++ -mcygwin -O -Wall', 18 | + compiler_so_cxx='g++ -mcygwin -mdll -O -Wall', 19 | linker_exe='gcc -mcygwin', 20 | linker_so=('%s -mcygwin %s' % 21 | - (self.linker_dll, shared_option))) 22 | + (self.linker_dll, shared_option)), 23 | + linker_exe_cxx='g++ -mcygwin', 24 | + linker_so_cxx=('%s -mcygwin %s' % 25 | + (self.linker_dll_cxx, shared_option))) 26 | 27 | # cygwin and mingw32 need different sets of libraries 28 | if self.gcc_version == "2.91.57": 29 | @@ -160,8 +166,12 @@ 30 | raise CompileError, msg 31 | else: # for other files use the C-compiler 32 | try: 33 | - self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 34 | - extra_postargs) 35 | + if self.detect_language(src) == 'c++': 36 | + self.spawn(self.compiler_so_cxx + cc_args + [src, '-o', obj] + 37 | + extra_postargs) 38 | + else: 39 | + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 40 | + extra_postargs) 41 | except DistutilsExecError, msg: 42 | raise CompileError, msg 43 | 44 | @@ -327,9 +337,14 @@ 45 | self.set_executables(compiler='gcc%s -O -Wall' % no_cygwin, 46 | compiler_so='gcc%s -mdll -O -Wall' % no_cygwin, 47 | compiler_cxx='g++%s -O -Wall' % no_cygwin, 48 | + compiler_so_cxx='g++%s -mdll -O -Wall' % no_cygwin, 49 | linker_exe='gcc%s' % no_cygwin, 50 | linker_so='%s%s %s %s' 51 | % (self.linker_dll, no_cygwin, 52 | + shared_option, entry_point), 53 | + linker_exe_cxx='g++%s' % no_cygwin, 54 | + linker_so_cxx='%s%s %s %s' 55 | + % (self.linker_dll_cxx, no_cygwin, 56 | shared_option, entry_point)) 57 | # Maybe we should also append -mthreads, but then the finished 58 | # dlls need another dll (mingwm10.dll see Mingw32 docs) 59 | --- a/Lib/distutils/emxccompiler.py 60 | +++ b/Lib/distutils/emxccompiler.py 61 | @@ -65,8 +65,12 @@ 62 | # XXX optimization, warnings etc. should be customizable. 63 | self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall', 64 | compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall', 65 | + compiler_cxx='g++ -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall', 66 | + compiler_so_cxx='g++ -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall', 67 | linker_exe='gcc -Zomf -Zmt -Zcrtdll', 68 | - linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll') 69 | + linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll', 70 | + linker_exe_cxx='g++ -Zomf -Zmt -Zcrtdll', 71 | + linker_so_cxx='g++ -Zomf -Zmt -Zcrtdll -Zdll') 72 | 73 | # want the gcc library statically linked (so that we don't have 74 | # to distribute a version dependent on the compiler we have) 75 | @@ -83,8 +87,12 @@ 76 | raise CompileError, msg 77 | else: # for other files use the C-compiler 78 | try: 79 | - self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 80 | - extra_postargs) 81 | + if self.detect_language(src) == 'c++': 82 | + self.spawn(self.compiler_so_cxx + cc_args + [src, '-o', obj] + 83 | + extra_postargs) 84 | + else: 85 | + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 86 | + extra_postargs) 87 | except DistutilsExecError, msg: 88 | raise CompileError, msg 89 | 90 | --- a/Lib/distutils/sysconfig.py 91 | +++ b/Lib/distutils/sysconfig.py 92 | @@ -170,10 +170,12 @@ 93 | _osx_support.customize_compiler(_config_vars) 94 | _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' 95 | 96 | - (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \ 97 | - get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', 98 | - 'CCSHARED', 'LDSHARED', 'SO', 'AR', 99 | - 'ARFLAGS') 100 | + (cc, cxx, ccshared, ldshared, ldcxxshared, so_ext, ar, ar_flags) = \ 101 | + get_config_vars('CC', 'CXX', 'CCSHARED', 'LDSHARED', 'LDCXXSHARED', 102 | + 'SO', 'AR', 'ARFLAGS') 103 | + 104 | + cflags = '' 105 | + cxxflags = '' 106 | 107 | if 'CC' in os.environ: 108 | newcc = os.environ['CC'] 109 | @@ -188,19 +190,27 @@ 110 | cxx = os.environ['CXX'] 111 | if 'LDSHARED' in os.environ: 112 | ldshared = os.environ['LDSHARED'] 113 | + if 'LDCXXSHARED' in os.environ: 114 | + ldcxxshared = os.environ['LDCXXSHARED'] 115 | if 'CPP' in os.environ: 116 | cpp = os.environ['CPP'] 117 | else: 118 | cpp = cc + " -E" # not always 119 | if 'LDFLAGS' in os.environ: 120 | ldshared = ldshared + ' ' + os.environ['LDFLAGS'] 121 | + ldcxxshared = ldcxxshared + ' ' + os.environ['LDFLAGS'] 122 | if 'CFLAGS' in os.environ: 123 | - cflags = opt + ' ' + os.environ['CFLAGS'] 124 | + cflags = os.environ['CFLAGS'] 125 | ldshared = ldshared + ' ' + os.environ['CFLAGS'] 126 | + if 'CXXFLAGS' in os.environ: 127 | + cxxflags = os.environ['CXXFLAGS'] 128 | + ldcxxshared = ldcxxshared + ' ' + os.environ['CXXFLAGS'] 129 | if 'CPPFLAGS' in os.environ: 130 | cpp = cpp + ' ' + os.environ['CPPFLAGS'] 131 | cflags = cflags + ' ' + os.environ['CPPFLAGS'] 132 | + cxxflags = cxxflags + ' ' + os.environ['CPPFLAGS'] 133 | ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] 134 | + ldcxxshared = ldcxxshared + ' ' + os.environ['CPPFLAGS'] 135 | if 'AR' in os.environ: 136 | ar = os.environ['AR'] 137 | if 'ARFLAGS' in os.environ: 138 | @@ -209,13 +219,17 @@ 139 | archiver = ar + ' ' + ar_flags 140 | 141 | cc_cmd = cc + ' ' + cflags 142 | + cxx_cmd = cxx + ' ' + cxxflags 143 | compiler.set_executables( 144 | preprocessor=cpp, 145 | compiler=cc_cmd, 146 | compiler_so=cc_cmd + ' ' + ccshared, 147 | - compiler_cxx=cxx, 148 | + compiler_cxx=cxx_cmd, 149 | + compiler_so_cxx=cxx_cmd + ' ' + ccshared, 150 | linker_so=ldshared, 151 | linker_exe=cc, 152 | + linker_so_cxx=ldcxxshared, 153 | + linker_exe_cxx=cxx, 154 | archiver=archiver) 155 | 156 | compiler.shared_lib_extension = so_ext 157 | --- a/Lib/distutils/unixccompiler.py 158 | +++ b/Lib/distutils/unixccompiler.py 159 | @@ -55,14 +55,17 @@ 160 | # are pretty generic; they will probably have to be set by an outsider 161 | # (eg. using information discovered by the sysconfig about building 162 | # Python extensions). 163 | - executables = {'preprocessor' : None, 164 | - 'compiler' : ["cc"], 165 | - 'compiler_so' : ["cc"], 166 | - 'compiler_cxx' : ["cc"], 167 | - 'linker_so' : ["cc", "-shared"], 168 | - 'linker_exe' : ["cc"], 169 | - 'archiver' : ["ar", "-cr"], 170 | - 'ranlib' : None, 171 | + executables = {'preprocessor' : None, 172 | + 'compiler' : ["cc"], 173 | + 'compiler_so' : ["cc"], 174 | + 'compiler_cxx' : ["c++"], 175 | + 'compiler_so_cxx' : ["c++"], 176 | + 'linker_so' : ["cc", "-shared"], 177 | + 'linker_exe' : ["cc"], 178 | + 'linker_so_cxx' : ["c++", "-shared"], 179 | + 'linker_exe_cxx' : ["c++"], 180 | + 'archiver' : ["ar", "-cr"], 181 | + 'ranlib' : None, 182 | } 183 | 184 | if sys.platform[:6] == "darwin": 185 | @@ -112,12 +115,19 @@ 186 | 187 | def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): 188 | compiler_so = self.compiler_so 189 | + compiler_so_cxx = self.compiler_so_cxx 190 | if sys.platform == 'darwin': 191 | compiler_so = _osx_support.compiler_fixup(compiler_so, 192 | cc_args + extra_postargs) 193 | + compiler_so_cxx = _osx_support.compiler_fixup(compiler_so_cxx, 194 | + cc_args + extra_postargs) 195 | try: 196 | - self.spawn(compiler_so + cc_args + [src, '-o', obj] + 197 | - extra_postargs) 198 | + if self.detect_language(src) == 'c++': 199 | + self.spawn(compiler_so_cxx + cc_args + [src, '-o', obj] + 200 | + extra_postargs) 201 | + else: 202 | + self.spawn(compiler_so + cc_args + [src, '-o', obj] + 203 | + extra_postargs) 204 | except DistutilsExecError, msg: 205 | raise CompileError, msg 206 | 207 | @@ -174,23 +184,16 @@ 208 | ld_args.extend(extra_postargs) 209 | self.mkpath(os.path.dirname(output_filename)) 210 | try: 211 | - if target_desc == CCompiler.EXECUTABLE: 212 | - linker = self.linker_exe[:] 213 | + if target_lang == "c++": 214 | + if target_desc == CCompiler.EXECUTABLE: 215 | + linker = self.linker_exe_cxx[:] 216 | + else: 217 | + linker = self.linker_so_cxx[:] 218 | else: 219 | - linker = self.linker_so[:] 220 | - if target_lang == "c++" and self.compiler_cxx: 221 | - # skip over environment variable settings if /usr/bin/env 222 | - # is used to set up the linker's environment. 223 | - # This is needed on OSX. Note: this assumes that the 224 | - # normal and C++ compiler have the same environment 225 | - # settings. 226 | - i = 0 227 | - if os.path.basename(linker[0]) == "env": 228 | - i = 1 229 | - while '=' in linker[i]: 230 | - i = i + 1 231 | - 232 | - linker[i] = self.compiler_cxx[i] 233 | + if target_desc == CCompiler.EXECUTABLE: 234 | + linker = self.linker_exe[:] 235 | + else: 236 | + linker = self.linker_so[:] 237 | 238 | if sys.platform == 'darwin': 239 | linker = _osx_support.compiler_fixup(linker, ld_args) 240 | --- a/Lib/_osx_support.py 241 | +++ b/Lib/_osx_support.py 242 | @@ -14,13 +14,13 @@ 243 | # configuration variables that may contain universal build flags, 244 | # like "-arch" or "-isdkroot", that may need customization for 245 | # the user environment 246 | -_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', 247 | - 'BLDSHARED', 'LDSHARED', 'CC', 'CXX', 248 | - 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS', 249 | - 'PY_CORE_CFLAGS') 250 | +_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'CXXFLAGS', 'LDFLAGS', 'CPPFLAGS', 251 | + 'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'LDCXXSHARED', 252 | + 'CC', 'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 253 | + 'PY_CPPFLAGS', 'PY_CORE_CFLAGS') 254 | 255 | # configuration variables that may contain compiler calls 256 | -_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX') 257 | +_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'LDCXXSHARED', 'CC', 'CXX') 258 | 259 | # prefix added to original configuration variable names 260 | _INITPRE = '_OSX_SUPPORT_INITIAL_' -------------------------------------------------------------------------------- /patches/3.10-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 5330b6af9f832af59aa5c61d9ef6971053a8e709 Mon Sep 17 00:00:00 2001 2 | From: Jonathan Ringer 3 | Date: Mon, 9 Nov 2020 10:24:35 -0800 4 | Subject: [PATCH] CPython: Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ def _is_elf(filename): 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ def find_library(name, is64 = False): 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.33.1 107 | 108 | -------------------------------------------------------------------------------- /patches/3.11-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 5330b6af9f832af59aa5c61d9ef6971053a8e709 Mon Sep 17 00:00:00 2001 2 | From: Jonathan Ringer 3 | Date: Mon, 9 Nov 2020 10:24:35 -0800 4 | Subject: [PATCH] CPython: Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ def _is_elf(filename): 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ def find_library(name, is64 = False): 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.33.1 107 | 108 | -------------------------------------------------------------------------------- /patches/3.12-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 5330b6af9f832af59aa5c61d9ef6971053a8e709 Mon Sep 17 00:00:00 2001 2 | From: Jonathan Ringer 3 | Date: Mon, 9 Nov 2020 10:24:35 -0800 4 | Subject: [PATCH] CPython: Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ def _is_elf(filename): 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ def find_library(name, is64 = False): 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.33.1 107 | 108 | -------------------------------------------------------------------------------- /patches/3.13-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 5330b6af9f832af59aa5c61d9ef6971053a8e709 Mon Sep 17 00:00:00 2001 2 | From: Jonathan Ringer 3 | Date: Mon, 9 Nov 2020 10:24:35 -0800 4 | Subject: [PATCH] CPython: Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ def _is_elf(filename): 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ def find_library(name, is64 = False): 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.33.1 107 | 108 | -------------------------------------------------------------------------------- /patches/3.4-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 81bd99ad9058feb1d0361bc8862e8567c21a6142 Mon Sep 17 00:00:00 2001 2 | From: Frederik Rietdijk 3 | Date: Mon, 28 Aug 2017 09:24:06 +0200 4 | Subject: [PATCH] Don't use ldconfig and speed up uuid load 5 | 6 | --- 7 | Lib/ctypes/util.py | 52 ++-------------------------------------------------- 8 | Lib/uuid.py | 50 ++------------------------------------------------ 9 | 2 files changed, 4 insertions(+), 98 deletions(-) 10 | 11 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 12 | index 595113bffd..780cd5d21b 100644 13 | --- a/Lib/ctypes/util.py 14 | +++ b/Lib/ctypes/util.py 15 | @@ -88,28 +88,7 @@ elif os.name == "posix": 16 | import re, tempfile 17 | 18 | def _findLib_gcc(name): 19 | - expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) 20 | - fdout, ccout = tempfile.mkstemp() 21 | - os.close(fdout) 22 | - cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;' \ 23 | - 'LANG=C LC_ALL=C $CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name 24 | - try: 25 | - f = os.popen(cmd) 26 | - try: 27 | - trace = f.read() 28 | - finally: 29 | - rv = f.close() 30 | - finally: 31 | - try: 32 | - os.unlink(ccout) 33 | - except FileNotFoundError: 34 | - pass 35 | - if rv == 10: 36 | - raise OSError('gcc or cc command not found') 37 | - res = re.search(expr, trace) 38 | - if not res: 39 | - return None 40 | - return res.group(0) 41 | + return None 42 | 43 | 44 | if sys.platform == "sunos5": 45 | @@ -200,34 +179,7 @@ elif os.name == "posix": 46 | else: 47 | 48 | def _findSoname_ldconfig(name): 49 | - import struct 50 | - if struct.calcsize('l') == 4: 51 | - machine = os.uname().machine + '-32' 52 | - else: 53 | - machine = os.uname().machine + '-64' 54 | - mach_map = { 55 | - 'x86_64-64': 'libc6,x86-64', 56 | - 'ppc64-64': 'libc6,64bit', 57 | - 'sparc64-64': 'libc6,64bit', 58 | - 's390x-64': 'libc6,64bit', 59 | - 'ia64-64': 'libc6,IA-64', 60 | - } 61 | - abi_type = mach_map.get(machine, 'libc6') 62 | - 63 | - # XXX assuming GLIBC's ldconfig (with option -p) 64 | - regex = os.fsencode( 65 | - '\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type)) 66 | - try: 67 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 68 | - stdin=subprocess.DEVNULL, 69 | - stderr=subprocess.DEVNULL, 70 | - stdout=subprocess.PIPE, 71 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 72 | - res = re.search(regex, p.stdout.read()) 73 | - if res: 74 | - return os.fsdecode(res.group(1)) 75 | - except OSError: 76 | - pass 77 | + return None 78 | 79 | def find_library(name): 80 | return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) 81 | diff --git a/Lib/uuid.py b/Lib/uuid.py 82 | index 1061bffc43..846f5819f5 100644 83 | --- a/Lib/uuid.py 84 | +++ b/Lib/uuid.py 85 | @@ -451,57 +451,11 @@ def _netbios_getnode(): 86 | return ((bytes[0]<<40) + (bytes[1]<<32) + (bytes[2]<<24) + 87 | (bytes[3]<<16) + (bytes[4]<<8) + bytes[5]) 88 | 89 | -# Thanks to Thomas Heller for ctypes and for his help with its use here. 90 | 91 | -# If ctypes is available, use it to find system routines for UUID generation. 92 | -# XXX This makes the module non-thread-safe! 93 | _uuid_generate_random = _uuid_generate_time = _UuidCreate = None 94 | -try: 95 | - import ctypes, ctypes.util 96 | 97 | - # The uuid_generate_* routines are provided by libuuid on at least 98 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 99 | - for libname in ['uuid', 'c']: 100 | - try: 101 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 102 | - except: 103 | - continue 104 | - if hasattr(lib, 'uuid_generate_random'): 105 | - _uuid_generate_random = lib.uuid_generate_random 106 | - if hasattr(lib, 'uuid_generate_time'): 107 | - _uuid_generate_time = lib.uuid_generate_time 108 | - if _uuid_generate_random is not None: 109 | - break # found everything we were looking for 110 | - 111 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 112 | - # in issue #8621 the function generates the same sequence of values 113 | - # in the parent process and all children created using fork (unless 114 | - # those children use exec as well). 115 | - # 116 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 117 | - # the test can be adjusted when a later version is fixed. 118 | - import sys 119 | - if sys.platform == 'darwin': 120 | - import os 121 | - if int(os.uname().release.split('.')[0]) >= 9: 122 | - _uuid_generate_random = _uuid_generate_time = None 123 | - 124 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 125 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 126 | - # random UUID and UuidCreateSequential gives a UUID containing the 127 | - # hardware address. These routines are provided by the RPC runtime. 128 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 129 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 130 | - # to bear any relationship to the MAC address of any network device 131 | - # on the box. 132 | - try: 133 | - lib = ctypes.windll.rpcrt4 134 | - except: 135 | - lib = None 136 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 137 | - getattr(lib, 'UuidCreate', None)) 138 | -except: 139 | - pass 140 | +_uuid_generate_time = _UuidCreate = None 141 | + 142 | 143 | def _unixdll_getnode(): 144 | """Get the hardware address on Unix using ctypes.""" 145 | -- 146 | 2.14.1 147 | 148 | -------------------------------------------------------------------------------- /patches/3.5-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 590c46bb04f79ab611b2f8fd682dd7e43a01f268 Mon Sep 17 00:00:00 2001 2 | From: Frederik Rietdijk 3 | Date: Mon, 28 Aug 2017 09:24:06 +0200 4 | Subject: [PATCH] Don't use ldconfig and speed up uuid load 5 | 6 | --- 7 | Lib/ctypes/util.py | 70 ++---------------------------------------------------- 8 | Lib/uuid.py | 49 -------------------------------------- 9 | 2 files changed, 2 insertions(+), 117 deletions(-) 10 | 11 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 12 | index 7684eab81d..e9957d7951 100644 13 | --- a/Lib/ctypes/util.py 14 | +++ b/Lib/ctypes/util.py 15 | @@ -95,46 +95,7 @@ elif os.name == "posix": 16 | import re, tempfile 17 | 18 | def _findLib_gcc(name): 19 | - # Run GCC's linker with the -t (aka --trace) option and examine the 20 | - # library name it prints out. The GCC command will fail because we 21 | - # haven't supplied a proper program with main(), but that does not 22 | - # matter. 23 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 24 | - 25 | - c_compiler = shutil.which('gcc') 26 | - if not c_compiler: 27 | - c_compiler = shutil.which('cc') 28 | - if not c_compiler: 29 | - # No C compiler available, give up 30 | - return None 31 | - 32 | - temp = tempfile.NamedTemporaryFile() 33 | - try: 34 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 35 | - 36 | - env = dict(os.environ) 37 | - env['LC_ALL'] = 'C' 38 | - env['LANG'] = 'C' 39 | - try: 40 | - proc = subprocess.Popen(args, 41 | - stdout=subprocess.PIPE, 42 | - stderr=subprocess.STDOUT, 43 | - env=env) 44 | - except OSError: # E.g. bad executable 45 | - return None 46 | - with proc: 47 | - trace = proc.stdout.read() 48 | - finally: 49 | - try: 50 | - temp.close() 51 | - except FileNotFoundError: 52 | - # Raised if the file was already removed, which is the normal 53 | - # behaviour of GCC if linking fails 54 | - pass 55 | - res = re.search(expr, trace) 56 | - if not res: 57 | - return None 58 | - return os.fsdecode(res.group(0)) 59 | + return None 60 | 61 | 62 | if sys.platform == "sunos5": 63 | @@ -256,34 +217,7 @@ elif os.name == "posix": 64 | else: 65 | 66 | def _findSoname_ldconfig(name): 67 | - import struct 68 | - if struct.calcsize('l') == 4: 69 | - machine = os.uname().machine + '-32' 70 | - else: 71 | - machine = os.uname().machine + '-64' 72 | - mach_map = { 73 | - 'x86_64-64': 'libc6,x86-64', 74 | - 'ppc64-64': 'libc6,64bit', 75 | - 'sparc64-64': 'libc6,64bit', 76 | - 's390x-64': 'libc6,64bit', 77 | - 'ia64-64': 'libc6,IA-64', 78 | - } 79 | - abi_type = mach_map.get(machine, 'libc6') 80 | - 81 | - # XXX assuming GLIBC's ldconfig (with option -p) 82 | - regex = os.fsencode( 83 | - '\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type)) 84 | - try: 85 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 86 | - stdin=subprocess.DEVNULL, 87 | - stderr=subprocess.DEVNULL, 88 | - stdout=subprocess.PIPE, 89 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 90 | - res = re.search(regex, p.stdout.read()) 91 | - if res: 92 | - return os.fsdecode(res.group(1)) 93 | - except OSError: 94 | - pass 95 | + return None 96 | 97 | def find_library(name): 98 | return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) 99 | diff --git a/Lib/uuid.py b/Lib/uuid.py 100 | index e96e7e034c..31160ace95 100644 101 | --- a/Lib/uuid.py 102 | +++ b/Lib/uuid.py 103 | @@ -455,58 +455,9 @@ def _netbios_getnode(): 104 | continue 105 | return int.from_bytes(bytes, 'big') 106 | 107 | -# Thanks to Thomas Heller for ctypes and for his help with its use here. 108 | 109 | -# If ctypes is available, use it to find system routines for UUID generation. 110 | -# XXX This makes the module non-thread-safe! 111 | _uuid_generate_time = _UuidCreate = None 112 | -try: 113 | - import ctypes, ctypes.util 114 | - import sys 115 | 116 | - # The uuid_generate_* routines are provided by libuuid on at least 117 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 118 | - _libnames = ['uuid'] 119 | - if not sys.platform.startswith('win'): 120 | - _libnames.append('c') 121 | - for libname in _libnames: 122 | - try: 123 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 124 | - except Exception: 125 | - continue 126 | - if hasattr(lib, 'uuid_generate_time'): 127 | - _uuid_generate_time = lib.uuid_generate_time 128 | - break 129 | - del _libnames 130 | - 131 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 132 | - # in issue #8621 the function generates the same sequence of values 133 | - # in the parent process and all children created using fork (unless 134 | - # those children use exec as well). 135 | - # 136 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 137 | - # the test can be adjusted when a later version is fixed. 138 | - if sys.platform == 'darwin': 139 | - import os 140 | - if int(os.uname().release.split('.')[0]) >= 9: 141 | - _uuid_generate_time = None 142 | - 143 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 144 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 145 | - # random UUID and UuidCreateSequential gives a UUID containing the 146 | - # hardware address. These routines are provided by the RPC runtime. 147 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 148 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 149 | - # to bear any relationship to the MAC address of any network device 150 | - # on the box. 151 | - try: 152 | - lib = ctypes.windll.rpcrt4 153 | - except: 154 | - lib = None 155 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 156 | - getattr(lib, 'UuidCreate', None)) 157 | -except: 158 | - pass 159 | 160 | def _unixdll_getnode(): 161 | """Get the hardware address on Unix using ctypes.""" 162 | -- 163 | 2.14.1 164 | 165 | -------------------------------------------------------------------------------- /patches/3.6-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 105621b99cc30615c79b5aa3d12d6732e14b0d59 Mon Sep 17 00:00:00 2001 2 | From: Frederik Rietdijk 3 | Date: Mon, 28 Aug 2017 09:24:06 +0200 4 | Subject: [PATCH] Don't use ldconfig and speed up uuid load 5 | 6 | --- 7 | Lib/ctypes/util.py | 70 ++---------------------------------------------------- 8 | Lib/uuid.py | 48 ------------------------------------- 9 | 2 files changed, 2 insertions(+), 116 deletions(-) 10 | 11 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 12 | index 339ae8aa8a..2944985c30 100644 13 | --- a/Lib/ctypes/util.py 14 | +++ b/Lib/ctypes/util.py 15 | @@ -85,46 +85,7 @@ elif os.name == "posix": 16 | import re, tempfile 17 | 18 | def _findLib_gcc(name): 19 | - # Run GCC's linker with the -t (aka --trace) option and examine the 20 | - # library name it prints out. The GCC command will fail because we 21 | - # haven't supplied a proper program with main(), but that does not 22 | - # matter. 23 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 24 | - 25 | - c_compiler = shutil.which('gcc') 26 | - if not c_compiler: 27 | - c_compiler = shutil.which('cc') 28 | - if not c_compiler: 29 | - # No C compiler available, give up 30 | - return None 31 | - 32 | - temp = tempfile.NamedTemporaryFile() 33 | - try: 34 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 35 | - 36 | - env = dict(os.environ) 37 | - env['LC_ALL'] = 'C' 38 | - env['LANG'] = 'C' 39 | - try: 40 | - proc = subprocess.Popen(args, 41 | - stdout=subprocess.PIPE, 42 | - stderr=subprocess.STDOUT, 43 | - env=env) 44 | - except OSError: # E.g. bad executable 45 | - return None 46 | - with proc: 47 | - trace = proc.stdout.read() 48 | - finally: 49 | - try: 50 | - temp.close() 51 | - except FileNotFoundError: 52 | - # Raised if the file was already removed, which is the normal 53 | - # behaviour of GCC if linking fails 54 | - pass 55 | - res = re.search(expr, trace) 56 | - if not res: 57 | - return None 58 | - return os.fsdecode(res.group(0)) 59 | + return None 60 | 61 | 62 | if sys.platform == "sunos5": 63 | @@ -246,34 +207,7 @@ elif os.name == "posix": 64 | else: 65 | 66 | def _findSoname_ldconfig(name): 67 | - import struct 68 | - if struct.calcsize('l') == 4: 69 | - machine = os.uname().machine + '-32' 70 | - else: 71 | - machine = os.uname().machine + '-64' 72 | - mach_map = { 73 | - 'x86_64-64': 'libc6,x86-64', 74 | - 'ppc64-64': 'libc6,64bit', 75 | - 'sparc64-64': 'libc6,64bit', 76 | - 's390x-64': 'libc6,64bit', 77 | - 'ia64-64': 'libc6,IA-64', 78 | - } 79 | - abi_type = mach_map.get(machine, 'libc6') 80 | - 81 | - # XXX assuming GLIBC's ldconfig (with option -p) 82 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 83 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 84 | - try: 85 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 86 | - stdin=subprocess.DEVNULL, 87 | - stderr=subprocess.DEVNULL, 88 | - stdout=subprocess.PIPE, 89 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 90 | - res = re.search(regex, p.stdout.read()) 91 | - if res: 92 | - return os.fsdecode(res.group(1)) 93 | - except OSError: 94 | - pass 95 | + return None 96 | 97 | def _findLib_ld(name): 98 | # See issue #9998 for why this is needed 99 | diff --git a/Lib/uuid.py b/Lib/uuid.py 100 | index 200c800b34..31160ace95 100644 101 | --- a/Lib/uuid.py 102 | +++ b/Lib/uuid.py 103 | @@ -455,57 +455,9 @@ def _netbios_getnode(): 104 | continue 105 | return int.from_bytes(bytes, 'big') 106 | 107 | -# Thanks to Thomas Heller for ctypes and for his help with its use here. 108 | 109 | -# If ctypes is available, use it to find system routines for UUID generation. 110 | -# XXX This makes the module non-thread-safe! 111 | _uuid_generate_time = _UuidCreate = None 112 | -try: 113 | - import ctypes, ctypes.util 114 | - import sys 115 | 116 | - # The uuid_generate_* routines are provided by libuuid on at least 117 | - # Linux and FreeBSD, and provided by libc on Mac OS X. 118 | - _libnames = ['uuid'] 119 | - if not sys.platform.startswith('win'): 120 | - _libnames.append('c') 121 | - for libname in _libnames: 122 | - try: 123 | - lib = ctypes.CDLL(ctypes.util.find_library(libname)) 124 | - except Exception: 125 | - continue 126 | - if hasattr(lib, 'uuid_generate_time'): 127 | - _uuid_generate_time = lib.uuid_generate_time 128 | - break 129 | - del _libnames 130 | - 131 | - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 132 | - # in issue #8621 the function generates the same sequence of values 133 | - # in the parent process and all children created using fork (unless 134 | - # those children use exec as well). 135 | - # 136 | - # Assume that the uuid_generate functions are broken from 10.5 onward, 137 | - # the test can be adjusted when a later version is fixed. 138 | - if sys.platform == 'darwin': 139 | - if int(os.uname().release.split('.')[0]) >= 9: 140 | - _uuid_generate_time = None 141 | - 142 | - # On Windows prior to 2000, UuidCreate gives a UUID containing the 143 | - # hardware address. On Windows 2000 and later, UuidCreate makes a 144 | - # random UUID and UuidCreateSequential gives a UUID containing the 145 | - # hardware address. These routines are provided by the RPC runtime. 146 | - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 147 | - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 148 | - # to bear any relationship to the MAC address of any network device 149 | - # on the box. 150 | - try: 151 | - lib = ctypes.windll.rpcrt4 152 | - except: 153 | - lib = None 154 | - _UuidCreate = getattr(lib, 'UuidCreateSequential', 155 | - getattr(lib, 'UuidCreate', None)) 156 | -except: 157 | - pass 158 | 159 | def _unixdll_getnode(): 160 | """Get the hardware address on Unix using ctypes.""" 161 | -- 162 | 2.14.1 163 | -------------------------------------------------------------------------------- /patches/3.7-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 66f492d2eda94bd64db833839a325caf6ba0fed5 Mon Sep 17 00:00:00 2001 2 | From: Greg Roodt 3 | Date: Wed, 9 Dec 2020 17:59:24 +1100 4 | Subject: [PATCH] Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ elif os.name == "posix": 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ elif os.name == "posix": 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.24.3 (Apple Git-128) 107 | -------------------------------------------------------------------------------- /patches/3.7.9-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 597e73f2a4b2f0b508127931b36d5540d6941823 Mon Sep 17 00:00:00 2001 2 | From: Frederik Rietdijk 3 | Date: Mon, 28 Aug 2017 09:24:06 +0200 4 | Subject: [PATCH] Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 70 ++---------------------------------------------------- 8 | 1 file changed, 2 insertions(+), 68 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 5e8b31a854..7b45ce6c15 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -94,46 +94,7 @@ elif os.name == "posix": 15 | import re, tempfile 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.search(expr, trace) 55 | - if not res: 56 | - return None 57 | - return os.fsdecode(res.group(0)) 58 | + return None 59 | 60 | 61 | if sys.platform == "sunos5": 62 | @@ -255,34 +216,7 @@ elif os.name == "posix": 63 | else: 64 | 65 | def _findSoname_ldconfig(name): 66 | - import struct 67 | - if struct.calcsize('l') == 4: 68 | - machine = os.uname().machine + '-32' 69 | - else: 70 | - machine = os.uname().machine + '-64' 71 | - mach_map = { 72 | - 'x86_64-64': 'libc6,x86-64', 73 | - 'ppc64-64': 'libc6,64bit', 74 | - 'sparc64-64': 'libc6,64bit', 75 | - 's390x-64': 'libc6,64bit', 76 | - 'ia64-64': 'libc6,IA-64', 77 | - } 78 | - abi_type = mach_map.get(machine, 'libc6') 79 | - 80 | - # XXX assuming GLIBC's ldconfig (with option -p) 81 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 82 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 83 | - try: 84 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 85 | - stdin=subprocess.DEVNULL, 86 | - stderr=subprocess.DEVNULL, 87 | - stdout=subprocess.PIPE, 88 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 89 | - res = re.search(regex, p.stdout.read()) 90 | - if res: 91 | - return os.fsdecode(res.group(1)) 92 | - except OSError: 93 | - pass 94 | + return None 95 | 96 | def _findLib_ld(name): 97 | # See issue #9998 for why this is needed 98 | -- 99 | 2.15.0 100 | 101 | -------------------------------------------------------------------------------- /patches/3.8-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 66f492d2eda94bd64db833839a325caf6ba0fed5 Mon Sep 17 00:00:00 2001 2 | From: Greg Roodt 3 | Date: Wed, 9 Dec 2020 17:59:24 +1100 4 | Subject: [PATCH] Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ elif os.name == "posix": 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ elif os.name == "posix": 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.24.3 (Apple Git-128) 107 | -------------------------------------------------------------------------------- /patches/3.8.6-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 597e73f2a4b2f0b508127931b36d5540d6941823 Mon Sep 17 00:00:00 2001 2 | From: Frederik Rietdijk 3 | Date: Mon, 28 Aug 2017 09:24:06 +0200 4 | Subject: [PATCH] Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 70 ++---------------------------------------------------- 8 | 1 file changed, 2 insertions(+), 68 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 5e8b31a854..7b45ce6c15 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -94,46 +94,7 @@ elif os.name == "posix": 15 | import re, tempfile 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.search(expr, trace) 55 | - if not res: 56 | - return None 57 | - return os.fsdecode(res.group(0)) 58 | + return None 59 | 60 | 61 | if sys.platform == "sunos5": 62 | @@ -255,34 +216,7 @@ elif os.name == "posix": 63 | else: 64 | 65 | def _findSoname_ldconfig(name): 66 | - import struct 67 | - if struct.calcsize('l') == 4: 68 | - machine = os.uname().machine + '-32' 69 | - else: 70 | - machine = os.uname().machine + '-64' 71 | - mach_map = { 72 | - 'x86_64-64': 'libc6,x86-64', 73 | - 'ppc64-64': 'libc6,64bit', 74 | - 'sparc64-64': 'libc6,64bit', 75 | - 's390x-64': 'libc6,64bit', 76 | - 'ia64-64': 'libc6,IA-64', 77 | - } 78 | - abi_type = mach_map.get(machine, 'libc6') 79 | - 80 | - # XXX assuming GLIBC's ldconfig (with option -p) 81 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 82 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 83 | - try: 84 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 85 | - stdin=subprocess.DEVNULL, 86 | - stderr=subprocess.DEVNULL, 87 | - stdout=subprocess.PIPE, 88 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 89 | - res = re.search(regex, p.stdout.read()) 90 | - if res: 91 | - return os.fsdecode(res.group(1)) 92 | - except OSError: 93 | - pass 94 | + return None 95 | 96 | def _findLib_ld(name): 97 | # See issue #9998 for why this is needed 98 | -- 99 | 2.15.0 100 | 101 | -------------------------------------------------------------------------------- /patches/3.9-no-ldconfig.patch: -------------------------------------------------------------------------------- 1 | From 66f492d2eda94bd64db833839a325caf6ba0fed5 Mon Sep 17 00:00:00 2001 2 | From: Greg Roodt 3 | Date: Wed, 9 Dec 2020 17:59:24 +1100 4 | Subject: [PATCH] Don't use ldconfig 5 | 6 | --- 7 | Lib/ctypes/util.py | 77 ++-------------------------------------------- 8 | 1 file changed, 2 insertions(+), 75 deletions(-) 9 | 10 | diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 11 | index 0c2510e161..7fb98af308 100644 12 | --- a/Lib/ctypes/util.py 13 | +++ b/Lib/ctypes/util.py 14 | @@ -100,53 +100,7 @@ elif os.name == "posix": 15 | return thefile.read(4) == elf_header 16 | 17 | def _findLib_gcc(name): 18 | - # Run GCC's linker with the -t (aka --trace) option and examine the 19 | - # library name it prints out. The GCC command will fail because we 20 | - # haven't supplied a proper program with main(), but that does not 21 | - # matter. 22 | - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) 23 | - 24 | - c_compiler = shutil.which('gcc') 25 | - if not c_compiler: 26 | - c_compiler = shutil.which('cc') 27 | - if not c_compiler: 28 | - # No C compiler available, give up 29 | - return None 30 | - 31 | - temp = tempfile.NamedTemporaryFile() 32 | - try: 33 | - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] 34 | - 35 | - env = dict(os.environ) 36 | - env['LC_ALL'] = 'C' 37 | - env['LANG'] = 'C' 38 | - try: 39 | - proc = subprocess.Popen(args, 40 | - stdout=subprocess.PIPE, 41 | - stderr=subprocess.STDOUT, 42 | - env=env) 43 | - except OSError: # E.g. bad executable 44 | - return None 45 | - with proc: 46 | - trace = proc.stdout.read() 47 | - finally: 48 | - try: 49 | - temp.close() 50 | - except FileNotFoundError: 51 | - # Raised if the file was already removed, which is the normal 52 | - # behaviour of GCC if linking fails 53 | - pass 54 | - res = re.findall(expr, trace) 55 | - if not res: 56 | - return None 57 | - 58 | - for file in res: 59 | - # Check if the given file is an elf file: gcc can report 60 | - # some files that are linker scripts and not actual 61 | - # shared objects. See bpo-41976 for more details 62 | - if not _is_elf(file): 63 | - continue 64 | - return os.fsdecode(file) 65 | + return None 66 | 67 | 68 | if sys.platform == "sunos5": 69 | @@ -268,34 +222,7 @@ elif os.name == "posix": 70 | else: 71 | 72 | def _findSoname_ldconfig(name): 73 | - import struct 74 | - if struct.calcsize('l') == 4: 75 | - machine = os.uname().machine + '-32' 76 | - else: 77 | - machine = os.uname().machine + '-64' 78 | - mach_map = { 79 | - 'x86_64-64': 'libc6,x86-64', 80 | - 'ppc64-64': 'libc6,64bit', 81 | - 'sparc64-64': 'libc6,64bit', 82 | - 's390x-64': 'libc6,64bit', 83 | - 'ia64-64': 'libc6,IA-64', 84 | - } 85 | - abi_type = mach_map.get(machine, 'libc6') 86 | - 87 | - # XXX assuming GLIBC's ldconfig (with option -p) 88 | - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' 89 | - regex = os.fsencode(regex % (re.escape(name), abi_type)) 90 | - try: 91 | - with subprocess.Popen(['/sbin/ldconfig', '-p'], 92 | - stdin=subprocess.DEVNULL, 93 | - stderr=subprocess.DEVNULL, 94 | - stdout=subprocess.PIPE, 95 | - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: 96 | - res = re.search(regex, p.stdout.read()) 97 | - if res: 98 | - return os.fsdecode(res.group(1)) 99 | - except OSError: 100 | - pass 101 | + return None 102 | 103 | def _findLib_ld(name): 104 | # See issue #9998 for why this is needed 105 | -- 106 | 2.24.3 (Apple Git-128) 107 | -------------------------------------------------------------------------------- /patches/python-3.7.3-distutils-C++.patch: -------------------------------------------------------------------------------- 1 | --- a/Lib/_osx_support.py 2 | +++ b/Lib/_osx_support.py 3 | @@ -14,13 +14,13 @@ __all__ = [ 4 | # configuration variables that may contain universal build flags, 5 | # like "-arch" or "-isdkroot", that may need customization for 6 | # the user environment 7 | -_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', 8 | - 'BLDSHARED', 'LDSHARED', 'CC', 'CXX', 9 | - 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS', 10 | - 'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS') 11 | +_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'CXXFLAGS', 'LDFLAGS', 'CPPFLAGS', 12 | + 'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'LDCXXSHARED', 13 | + 'CC', 'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 14 | + 'PY_CPPFLAGS', 'PY_CORE_LDFLAGS', 'PY_CORE_CFLAGS') 15 | 16 | # configuration variables that may contain compiler calls 17 | -_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX') 18 | +_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'LDCXXSHARED', 'CC', 'CXX') 19 | 20 | # prefix added to original configuration variable names 21 | _INITPRE = '_OSX_SUPPORT_INITIAL_' 22 | --- a/Lib/distutils/cygwinccompiler.py 23 | +++ b/Lib/distutils/cygwinccompiler.py 24 | @@ -125,8 +125,10 @@ class CygwinCCompiler(UnixCCompiler): 25 | # dllwrap 2.10.90 is buggy 26 | if self.ld_version >= "2.10.90": 27 | self.linker_dll = "gcc" 28 | + self.linker_dll_cxx = "g++" 29 | else: 30 | self.linker_dll = "dllwrap" 31 | + self.linker_dll_cxx = "dllwrap" 32 | 33 | # ld_version >= "2.13" support -shared so use it instead of 34 | # -mdll -static 35 | @@ -140,9 +142,13 @@ class CygwinCCompiler(UnixCCompiler): 36 | self.set_executables(compiler='gcc -mcygwin -O -Wall', 37 | compiler_so='gcc -mcygwin -mdll -O -Wall', 38 | compiler_cxx='g++ -mcygwin -O -Wall', 39 | + compiler_so_cxx='g++ -mcygwin -mdll -O -Wall', 40 | linker_exe='gcc -mcygwin', 41 | linker_so=('%s -mcygwin %s' % 42 | - (self.linker_dll, shared_option))) 43 | + (self.linker_dll, shared_option)), 44 | + linker_exe_cxx='g++ -mcygwin', 45 | + linker_so_cxx=('%s -mcygwin %s' % 46 | + (self.linker_dll_cxx, shared_option))) 47 | 48 | # cygwin and mingw32 need different sets of libraries 49 | if self.gcc_version == "2.91.57": 50 | @@ -166,8 +172,12 @@ class CygwinCCompiler(UnixCCompiler): 51 | raise CompileError(msg) 52 | else: # for other files use the C-compiler 53 | try: 54 | - self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 55 | - extra_postargs) 56 | + if self.detect_language(src) == 'c++': 57 | + self.spawn(self.compiler_so_cxx + cc_args + [src, '-o', obj] + 58 | + extra_postargs) 59 | + else: 60 | + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 61 | + extra_postargs) 62 | except DistutilsExecError as msg: 63 | raise CompileError(msg) 64 | 65 | @@ -302,9 +312,14 @@ class Mingw32CCompiler(CygwinCCompiler): 66 | self.set_executables(compiler='gcc -O -Wall', 67 | compiler_so='gcc -mdll -O -Wall', 68 | compiler_cxx='g++ -O -Wall', 69 | + compiler_so_cxx='g++ -mdll -O -Wall', 70 | linker_exe='gcc', 71 | linker_so='%s %s %s' 72 | % (self.linker_dll, shared_option, 73 | + entry_point), 74 | + linker_exe_cxx='g++', 75 | + linker_so_cxx='%s %s %s' 76 | + % (self.linker_dll_cxx, shared_option, 77 | entry_point)) 78 | # Maybe we should also append -mthreads, but then the finished 79 | # dlls need another dll (mingwm10.dll see Mingw32 docs) 80 | --- a/Lib/distutils/sysconfig.py 81 | +++ b/Lib/distutils/sysconfig.py 82 | @@ -170,9 +170,11 @@ def customize_compiler(compiler): 83 | _osx_support.customize_compiler(_config_vars) 84 | _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' 85 | 86 | - (cc, cxx, opt, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \ 87 | - get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', 88 | - 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS') 89 | + (cc, cxx, cflags, ccshared, ldshared, ldcxxshared, shlib_suffix, ar, ar_flags) = \ 90 | + get_config_vars('CC', 'CXX', 'CFLAGS', 'CCSHARED', 'LDSHARED', 'LDCXXSHARED', 91 | + 'SHLIB_SUFFIX', 'AR', 'ARFLAGS') 92 | + 93 | + cxxflags = cflags 94 | 95 | if 'CC' in os.environ: 96 | newcc = os.environ['CC'] 97 | @@ -187,19 +189,27 @@ def customize_compiler(compiler): 98 | cxx = os.environ['CXX'] 99 | if 'LDSHARED' in os.environ: 100 | ldshared = os.environ['LDSHARED'] 101 | + if 'LDCXXSHARED' in os.environ: 102 | + ldcxxshared = os.environ['LDCXXSHARED'] 103 | if 'CPP' in os.environ: 104 | cpp = os.environ['CPP'] 105 | else: 106 | cpp = cc + " -E" # not always 107 | if 'LDFLAGS' in os.environ: 108 | ldshared = ldshared + ' ' + os.environ['LDFLAGS'] 109 | + ldcxxshared = ldcxxshared + ' ' + os.environ['LDFLAGS'] 110 | if 'CFLAGS' in os.environ: 111 | - cflags = opt + ' ' + os.environ['CFLAGS'] 112 | + cflags = os.environ['CFLAGS'] 113 | ldshared = ldshared + ' ' + os.environ['CFLAGS'] 114 | + if 'CXXFLAGS' in os.environ: 115 | + cxxflags = os.environ['CXXFLAGS'] 116 | + ldcxxshared = ldcxxshared + ' ' + os.environ['CXXFLAGS'] 117 | if 'CPPFLAGS' in os.environ: 118 | cpp = cpp + ' ' + os.environ['CPPFLAGS'] 119 | cflags = cflags + ' ' + os.environ['CPPFLAGS'] 120 | + cxxflags = cxxflags + ' ' + os.environ['CPPFLAGS'] 121 | ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] 122 | + ldcxxshared = ldcxxshared + ' ' + os.environ['CPPFLAGS'] 123 | if 'AR' in os.environ: 124 | ar = os.environ['AR'] 125 | if 'ARFLAGS' in os.environ: 126 | @@ -208,13 +218,17 @@ def customize_compiler(compiler): 127 | archiver = ar + ' ' + ar_flags 128 | 129 | cc_cmd = cc + ' ' + cflags 130 | + cxx_cmd = cxx + ' ' + cxxflags 131 | compiler.set_executables( 132 | preprocessor=cpp, 133 | compiler=cc_cmd, 134 | compiler_so=cc_cmd + ' ' + ccshared, 135 | - compiler_cxx=cxx, 136 | + compiler_cxx=cxx_cmd, 137 | + compiler_so_cxx=cxx_cmd + ' ' + ccshared, 138 | linker_so=ldshared, 139 | linker_exe=cc, 140 | + linker_so_cxx=ldcxxshared, 141 | + linker_exe_cxx=cxx, 142 | archiver=archiver) 143 | 144 | compiler.shared_lib_extension = shlib_suffix 145 | --- a/Lib/distutils/unixccompiler.py 146 | +++ b/Lib/distutils/unixccompiler.py 147 | @@ -52,14 +52,17 @@ class UnixCCompiler(CCompiler): 148 | # are pretty generic; they will probably have to be set by an outsider 149 | # (eg. using information discovered by the sysconfig about building 150 | # Python extensions). 151 | - executables = {'preprocessor' : None, 152 | - 'compiler' : ["cc"], 153 | - 'compiler_so' : ["cc"], 154 | - 'compiler_cxx' : ["cc"], 155 | - 'linker_so' : ["cc", "-shared"], 156 | - 'linker_exe' : ["cc"], 157 | - 'archiver' : ["ar", "-cr"], 158 | - 'ranlib' : None, 159 | + executables = {'preprocessor' : None, 160 | + 'compiler' : ["cc"], 161 | + 'compiler_so' : ["cc"], 162 | + 'compiler_cxx' : ["c++"], 163 | + 'compiler_so_cxx' : ["c++"], 164 | + 'linker_so' : ["cc", "-shared"], 165 | + 'linker_exe' : ["cc"], 166 | + 'linker_so_cxx' : ["c++", "-shared"], 167 | + 'linker_exe_cxx' : ["c++"], 168 | + 'archiver' : ["ar", "-cr"], 169 | + 'ranlib' : None, 170 | } 171 | 172 | if sys.platform[:6] == "darwin": 173 | @@ -110,12 +113,19 @@ class UnixCCompiler(CCompiler): 174 | 175 | def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): 176 | compiler_so = self.compiler_so 177 | + compiler_so_cxx = self.compiler_so_cxx 178 | if sys.platform == 'darwin': 179 | compiler_so = _osx_support.compiler_fixup(compiler_so, 180 | cc_args + extra_postargs) 181 | + compiler_so_cxx = _osx_support.compiler_fixup(compiler_so_cxx, 182 | + cc_args + extra_postargs) 183 | try: 184 | - self.spawn(compiler_so + cc_args + [src, '-o', obj] + 185 | - extra_postargs) 186 | + if self.detect_language(src) == 'c++': 187 | + self.spawn(compiler_so_cxx + cc_args + [src, '-o', obj] + 188 | + extra_postargs) 189 | + else: 190 | + self.spawn(compiler_so + cc_args + [src, '-o', obj] + 191 | + extra_postargs) 192 | except DistutilsExecError as msg: 193 | raise CompileError(msg) 194 | 195 | @@ -173,30 +183,16 @@ class UnixCCompiler(CCompiler): 196 | ld_args.extend(extra_postargs) 197 | self.mkpath(os.path.dirname(output_filename)) 198 | try: 199 | - if target_desc == CCompiler.EXECUTABLE: 200 | - linker = self.linker_exe[:] 201 | + if target_lang == "c++": 202 | + if target_desc == CCompiler.EXECUTABLE: 203 | + linker = self.linker_exe_cxx[:] 204 | + else: 205 | + linker = self.linker_so_cxx[:] 206 | else: 207 | - linker = self.linker_so[:] 208 | - if target_lang == "c++" and self.compiler_cxx: 209 | - # skip over environment variable settings if /usr/bin/env 210 | - # is used to set up the linker's environment. 211 | - # This is needed on OSX. Note: this assumes that the 212 | - # normal and C++ compiler have the same environment 213 | - # settings. 214 | - i = 0 215 | - if os.path.basename(linker[0]) == "env": 216 | - i = 1 217 | - while '=' in linker[i]: 218 | - i += 1 219 | - 220 | - if os.path.basename(linker[i]) == 'ld_so_aix': 221 | - # AIX platforms prefix the compiler with the ld_so_aix 222 | - # script, so we need to adjust our linker index 223 | - offset = 1 224 | + if target_desc == CCompiler.EXECUTABLE: 225 | + linker = self.linker_exe[:] 226 | else: 227 | - offset = 0 228 | - 229 | - linker[i+offset] = self.compiler_cxx[i] 230 | + linker = self.linker_so[:] 231 | 232 | if sys.platform == 'darwin': 233 | linker = _osx_support.compiler_fixup(linker, ld_args) 234 | --- a/Makefile.pre.in 235 | +++ b/Makefile.pre.in 236 | @@ -584,10 +584,10 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o 237 | *\ -s*|s*) quiet="-q";; \ 238 | *) quiet="";; \ 239 | esac; \ 240 | - echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ 241 | + echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' CFLAGS='$(PY_CFLAGS)' \ 242 | _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ 243 | $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ 244 | - $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ 245 | + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' CFLAGS='$(PY_CFLAGS)' \ 246 | _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ 247 | $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build 248 | 249 | -------------------------------------------------------------------------------- /patches/segfault.patch: -------------------------------------------------------------------------------- 1 | # HG changeset patch 2 | # Parent 7fafbb7e1a8fbcb8875e25d8cd07273069127556 3 | Issue #21166: Prevent possible segfaults and other random failures of 4 | python --generate-posix-vars in pybuilddir.txt build target by ensuring 5 | that pybuilddir.txt is always regenerated when configure is run and 6 | that the newly built skeleton python does not inadvertently import 7 | modules from previously installed instances. 8 | 9 | diff -r 7fafbb7e1a8f Makefile.pre.in 10 | --- a/Makefile.pre.in Mon Aug 11 15:01:28 2014 -0500 11 | +++ b/Makefile.pre.in Mon Aug 11 18:16:56 2014 -0700 12 | @@ -553,8 +553,18 @@ 13 | # Create build directory and generate the sysconfig build-time data there. 14 | # pybuilddir.txt contains the name of the build dir and is used for 15 | # sys.path fixup -- see Modules/getpath.c. 16 | +# Since this step runs before shared modules are built, try to avoid bootstrap 17 | +# problems by creating a dummy pybuildstr.txt just to allow interpreter 18 | +# initialization to succeed. It will be overwritten by generate-posix-vars 19 | +# or removed in case of failure. 20 | pybuilddir.txt: $(BUILDPYTHON) 21 | - $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars 22 | + @echo "none" > ./pybuilddir.txt 23 | + $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars ;\ 24 | + if test $$? -ne 0 ; then \ 25 | + echo "generate-posix-vars failed" ; \ 26 | + rm -f ./pybuilddir.txt ; \ 27 | + exit 1 ; \ 28 | + fi 29 | 30 | # Build the shared modules 31 | # Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for 32 | diff -r 7fafbb7e1a8f configure.ac 33 | --- a/configure.ac Mon Aug 11 15:01:28 2014 -0500 34 | +++ b/configure.ac Mon Aug 11 18:16:56 2014 -0700 35 | @@ -53,6 +53,9 @@ 36 | AC_SUBST(build) 37 | AC_SUBST(host) 38 | 39 | +# pybuilddir.txt will be created by --generate-posix-vars in the Makefile 40 | +rm -f pybuilddir.txt 41 | + 42 | if test "$cross_compiling" = yes; then 43 | AC_MSG_CHECKING([for python interpreter for cross build]) 44 | if test -z "$PYTHON_FOR_BUILD"; then 45 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "nix": { 3 | "enabled": true 4 | }, 5 | "lockFileMaintenance": { 6 | "enabled": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /update.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import base64 4 | import hashlib 5 | 6 | source = lambda version: f"https://www.python.org/ftp/python/{version}/Python-{version}.tgz" 7 | activestate_source = lambda version: f"https://github.com/ActiveState/cpython/archive/refs/tags/v{version}.tar.gz" 8 | 9 | # open versions.json and parse json 10 | def get_versions(): 11 | # if versions.json doesn't exist, create it 12 | try: 13 | with open("versions.json", "r") as f: 14 | return json.load(f) 15 | except FileNotFoundError: 16 | d = {"releases": {}, "latest": {}} 17 | with open("versions.json", "w") as f: 18 | json.dump(d, f) 19 | return d 20 | 21 | def get_all_releases(response, versions): 22 | for entry in response.json(): 23 | cycle = entry['cycle'] 24 | latest_version = entry['latest'] 25 | latest_version_split = latest_version.split('.') 26 | latest_patch = int(latest_version_split[-1]) 27 | 28 | if cycle in ["2.6", "3.0", "3.1", "3.2"]: 29 | continue 30 | 31 | versions['latest'][cycle] = latest_version 32 | 33 | 34 | for i in range(0, latest_patch + 1): 35 | version = f"{cycle}.{i}" 36 | # unsupported openssl version & no distutils patch 37 | if version in [ 38 | "2.7.0", 39 | "2.7.1", 40 | "2.7.2", 41 | "2.7.3", 42 | "2.7.4", 43 | "2.7.5", 44 | # patches fail: 45 | "3.3.0", 46 | "3.9.0"]: 47 | continue 48 | release = versions['releases'].get(version, {}) 49 | if release.get('hash'): 50 | continue 51 | else: 52 | url = source(version) 53 | print(f'Downloading {url}') 54 | response = requests.get(url) 55 | response.raise_for_status() 56 | versions['releases'][version] = { 57 | "hash": calculate_sha256(response.content), 58 | "url": url 59 | } 60 | return versions 61 | 62 | def get_activestate_releases(response, versions): 63 | for entry in response.json(): 64 | version = entry["tag_name"].lstrip("v") 65 | cycle = '.'.join(version.split('.')[:2]) 66 | release = versions['releases'].get(version, {}) 67 | 68 | if cycle != "2.7": 69 | continue 70 | 71 | versions['latest'][cycle] = max(version, versions['latest'].get(cycle, '')) 72 | 73 | if release.get("hash"): 74 | continue 75 | else: 76 | url = activestate_source(version) 77 | print(f'Downloading {url}') 78 | response = requests.get(url) 79 | response.raise_for_status() 80 | versions['releases'][version] = { 81 | "hash": calculate_sha256(response.content), 82 | "url": url 83 | } 84 | return versions 85 | 86 | def calculate_sha256(contents): 87 | return base64.b64encode(hashlib.sha256(contents).digest()).decode('utf-8') 88 | 89 | if __name__ == "__main__": 90 | versions = get_versions() 91 | 92 | # TODO: pypy: https://downloads.python.org/pypy/versions.json 93 | response = requests.get("https://endoflife.date/api/python.json") 94 | 95 | versions = get_all_releases(response, versions) 96 | 97 | activestate_response = requests.get("https://api.github.com/repos/ActiveState/cpython/releases") 98 | versions = get_activestate_releases(activestate_response, versions) 99 | 100 | with open("versions.json", "w") as f: 101 | json.dump(versions, f, indent=4) 102 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "releases": { 3 | "3.12.0": { 4 | "hash": "UUEpVtJKHvfJfxy19w4YXBPj3h9Q0THAqsYzgIBoevs=", 5 | "url": "https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tgz" 6 | }, 7 | "3.12.1": { 8 | "hash": "0B7GozvBAAmwnBfalcwnWa9aWApzFrOkRutBkOE/l7I=", 9 | "url": "https://www.python.org/ftp/python/3.12.1/Python-3.12.1.tgz" 10 | }, 11 | "3.12.2": { 12 | "hash": "p8T2qdxCPYwygAMlSrDJM4uDA3vXh9aAgmpb+EMIEW4=", 13 | "url": "https://www.python.org/ftp/python/3.12.2/Python-3.12.2.tgz" 14 | }, 15 | "3.11.0": { 16 | "hash": "ZEJOluJFerusiZuQ+VMJhbUe7ykFlR/r2TXw5zQUyus=", 17 | "url": "https://www.python.org/ftp/python/3.11.0/Python-3.11.0.tgz" 18 | }, 19 | "3.11.1": { 20 | "hash": "uu1RjiazN9TYEFZ5yvaMXDJjDXAmFPwXTpjLlcRr36Q=", 21 | "url": "https://www.python.org/ftp/python/3.11.1/Python-3.11.1.tgz" 22 | }, 23 | "3.11.2": { 24 | "hash": "JBHHS9pbvPzdr0Ux9m0a3HPyR/UprumBsClROu/b+Ek=", 25 | "url": "https://www.python.org/ftp/python/3.11.2/Python-3.11.2.tgz" 26 | }, 27 | "3.11.3": { 28 | "hash": "Gnnz3zImXZ5mJfGgsxwo6xWU35EUA9EfMyDuHaGz4Eg=", 29 | "url": "https://www.python.org/ftp/python/3.11.3/Python-3.11.3.tgz" 30 | }, 31 | "3.11.4": { 32 | "hash": "hcN6Jl5cndn3WzX5VOMfv8EDgxYkFyheMK0lzAc6DWM=", 33 | "url": "https://www.python.org/ftp/python/3.11.4/Python-3.11.4.tgz" 34 | }, 35 | "3.11.5": { 36 | "hash": "oSoKATowuEbHhsAQ8sGd02tymNiI98S9FYHZDOGLXlg=", 37 | "url": "https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz" 38 | }, 39 | "3.11.6": { 40 | "hash": "wEm/MX6HfL+fzow6+QJDZ3Ts71JJop0QmEyjo39/RzY=", 41 | "url": "https://www.python.org/ftp/python/3.11.6/Python-3.11.6.tgz" 42 | }, 43 | "3.11.7": { 44 | "hash": "BowF+CJi5XZBvZNFjfqIMSiFj19Jl6rXo2/SWxOykgk=", 45 | "url": "https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz" 46 | }, 47 | "3.11.8": { 48 | "hash": "0wGaYTueh2HSYNnr471N9jl23jBGTlwBiVZuGuP2GIk=", 49 | "url": "https://www.python.org/ftp/python/3.11.8/Python-3.11.8.tgz" 50 | }, 51 | "3.11.9": { 52 | "hash": "594yQKi8Kx4bpcgb+UPwaGH/SUtp/amQzicipQTGFT0=", 53 | "url": "https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tgz" 54 | }, 55 | "3.10.0": { 56 | "hash": "xODLrVfJBpDLgT+0Zj72cLTQ9YfYFx4sQr1MkkW9J1g=", 57 | "url": "https://www.python.org/ftp/python/3.10.0/Python-3.10.0.tgz" 58 | }, 59 | "3.10.1": { 60 | "hash": "t2EXZw58UGQ0S5wTjhQaN35oa5Bj86imIP9nT6jskNM=", 61 | "url": "https://www.python.org/ftp/python/3.10.1/Python-3.10.1.tgz" 62 | }, 63 | "3.10.2": { 64 | "hash": "PA7eiTARMZ+bCla0SVOj1Sx6v5ZXwj+0vJztk7hunJc=", 65 | "url": "https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tgz" 66 | }, 67 | "3.10.3": { 68 | "hash": "WjsCm61wuioBnr/wimUGCoubVC/8GoPGl/FEnsypgTs=", 69 | "url": "https://www.python.org/ftp/python/3.10.3/Python-3.10.3.tgz" 70 | }, 71 | "3.10.4": { 72 | "hash": "87zGWx1fHceGdcdGyY/O6CPAOBaPxinFk1sETQkRrSg=", 73 | "url": "https://www.python.org/ftp/python/3.10.4/Python-3.10.4.tgz" 74 | }, 75 | "3.10.5": { 76 | "hash": "GPVxgqLeOwvnbfw5/c/SgVa7bdI+Xwhpb3SS6ePQvy0=", 77 | "url": "https://www.python.org/ftp/python/3.10.5/Python-3.10.5.tgz" 78 | }, 79 | "3.10.6": { 80 | "hash": "hIywalyqhdpcRb16kiG7gh4z/CvcugiMEnxY+tROY0M=", 81 | "url": "https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tgz" 82 | }, 83 | "3.10.7": { 84 | "hash": "Gy5OLfaXxS02cxZml55ki+7aWUHQ+VdAqvv0Fj5cwSY=", 85 | "url": "https://www.python.org/ftp/python/3.10.7/Python-3.10.7.tgz" 86 | }, 87 | "3.10.8": { 88 | "hash": "9ADD+zlLi+8SkvbcEpLF+tw1MwOaW8DD6IXz4Wc4Apo=", 89 | "url": "https://www.python.org/ftp/python/3.10.8/Python-3.10.8.tgz" 90 | }, 91 | "3.10.9": { 92 | "hash": "TM1+RsiJj0x4YpEKFwOqDmNSWROlGauy9V4mIgqRTYg=", 93 | "url": "https://www.python.org/ftp/python/3.10.9/Python-3.10.9.tgz" 94 | }, 95 | "3.10.10": { 96 | "hash": "+6ZFWd3iHr3JU+RWXnMVc7thFZ3o5NTO3ucPsRlvYQ0=", 97 | "url": "https://www.python.org/ftp/python/3.10.10/Python-3.10.10.tgz" 98 | }, 99 | "3.10.11": { 100 | "hash": "89sxtmjvqYNQi9Z7VxKJiqQkeJmjRvLrdFc0aZzNOFk=", 101 | "url": "https://www.python.org/ftp/python/3.10.11/Python-3.10.11.tgz" 102 | }, 103 | "3.10.12": { 104 | "hash": "pDzTg/OZmm9KfbIGKy/JWU/vpz4XWzrtr6KVpRp7tlw=", 105 | "url": "https://www.python.org/ftp/python/3.10.12/Python-3.10.12.tgz" 106 | }, 107 | "3.10.13": { 108 | "hash": "aY7FUjTBNjvYE7Rg7VOw8QiHfHoTPUi96aUKHrV7fmU=", 109 | "url": "https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz" 110 | }, 111 | "3.10.14": { 112 | "hash": "zv6jLTvonAJDZxHJWkXH+OiAEFUUt4aAwU/nb1cJoPY=", 113 | "url": "https://www.python.org/ftp/python/3.10.14/Python-3.10.14.tgz" 114 | }, 115 | "3.9.1": { 116 | "hash": "KcuRugODRtoL2auEoKVahF2HLDQaTaaHn0YulMdB8Rc=", 117 | "url": "https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tgz" 118 | }, 119 | "3.9.2": { 120 | "hash": "eJnopveUZ0iDDWZzny2PKzAhTa2Vbla5uiFrPeVYFRk=", 121 | "url": "https://www.python.org/ftp/python/3.9.2/Python-3.9.2.tgz" 122 | }, 123 | "3.9.3": { 124 | "hash": "Ov62GkW1oubxwPYhvYz5JaT/QGCZ/bPYyXuZOl9D0Eg=", 125 | "url": "https://www.python.org/ftp/python/3.9.3/Python-3.9.3.tgz" 126 | }, 127 | "3.9.4": { 128 | "hash": "ZsTeFtqnSoJc+dqd2uH+Agtyw4VLc7F2IBHMM/nkWS8=", 129 | "url": "https://www.python.org/ftp/python/3.9.4/Python-3.9.4.tgz" 130 | }, 131 | "3.9.5": { 132 | "hash": "4PvVtuHuJCUkQw3uPJG69Mu6ukpy3RZ0uQ/ah7cTx6s=", 133 | "url": "https://www.python.org/ftp/python/3.9.5/Python-3.9.5.tgz" 134 | }, 135 | "3.9.6": { 136 | "hash": "0KNRguGeQW/I6uJaPc1NAtSZczPkrR8u7mAQqtw/6GY=", 137 | "url": "https://www.python.org/ftp/python/3.9.6/Python-3.9.6.tgz" 138 | }, 139 | "3.9.7": { 140 | "hash": "qDjT+TYNFXBAFCtxXbNPAhjlNTM2lqVWncb4VGBOudE=", 141 | "url": "https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tgz" 142 | }, 143 | "3.9.8": { 144 | "hash": "dEf7i7JwlC1iDdJPqngUsTg7YfqZApokACX9gcHbgoM=", 145 | "url": "https://www.python.org/ftp/python/3.9.8/Python-3.9.8.tgz" 146 | }, 147 | "3.9.9": { 148 | "hash": "LMe2fB8/ZsVxrMQkec32kdjta0e+4SybaEMEE6F6ROo=", 149 | "url": "https://www.python.org/ftp/python/3.9.9/Python-3.9.9.tgz" 150 | }, 151 | "3.9.10": { 152 | "hash": "GqnAcC7bro9qLJX3CknahCCqp2t4idNBnBhr/IwOVx4=", 153 | "url": "https://www.python.org/ftp/python/3.9.10/Python-3.9.10.tgz" 154 | }, 155 | "3.9.11": { 156 | "hash": "NEJAAHL1gqwvDfMIlVWPCIg7QWyMeHfqVdQNANipMRI=", 157 | "url": "https://www.python.org/ftp/python/3.9.11/Python-3.9.11.tgz" 158 | }, 159 | "3.9.12": { 160 | "hash": "cOCEYuvyZQEr0r6Ipj0hSdiAxz5T8XEre7vpN1BWCug=", 161 | "url": "https://www.python.org/ftp/python/3.9.12/Python-3.9.12.tgz" 162 | }, 163 | "3.9.13": { 164 | "hash": "gpsNJgcqRGiaawgQ9bSjkz7ioLikv8mdfFiT/9T5fEQ=", 165 | "url": "https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tgz" 166 | }, 167 | "3.9.14": { 168 | "hash": "kgGDbiwWNhsrdAhoBQI5NzfUTyJzM/4uVynH1fYEFnU=", 169 | "url": "https://www.python.org/ftp/python/3.9.14/Python-3.9.14.tgz" 170 | }, 171 | "3.9.15": { 172 | "hash": "SNHMsp1fuvH7j5EicdCfdFDkJtTf6Vl472qq2nDs5Ng=", 173 | "url": "https://www.python.org/ftp/python/3.9.15/Python-3.9.15.tgz" 174 | }, 175 | "3.9.16": { 176 | "hash": "GtU56dvStC33FLaXJuBpO8a50tLI6RwuQyBAJmBRQMU=", 177 | "url": "https://www.python.org/ftp/python/3.9.16/Python-3.9.16.tgz" 178 | }, 179 | "3.9.17": { 180 | "hash": "jq1Y9mn34Z13fDVWti+uKagdfwanEi/5vFf33YLX4BQ=", 181 | "url": "https://www.python.org/ftp/python/3.9.17/Python-3.9.17.tgz" 182 | }, 183 | "3.9.18": { 184 | "hash": "UEzoz9Wa3cBMIvWQN3xr5FSudAbLHr9vWjUBSSJak1Q=", 185 | "url": "https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz" 186 | }, 187 | "3.9.19": { 188 | "hash": "9fnsgIiryp45nDti/Y7zHb0uFHLAzLNQcNTRNoIar3E=", 189 | "url": "https://www.python.org/ftp/python/3.9.19/Python-3.9.19.tgz" 190 | }, 191 | "3.8.0": { 192 | "hash": "8Qaa08ro5+xGeqmKZWWmKkjvGWy48UVaJFoI214Xkt8=", 193 | "url": "https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz" 194 | }, 195 | "3.8.1": { 196 | "hash": "x8+jmkO5lGIbJF4Cl2npEmyqKpNXHO4udDshPM6sNfs=", 197 | "url": "https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz" 198 | }, 199 | "3.8.2": { 200 | "hash": "5jSnp0d2wriVFrLgE92hcoyJyBSbmGO4zqIZRtr51WE=", 201 | "url": "https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tgz" 202 | }, 203 | "3.8.3": { 204 | "hash": "avbU0uAQ+WVVGND8ZzjH/3Bp8QpNL71VUJ5Gfwkqi5A=", 205 | "url": "https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz" 206 | }, 207 | "3.8.4": { 208 | "hash": "MsTZgX7xF5PaTQ2VsxkcTbgdLkVURhToRJJVyprjzBg=", 209 | "url": "https://www.python.org/ftp/python/3.8.4/Python-3.8.4.tgz" 210 | }, 211 | "3.8.5": { 212 | "hash": "AVEVAjw4Lrarg9USdi/jxVAvoMbFL/68SDHE4aBv/Ek=", 213 | "url": "https://www.python.org/ftp/python/3.8.5/Python-3.8.5.tgz" 214 | }, 215 | "3.8.6": { 216 | "hash": "MTVi7pmG3Dac1ngBG9/ZgA72L797FJYiihj4azZCjCE=", 217 | "url": "https://www.python.org/ftp/python/3.8.6/Python-3.8.6.tgz" 218 | }, 219 | "3.8.7": { 220 | "hash": "IOWgQmLwry65wZJA1+w2jzhXiLui2N+6fnSyC6tNK6w=", 221 | "url": "https://www.python.org/ftp/python/3.8.7/Python-3.8.7.tgz" 222 | }, 223 | "3.8.8": { 224 | "hash": "dsB2PwSOT5uGHSTadrfdXHo7p+wIb0DK7e6jWSYydvc=", 225 | "url": "https://www.python.org/ftp/python/3.8.8/Python-3.8.8.tgz" 226 | }, 227 | "3.8.9": { 228 | "hash": "l3nsHfAAv4aRTN1AhguI2lbB5h21nTd4S+yhSiWayek=", 229 | "url": "https://www.python.org/ftp/python/3.8.9/Python-3.8.9.tgz" 230 | }, 231 | "3.8.10": { 232 | "hash": "s3rHTSy60lkOfNDdKzgmwpr+iac0CQqHv4wDxFBmy2U=", 233 | "url": "https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz" 234 | }, 235 | "3.8.11": { 236 | "hash": "t3Rk6oDOwUWBuGrrf7L/AoMOCrx7zcdSt7S9/Njz45M=", 237 | "url": "https://www.python.org/ftp/python/3.8.11/Python-3.8.11.tgz" 238 | }, 239 | "3.8.12": { 240 | "hash": "MWqjPzt3B9BB5z8kbv7bKXpwiYxLkfEn9m3I2AxZbxo=", 241 | "url": "https://www.python.org/ftp/python/3.8.12/Python-3.8.12.tgz" 242 | }, 243 | "3.8.13": { 244 | "hash": "kDuS12NUNmsdnEQ00MgWQzRc74fBYArfo2CV17AO7eQ=", 245 | "url": "https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tgz" 246 | }, 247 | "3.8.14": { 248 | "hash": "QflZxIDFkhH+tV1aKIUaVsfiLQLvkQNWBuuyEBFyPDE=", 249 | "url": "https://www.python.org/ftp/python/3.8.14/Python-3.8.14.tgz" 250 | }, 251 | "3.8.15": { 252 | "hash": "kk1GmZ34KqLqod5cpR1oAP+1a0v1JIaij0BjTjNiq8Q=", 253 | "url": "https://www.python.org/ftp/python/3.8.15/Python-3.8.15.tgz" 254 | }, 255 | "3.8.16": { 256 | "hash": "ccqdk1Y37S/rWekKNoNh3JHspHKpCssdNEougXjMrxA=", 257 | "url": "https://www.python.org/ftp/python/3.8.16/Python-3.8.16.tgz" 258 | }, 259 | "3.8.17": { 260 | "hash": "3vQo+mz2G2a83nLj2ffQfTOy5CJvBPnW/Og4TAVRE64=", 261 | "url": "https://www.python.org/ftp/python/3.8.17/Python-3.8.17.tgz" 262 | }, 263 | "3.8.18": { 264 | "hash": "fF32i6sb6BpS3qDMLicF6gBVO2cQejARiDg9e1cyCxY=", 265 | "url": "https://www.python.org/ftp/python/3.8.18/Python-3.8.18.tgz" 266 | }, 267 | "3.8.19": { 268 | "hash": "x/pVo25cehnsN9j5D2CiGXVIkIyayLMefA2//dRw7qw=", 269 | "url": "https://www.python.org/ftp/python/3.8.19/Python-3.8.19.tgz" 270 | }, 271 | "3.7.0": { 272 | "hash": "hbuf62hj4E+xcAsBjZ1C0cqsF4VZ/6RT1+akNuJZ/Q0=", 273 | "url": "https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz" 274 | }, 275 | "3.7.1": { 276 | "hash": "NsG4GsKdD4NB9yfvQIZNmdggaJe+lr5z3DTUc5ycnwY=", 277 | "url": "https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tgz" 278 | }, 279 | "3.7.2": { 280 | "hash": "8J2Dx3O5zHJCGruiwxfk5uBdkZ+bzzRGjhkramyOMo0=", 281 | "url": "https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tgz" 282 | }, 283 | "3.7.3": { 284 | "hash": "1i4wFfL4nJcKxSNDl2tAZpSTF0L73i/tjRzo67Th+P8=", 285 | "url": "https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz" 286 | }, 287 | "3.7.4": { 288 | "hash": "1j5j4U5tKeF0kKu+b30Xr7PbGC29gBIp8U5V9BV8S6M=", 289 | "url": "https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz" 290 | }, 291 | "3.7.5": { 292 | "hash": "jsxoHqBgC7+zZvKxc/cnsgW7gl2T0vCyhrxOWNN2k9o=", 293 | "url": "https://www.python.org/ftp/python/3.7.5/Python-3.7.5.tgz" 294 | }, 295 | "3.7.6": { 296 | "hash": "ru5oHCNa0zavEW8Iq2VjNhoMgcU3BywbMJ1uQFCqIRQ=", 297 | "url": "https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz" 298 | }, 299 | "3.7.7": { 300 | "hash": "jIvpHNJkihoMJR8E6gu0wqVXD+ucReqqIkHHhVhbR1o=", 301 | "url": "https://www.python.org/ftp/python/3.7.7/Python-3.7.7.tgz" 302 | }, 303 | "3.7.8": { 304 | "hash": "DiWDVhTcIh4+zqWDGzj6kHiLU4m5m2dadRQUyFh4mrA=", 305 | "url": "https://www.python.org/ftp/python/3.7.8/Python-3.7.8.tgz" 306 | }, 307 | "3.7.9": { 308 | "hash": "ObAYvH2KFl5ZqoJ9muRcRZAXObC7sTch5Plz81IcFmo=", 309 | "url": "https://www.python.org/ftp/python/3.7.9/Python-3.7.9.tgz" 310 | }, 311 | "3.7.10": { 312 | "hash": "yWSa2E3DpDTIY332ljEAsuVghpf5ulbYLjgJ5BSOCXU=", 313 | "url": "https://www.python.org/ftp/python/3.7.10/Python-3.7.10.tgz" 314 | }, 315 | "3.7.11": { 316 | "hash": "tPujIYLhZIXQpgIrqDySUeahwUZ27CQ6mgfTcizUZho=", 317 | "url": "https://www.python.org/ftp/python/3.7.11/Python-3.7.11.tgz" 318 | }, 319 | "3.7.12": { 320 | "hash": "M7Tar4Mb4ZIZZZRm0SZF+H7Oxush1Nn5cRAYp7ZszkY=", 321 | "url": "https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz" 322 | }, 323 | "3.7.13": { 324 | "hash": "5AVBf1CYS8WHDH56n5rrk+nScPWsZ/ZnoM06CUOWgrU=", 325 | "url": "https://www.python.org/ftp/python/3.7.13/Python-3.7.13.tgz" 326 | }, 327 | "3.7.14": { 328 | "hash": "grKr+JeMqmGpAR0Wbu3oMbMt6cvrwNuBYpAPojQ3twk=", 329 | "url": "https://www.python.org/ftp/python/3.7.14/Python-3.7.14.tgz" 330 | }, 331 | "3.7.15": { 332 | "hash": "zymTeYroQw8686ANltn98yBxn0BC8Dk4Dcp5lnwl5DY=", 333 | "url": "https://www.python.org/ftp/python/3.7.15/Python-3.7.15.tgz" 334 | }, 335 | "3.7.16": { 336 | "hash": "DPLaB/pGRjZ1UhVBWQniLrHQWIF69IJLwVr4OQ0F+zg=", 337 | "url": "https://www.python.org/ftp/python/3.7.16/Python-3.7.16.tgz" 338 | }, 339 | "3.7.17": { 340 | "hash": "/VAWG8KgT0wioJcf8POFbZi0vylPiXQKnwa1IKrmO0k=", 341 | "url": "https://www.python.org/ftp/python/3.7.17/Python-3.7.17.tgz" 342 | }, 343 | "3.6.0": { 344 | "hash": "qkclFYANJaNzmDP3bKNzXZ9LL+d8PLIfaSdeDM4wyys=", 345 | "url": "https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz" 346 | }, 347 | "3.6.1": { 348 | "hash": "qlCwFD33yJzpG+Ag/kE4JhOoFzVLM6zcZkG0T4ztOCg=", 349 | "url": "https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz" 350 | }, 351 | "3.6.2": { 352 | "hash": "eRlIkxCl8X96y6tk1zHkbcoHAodIQNrc6L1LKzuOeoI=", 353 | "url": "https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz" 354 | }, 355 | "3.6.3": { 356 | "hash": "q2GTrxkhsw9YezAv44UmhRDoAYfKg8qC0r/nq1RMb5E=", 357 | "url": "https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz" 358 | }, 359 | "3.6.4": { 360 | "hash": "fcRT4ak8CDOI6xojolaGJAf4I0qW3E+uD8doICAidIY=", 361 | "url": "https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz" 362 | }, 363 | "3.6.5": { 364 | "hash": "U6PhfXfNFcUjAZK2qMHgMcB82fNKLwiacxxva9ND1cY=", 365 | "url": "https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgz" 366 | }, 367 | "3.6.6": { 368 | "hash": "fVba32x9kqI4cCOJ6Az+Zvv65z5YQYntb4nHW78+2lg=", 369 | "url": "https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz" 370 | }, 371 | "3.6.7": { 372 | "hash": "t8Nvftj3FDssRhU7czLbIidmn1g+oMznU/rPVJ0aQjk=", 373 | "url": "https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tgz" 374 | }, 375 | "3.6.8": { 376 | "hash": "f1sfCLOwpZU4fvbGTIWxsTs4q+8N2HGDXukjJi5PMvA=", 377 | "url": "https://www.python.org/ftp/python/3.6.8/Python-3.6.8.tgz" 378 | }, 379 | "3.6.9": { 380 | "hash": "R/ySody5RrntCrwxHTdntyFcVOZVsX/R0/m1OBlVJao=", 381 | "url": "https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz" 382 | }, 383 | "3.6.10": { 384 | "hash": "cDTdfLqY1PlMdPnt1zRbrHHIgUxBZyxk2QRPovlvM00=", 385 | "url": "https://www.python.org/ftp/python/3.6.10/Python-3.6.10.tgz" 386 | }, 387 | "3.6.11": { 388 | "hash": "lmIZAviXRv/8IvOXScB9p8KReyMucjUuaDfUGFD3uQw=", 389 | "url": "https://www.python.org/ftp/python/3.6.11/Python-3.6.11.tgz" 390 | }, 391 | "3.6.12": { 392 | "hash": "Et3b5SOFoPcC+4Bx4S3Mazyy3eB82Ns+1g6Q2Qq3hpM=", 393 | "url": "https://www.python.org/ftp/python/3.6.12/Python-3.6.12.tgz" 394 | }, 395 | "3.6.13": { 396 | "hash": "YUlQ09VPbnjaxlG0nGTP4s7v6lrzr/M3Gp5LJ6U7Jmk=", 397 | "url": "https://www.python.org/ftp/python/3.6.13/Python-3.6.13.tgz" 398 | }, 399 | "3.6.14": { 400 | "hash": "cAZIl7xDTW6ui8w+VnjygrXqd21g5pXaVIoSGcz9J6U=", 401 | "url": "https://www.python.org/ftp/python/3.6.14/Python-3.6.14.tgz" 402 | }, 403 | "3.6.15": { 404 | "hash": "VFcLfjOeLP1yspx+L9tHwLexi3QS5h3ltGP8CHwTsEM=", 405 | "url": "https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tgz" 406 | }, 407 | "3.5.0": { 408 | "hash": "WE49WgJpLKUvzlBeaOzXckim8sma352xRKOQhzNrD+A=", 409 | "url": "https://www.python.org/ftp/python/3.5.0/Python-3.5.0.tgz" 410 | }, 411 | "3.5.1": { 412 | "hash": "aH4GfZ85HaZFQjx+2oIFuunTXtwMdu9SGNy+TMdw0Nc=", 413 | "url": "https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz" 414 | }, 415 | "3.5.2": { 416 | "hash": "FSS4QOQs87kJ6PjfZ8FyQBLH3H+dB21P7vLT7/Ax6KA=", 417 | "url": "https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz" 418 | }, 419 | "3.5.3": { 420 | "hash": "2IkLhNdzzXBZ5Zfb76UQNA3oM27JuekDK/Aw8ZKRVlo=", 421 | "url": "https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tgz" 422 | }, 423 | "3.5.4": { 424 | "hash": "bth6i2x1jMMpmotDPoqakSIFStW8iq1DKZz/OlPYykQ=", 425 | "url": "https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tgz" 426 | }, 427 | "3.5.5": { 428 | "hash": "L5iNszkT3O8XVS/RRHtBr7idvCbjzfwGjqbGIBOjoqU=", 429 | "url": "https://www.python.org/ftp/python/3.5.5/Python-3.5.5.tgz" 430 | }, 431 | "3.5.6": { 432 | "hash": "MNL/CTmI50KD4av+6CMpLGtZWQeWuYJ+lbpJQLJ9Jvg=", 433 | "url": "https://www.python.org/ftp/python/3.5.6/Python-3.5.6.tgz" 434 | }, 435 | "3.5.7": { 436 | "hash": "VC2UkgoqBqRxpztRYUgFrWU2avmBRbA2m8N0zySLUhs=", 437 | "url": "https://www.python.org/ftp/python/3.5.7/Python-3.5.7.tgz" 438 | }, 439 | "3.5.8": { 440 | "hash": "GMiN/SYBR7xyR+Y1YBDl1JFt+/xID2Q0kX+I5hIoF3o=", 441 | "url": "https://www.python.org/ftp/python/3.5.8/Python-3.5.8.tgz" 442 | }, 443 | "3.5.9": { 444 | "hash": "Z6HU/G5FQNagksrcSI5TOvqWGzyb7MdNw9a1XLVuDME=", 445 | "url": "https://www.python.org/ftp/python/3.5.9/Python-3.5.9.tgz" 446 | }, 447 | "3.5.10": { 448 | "hash": "NJag2vUZE3GKbxDj7aUfpDY0y2FRywlvMS1Ivb7/fTo=", 449 | "url": "https://www.python.org/ftp/python/3.5.10/Python-3.5.10.tgz" 450 | }, 451 | "3.4.0": { 452 | "hash": "0sg+oCF3aac+ix7jP/vKgUkD+FaOMPjRPmjj0fdDRJw=", 453 | "url": "https://www.python.org/ftp/python/3.4.0/Python-3.4.0.tgz" 454 | }, 455 | "3.4.1": { 456 | "hash": "jQB+PvgLEoopK+EBIB513sVIDlYy6ZR3HnwjHRdyC2Y=", 457 | "url": "https://www.python.org/ftp/python/3.4.1/Python-3.4.1.tgz" 458 | }, 459 | "3.4.2": { 460 | "hash": "RKPB7xx8o+T9JSQq+A7XLalBIDy07RqMG3JNkHiWXdg=", 461 | "url": "https://www.python.org/ftp/python/3.4.2/Python-3.4.2.tgz" 462 | }, 463 | "3.4.3": { 464 | "hash": "i3Q/VunlC/CSO56cRd2SfAcdeqVs1GVp2IGK3YzwEUc=", 465 | "url": "https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tgz" 466 | }, 467 | "3.4.4": { 468 | "hash": "vJPpRAJYFuw2BxK0xC2NX3KertKyZYXpvIhE+T8MOC4=", 469 | "url": "https://www.python.org/ftp/python/3.4.4/Python-3.4.4.tgz" 470 | }, 471 | "3.4.5": { 472 | "hash": "mXrKTdhpLzyVRlij2xHB0IYry/jq3WoWR0brM9MXwDQ=", 473 | "url": "https://www.python.org/ftp/python/3.4.5/Python-3.4.5.tgz" 474 | }, 475 | "3.4.6": { 476 | "hash": "/lnaztmVSdHUUnJ8BQrkhhaelxaokM/7DUaLN22Ra0g=", 477 | "url": "https://www.python.org/ftp/python/3.4.6/Python-3.4.6.tgz" 478 | }, 479 | "3.4.7": { 480 | "hash": "FhRzSEf9B+KhqxxlroQdskM/i4RfSbNLe1yryxw/SR8=", 481 | "url": "https://www.python.org/ftp/python/3.4.7/Python-3.4.7.tgz" 482 | }, 483 | "3.4.8": { 484 | "hash": "ixoc4EPhMggtKaXQnyhB8ZPHe2MSgqgvmIlaXbq6Fjk=", 485 | "url": "https://www.python.org/ftp/python/3.4.8/Python-3.4.8.tgz" 486 | }, 487 | "3.4.9": { 488 | "hash": "4C5WU3J1CmZ47+Nd3svlzNUzCooui7440wYHE0kuPas=", 489 | "url": "https://www.python.org/ftp/python/3.4.9/Python-3.4.9.tgz" 490 | }, 491 | "3.4.10": { 492 | "hash": "IXdXaZJJq0MlcbOBOG1EHhK0MxAKtfkIBR/LfM7SU50=", 493 | "url": "https://www.python.org/ftp/python/3.4.10/Python-3.4.10.tgz" 494 | }, 495 | "3.3.1": { 496 | "hash": "Zx3DYy8xHmPGczcDqgoa2QyZJ33cgpnTnkh3GKUDGb0=", 497 | "url": "https://www.python.org/ftp/python/3.3.1/Python-3.3.1.tgz" 498 | }, 499 | "3.3.2": { 500 | "hash": "3mZPyjuOCrIPtCv+0aNuJvEW8YU+iK2hLbyTh2EDYXI=", 501 | "url": "https://www.python.org/ftp/python/3.3.2/Python-3.3.2.tgz" 502 | }, 503 | "3.3.3": { 504 | "hash": "MLYIOb/grootuhHpCTKEWbuO5KJYr+dJSwayztoIDvw=", 505 | "url": "https://www.python.org/ftp/python/3.3.3/Python-3.3.3.tgz" 506 | }, 507 | "3.3.4": { 508 | "hash": "6gVdud0ASm7NdpCryXNFc3Y2ht12gSIxa64t/QJkEq8=", 509 | "url": "https://www.python.org/ftp/python/3.3.4/Python-3.3.4.tgz" 510 | }, 511 | "3.3.5": { 512 | "hash": "kWvFfdhSTcJ0Kb6657OdaUJ0LPlpm4dbK0lqPZYMcWg=", 513 | "url": "https://www.python.org/ftp/python/3.3.5/Python-3.3.5.tgz" 514 | }, 515 | "3.3.6": { 516 | "hash": "ClitHx3vTsyQsYsMQQo6DhpIz3aSx10fg9CvCA5dIDQ=", 517 | "url": "https://www.python.org/ftp/python/3.3.6/Python-3.3.6.tgz" 518 | }, 519 | "3.3.7": { 520 | "hash": "mSRhqVmOhaRTI1EtTmD6bB1arvCVa/nbmHM8xaqbBeE=", 521 | "url": "https://www.python.org/ftp/python/3.3.7/Python-3.3.7.tgz" 522 | }, 523 | "2.7.6": { 524 | "hash": "mcaGC3CXe++hWQAp+uCS3bGNsdaa5n6Lk4W2btEEulg=", 525 | "url": "https://www.python.org/ftp/python/2.7.6/Python-2.7.6.tgz" 526 | }, 527 | "2.7.7": { 528 | "hash": "f0nApnBa2J2SUYHifQqqAl7kcxzg3mR3bHIiFsPmbEI=", 529 | "url": "https://www.python.org/ftp/python/2.7.7/Python-2.7.7.tgz" 530 | }, 531 | "2.7.8": { 532 | "hash": "dNcLkU2kSHqh2XIisp6VVNBC+CXybLK5Or0g/dpWtVc=", 533 | "url": "https://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz" 534 | }, 535 | "2.7.9": { 536 | "hash": "yLujPmasMgHavcVW8Op8/mrBGUbsMtNXxMb5sBjBLFs=", 537 | "url": "https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz" 538 | }, 539 | "2.7.10": { 540 | "hash": "7ajObuwD50mRq7U4QXDnxl/NdSLkCbjoPX5jcq3Q8So=", 541 | "url": "https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz" 542 | }, 543 | "2.7.11": { 544 | "hash": "gpKblv1q/I2oOLFJEHB4wC+hdEt+YJmai6u8DT+ob8Y=", 545 | "url": "https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz" 546 | }, 547 | "2.7.12": { 548 | "hash": "PLUi0XRj36aaFVqxjP+jmbNYyWbANj1si1s78ThNpLY=", 549 | "url": "https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz" 550 | }, 551 | "2.7.13": { 552 | "hash": "pPBaByDOD9kmJvAni2tDPu6aYXPd8rzteVfftZml7OE=", 553 | "url": "https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz" 554 | }, 555 | "2.7.14": { 556 | "hash": "MEybIC6m+9CkqOCtNzNxX71HSfIgSpFzpY7FPDLqc+g=", 557 | "url": "https://www.python.org/ftp/python/2.7.14/Python-2.7.14.tgz" 558 | }, 559 | "2.7.15": { 560 | "hash": "GGF9HxWjgKkZ1RdjCpzYXOF+pgL5u9xY3cZy30sCOds=", 561 | "url": "https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tgz" 562 | }, 563 | "2.7.16": { 564 | "hash": "AdqBOjYAh28D9G2xHMXECBdemfA68rqULvMkOJqDutU=", 565 | "url": "https://www.python.org/ftp/python/2.7.16/Python-2.7.16.tgz" 566 | }, 567 | "2.7.17": { 568 | "hash": "8iBZ0JzfliXgpyhNJKEwYgRPW/Wdk6fzOCGQ36lM7N4=", 569 | "url": "https://www.python.org/ftp/python/2.7.17/Python-2.7.17.tgz" 570 | }, 571 | "2.7.18": { 572 | "hash": "2jCA47SI9kij16RWDd7olShMM4CxHW3nXtuYZSa5qBQ=", 573 | "url": "https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz" 574 | }, 575 | "3.12.3": { 576 | "hash": "prlFn0Wm67vBr0T1diYj+jVaDIcgjtQXYos3nXYt3bA=", 577 | "url": "https://www.python.org/ftp/python/3.12.3/Python-3.12.3.tgz" 578 | }, 579 | "3.12.4": { 580 | "hash": "AbPBwIIZbzszFo00SpyF+we/4Ofs/nf+5EQ0INHOKtk=", 581 | "url": "https://www.python.org/ftp/python/3.12.4/Python-3.12.4.tgz" 582 | }, 583 | "2.7.18.1": { 584 | "hash": "Pw2VZwNLmgpf1cKKM5sqh2a15Kub1+7YMQ/4TUUDUO4=", 585 | "url": "https://github.com/ActiveState/cpython/archive/refs/tags/v2.7.18.1.tar.gz" 586 | }, 587 | "2.7.18.8": { 588 | "hash": "I5zq0CGYTmY0/UO66GQVWqXwlOx/XovbZvQdSzJ3hB4=", 589 | "url": "https://github.com/ActiveState/cpython/archive/refs/tags/v2.7.18.8.tar.gz" 590 | }, 591 | "2.7.18.9": { 592 | "hash": "Tl94mHYHLTDKhYxwaPVvPqhNC+V2QzV+F67jKSMA39U=", 593 | "url": "https://github.com/ActiveState/cpython/archive/refs/tags/v2.7.18.9.tar.gz" 594 | }, 595 | "3.13.0": { 596 | "hash": "EkRcez2zEmxBGQv9wcgjnDnHGUBOhEurvQFaG8P6/NQ=", 597 | "url": "https://www.python.org/ftp/python/3.13.0/Python-3.13.0.tgz" 598 | }, 599 | "3.12.5": { 600 | "hash": "ONxOLCYdScZhGWBm7b+3D9sWvkp5zIIgwiTf61Y21AU=", 601 | "url": "https://www.python.org/ftp/python/3.12.5/Python-3.12.5.tgz" 602 | }, 603 | "3.12.6": { 604 | "hash": "haTBvpBtIOXFpp8kZrANp2nCIdamhKz9OlFNv1vxCmY=", 605 | "url": "https://www.python.org/ftp/python/3.12.6/Python-3.12.6.tgz" 606 | }, 607 | "3.12.7": { 608 | "hash": "c6yP54Aie/Nxrdg3PDB59CoNxi3v+NYSzRWmGAgqtiM=", 609 | "url": "https://www.python.org/ftp/python/3.12.7/Python-3.12.7.tgz" 610 | }, 611 | "3.11.10": { 612 | "hash": "kvL68kJoG/pAbVOlHhfULFNzr/4joTDNlpfhMu9XRwY=", 613 | "url": "https://www.python.org/ftp/python/3.11.10/Python-3.11.10.tgz" 614 | }, 615 | "3.10.15": { 616 | "hash": "onhk5boqRHT49sWKuS/1J2esi2bxZGkjNVpT/j7xUHQ=", 617 | "url": "https://www.python.org/ftp/python/3.10.15/Python-3.10.15.tgz" 618 | }, 619 | "3.9.20": { 620 | "hash": "HnHwBiImZuCjn1pHvoIhQVwixN2PJTNMxBruJgs9N54=", 621 | "url": "https://www.python.org/ftp/python/3.9.20/Python-3.9.20.tgz" 622 | }, 623 | "3.8.20": { 624 | "hash": "ny1ZYsJYPmfvdZJM1W0MGveL9F7FcDXPiizAn3T0v3g=", 625 | "url": "https://www.python.org/ftp/python/3.8.20/Python-3.8.20.tgz" 626 | }, 627 | "2.7.18.10": { 628 | "hash": "hiYhfSaHsXTD0NI4+JuNqhvd2ali2qfsmXfXCbCKorg=", 629 | "url": "https://github.com/ActiveState/cpython/archive/refs/tags/v2.7.18.10.tar.gz" 630 | }, 631 | "3.13.1": { 632 | "hash": "FROSWp8lXvB5Pb8veLtFM8nxhL3QrRl2P9f0ekAKfFU=", 633 | "url": "https://www.python.org/ftp/python/3.13.1/Python-3.13.1.tgz" 634 | }, 635 | "3.12.8": { 636 | "hash": "WXhDXEeaN2ZIywKFTfO4kqzp7X0ysf6tZScSvunQOkU=", 637 | "url": "https://www.python.org/ftp/python/3.12.8/Python-3.12.8.tgz" 638 | }, 639 | "3.11.11": { 640 | "hash": "iDvd7jyS/Lkc+cCcU0MZaVPLuc7YJiE1RYSWk5cIaO0=", 641 | "url": "https://www.python.org/ftp/python/3.11.11/Python-3.11.11.tgz" 642 | }, 643 | "3.10.16": { 644 | "hash": "8uIu2WWpPP62QjeO1ubNvBJ2gmZLJBI2efPQE/r+nNA=", 645 | "url": "https://www.python.org/ftp/python/3.10.16/Python-3.10.16.tgz" 646 | }, 647 | "3.9.21": { 648 | "hash": "Znw7osqY056tEWL2VIw0dXaFguL/ieCCHSXrlWrAmUQ=", 649 | "url": "https://www.python.org/ftp/python/3.9.21/Python-3.9.21.tgz" 650 | }, 651 | "3.13.2": { 652 | "hash": "uNeVMOO3yWpcstQNQx3bUSr0pWPoY3KNhxMDmqUCA/k=", 653 | "url": "https://www.python.org/ftp/python/3.13.2/Python-3.13.2.tgz" 654 | }, 655 | "3.13.3": { 656 | "hash": "mI1zWm0zVoy6/xOEplyyKh+xip7Lc9Q++GgAAZPOI+0=", 657 | "url": "https://www.python.org/ftp/python/3.13.3/Python-3.13.3.tgz" 658 | }, 659 | "3.12.9": { 660 | "hash": "RTE+TF8Ois3slYAWHVZc9f6leOPqvyXffMY1W/Svoe4=", 661 | "url": "https://www.python.org/ftp/python/3.12.9/Python-3.12.9.tgz" 662 | }, 663 | "3.12.10": { 664 | "hash": "FdnGI6v9IWX+gW6h+zhdbtjPPGZGYas1fxeC4wNqbaw=", 665 | "url": "https://www.python.org/ftp/python/3.12.10/Python-3.12.10.tgz" 666 | }, 667 | "3.11.12": { 668 | "hash": "N5yZKamJqdZaH12FTgEfSHKxQiWfT8CoxAYtKBXtf7o=", 669 | "url": "https://www.python.org/ftp/python/3.11.12/Python-3.11.12.tgz" 670 | }, 671 | "3.10.17": { 672 | "hash": "j82g+9wTGFmkpCI6u5Jf1SKnfj+ztSxGzqXzvCrgzZ8=", 673 | "url": "https://www.python.org/ftp/python/3.10.17/Python-3.10.17.tgz" 674 | }, 675 | "3.9.22": { 676 | "hash": "dvTa70/85v0QcoCg240Qix+JbBwi8J2DAO/ZCmnEKYs=", 677 | "url": "https://www.python.org/ftp/python/3.9.22/Python-3.9.22.tgz" 678 | }, 679 | "2.7.18.11": { 680 | "hash": "EBWTGeAGyq1SZzN1eziFNzNluNUexduDYyb3x9G598c=", 681 | "url": "https://github.com/ActiveState/cpython/archive/refs/tags/v2.7.18.11.tar.gz" 682 | }, 683 | "3.13.4": { 684 | "hash": "JmYDjxUht6jsNL8pl7Njd4EY1vOXkoLJNyPocrzUZOA=", 685 | "url": "https://www.python.org/ftp/python/3.13.4/Python-3.13.4.tgz" 686 | }, 687 | "3.12.11": { 688 | "hash": "e41Zr4IWBE0jE96BIL/CzACpvS5ULxV5Xh1hbFH689Y=", 689 | "url": "https://www.python.org/ftp/python/3.12.11/Python-3.12.11.tgz" 690 | }, 691 | "3.11.13": { 692 | "hash": "Dxoi9N/TRZWinPae5+pzue/4scyJ16sps6sOwEF52tg=", 693 | "url": "https://www.python.org/ftp/python/3.11.13/Python-3.11.13.tgz" 694 | }, 695 | "3.10.18": { 696 | "hash": "GxmrgCUY6zaoUfXd71cYYsejHs5TMQmpnfbVrwoc65k=", 697 | "url": "https://www.python.org/ftp/python/3.10.18/Python-3.10.18.tgz" 698 | }, 699 | "3.9.23": { 700 | "hash": "mmmq0YTcHQb2gZkwdB2joyjTSHWkH4ujOHV3Tb/FG1E=", 701 | "url": "https://www.python.org/ftp/python/3.9.23/Python-3.9.23.tgz" 702 | } 703 | }, 704 | "latest": { 705 | "3.12": "3.12.11", 706 | "3.11": "3.11.13", 707 | "3.10": "3.10.18", 708 | "3.9": "3.9.23", 709 | "3.8": "3.8.20", 710 | "3.7": "3.7.17", 711 | "3.6": "3.6.15", 712 | "3.5": "3.5.10", 713 | "3.4": "3.4.10", 714 | "3.3": "3.3.7", 715 | "2.7": "2.7.18.9", 716 | "3.13": "3.13.4" 717 | } 718 | } --------------------------------------------------------------------------------