Skip to content

Commit 35089ae

Browse files
add script to retrieve supported Python versions, optionally from package source metadata
1 parent 0b56bf7 commit 35089ae

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

.github/workflows/tox.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ jobs:
123123
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
124124
with:
125125
python-version: '3.12'
126+
- if: inputs.envs == ''
127+
run: echo $SUPPORTED_PYTHONS_SCRIPT | base64 --decode > supported_pythons.py
128+
env:
129+
SUPPORTED_PYTHONS_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj49My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJjbGljaz09OC4yLjEiLAojICAgICAicGVwcHlwcm9qZWN0PT0xLjAuMiIsCiMgICAgICJyZXF1ZXN0cz09Mi4zMi41IiwKIyAgICAgInBhY2thZ2luZz09MjUuMCIsCiMgXQojIC8vLwoKaW1wb3J0IGpzb24KaW1wb3J0IG9zCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aAppbXBvcnQgd2FybmluZ3MKCmltcG9ydCBjbGljawppbXBvcnQgcmVxdWVzdHMKZnJvbSBwYWNrYWdpbmcuc3BlY2lmaWVycyBpbXBvcnQgU3BlY2lmaWVyU2V0CmZyb20gcGFja2FnaW5nLnZlcnNpb24gaW1wb3J0IFZlcnNpb24KZnJvbSBwZXBweXByb2plY3QgaW1wb3J0IFB5UHJvamVjdENvbmZpZ3VyYXRpb24KCgpAY2xpY2suY29tbWFuZCgpCkBjbGljay5vcHRpb24oIi0tc291cmNlIiwgZGVmYXVsdD1Ob25lKQpAY2xpY2sub3B0aW9uKCItLWZsYWdzIiwgZGVmYXVsdD1Ob25lKQpAY2xpY2sub3B0aW9uKCItLW5vLWVvYXMiLCBpc19mbGFnPVRydWUsIGRlZmF1bHQ9RmFsc2UpCmRlZiBwcmludF9zdXBwb3J0ZWRfcHl0aG9ucygKICAgIHNvdXJjZTogUGF0aCA9IE5vbmUsCiAgICBmbGFnczogbGlzdFtzdHJdID0gTm9uZSwKICAgIG5vX2VvYXM6IGJvb2wgPSBGYWxzZSwKKToKICAgICIiImVudW1lcmF0ZSB0b3hlbnZzIFB5dGhvbiBmcm9tIGEgcGFja2FnZSBzb3VyY2UiIiIKCiAgICB0b3hlbnZzID0gc3VwcG9ydGVkX3B5dGhvbl90b3hlbnZzKHNvdXJjZSwgZmxhZ3MsIG5vX2VvYXMpCiAgICBwcmludChqc29uLmR1bXBzKHRveGVudnMsIGluZGVudD0yKSkKICAgIHdpdGggb3Blbihvcy5lbnZpcm9uWyJHSVRIVUJfT1VUUFVUIl0sICJhIikgYXMgZjoKICAgICAgICBmLndyaXRlKGYiZW52cz17anNvbi5kdW1wcyh0b3hlbnZzKX1cbiIpCgoKZGVmIHN1cHBvcnRlZF9weXRob25fdG94ZW52cygKICAgIHNvdXJjZTogUGF0aCA9IE5vbmUsCiAgICBmbGFnczogbGlzdFtzdHJdID0gTm9uZSwKICAgIG5vX2VvYXM6IGJvb2wgPSBGYWxzZSwKKSAtPiBsaXN0W3N0cl06CiAgICBweXRob25zID0gY3VycmVudF9weXRob25fdmVyc2lvbnMobm9fZW9hcz1ub19lb2FzKQoKICAgIGlmIHNvdXJjZSBpcyBOb25lIG9yIHNvdXJjZSA9PSAiIjoKICAgICAgICBzdXBwb3J0ZWRfcHl0aG9ucyA9IHB5dGhvbnMKICAgIGVsc2U6CiAgICAgICAgY29uZmlndXJhdGlvbiA9IFB5UHJvamVjdENvbmZpZ3VyYXRpb24uZnJvbV9kaXJlY3Rvcnkoc291cmNlKQogICAgICAgIHRyeToKICAgICAgICAgICAgcHl0aG9uX3JlcXVpcmVtZW50cyA9IFNwZWNpZmllclNldChjb25maWd1cmF0aW9uWyJwcm9qZWN0Il1bInJlcXVpcmVzLXB5dGhvbiJdKQoKICAgICAgICAgICAgc3VwcG9ydGVkX3B5dGhvbnMgPSBbcHl0aG9uIGZvciBweXRob24gaW4gcHl0aG9ucyBpZiBweXRob24gaW4gcHl0aG9uX3JlcXVpcmVtZW50c10KICAgICAgICBleGNlcHQgKEtleUVycm9yLCBUeXBlRXJyb3IpOgogICAgICAgICAgICB3YXJuaW5ncy53YXJuKCJjb3VsZCBub3QgZmluZCBgcmVxdWlyZXMtcHl0aG9uYCBpbiBtZXRhZGF0YTsgZmFsbGluZyBiYWNrIHRvIGN1cnJlbnQgUHl0aG9uIHZlcnNpb25zLi4uIikKICAgICAgICAgICAgc3VwcG9ydGVkX3B5dGhvbnMgPSBweXRob25zCgogICAgcmV0dXJuIFsKICAgICAgICBmInB5e3N0cihweXRob24pLnJlcGxhY2UoJy4nLCAnJyl9eyctJyArICctJy5qb2luKGZsYWdzKSBpZiBmbGFncyBpcyBub3QgTm9uZSBhbmQgbGVuKGZsYWdzKSA+IDAgZWxzZSAnJ30iCiAgICAgICAgZm9yIHB5dGhvbiBpbiBzdXBwb3J0ZWRfcHl0aG9ucwogICAgXQoKCmRlZiBjdXJyZW50X3B5dGhvbl92ZXJzaW9ucyhub19lb2FzOiBib29sID0gRmFsc2UpIC0+IGxpc3RbVmVyc2lvbl06CiAgICB1cmwgPSAiaHR0cHM6Ly9lbmRvZmxpZmUuZGF0ZS9hcGkvdjEvcHJvZHVjdHMvcHl0aG9uIgogICAgcmVzcG9uc2UgPSByZXF1ZXN0cy5nZXQoImh0dHBzOi8vZW5kb2ZsaWZlLmRhdGUvYXBpL3YxL3Byb2R1Y3RzL3B5dGhvbiIpCiAgICBpZiByZXNwb25zZS5zdGF0dXNfY29kZSA9PSAyMDA6CiAgICAgICAgcmV0dXJuIFsKICAgICAgICAgICAgVmVyc2lvbihweXRob25bIm5hbWUiXSkKICAgICAgICAgICAgZm9yIHB5dGhvbiBpbiByZXNwb25zZS5qc29uKClbInJlc3VsdCJdWyJyZWxlYXNlcyJdCiAgICAgICAgICAgIGlmIG5vdCBweXRob25bImlzRW9hcyIgaWYgbm9fZW9hcyBlbHNlICJpc0VvbCJdCiAgICAgICAgXQogICAgZWxzZToKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKGYicmVxdWVzdCByZXR1cm5lZCBzdGF0dXMgY29kZSB7cmVzcG9uc2Uuc3RhdHVzX2NvZGV9IFt7dXJsfV0iKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBwcmludF9zdXBwb3J0ZWRfcHl0aG9ucygpCg==
130+
- if: inputs.envs == ''
131+
run: cat supported_pythons.py
132+
- id: get-envs
133+
run: |
134+
pipx run supported_pythons.py
135+
shell: sh
136+
- run: cat ${{ steps.get-envs.outputs.envs }}
126137
- run: echo $TOX_MATRIX_SCRIPT | base64 --decode > tox_matrix.py
127138
env:
128139
TOX_MATRIX_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJjbGljaz09OC4yLjEiLAojICAgICAicHl5YW1sPT02LjAuMiIsCiMgXQojIC8vLwppbXBvcnQganNvbgppbXBvcnQgb3MKaW1wb3J0IHJlCgppbXBvcnQgY2xpY2sKaW1wb3J0IHlhbWwKCgpAY2xpY2suY29tbWFuZCgpCkBjbGljay5vcHRpb24oIi0tZW52cyIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tbGlicmFyaWVzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1wb3NhcmdzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS10b3hkZXBzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS10b3hhcmdzIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1weXRlc3QiLCBkZWZhdWx0PSJ0cnVlIikKQGNsaWNrLm9wdGlvbigiLS1weXRlc3QtcmVzdWx0cy1zdW1tYXJ5IiwgZGVmYXVsdD0iZmFsc2UiKQpAY2xpY2sub3B0aW9uKCItLWNvdmVyYWdlIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1jb25kYSIsIGRlZmF1bHQ9ImF1dG8iKQpAY2xpY2sub3B0aW9uKCItLXNldGVudiIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tZGlzcGxheSIsIGRlZmF1bHQ9ImZhbHNlIikKQGNsaWNrLm9wdGlvbigiLS1jYWNoZS1wYXRoIiwgZGVmYXVsdD0iIikKQGNsaWNrLm9wdGlvbigiLS1jYWNoZS1rZXkiLCBkZWZhdWx0PSIiKQpAY2xpY2sub3B0aW9uKCItLWNhY2hlLXJlc3RvcmUta2V5cyIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tYXJ0aWZhY3QtcGF0aCIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tcnVucy1vbiIsIGRlZmF1bHQ9IiIpCkBjbGljay5vcHRpb24oIi0tZGVmYXVsdC1weXRob24iLCBkZWZhdWx0PSIiKQpAY2xpY2sub3B0aW9uKCItLXRpbWVvdXQtbWludXRlcyIsIGRlZmF1bHQ9IjM2MCIpCmRlZiBsb2FkX3RveF90YXJnZXRzKGVudnMsIGxpYnJhcmllcywgcG9zYXJncywgdG94ZGVwcywgdG94YXJncywgcHl0ZXN0LCBweXRlc3RfcmVzdWx0c19zdW1tYXJ5LAogICAgICAgICAgICAgICAgICAgICBjb3ZlcmFnZSwgY29uZGEsIHNldGVudiwgZGlzcGxheSwgY2FjaGVfcGF0aCwgY2FjaGVfa2V5LAogICAgICAgICAgICAgICAgICAgICBjYWNoZV9yZXN0b3JlX2tleXMsIGFydGlmYWN0X3BhdGgsIHJ1bnNfb24sIGRlZmF1bHRfcHl0aG9uLCB0aW1lb3V0X21pbnV0ZXMpOgogICAgIiIiU2NyaXB0IHRvIGxvYWQgdG94IHRhcmdldHMgZm9yIEdpdEh1YiBBY3Rpb25zIHdvcmtmbG93LiIiIgogICAgIyBMb2FkIGVudnMgY29uZmlnCiAgICBlbnZzID0geWFtbC5sb2FkKGVudnMsIExvYWRlcj15YW1sLkJhc2VMb2FkZXIpCiAgICBwcmludChqc29uLmR1bXBzKGVudnMsIGluZGVudD0yKSkKCiAgICAjIExvYWQgZ2xvYmFsIGxpYnJhcmllcyBjb25maWcKICAgIGdsb2JhbF9saWJyYXJpZXMgPSB7CiAgICAgICAgImJyZXciOiBbXSwKICAgICAgICAiYnJldy1jYXNrIjogW10sCiAgICAgICAgImFwdCI6IFtdLAogICAgICAgICJjaG9jbyI6IFtdLAogICAgfQogICAgbGlicmFyaWVzID0geWFtbC5sb2FkKGxpYnJhcmllcywgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIGlmIGxpYnJhcmllcyBpcyBub3QgTm9uZToKICAgICAgICBnbG9iYWxfbGlicmFyaWVzLnVwZGF0ZShsaWJyYXJpZXMpCiAgICBwcmludChqc29uLmR1bXBzKGdsb2JhbF9saWJyYXJpZXMsIGluZGVudD0yKSkKCiAgICAjIERlZmF1bHQgaW1hZ2VzIHRvIHVzZSBmb3IgcnVubmVycwogICAgZGVmYXVsdF9ydW5zX29uID0gewogICAgICAgICJsaW51eCI6ICJ1YnVudHUtbGF0ZXN0IiwKICAgICAgICAibWFjb3MiOiAibWFjb3MtbGF0ZXN0IiwKICAgICAgICAid2luZG93cyI6ICJ3aW5kb3dzLWxhdGVzdCIsCiAgICB9CiAgICBjdXN0b21fcnVuc19vbiA9IHlhbWwubG9hZChydW5zX29uLCBMb2FkZXI9eWFtbC5CYXNlTG9hZGVyKQogICAgaWYgaXNpbnN0YW5jZShjdXN0b21fcnVuc19vbiwgZGljdCk6CiAgICAgICAgZGVmYXVsdF9ydW5zX29uLnVwZGF0ZShjdXN0b21fcnVuc19vbikKICAgIHByaW50KGpzb24uZHVtcHMoZGVmYXVsdF9ydW5zX29uLCBpbmRlbnQ9MikpCgogICAgIyBEZWZhdWx0IHN0cmluZyBwYXJhbWV0ZXJzIHdoaWNoIGNhbiBiZSBvdmVyd3JpdHRlbiBieSBlYWNoIGVudgogICAgc3RyaW5nX3BhcmFtZXRlcnMgPSB7CiAgICAgICAgInBvc2FyZ3MiOiBwb3NhcmdzLAogICAgICAgICJ0b3hkZXBzIjogdG94ZGVwcywKICAgICAgICAidG94YXJncyI6IHRveGFyZ3MsCiAgICAgICAgInB5dGVzdCI6IHB5dGVzdCwKICAgICAgICAicHl0ZXN0LXJlc3VsdHMtc3VtbWFyeSI6IHB5dGVzdF9yZXN1bHRzX3N1bW1hcnksCiAgICAgICAgImNvdmVyYWdlIjogY292ZXJhZ2UsCiAgICAgICAgImNvbmRhIjogY29uZGEsCiAgICAgICAgInNldGVudiI6IHNldGVudiwKICAgICAgICAiZGlzcGxheSI6IGRpc3BsYXksCiAgICAgICAgImNhY2hlLXBhdGgiOiBjYWNoZV9wYXRoLAogICAgICAgICJjYWNoZS1rZXkiOiBjYWNoZV9rZXksCiAgICAgICAgImNhY2hlLXJlc3RvcmUta2V5cyI6IGNhY2hlX3Jlc3RvcmVfa2V5cywKICAgICAgICAiYXJ0aWZhY3QtcGF0aCI6IGFydGlmYWN0X3BhdGgsCiAgICAgICAgInRpbWVvdXQtbWludXRlcyI6IHRpbWVvdXRfbWludXRlcywKICAgIH0KCiAgICAjIENyZWF0ZSBtYXRyaXgKICAgIG1hdHJpeCA9IHsiaW5jbHVkZSI6IFtdfQogICAgZm9yIGVudiBpbiBlbnZzOgogICAgICAgIG1hdHJpeFsiaW5jbHVkZSJdLmFwcGVuZChnZXRfbWF0cml4X2l0ZW0oCiAgICAgICAgICAgIGVudiwKICAgICAgICAgICAgZ2xvYmFsX2xpYnJhcmllcz1nbG9iYWxfbGlicmFyaWVzLAogICAgICAgICAgICBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnM9c3RyaW5nX3BhcmFtZXRlcnMsCiAgICAgICAgICAgIHJ1bnNfb249ZGVmYXVsdF9ydW5zX29uLAogICAgICAgICAgICBkZWZhdWx0X3B5dGhvbj1kZWZhdWx0X3B5dGhvbiwKICAgICAgICApKQoKICAgICMgT3V0cHV0IG1hdHJpeAogICAgcHJpbnQoanNvbi5kdW1wcyhtYXRyaXgsIGluZGVudD0yKSkKICAgIHdpdGggb3Blbihvcy5lbnZpcm9uWyJHSVRIVUJfT1VUUFVUIl0sICJhIikgYXMgZjoKICAgICAgICBmLndyaXRlKGYibWF0cml4PXtqc29uLmR1bXBzKG1hdHJpeCl9XG4iKQoKCmRlZiBnZXRfbWF0cml4X2l0ZW0oZW52LCBnbG9iYWxfbGlicmFyaWVzLCBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnMsCiAgICAgICAgICAgICAgICAgICAgcnVuc19vbiwgZGVmYXVsdF9weXRob24pOgoKICAgICMgZGVmaW5lIHNwZWMgZm9yIGVhY2ggbWF0cml4IGluY2x1ZGUgKCsgZ2xvYmFsX3N0cmluZ19wYXJhbWV0ZXJzKQogICAgaXRlbSA9IHsKICAgICAgICAib3MiOiBOb25lLAogICAgICAgICJ0b3hlbnYiOiBOb25lLAogICAgICAgICJweXRob25fdmVyc2lvbiI6IE5vbmUsCiAgICAgICAgIm5hbWUiOiBOb25lLAogICAgICAgICJweXRlc3RfZmxhZyI6IE5vbmUsCiAgICAgICAgImxpYnJhcmllc19icmV3IjogTm9uZSwKICAgICAgICAibGlicmFyaWVzX2JyZXdfY2FzayI6IE5vbmUsCiAgICAgICAgImxpYnJhcmllc19hcHQiOiBOb25lLAogICAgICAgICJsaWJyYXJpZXNfY2hvY28iOiBOb25lLAogICAgICAgICJjYWNoZS1wYXRoIjogTm9uZSwKICAgICAgICAiY2FjaGUta2V5IjogTm9uZSwKICAgICAgICAiY2FjaGUtcmVzdG9yZS1rZXlzIjogTm9uZSwKICAgICAgICAiYXJ0aWZhY3QtbmFtZSI6IE5vbmUsCiAgICAgICAgImFydGlmYWN0LXBhdGgiOiBOb25lLAogICAgICAgICJ0aW1lb3V0LW1pbnV0ZXMiOiBOb25lLAogICAgfQogICAgZm9yIHN0cmluZ19wYXJhbSwgZGVmYXVsdCBpbiBnbG9iYWxfc3RyaW5nX3BhcmFtZXRlcnMuaXRlbXMoKToKICAgICAgICBlbnZfdmFsdWUgPSBlbnYuZ2V0KHN0cmluZ19wYXJhbSkKICAgICAgICBpdGVtW3N0cmluZ19wYXJhbV0gPSBkZWZhdWx0IGlmIGVudl92YWx1ZSBpcyBOb25lIGVsc2UgZW52X3ZhbHVlCgogICAgIyBzZXQgb3MgYW5kIHRveGVudgogICAgZm9yIGssIHYgaW4gcnVuc19vbi5pdGVtcygpOgogICAgICAgIGlmIGsgaW4gZW52OgogICAgICAgICAgICBwbGF0Zm9ybSA9IGsKICAgICAgICAgICAgaXRlbVsib3MiXSA9IGVudi5nZXQoInJ1bnMtb24iLCB2KQogICAgICAgICAgICBpdGVtWyJ0b3hlbnYiXSA9IGVudltrXQogICAgYXNzZXJ0IGl0ZW1bIm9zIl0gaXMgbm90IE5vbmUgYW5kIGl0ZW1bInRveGVudiJdIGlzIG5vdCBOb25lCgogICAgIyBzZXQgcHl0aG9uX3ZlcnNpb24KICAgIHB5dGhvbl92ZXJzaW9uID0gZW52LmdldCgicHl0aG9uLXZlcnNpb24iKQogICAgbSA9IHJlLnNlYXJjaCgiXnB5KDJ8MykoWzAtOV0rdD8pIiwgaXRlbVsidG94ZW52Il0pCiAgICBpZiBweXRob25fdmVyc2lvbiBpcyBub3QgTm9uZToKICAgICAgICBpdGVtWyJweXRob25fdmVyc2lvbiJdID0gcHl0aG9uX3ZlcnNpb24KICAgIGVsaWYgbSBpcyBub3QgTm9uZToKICAgICAgICBtYWpvciwgbWlub3IgPSBtLmdyb3VwcygpCiAgICAgICAgaXRlbVsicHl0aG9uX3ZlcnNpb24iXSA9IGYie21ham9yfS57bWlub3J9IgogICAgZWxzZToKICAgICAgICBpdGVtWyJweXRob25fdmVyc2lvbiJdID0gZW52LmdldCgiZGVmYXVsdF9weXRob24iKSBvciBkZWZhdWx0X3B5dGhvbgoKICAgICMgc2V0IG5hbWUKICAgIGl0ZW1bIm5hbWUiXSA9IGVudi5nZXQoIm5hbWUiKSBvciBmJ3tpdGVtWyJ0b3hlbnYiXX0gKHtpdGVtWyJvcyJdfSknCgogICAgIyBzZXQgYXJ0aWZhY3QtbmFtZSAocmVwbGFjZSBpbnZhbGlkIHBhdGggY2hhcmFjdGVycykKICAgIGl0ZW1bImFydGlmYWN0LW5hbWUiXSA9IHJlLnN1YihyIltcXCAvOjw+fCo/XCInXSIsICItIiwgaXRlbVsibmFtZSJdKQogICAgaXRlbVsiYXJ0aWZhY3QtbmFtZSJdID0gcmUuc3ViKHIiLSsiLCAiLSIsIGl0ZW1bImFydGlmYWN0LW5hbWUiXSkKCiAgICAjIHNldCBweXRlc3RfZmxhZwogICAgaXRlbVsicHl0ZXN0X2ZsYWciXSA9ICIiCiAgICBzZXAgPSByIlxcIiBpZiBwbGF0Zm9ybSA9PSAid2luZG93cyIgZWxzZSAiLyIKICAgIGlmIGl0ZW1bInB5dGVzdCJdID09ICJ0cnVlIiBhbmQgImNvZGVjb3YiIGluIGl0ZW0uZ2V0KCJjb3ZlcmFnZSIsICIiKToKICAgICAgICBpdGVtWyJweXRlc3RfZmxhZyJdICs9ICgKICAgICAgICAgICAgcmYiLS1jb3YtcmVwb3J0PXhtbDoke3tHSVRIVUJfV09SS1NQQUNFfX17c2VwfWNvdmVyYWdlLnhtbCAiKQogICAgaWYgaXRlbVsicHl0ZXN0Il0gPT0gInRydWUiIGFuZCBpdGVtWyJweXRlc3QtcmVzdWx0cy1zdW1tYXJ5Il0gPT0gInRydWUiOgogICAgICAgIGl0ZW1bInB5dGVzdF9mbGFnIl0gKz0gcmYiLS1qdW5pdHhtbCAke3tHSVRIVUJfV09SS1NQQUNFfX17c2VwfXJlc3VsdHMueG1sICIKCiAgICAjIHNldCBsaWJyYXJpZXMKICAgIGVudl9saWJyYXJpZXMgPSBlbnYuZ2V0KCJsaWJyYXJpZXMiKQogICAgaWYgaXNpbnN0YW5jZShlbnZfbGlicmFyaWVzLCBzdHIpIGFuZCBsZW4oZW52X2xpYnJhcmllcy5zdHJpcCgpKSA9PSAwOgogICAgICAgIGVudl9saWJyYXJpZXMgPSB7fSAgIyBubyBsaWJyYXJpZXMgcmVxdWVzdGVkIGZvciBlbnZpcm9ubWVudAogICAgbGlicmFyaWVzID0gZ2xvYmFsX2xpYnJhcmllcyBpZiBlbnZfbGlicmFyaWVzIGlzIE5vbmUgZWxzZSBlbnZfbGlicmFyaWVzCiAgICBmb3IgbWFuYWdlciBpbiBbImJyZXciLCAiYnJld19jYXNrIiwgImFwdCIsICJjaG9jbyJdOgogICAgICAgIGl0ZW1bZiJsaWJyYXJpZXNfe21hbmFnZXJ9Il0gPSAiICIuam9pbihsaWJyYXJpZXMuZ2V0KG1hbmFnZXIsIFtdKSkKCiAgICAjIHNldCAiYXV0byIgY29uZGEgdmFsdWUKICAgIGlmIGl0ZW1bImNvbmRhIl0gPT0gImF1dG8iOgogICAgICAgIGl0ZW1bImNvbmRhIl0gPSAidHJ1ZSIgaWYgImNvbmRhIiBpbiBpdGVtWyJ0b3hlbnYiXSBlbHNlICJmYWxzZSIKCiAgICAjIGluamVjdCB0b3hkZXBzIGZvciBjb25kYQogICAgaWYgaXRlbVsiY29uZGEiXSA9PSAidHJ1ZSIgYW5kICJ0b3gtY29uZGEiIG5vdCBpbiBpdGVtWyJ0b3hkZXBzIl0ubG93ZXIoKToKICAgICAgICBpdGVtWyJ0b3hkZXBzIl0gPSAoInRveC1jb25kYSAiICsgaXRlbVsidG94ZGVwcyJdKS5zdHJpcCgpCgogICAgIyBtYWtlIHRpbWVvdXQtbWludXRlcyBhIG51bWJlcgogICAgaXRlbVsidGltZW91dC1taW51dGVzIl0gPSBpbnQoaXRlbVsidGltZW91dC1taW51dGVzIl0pCgogICAgIyB2ZXJpZnkgdmFsdWVzCiAgICBhc3NlcnQgaXRlbVsicHl0ZXN0Il0gaW4geyJ0cnVlIiwgImZhbHNlIn0KICAgIGFzc2VydCBpdGVtWyJjb25kYSJdIGluIHsidHJ1ZSIsICJmYWxzZSJ9CiAgICBhc3NlcnQgaXRlbVsiZGlzcGxheSJdIGluIHsidHJ1ZSIsICJmYWxzZSJ9CgogICAgcmV0dXJuIGl0ZW0KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbG9hZF90b3hfdGFyZ2V0cygpCg==

tools/supported_pythons.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# /// script
2+
# requires-python = ">=3.12"
3+
# dependencies = [
4+
# "click==8.2.1",
5+
# "peppyproject==1.0.2",
6+
# "requests==2.32.5",
7+
# "packaging==25.0",
8+
# ]
9+
# ///
10+
11+
import json
12+
import os
13+
from pathlib import Path
14+
import warnings
15+
16+
import click
17+
import requests
18+
from packaging.specifiers import SpecifierSet
19+
from packaging.version import Version
20+
from peppyproject import PyProjectConfiguration
21+
22+
23+
@click.command()
24+
@click.option("--source", default=None)
25+
@click.option("--flags", default=None)
26+
@click.option("--no-eoas", is_flag=True, default=False)
27+
def print_supported_pythons(
28+
source: Path = None,
29+
flags: list[str] = None,
30+
no_eoas: bool = False,
31+
):
32+
"""enumerate toxenvs Python from a package source"""
33+
34+
toxenvs = supported_python_toxenvs(source, flags, no_eoas)
35+
print(json.dumps(toxenvs, indent=2))
36+
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
37+
f.write(f"envs={json.dumps(toxenvs)}\n")
38+
39+
40+
def supported_python_toxenvs(
41+
source: Path = None,
42+
flags: list[str] = None,
43+
no_eoas: bool = False,
44+
) -> list[str]:
45+
pythons = current_python_versions(no_eoas=no_eoas)
46+
47+
if source is None or source == "":
48+
supported_pythons = pythons
49+
else:
50+
configuration = PyProjectConfiguration.from_directory(source)
51+
try:
52+
python_requirements = SpecifierSet(configuration["project"]["requires-python"])
53+
54+
supported_pythons = [python for python in pythons if python in python_requirements]
55+
except (KeyError, TypeError):
56+
warnings.warn("could not find `requires-python` in metadata; falling back to current Python versions...")
57+
supported_pythons = pythons
58+
59+
return [
60+
f"py{str(python).replace('.', '')}{'-' + '-'.join(flags) if flags is not None and len(flags) > 0 else ''}"
61+
for python in supported_pythons
62+
]
63+
64+
65+
def current_python_versions(no_eoas: bool = False) -> list[Version]:
66+
url = "https://endoflife.date/api/v1/products/python"
67+
response = requests.get("https://endoflife.date/api/v1/products/python")
68+
if response.status_code == 200:
69+
return [
70+
Version(python["name"])
71+
for python in response.json()["result"]["releases"]
72+
if not python["isEoas" if no_eoas else "isEol"]
73+
]
74+
else:
75+
raise ValueError(f"request returned status code {response.status_code} [{url}]")
76+
77+
78+
if __name__ == "__main__":
79+
print_supported_pythons()

update_scripts_in_yml.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ def base64_encode_into(script, yml_file, env_var):
3232
base64_encode_into('set_env.py', 'tox.yml', 'SET_ENV_SCRIPT')
3333
base64_encode_into('set_env.py', 'publish.yml', 'SET_ENV_SCRIPT')
3434
base64_encode_into('set_env.py', 'publish_pure_python.yml', 'SET_ENV_SCRIPT')
35+
base64_encode_into('supported_pythons.py', 'tox.yml', 'SUPPORTED_PYTHONS_SCRIPT')

0 commit comments

Comments
 (0)