From da1cbfbc0d5ac391dcaceafad09d51b441903129 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Mon, 3 Aug 2026 04:00:21 +0200 Subject: [PATCH] Add configuration for `python` --- .config/bpython/README.md | 5 ++++ .config/bpython/config | 8 ++++++ .config/git/ignore | 8 ++++++ .config/pypoetry/README.md | 5 ++++ .config/pypoetry/config.toml | 9 ++++++ .config/python/README.md | 6 ++++ .config/python/startup.py | 54 ++++++++++++++++++++++++++++++++++++ .config/shell/aliases | 26 +++++++++++++++++ .config/shell/env | 4 +++ .local/state/python/.gitkeep | 0 .profile | 21 ++++++++++++++ 11 files changed, 146 insertions(+) create mode 100644 .config/bpython/README.md create mode 100644 .config/bpython/config create mode 100644 .config/pypoetry/README.md create mode 100644 .config/pypoetry/config.toml create mode 100644 .config/python/README.md create mode 100644 .config/python/startup.py create mode 100644 .local/state/python/.gitkeep diff --git a/.config/bpython/README.md b/.config/bpython/README.md new file mode 100644 index 0000000..3943149 --- /dev/null +++ b/.config/bpython/README.md @@ -0,0 +1,5 @@ +# `bpython`-related Configurations + +This folder contains + the [config](./config) + for the [`bpython`](https://github.com/bpython/bpython) interpreter. diff --git a/.config/bpython/config b/.config/bpython/config new file mode 100644 index 0000000..cc6f7ab --- /dev/null +++ b/.config/bpython/config @@ -0,0 +1,8 @@ +[general] + +# Make `bpython` and `python` share their history +# (Note: `$XDG_STATE_HOME` is not expanded) +hist_file = ~/.local/state/python/history + +# No limit +hist_length = 999999 diff --git a/.config/git/ignore b/.config/git/ignore index a0ed808..5e96e2b 100644 --- a/.config/git/ignore +++ b/.config/git/ignore @@ -4,3 +4,11 @@ *.orig *.temp *.tmp + +# Python +__pycache__/ +*.py[cod] +.python-version +.venv/ +venv/ +.env diff --git a/.config/pypoetry/README.md b/.config/pypoetry/README.md new file mode 100644 index 0000000..22a2a45 --- /dev/null +++ b/.config/pypoetry/README.md @@ -0,0 +1,5 @@ +# `poetry`-related Configurations + +This folder contains + the [config](./config.toml) + for [`poetry`](https://python-poetry.org/). diff --git a/.config/pypoetry/config.toml b/.config/pypoetry/config.toml new file mode 100644 index 0000000..a815e69 --- /dev/null +++ b/.config/pypoetry/config.toml @@ -0,0 +1,9 @@ +[virtualenvs] + +create = true +in-project = true # .venv/ inside the project, not a central cache + + +[installer] + +parallel = true diff --git a/.config/python/README.md b/.config/python/README.md new file mode 100644 index 0000000..6a084e6 --- /dev/null +++ b/.config/python/README.md @@ -0,0 +1,6 @@ +# `python`-related Configurations + +This folder contains + the [interactive startup file](./startup.py) + for [Python](https://python.org/), + found via `$PYTHONSTARTUP` set in [`~/.config/shell/env`](../shell/env). diff --git a/.config/python/startup.py b/.config/python/startup.py new file mode 100644 index 0000000..1c70c26 --- /dev/null +++ b/.config/python/startup.py @@ -0,0 +1,54 @@ +"""Move Python's history file to "$XDG_STATE_HOME/python/history". + +Python 3.13+ honors the `$PYTHON_HISTORY` environment variable, +so this file is only needed for older interpreters (e.g., via `pyenv`). + +`$PYTHONSTARTUP` is executed in the REPL's own namespace +=> Everything is wrapped in a function that is deleted afterwards + to avoid polluting the prompt with temporary names +""" + +import sys + + +def _setup_history(): + if sys.version_info >= (3, 13): + return # `$PYTHON_HISTORY` handles it + + try: + import readline # because it is not in every build + except ImportError: + return + + import atexit + import os + + state_home = os.environ.get("XDG_STATE_HOME") or os.path.join( + os.path.expanduser("~"), ".local", "state" + ) + history_file = os.path.join(state_home, "python", "history") + + os.makedirs(os.path.dirname(history_file), exist_ok=True) + if os.path.isdir(history_file): + raise OSError(history_file + " must not be a directory") + + try: + readline.read_history_file(history_file) + except OSError: # History file does not exist yet or is unreadable + pass + + readline.set_auto_history(True) + readline.set_history_length(999999) + + def write_history(): + try: + readline.write_history_file(history_file) + except OSError: + pass + + atexit.register(write_history) # Keep a reference to `write_history` + + +_setup_history() + +del _setup_history diff --git a/.config/shell/aliases b/.config/shell/aliases index 83e61f8..cf6fe17 100644 --- a/.config/shell/aliases +++ b/.config/shell/aliases @@ -97,3 +97,29 @@ if _command_exists git; then esac fi + + + +alias py='python3' + +ipy() { + if _command_exists ipython; then + ipython "$@" + elif _command_exists ipython3; then + ipython3 "$@" + else + echo "ipython is not installed" >&2 + return 1 + fi +} + +_command_exists poetry && alias pr='poetry run' + +if _command_exists pyenv; then + + alias pyvenvs='pyenv virtualenvs --bare --skip-aliases' + alias pyver='pyenv version' + alias pyvers='pyenv versions --skip-aliases' + alias pywhich='pyenv which' + +fi diff --git a/.config/shell/env b/.config/shell/env index 7f9cb4a..d6a75fd 100644 --- a/.config/shell/env +++ b/.config/shell/env @@ -63,3 +63,7 @@ unset _bat export BAT_CONFIG_PATH="$XDG_CONFIG_HOME/bat/config" export LESSHISTFILE="$XDG_STATE_HOME/less/history" export PSQLRC="$XDG_CONFIG_HOME/psql/psqlrc" +export PYENV_ROOT="$XDG_DATA_HOME/pyenv" +export PYTHONPYCACHEPREFIX="$XDG_CACHE_HOME/python" +export PYTHONSTARTUP="$XDG_CONFIG_HOME/python/startup.py" +export PYTHON_HISTORY="$XDG_STATE_HOME/python/history" diff --git a/.local/state/python/.gitkeep b/.local/state/python/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.profile b/.profile index f068260..981a579 100644 --- a/.profile +++ b/.profile @@ -74,6 +74,12 @@ _prepend_to_path "$HOME/.local/bin" [ -f "$HOME/.config/shell/env" ] && . "$HOME/.config/shell/env" +# Must be between sourcing ~/.config/shell/env and ~/.config/shell/aliases +# because the first defines the `pyenv` related environment variables +# while the second creates `pyenv` related aliases +[ -n "${PYENV_ROOT:-}" ] && _prepend_to_path "$PYENV_ROOT/bin" + + [ -f "$HOME/.config/shell/aliases" ] && . "$HOME/.config/shell/aliases" @@ -91,5 +97,20 @@ fi # which then also ensures that this file is sourced +if [ -z "${PYENV_SHELL:-}" ] && _command_exists pyenv; then + + eval "$(pyenv init -)" || echo "WARN: pyenv init failed" >&2 + + case $- in + *i*) + if [ -d "$PYENV_ROOT/plugins/pyenv-virtualenv" ]; then + eval "$(pyenv virtualenv-init -)" || true + fi + ;; + esac + +fi + + # When everything is loaded, show a little welcome message case $- in *i*) [ -f "$HOME/.config/shell/welcome" ] && . "$HOME/.config/shell/welcome";; esac