-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1e0f76f
Showing
6 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: "Test" | ||
|
||
on: | ||
push: | ||
branches: | ||
- "main" | ||
|
||
jobs: | ||
test-linux: | ||
name: "Test on ${{ matrix.config.os-name }}" | ||
runs-on: "${{ matrix.config.runner }}" | ||
strategy: | ||
matrix: | ||
config: | ||
- os-name: "Linux" | ||
runner: "ubuntu-latest" | ||
test-label: "ci-test-linux" | ||
- os-name: "macOS" | ||
runner: "macos-latest" | ||
test-label: "ci-test-macos" | ||
- os-name: "Windows" | ||
runner: "windows-latest" | ||
test-label: "ci-test-windows" | ||
fail-fast: false | ||
|
||
steps: | ||
- name: "Use it!" | ||
id: "finder" | ||
uses: "kurtmckee/setup-python-version-detector@main" | ||
|
||
- name: "Print it!" | ||
shell: "bash" | ||
run: | | ||
echo '${{ steps.finder.outputs.python-identifiers }}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Identify Python interpreters | ||
############################ | ||
|
||
*Robust cache-busting based on Python implementations, architectures, and versions.* | ||
|
||
---- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
name: "Identify installed Python interpreters" | ||
description: | | ||
Find installed Python interpreters and output them as "python-identifiers". | ||
This can be useful for cache busting of tox, virtual environments, | ||
and other items that are sensitive to changes in Python minor versions. | ||
Only Python interpreters named "python" in the $PATH will be found. | ||
outputs: | ||
python-identifiers: | ||
description: | | ||
A string of sorted Python identifiers. | ||
In most cases the identifiers will be paths, | ||
but for system Pythons, 'sysconfig.get_config_var("EXT_SUFFIX")' will be included. | ||
The string will be separated by OS-specific PATH separators; | ||
":" is used on Linux and macOS, and ";" is used on Windows. | ||
value: "${{ steps.final-step.outputs.python-identifiers }}" | ||
|
||
runs: | ||
using: "composite" | ||
steps: | ||
- name: "Find Pythons on Linux / macOS" | ||
id: "linux" | ||
if: "runner.os != 'windows'" | ||
shell: "bash" | ||
run: | | ||
true > /dev/null # Prevent YAML syntax errors when embedded in 'action.yml'. | ||
code=$( | ||
cat <<'END_CODE' | ||
from __future__ import print_function | ||
import sysconfig | ||
ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") | ||
if ext_suffix is not None: | ||
print(ext_suffix) | ||
else: | ||
# Python 2.7 on macOS | ||
import platform | ||
print( | ||
"." + platform.python_implementation().lower(), | ||
sysconfig.get_config_var("py_version_nodot"), | ||
sysconfig.get_config_var("build"), | ||
sep="-" | ||
) | ||
END_CODE | ||
) | ||
# Search paths in $PATH for Python interpreters. | ||
IFS=: read -r -a all_paths <<< "$PATH" | ||
# Find Python interpreters. | ||
paths=() | ||
for path in "${all_paths[@]}"; do | ||
# Interpreters in RUNNER_TOOL_CACHE have directory names that include: | ||
# | ||
# * The implementation (like "Python" or "PyPy") | ||
# * A version (like "3.10.12") | ||
# * The architecture (like "x64") | ||
# | ||
# In such cases, the path can be used as the identifier. | ||
if [[ "${path/#${RUNNER_TOOL_CACHE}/}" != "${path}" ]]; then | ||
# Check for bin/python first; | ||
# this results in duplicate paths which are later removed. | ||
if [[ -x "${path}/bin/python" ]]; then | ||
paths+=("${path}/bin") | ||
elif [[ -x "${path}/python" ]]; then | ||
paths+=("${path}") | ||
fi | ||
else | ||
# System Pythons (e.g. /usr/bin/python) have nothing unique in the path. | ||
# In such cases, it's necessary to run the executable to get something unique. | ||
if [[ -x "${path}/python" ]]; then | ||
paths+=("${path}" "$(echo "${code}" | "${path}/python" -)") | ||
fi | ||
fi | ||
done | ||
# Sort the paths, ensure each path is unique, and create the output result. | ||
result="$( | ||
echo "${paths[*]}" \ | ||
| tr ' ' '\n' \ | ||
| sort \ | ||
| uniq \ | ||
| tr '\n' ':' | ||
)" | ||
# Trim trailing colons. | ||
result="${result%:}" | ||
# Output path information. | ||
echo "python-identifiers=${result}" > "$GITHUB_OUTPUT" | ||
- name: "Find Pythons on Windows" | ||
id: "windows" | ||
if: "runner.os == 'windows'" | ||
shell: "powershell" | ||
run: | | ||
$true | Out-Null # Prevent YAML syntax errors when embedded in 'action.yml'. | ||
# Search paths in $PATH for Python interpreters. | ||
$all_paths = $env:PATH -split ";" | ||
# Find Python interpreters. | ||
$paths = @() | ||
foreach ($path in $all_paths) { | ||
# Only consider paths in RUNNER_TOOL_CACHE. | ||
if ($path.StartsWith($env:RUNNER_TOOL_CACHE)) { | ||
if (Test-Path "$path\python.exe") { | ||
$paths += $path | ||
} | ||
} | ||
} | ||
# Sort the paths, ensure each path is unique, and create the output result. | ||
$result = ( | ||
$paths ` | ||
| Sort-Object ` | ||
| Get-Unique | ||
) -join ";" | ||
# Output path information. | ||
Write-Output "python-identifiers=$result" > "$env:GITHUB_OUTPUT" | ||
- name: "Output" | ||
id: "final-step" | ||
shell: "bash" | ||
run: | | ||
echo 'python-identifiers=${{ steps.linux.outputs.python-identifiers }}${{ steps.windows.outputs.python-identifiers }}' > "$GITHUB_OUTPUT" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
$true | Out-Null # Prevent YAML syntax errors when embedded in 'action.yml'. | ||
|
||
# Search paths in $PATH for Python interpreters. | ||
$all_paths = $env:PATH -split ";" | ||
|
||
# Find Python interpreters. | ||
$paths = @() | ||
foreach ($path in $all_paths) { | ||
# Only consider paths in RUNNER_TOOL_CACHE. | ||
if ($path.StartsWith($env:RUNNER_TOOL_CACHE)) { | ||
if (Test-Path "$path\python.exe") { | ||
$paths += $path | ||
} | ||
} | ||
} | ||
|
||
# Sort the paths, ensure each path is unique, and create the output result. | ||
$result = ( | ||
$paths ` | ||
| Sort-Object ` | ||
| Get-Unique | ||
) -join ";" | ||
|
||
# Output path information. | ||
Write-Output "python-identifiers=$result" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
true > /dev/null # Prevent YAML syntax errors when embedded in 'action.yml'. | ||
|
||
code=$( | ||
cat <<'END_CODE' | ||
from __future__ import print_function | ||
import sysconfig | ||
ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") | ||
if ext_suffix is not None: | ||
print(ext_suffix) | ||
else: | ||
# Python 2.7 on macOS | ||
import platform | ||
print( | ||
"." + platform.python_implementation().lower(), | ||
sysconfig.get_config_var("py_version_nodot"), | ||
sysconfig.get_config_var("build"), | ||
sep="-" | ||
) | ||
END_CODE | ||
) | ||
|
||
# Search paths in $PATH for Python interpreters. | ||
IFS=: read -r -a all_paths <<< "$PATH" | ||
|
||
# Find Python interpreters. | ||
paths=() | ||
for path in "${all_paths[@]}"; do | ||
# Interpreters in RUNNER_TOOL_CACHE have directory names that include: | ||
# | ||
# * The implementation (like "Python" or "PyPy") | ||
# * A version (like "3.10.12") | ||
# * The architecture (like "x64") | ||
# | ||
# In such cases, the path can be used as the identifier. | ||
if [[ "${path/#${RUNNER_TOOL_CACHE}/}" != "${path}" ]]; then | ||
# Check for bin/python first; | ||
# this results in duplicate paths which are later removed. | ||
if [[ -x "${path}/bin/python" ]]; then | ||
paths+=("${path}/bin") | ||
elif [[ -x "${path}/python" ]]; then | ||
paths+=("${path}") | ||
fi | ||
else | ||
# System Pythons (e.g. /usr/bin/python) have nothing unique in the path. | ||
# In such cases, it's necessary to run the executable to get something unique. | ||
if [[ -x "${path}/python" ]]; then | ||
paths+=("${path}" "$(echo "${code}" | "${path}/python" -)") | ||
fi | ||
fi | ||
done | ||
|
||
# Sort the paths, ensure each path is unique, and create the output result. | ||
result="$( | ||
echo "${paths[*]}" \ | ||
| tr ' ' '\n' \ | ||
| sort \ | ||
| uniq \ | ||
| tr '\n' ':' | ||
)" | ||
|
||
# Trim trailing colons. | ||
result="${result%:}" | ||
|
||
# Output path information. | ||
echo "python-identifiers=${result}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from __future__ import print_function | ||
|
||
import platform | ||
import sys | ||
|
||
|
||
def main(): | ||
python_version = platform.python_version() | ||
implementation = platform.python_implementation() | ||
architecture = "/".join(platform.architecture()) | ||
|
||
# PyPy | ||
if hasattr(sys, "pypy_version_info"): | ||
implementation_version = ".".join(str(v) for v in sys.pypy_version_info[:3]) | ||
|
||
# CPython | ||
else: | ||
implementation_version, _, _ = sys.version.partition(" ") | ||
|
||
# GraalPy | ||
try: | ||
implementation_version = __graalpython__.get_graalvm_version() | ||
except NameError: | ||
pass | ||
|
||
output = "{0} [{1} {2}; {3}]".format( | ||
python_version, implementation, implementation_version, architecture | ||
) | ||
print(output) | ||
|
||
return 0 | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |