Skip to content

Instantly share code, notes, and snippets.

@tomviner
Last active November 4, 2023 23:42
Show Gist options
  • Save tomviner/a8df1ba639ccee20f9f6de63c6352c85 to your computer and use it in GitHub Desktop.
Save tomviner/a8df1ba639ccee20f9f6de63c6352c85 to your computer and use it in GitHub Desktop.
Instal latest patch versions of python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

latest python versions

Clone

$ git clone git@gist.github.com:a8df1ba639ccee20f9f6de63c6352c85.git latest_python_versions

Use pyenv to install the latest patch version of each minor version of Python.

$ git clone git@gist.github.com:a8df1ba639ccee20f9f6de63c6352c85.git latest_python_versions
$ python latest_python_versions.py

Current:
	pyenv global  3.11.1  3.10.9  3.9.16  3.8.16  3.7.16  3.6.15  2.7.18  3.12.0a4  system

After new installs:
	pyenv global  3.11.3  3.10.11  3.9.16  3.8.16  3.7.16  3.6.15  2.7.18  3.12.0b1  3.13-dev  system

Need:
	pyenv install --skip-existing 3.11.3; \
	pyenv install --skip-existing 3.10.11; \
	pyenv install --skip-existing 3.12.0b1; \
	pyenv install --skip-existing 3.13-dev

Got latest:
	3.9.16
	3.8.16
	3.7.16
	3.6.15
	2.7.18
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "a0e3b3f3",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from subprocess import check_output\n",
"\n",
"def p(ls):\n",
" print(' '.join(sorted(ls)))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "07552d09",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'ca-certificates'}"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"work_rosetta = {'ca-certificates'}\n",
"work_rosetta"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "f0701f6a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ca-certificates\n"
]
}
],
"source": [
"rosetta = set(check_output('arch -x86_64 /usr/local/bin/brew list'.split(), text=True).split())\n",
"p(rosetta)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9cf34db5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"antigen autoconf awscli bat ca-certificates fd fzf gdbm gettext go hugo icu4c krb5 libevent libffi libidn2 libssh2 libtermkey libunistring libuv luajit-openresty luv m4 mpdecimal msgpack ncurses neovim openssl@1.1 openssl@3 packer pcre2 pkg-config postgresql python@3.10 python@3.8 python@3.9 readline ripgrep rust six sqlite starship tcl-tk tmux tree tree-sitter unibilium utf8proc wget xz zlib\n"
]
}
],
"source": [
"work_native = {'antigen', 'autoconf', 'awscli', 'bat', 'ca-certificates', 'fd', 'fzf', 'gdbm', 'gettext', 'go', 'hugo', 'icu4c', 'krb5', 'libevent', 'libffi', 'libidn2', 'libssh2', 'libtermkey', 'libunistring', 'libuv', 'luajit-openresty', 'luv', 'm4', 'mpdecimal', 'msgpack', 'ncurses', 'neovim', 'openssl@1.1', 'openssl@3', 'packer', 'pcre2', 'pkg-config', 'postgresql', 'python@3.10', 'python@3.8', 'python@3.9', 'readline', 'ripgrep', 'rust', 'six', 'sqlite', 'starship', 'tcl-tk', 'tmux', 'tree', 'tree-sitter', 'unibilium', 'utf8proc', 'wget', 'xz', 'zlib'}\n",
"p(work_native)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d1d58c10",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"aom asdf atool autoconf automake aws-vault bat bdw-gc brotli btop bzip2 c-ares ca-certificates cairo cjson cmocka colordiff coreutils dav1d duf ffmpeg flac fontconfig fop freetype frei0r fribidi fzf gawk gcc gd gdbm gdk-pixbuf gettext giflib glib gmp gnupg gnutls go gobject-introspection gping graphite2 graphviz gron gts guile harfbuzz htop httpie icu4c imath isl jansson jasper jpeg jpeg-xl jq keepingyouawake krb5 lame leptonica libarchive libass libassuan libavif libb2 libbluray libevent libffi libgcrypt libgpg-error libidn2 libksba libmaxminddb libmpc libnghttp2 libogg libpng libpq libpthread-stubs libreoffice librist librsvg libsamplerate libsmi libsndfile libsodium libsoxr libssh libssh2 libtasn1 libtiff libtool libunistring libusb libvidstab libvmaf libvorbis libvpx libx11 libxau libxcb libxdmcp libxext libxml2 libxrender libxslt libyaml little-cms2 lua lz4 lzo m4 mbedtls mpdecimal mpfr mtr ncurses netpbm nettle nmap npth oniguruma opencore-amr openexr openjdk openjpeg openssl@1.1 openssl@3 opus p11-kit pango pcre pdftohtml pinentry pipx pixman pkg-config prips procs pyenv pyenv-virtualenv pyenv-virtualenvwrapper python@3.10 python@3.9 rav1e readline rubberband rust sd sdl2 snappy speex sqlite srt tcl-tk telnet tesseract theora tree unbound unixodbc unzip watch webp wget wireshark wxwidgets x264 x265 xorgproto xvid xz youtube-dl zeromq zimg zip zlib zstd\n"
]
}
],
"source": [
"native = set(check_output('brew list'.split(), text=True).split())\n",
"p(native)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0ae237a8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"antigen autoconf awscli bat ca-certificates fd fzf gdbm gettext go hugo icu4c krb5 libevent libffi libidn2 libssh2 libtermkey libunistring libuv luajit-openresty luv m4 mpdecimal msgpack ncurses neovim openssl@1.1 openssl@3 packer pcre2 pkg-config postgresql python@3.10 python@3.8 python@3.9 readline ripgrep rust six sqlite starship tcl-tk tmux tree tree-sitter unibilium utf8proc wget xz zlib\n"
]
}
],
"source": [
"ross = set('''antigen icu4c m4 python@3.10 tree\n",
"autoconf krb5 mpdecimal python@3.8 tree-sitter\n",
"awscli libevent msgpack python@3.9 unibilium\n",
"bat libffi ncurses readline utf8proc\n",
"ca-certificates libidn2 neovim ripgrep wget\n",
"fd libssh2 openssl@1.1 rust xz\n",
"fzf libtermkey openssl@3 six zlib\n",
"gdbm libunistring packer sqlite\n",
"gettext libuv pcre2 starship\n",
"go luajit-openresty pkg-config tcl-tk\n",
"hugo luv postgresql tmux\n",
"'''.split())\n",
"p(ross)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "417fcc93",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"m1-terraform-provider-helper\n"
]
}
],
"source": [
"p(rosetta - native)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "1496aecf",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"antigen awscli fd hugo libtermkey libuv luajit-openresty luv msgpack neovim packer pcre2 postgresql python@3.8 ripgrep six starship tmux tree-sitter unibilium utf8proc\n"
]
}
],
"source": [
"p(ross - rosetta - native)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "96d12c02",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"antigen awscli fd hugo libtermkey libuv luajit-openresty luv msgpack neovim packer pcre2 postgresql python@3.8 ripgrep six starship tmux tree-sitter unibilium utf8proc\n"
]
}
],
"source": [
"p(work_native - native - rosetta)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "c831415c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"m1-terraform-provider-helper\n"
]
}
],
"source": [
"p(rosetta - native)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "39c72d69",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"aom asdf atool automake aws-vault bat bdw-gc brotli btop c-ares cjson cmocka colordiff coreutils dav1d duf ffmpeg flac fop frei0r fzf gawk gcc gmp gnupg gnutls gping gron guile htop httpie imath isl jansson jpeg-xl jq keepingyouawake krb5 lame leptonica libarchive libass libassuan libavif libb2 libbluray libevent libgcrypt libgpg-error libidn2 libksba libmaxminddb libmpc libnghttp2 libogg libpq libreoffice librist libsamplerate libsmi libsndfile libsodium libsoxr libssh libssh2 libtasn1 libunistring libusb libvidstab libvmaf libvorbis libvpx libxml2 libxslt libyaml little-cms2 lua lz4 mbedtls mpfr mtr ncurses nettle nmap npth oniguruma opencore-amr openexr openjdk openjpeg opus p11-kit pdftohtml pinentry pipx prips procs pyenv pyenv-virtualenv pyenv-virtualenvwrapper python@3.10 rav1e rubberband rust sd sdl2 snappy speex srt telnet tesseract theora tree unbound unixodbc unzip watch wget wireshark wxwidgets x264 x265 xvid youtube-dl zeromq zimg zip zstd\n"
]
}
],
"source": [
"p(native - rosetta)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "4eae3a06",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"autoconf bzip2 ca-certificates cairo fontconfig freetype fribidi gd gdbm gdk-pixbuf gettext giflib glib go gobject-introspection graphite2 graphviz gts harfbuzz icu4c jasper jpeg libffi libpng libpthread-stubs librsvg libtiff libtool libx11 libxau libxcb libxdmcp libxext libxrender lzo m4 mpdecimal netpbm openssl@1.1 openssl@3 pango pcre pixman pkg-config python@3.9 readline sqlite tcl-tk webp xorgproto xz zlib\n"
]
}
],
"source": [
"p(native & rosetta)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b8104a82",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
{
"pyenv install --list --bare": "Available versions:\n 2.1.3\n 2.2.3\n 2.3.7\n 2.4.0\n 2.4.1\n 2.4.2\n 2.4.3\n 2.4.4\n 2.4.5\n 2.4.6\n 2.5.0\n 2.5.1\n 2.5.2\n 2.5.3\n 2.5.4\n 2.5.5\n 2.5.6\n 2.6.0\n 2.6.1\n 2.6.2\n 2.6.3\n 2.6.4\n 2.6.5\n 2.6.6\n 2.6.7\n 2.6.8\n 2.6.9\n 2.7.0\n 2.7-dev\n 2.7.1\n 2.7.2\n 2.7.3\n 2.7.4\n 2.7.5\n 2.7.6\n 2.7.7\n 2.7.8\n 2.7.9\n 2.7.10\n 2.7.11\n 2.7.12\n 2.7.13\n 2.7.14\n 2.7.15\n 2.7.16\n 2.7.17\n 2.7.18\n 3.0.1\n 3.1.0\n 3.1.1\n 3.1.2\n 3.1.3\n 3.1.4\n 3.1.5\n 3.2.0\n 3.2.1\n 3.2.2\n 3.2.3\n 3.2.4\n 3.2.5\n 3.2.6\n 3.3.0\n 3.3.1\n 3.3.2\n 3.3.3\n 3.3.4\n 3.3.5\n 3.3.6\n 3.3.7\n 3.4.0\n 3.4-dev\n 3.4.1\n 3.4.2\n 3.4.3\n 3.4.4\n 3.4.5\n 3.4.6\n 3.4.7\n 3.4.8\n 3.4.9\n 3.4.10\n 3.5.0\n 3.5-dev\n 3.5.1\n 3.5.2\n 3.5.3\n 3.5.4\n 3.5.5\n 3.5.6\n 3.5.7\n 3.5.8\n 3.5.9\n 3.5.10\n 3.6.0\n 3.6-dev\n 3.6.1\n 3.6.2\n 3.6.3\n 3.6.4\n 3.6.5\n 3.6.6\n 3.6.7\n 3.6.8\n 3.6.9\n 3.6.10\n 3.6.11\n 3.6.12\n 3.6.13\n 3.6.14\n 3.6.15\n 3.7.0\n 3.7-dev\n 3.7.1\n 3.7.2\n 3.7.3\n 3.7.4\n 3.7.5\n 3.7.6\n 3.7.7\n 3.7.8\n 3.7.9\n 3.7.10\n 3.7.11\n 3.7.12\n 3.8.0\n 3.8-dev\n 3.8.1\n 3.8.2\n 3.8.3\n 3.8.4\n 3.8.5\n 3.8.6\n 3.8.7\n 3.8.8\n 3.8.9\n 3.8.10\n 3.8.11\n 3.8.12\n 3.9.0\n 3.9-dev\n 3.9.1\n 3.9.2\n 3.9.4\n 3.9.5\n 3.9.6\n 3.9.7\n 3.9.8\n 3.9.9\n 3.9.10\n 3.10.0\n 3.10-dev\n 3.10.1\n 3.10.2\n 3.11.0a4\n 3.11-dev\n activepython-2.7.14\n activepython-3.5.4\n activepython-3.6.0\n anaconda-1.4.0\n anaconda-1.5.0\n anaconda-1.5.1\n anaconda-1.6.0\n anaconda-1.6.1\n anaconda-1.7.0\n anaconda-1.8.0\n anaconda-1.9.0\n anaconda-1.9.1\n anaconda-1.9.2\n anaconda-2.0.0\n anaconda-2.0.1\n anaconda-2.1.0\n anaconda-2.2.0\n anaconda-2.3.0\n anaconda-2.4.0\n anaconda-4.0.0\n anaconda2-2.4.0\n anaconda2-2.4.1\n anaconda2-2.5.0\n anaconda2-4.0.0\n anaconda2-4.1.0\n anaconda2-4.1.1\n anaconda2-4.2.0\n anaconda2-4.3.0\n anaconda2-4.3.1\n anaconda2-4.4.0\n anaconda2-5.0.0\n anaconda2-5.0.1\n anaconda2-5.1.0\n anaconda2-5.2.0\n anaconda2-5.3.0\n anaconda2-5.3.1\n anaconda2-2018.12\n anaconda2-2019.03\n anaconda2-2019.07\n anaconda3-2.0.0\n anaconda3-2.0.1\n anaconda3-2.1.0\n anaconda3-2.2.0\n anaconda3-2.3.0\n anaconda3-2.4.0\n anaconda3-2.4.1\n anaconda3-2.5.0\n anaconda3-4.0.0\n anaconda3-4.1.0\n anaconda3-4.1.1\n anaconda3-4.2.0\n anaconda3-4.3.0\n anaconda3-4.3.1\n anaconda3-4.4.0\n anaconda3-5.0.0\n anaconda3-5.0.1\n anaconda3-5.1.0\n anaconda3-5.2.0\n anaconda3-5.3.0\n anaconda3-5.3.1\n anaconda3-2018.12\n anaconda3-2019.03\n anaconda3-2019.07\n anaconda3-2019.10\n anaconda3-2020.02\n anaconda3-2020.07\n anaconda3-2020.11\n anaconda3-2021.05\n anaconda3-2021.11\n graalpython-20.1.0\n graalpython-20.2.0\n graalpython-20.3.0\n graalpython-21.0.0\n graalpython-21.1.0\n graalpython-21.2.0\n graalpython-21.3.0\n ironpython-dev\n ironpython-2.7.4\n ironpython-2.7.5\n ironpython-2.7.6.3\n ironpython-2.7.7\n jython-dev\n jython-2.5.0\n jython-2.5-dev\n jython-2.5.1\n jython-2.5.2\n jython-2.5.3\n jython-2.5.4-rc1\n jython-2.7.0\n jython-2.7.1\n jython-2.7.2\n mambaforge-pypy3\n mambaforge\n mambaforge-4.10.1-4\n mambaforge-4.10.1-5\n mambaforge-4.10.3-10\n micropython-dev\n micropython-1.9.3\n micropython-1.9.4\n micropython-1.10\n micropython-1.11\n micropython-1.12\n micropython-1.13\n micropython-1.14\n micropython-1.15\n micropython-1.16\n micropython-1.17\n miniconda-latest\n miniconda-2.2.2\n miniconda-3.0.0\n miniconda-3.0.4\n miniconda-3.0.5\n miniconda-3.3.0\n miniconda-3.4.2\n miniconda-3.7.0\n miniconda-3.8.3\n miniconda-3.9.1\n miniconda-3.10.1\n miniconda-3.16.0\n miniconda-3.18.3\n miniconda2-latest\n miniconda2-2.7-4.8.3\n miniconda2-3.18.3\n miniconda2-3.19.0\n miniconda2-4.0.5\n miniconda2-4.1.11\n miniconda2-4.3.14\n miniconda2-4.3.21\n miniconda2-4.3.27\n miniconda2-4.3.30\n miniconda2-4.3.31\n miniconda2-4.4.10\n miniconda2-4.5.1\n miniconda2-4.5.4\n miniconda2-4.5.11\n miniconda2-4.5.12\n miniconda2-4.6.14\n miniconda2-4.7.10\n miniconda2-4.7.12\n miniconda3-latest\n miniconda3-2.2.2\n miniconda3-3.0.0\n miniconda3-3.0.4\n miniconda3-3.0.5\n miniconda3-3.3.0\n miniconda3-3.4.2\n miniconda3-3.7.0\n miniconda3-3.7-4.8.2\n miniconda3-3.7-4.8.3\n miniconda3-3.7-4.9.2\n miniconda3-3.7-4.10.3\n miniconda3-3.8.3\n miniconda3-3.8-4.8.2\n miniconda3-3.8-4.8.3\n miniconda3-3.8-4.9.2\n miniconda3-3.8-4.10.3\n miniconda3-3.9.1\n miniconda3-3.9-4.9.2\n miniconda3-3.9-4.10.3\n miniconda3-3.10.1\n miniconda3-3.16.0\n miniconda3-3.18.3\n miniconda3-3.19.0\n miniconda3-4.0.5\n miniconda3-4.1.11\n miniconda3-4.2.12\n miniconda3-4.3.11\n miniconda3-4.3.14\n miniconda3-4.3.21\n miniconda3-4.3.27\n miniconda3-4.3.30\n miniconda3-4.3.31\n miniconda3-4.4.10\n miniconda3-4.5.1\n miniconda3-4.5.4\n miniconda3-4.5.11\n miniconda3-4.5.12\n miniconda3-4.6.14\n miniconda3-4.7.10\n miniconda3-4.7.12\n miniforge-pypy3\n miniforge3\n miniforge3-4.9.2\n miniforge3-4.10\n miniforge3-4.10.1-1\n miniforge3-4.10.1-3\n miniforge3-4.10.1-5\n miniforge3-4.10.3-10\n pypy-c-jit-latest\n pypy-dev\n pypy-stm-2.3\n pypy-stm-2.5.1\n pypy-1.5-src\n pypy-1.6\n pypy-1.7\n pypy-1.8\n pypy-1.9\n pypy-2.0-src\n pypy-2.0\n pypy-2.0.1-src\n pypy-2.0.1\n pypy-2.0.2-src\n pypy-2.0.2\n pypy-2.1-src\n pypy-2.1\n pypy-2.2-src\n pypy-2.2\n pypy-2.2.1-src\n pypy-2.2.1\n pypy-2.3-src\n pypy-2.3\n pypy-2.3.1-src\n pypy-2.3.1\n pypy-2.4.0-src\n pypy-2.4.0\n pypy-2.5.0-src\n pypy-2.5.0\n pypy-2.5.1-src\n pypy-2.5.1\n pypy-2.6.0-src\n pypy-2.6.0\n pypy-2.6.1-src\n pypy-2.6.1\n pypy-4.0.0-src\n pypy-4.0.0\n pypy-4.0.1-src\n pypy-4.0.1\n pypy-5.0.0-src\n pypy-5.0.0\n pypy-5.0.1-src\n pypy-5.0.1\n pypy-5.1-src\n pypy-5.1\n pypy-5.1.1-src\n pypy-5.1.1\n pypy-5.3-src\n pypy-5.3\n pypy-5.3.1-src\n pypy-5.3.1\n pypy-5.4-src\n pypy-5.4\n pypy-5.4.1-src\n pypy-5.4.1\n pypy-5.6.0-src\n pypy-5.6.0\n pypy-5.7.0-src\n pypy-5.7.0\n pypy-5.7.1-src\n pypy-5.7.1\n pypy2-5.3-src\n pypy2-5.3\n pypy2-5.3.1-src\n pypy2-5.3.1\n pypy2-5.4-src\n pypy2-5.4\n pypy2-5.4.1-src\n pypy2-5.4.1\n pypy2-5.6.0-src\n pypy2-5.6.0\n pypy2-5.7.0-src\n pypy2-5.7.0\n pypy2-5.7.1-src\n pypy2-5.7.1\n pypy2.7-5.8.0-src\n pypy2.7-5.8.0\n pypy2.7-5.9.0-src\n pypy2.7-5.9.0\n pypy2.7-5.10.0-src\n pypy2.7-5.10.0\n pypy2.7-6.0.0-src\n pypy2.7-6.0.0\n pypy2.7-7.0.0-src\n pypy2.7-7.0.0\n pypy2.7-7.1.0-src\n pypy2.7-7.1.0\n pypy2.7-7.1.1-src\n pypy2.7-7.1.1\n pypy2.7-7.2.0-src\n pypy2.7-7.2.0\n pypy2.7-7.3.0-src\n pypy2.7-7.3.0\n pypy2.7-7.3.1-src\n pypy2.7-7.3.1\n pypy2.7-7.3.2-src\n pypy2.7-7.3.2\n pypy2.7-7.3.3-src\n pypy2.7-7.3.3\n pypy2.7-7.3.4-src\n pypy2.7-7.3.4\n pypy2.7-7.3.5-src\n pypy2.7-7.3.5\n pypy2.7-7.3.6-src\n pypy2.7-7.3.6\n pypy3-2.3.1-src\n pypy3-2.3.1\n pypy3-2.4.0-src\n pypy3-2.4.0\n pypy3.3-5.2-alpha1-src\n pypy3.3-5.2-alpha1\n pypy3.3-5.5-alpha-src\n pypy3.3-5.5-alpha\n pypy3.5-c-jit-latest\n pypy3.5-5.7-beta-src\n pypy3.5-5.7-beta\n pypy3.5-5.7.1-beta-src\n pypy3.5-5.7.1-beta\n pypy3.5-5.8.0-src\n pypy3.5-5.8.0\n pypy3.5-5.9.0-src\n pypy3.5-5.9.0\n pypy3.5-5.10.0-src\n pypy3.5-5.10.0\n pypy3.5-5.10.1-src\n pypy3.5-5.10.1\n pypy3.5-6.0.0-src\n pypy3.5-6.0.0\n pypy3.5-7.0.0-src\n pypy3.5-7.0.0\n pypy3.6-7.0.0-src\n pypy3.6-7.0.0\n pypy3.6-7.1.0-src\n pypy3.6-7.1.0\n pypy3.6-7.1.1-src\n pypy3.6-7.1.1\n pypy3.6-7.2.0-src\n pypy3.6-7.2.0\n pypy3.6-7.3.0-src\n pypy3.6-7.3.0\n pypy3.6-7.3.1-src\n pypy3.6-7.3.1\n pypy3.6-7.3.2-src\n pypy3.6-7.3.2\n pypy3.6-7.3.3-src\n pypy3.6-7.3.3\n pypy3.7-c-jit-latest\n pypy3.7-7.3.2-src\n pypy3.7-7.3.2\n pypy3.7-7.3.3-src\n pypy3.7-7.3.3\n pypy3.7-7.3.4-src\n pypy3.7-7.3.4\n pypy3.7-7.3.5-src\n pypy3.7-7.3.5\n pypy3.7-7.3.6-src\n pypy3.7-7.3.6\n pypy3.7-7.3.7-src\n pypy3.7-7.3.7\n pypy3.8-7.3.6-src\n pypy3.8-7.3.6\n pypy3.8-7.3.7-src\n pypy3.8-7.3.7\n pyston-2.2\n pyston-2.3\n pyston-2.3.1\n stackless-dev\n stackless-2.7-dev\n stackless-2.7.2\n stackless-2.7.3\n stackless-2.7.4\n stackless-2.7.5\n stackless-2.7.6\n stackless-2.7.7\n stackless-2.7.8\n stackless-2.7.9\n stackless-2.7.10\n stackless-2.7.11\n stackless-2.7.12\n stackless-2.7.14\n stackless-2.7.16\n stackless-3.2.2\n stackless-3.2.5\n stackless-3.3.5\n stackless-3.3.7\n stackless-3.4-dev\n stackless-3.4.2\n stackless-3.4.7\n stackless-3.5.4\n stackless-3.7.5\n",
"pyenv versions --bare": "2.7.18\n3.10.0\n3.10.1\n3.11.0a2\n3.11.0a3\n3.11.0a4\n3.5.10\n3.6.15\n3.7.12\n3.8.12\n3.9.10\n3.9.9\npypy3.8-7.3.7\n",
"pyenv global": "3.10.1\n3.9.9\n3.8.12\n3.7.12\n3.6.15\n3.5.10\n2.7.18\n3.11.0a3\npypy3.8-7.3.7\nsystem\n"
}
import shlex
from functools import total_ordering
from itertools import groupby
from operator import attrgetter
from subprocess import check_output
import funcy
from packaging.version import Version, parse, InvalidVersion
CMD_LIST_AVAILABLE = "pyenv install --list --bare"
CMD_GLOBAL = "pyenv global"
CMD_LIST_INSTALLED = "pyenv versions --bare"
def get_output(cmd):
return check_output(shlex.split(cmd), encoding="utf-8")
def get_outputs(cmd):
return get_output(cmd).splitlines()
def get_versions(cmd):
return [PyVersion(version) for version in get_outputs(cmd) if ":" not in version]
@total_ordering
class PyVersion:
def __init__(self, original_version):
# keep original because Version is not round-trip safe: .dev becomes .dev0
self.original_version = original_version.strip()
try:
self.version = parse(self.original_version)
except InvalidVersion:
self.version = '-'
self.is_cpython = False
else:
# non cpythons like jython, pypy etc, will have versions
# if type `LegacyVersion`.
self.is_cpython = isinstance(self.version, Version)
if not self.is_cpython:
try:
self.version = parse(self.original_version.partition("-")[2])
except InvalidVersion:
self.version = Version('0.0.0')
self.implementation = (
"" if self.is_cpython else self.original_version.split("-")[0]
)
# i.e. 3.7 3.6 3.5 3.4 3.9-dev 3.8-dev when reversed
self.sort_val = (
self.is_cpython,
(self.version.dev is None),
(self.version.pre is None),
self.version,
)
def __lt__(self, other):
return self.sort_val < other.sort_val
def __eq__(self, other):
return self.version == other.version
def __str__(self):
return str(self.original_version)
def get_cpython_versions():
for version in get_versions(CMD_LIST_AVAILABLE):
if version.is_cpython:
yield version
def get_major_minor(version):
if version.implementation:
return version.implementation, version.version.release
return version.version.release[:2]
def get_latests(versions):
versions = sorted(get_cpython_versions(), key=attrgetter("version"), reverse=True)
for major_minor, patches in groupby(versions, get_major_minor):
if major_minor == (2, 7) or major_minor >= (3, 6):
yield max(patches)
def print_global_set(versions):
versions = list(versions)
versions_str = " ".join([v.original_version for v in versions])
print(f"\tpyenv global {versions_str}")
def main():
versions_available = get_cpython_versions()
# latest version for each minor release
latests = sorted(get_latests(versions_available), reverse=True)
installed = get_versions(CMD_LIST_INSTALLED)
global_order = get_versions(CMD_GLOBAL)
gots = []
needs = []
not_in_globals = []
for max_patch in latests:
if max_patch in installed:
if max_patch not in global_order:
not_in_globals.append(max_patch)
gots.append(max_patch)
else:
needs.append(max_patch)
print("Current:")
print_global_set(global_order)
print()
if not_in_globals:
print("Use latest installed versions:")
def get_latest_globals(current, new):
grouped = funcy.group_by(get_major_minor, [*current, *new]).values()
for patches in grouped:
yield max(patches)
latest_globals = get_latest_globals(global_order, not_in_globals)
print_global_set(latest_globals)
print()
if needs:
print("After new installs:")
non_cpython = [v for v in global_order if not v.is_cpython]
print_global_set([*latests, *non_cpython])
print()
print("Need:")
print(
"; \\\n".join(f"\tpyenv install --skip-existing {need}" for need in needs)
)
print()
if gots:
print("Got latest:")
for got in gots:
print(f"\t{got}")
print()
if not needs:
print("All latest versions found.")
if __name__ == "__main__":
main()
packaging
funcy
colorama
pytest
black
isort
import shlex
from itertools import groupby
from pathlib import Path
from subprocess import check_output
from colorama import Back, Style, init
from packaging.version import Version, parse
CMD_ROOT = "pyenv root"
CMD_VERSIONS = "pyenv versions --bare"
def get_output(cmd):
return check_output(shlex.split(cmd), encoding="utf-8")
def get_outputs(cmd):
return get_output(cmd).splitlines()
def get_major_minor(version):
if "pypy" in str(version):
return "pypy", str(version).replace("pypy", "").split("-")[0]
if not isinstance(version, Version):
version = parse(version)
return version.release[:2]
def group_versions(versions):
vs = [parse(version) for version in versions]
vs.sort()
for (major, minor), patches in groupby(vs, get_major_minor):
print(f"{major}.{minor}")
for v in sorted(patches):
yield str(v)
def main():
init()
root = get_outputs(CMD_ROOT)[0]
installed = get_outputs(CMD_VERSIONS)
for version in group_versions(installed):
path = Path(root) / "versions" / version / "bin/python"
cmd = "import platform; print(platform.machine())"
platform = get_output(f'{path} -c "{cmd}"').strip()
if platform == "x86_64":
platform = f"{Back.RED}{platform}"
elif platform == "arm64":
platform = f"{Back.GREEN}{platform}"
else:
platform = f"{Back.YELLOW}{platform}"
print("\t", version, platform, Style.RESET_ALL)
if __name__ == "__main__":
main()
import json
import sys
from contextlib import contextmanager
from unittest.mock import patch
import pytest
import latest_python_versions
CMD_RECORD_FILEPATH = "cmd-record.json"
orig_get_output = latest_python_versions.get_output
@contextmanager
def recorder():
history = {}
def record(cmd):
output = orig_get_output(cmd)
history[cmd] = output
return output
yield record
json.dump(history, open(CMD_RECORD_FILEPATH, "w"), indent=4)
@contextmanager
def player():
history = json.load(open(CMD_RECORD_FILEPATH))
def play(cmd):
return history.pop(cmd)
yield play
if history:
raise RuntimeError(f'cmd(s) missed: {", ".join(history)}')
@pytest.fixture
def fake_command_output():
with player() as play:
with patch.object(latest_python_versions, "get_output", play):
yield
@contextmanager
def record_command_output():
with recorder() as record:
with patch.object(latest_python_versions, "get_output", record):
yield
def test_main(fake_command_output, capsys):
latest_python_versions.main()
out, err = capsys.readouterr()
assert out == (
"Current:\n"
"\tpyenv global 3.10.1 3.9.9 3.8.12 3.7.12 3.6.15 3.5.10 2.7.18 "
"3.11.0a3 pypy3.8-7.3.7 system\n"
"\n"
"Use latest installed versions:\n"
"\tpyenv global 3.10.1 3.9.10 3.8.12 3.7.12 3.6.15 3.5.10 2.7.18 "
"3.11.0a4 pypy3.8-7.3.7 system\n"
"\n"
"After new installs:\n"
"\tpyenv global 3.10.2 3.9.10 3.8.12 3.7.12 3.6.15 3.5.10 2.7.18 "
"3.11.0a4 pypy3.8-7.3.7 system\n"
"\n"
"Need:\n"
"\tpyenv install --skip-existing 3.10.2\n"
"\n"
"Got latest:\n"
"\t3.9.10\n"
"\t3.8.12\n"
"\t3.7.12\n"
"\t3.6.15\n"
"\t3.5.10\n"
"\t2.7.18\n"
"\t3.11.0a4\n"
"\n"
)
assert not err
if __name__ == "__main__":
if sys.argv[1:2] == ["RECORD"]:
with record_command_output():
latest_python_versions.main()
pushd ~/.pyenv
git pull
popd
~/.virtualenvs/latest_python_versions/bin/python latest_python_versions.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment