Skip to content

Winding down for 2025

I have completed my 6,000 km distance goal for cycling, so I will focus on other activities such as walking and yoga. I aim to get into a rhythm of 3 yoga sessions a week, which will stretch my muscles and help with my breathing.

jr0cket Domainλ︎

The jr0cket domain has been renewed for 2 years.

I use the jr0cket domain for personal work, keeping the Practicalli domain focused on meaningful work projects (commercial and open source).

Domain renewal is supported by the money I earned from User Crowd UI/UX testing feedback.

Zensicalλ︎

Material for MkDocs project is now in maintenance mode and the maintainers started a new project from scratch. The new project is called Zensical and resolves design decisions that were entrenched in the Material for MkDocs project.

Zensical also combines Rust and Python to make a more efficient tool for generating static sites.

There is still some work to bring parity of features to Zensical (especially adding blog support), although for books the current feature set should be sufficient.

I am taking one of the less mature books, Practicalli Sustainable Life, and creating a new Zensical project. There are a lot of detailed tickets for this book, so it will give me a chance to give Zensical a meaninful test run.

I plan to use 'uv' python package manger over the traditional 'pip' tool. uv seems simpler to use and install, even though Debian Linux has not yet packaged uv.

Install via scriptλ︎

Download the install script with 'curl' and run the script to install in .local/share

curl -LsSf https://astral.sh/uv/install.sh | sh
❯ curl -LsSf https://astral.sh/uv/install.sh | sh
downloading uv 0.9.17 x86_64-unknown-linux-gnu
no checksums to verify
installing to /home/practicalli/.local/share/../bin
  uv
  uvx
everything's installed!

To add $HOME/.local/share/../bin to your PATH, either restart your shell or run:

    source $HOME/.local/share/../bin/env (sh, bash, zsh)
    source $HOME/.local/share/../bin/env.fish (fish)
WARN: The following commands are shadowed by other commands in your PATH: uv uv

Test the installλ︎

I opened up a new terminal session in kitty and ran the uv command.

uv command help information
❯ uv
An extremely fast Python package manager.

Usage: uv [OPTIONS] <COMMAND>

Commands:
  auth     Manage authentication
  run      Run a command or script
  init     Create a new project
  add      Add dependencies to the project
  remove   Remove dependencies from the project
  version  Read or update the project's version
  sync     Update the project's environment
  lock     Update the project's lockfile
  export   Export the project's lockfile to an alternate format
  tree     Display the project's dependency tree
  format   Format Python code in the project
  tool     Run and install commands provided by Python packages
  python   Manage Python versions and installations
  pip      Manage Python packages with a pip-compatible interface
  venv     Create a virtual environment
  build    Build Python packages into source distributions and wheels
  publish  Upload distributions to an index
  cache    Manage uv's cache
  self     Manage the uv executable
  help     Display documentation for a command

Cache options:
  -n, --no-cache               Avoid reading from or writing to the cache, instead using a temporary directory for the duration
                               of the operation [env: UV_NO_CACHE=]
      --cache-dir <CACHE_DIR>  Path to the cache directory [env: UV_CACHE_DIR=]

Python options:
      --managed-python       Require use of uv-managed Python versions [env: UV_MANAGED_PYTHON=]
      --no-managed-python    Disable use of uv-managed Python versions [env: UV_NO_MANAGED_PYTHON=]
      --no-python-downloads  Disable automatic downloads of Python. [env: "UV_PYTHON_DOWNLOADS=never"]

Global options:
  -q, --quiet...
          Use quiet output
  -v, --verbose...
          Use verbose output
      --color <COLOR_CHOICE>
          Control the use of color in output [possible values: auto, always, never]
      --native-tls
          Whether to load TLS certificates from the platform's native certificate store [env: UV_NATIVE_TLS=]
      --offline
          Disable network access [env: UV_OFFLINE=]
      --allow-insecure-host <ALLOW_INSECURE_HOST>
          Allow insecure connections to a host [env: UV_INSECURE_HOST=]
      --no-progress
          Hide all progress outputs [env: UV_NO_PROGRESS=]
      --directory <DIRECTORY>
          Change to the given directory prior to running the command [env: UV_WORKING_DIR=]
      --project <PROJECT>
          Discover a project in the given directory [env: UV_PROJECT=]
      --config-file <CONFIG_FILE>
          The path to a `uv.toml` file to use for configuration [env: UV_CONFIG_FILE=]
      --no-config
          Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=]
  -h, --help
          Display the concise help for this command
  -V, --version
          Display the uv version

Use `uv help` for more details.

There is also a uvx command added, so I took a look at the help to see what it does.

uvx command help
    ❯ uvx --help
    Run a command provided by a Python package.

    Usage: uvx [OPTIONS] [COMMAND]

    Options:
          --from <FROM>                            Use the given package to provide the command
      -w, --with <WITH>                            Run with the given packages installed
          --with-editable <WITH_EDITABLE>          Run with the given packages installed in editable mode
          --with-requirements <WITH_REQUIREMENTS>  Run with the packages listed in the given files
      -c, --constraints <CONSTRAINTS>              Constrain versions using the given requirements files [env: UV_CONSTRAINT=]
      -b, --build-constraints <BUILD_CONSTRAINTS>  Constrain build dependencies using the given requirements files when building
                                                   source distributions [env: UV_BUILD_CONSTRAINT=]
          --overrides <OVERRIDES>                  Override versions using the given requirements files [env: UV_OVERRIDE=]
          --isolated                               Run the tool in an isolated virtual environment, ignoring any already-installed
                                                   tools [env: UV_ISOLATED=]
          --env-file <ENV_FILE>                    Load environment variables from a `.env` file [env: UV_ENV_FILE=]
          --no-env-file                            Avoid reading environment variables from a `.env` file [env: UV_NO_ENV_FILE=]
          --lfs                                    Whether to use Git LFS when adding a dependency from Git [env: UV_GIT_LFS=]
          --python-platform <PYTHON_PLATFORM>      The platform for which requirements should be installed [possible values:
                                                   windows, linux, macos, x86_64-pc-windows-msvc, aarch64-pc-windows-msvc,
                                                   i686-pc-windows-msvc, x86_64-unknown-linux-gnu, aarch64-apple-darwin,
                                                   x86_64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-musl,
                                                   x86_64-unknown-linux-musl, riscv64-unknown-linux, x86_64-manylinux2014,
                                                   x86_64-manylinux_2_17, x86_64-manylinux_2_28, x86_64-manylinux_2_31,
                                                   x86_64-manylinux_2_32, x86_64-manylinux_2_33, x86_64-manylinux_2_34,
                                                   x86_64-manylinux_2_35, x86_64-manylinux_2_36, x86_64-manylinux_2_37,
                                                   x86_64-manylinux_2_38, x86_64-manylinux_2_39, x86_64-manylinux_2_40,
                                                   aarch64-manylinux2014, aarch64-manylinux_2_17, aarch64-manylinux_2_28,
                                                   aarch64-manylinux_2_31, aarch64-manylinux_2_32, aarch64-manylinux_2_33,
                                                   aarch64-manylinux_2_34, aarch64-manylinux_2_35, aarch64-manylinux_2_36,
                                                   aarch64-manylinux_2_37, aarch64-manylinux_2_38, aarch64-manylinux_2_39,
                                                   aarch64-manylinux_2_40, aarch64-linux-android, x86_64-linux-android,
                                                   wasm32-pyodide2024, arm64-apple-ios, arm64-apple-ios-simulator,
                                                   x86_64-apple-ios-simulator]
      -V, --version                                Display the uvx version

    Index options:
          --index <INDEX>                        The URLs to use when resolving dependencies, in addition to the default index
                                                 [env: UV_INDEX=]
          --default-index <DEFAULT_INDEX>        The URL of the default package index (by default: <https://pypi.org/simple>) [env:
                                                 UV_DEFAULT_INDEX=]
      -i, --index-url <INDEX_URL>                (Deprecated: use `--default-index` instead) The URL of the Python package index
                                                 (by default: <https://pypi.org/simple>) [env: UV_INDEX_URL=]
          --extra-index-url <EXTRA_INDEX_URL>    (Deprecated: use `--index` instead) Extra URLs of package indexes to use, in
                                                 addition to `--index-url` [env: UV_EXTRA_INDEX_URL=]
      -f, --find-links <FIND_LINKS>              Locations to search for candidate distributions, in addition to those found in the
                                                 registry indexes [env: UV_FIND_LINKS=]
          --no-index                             Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies
                                                 and those provided via `--find-links`
          --index-strategy <INDEX_STRATEGY>      The strategy to use when resolving against multiple index URLs [env:
                                                 UV_INDEX_STRATEGY=] [possible values: first-index, unsafe-first-match,
                                                 unsafe-best-match]
          --keyring-provider <KEYRING_PROVIDER>  Attempt to use `keyring` for authentication for index URLs [env:
                                                 UV_KEYRING_PROVIDER=] [possible values: disabled, subprocess]

    Resolver options:
      -U, --upgrade
              Allow package upgrades, ignoring pinned versions in any existing output file. Implies `--refresh`
      -P, --upgrade-package <UPGRADE_PACKAGE>
              Allow upgrades for a specific package, ignoring pinned versions in any existing output file. Implies
              `--refresh-package`
          --resolution <RESOLUTION>
              The strategy to use when selecting between the different compatible versions for a given package requirement [env:
              UV_RESOLUTION=] [possible values: highest, lowest, lowest-direct]
          --prerelease <PRERELEASE>
              The strategy to use when considering pre-release versions [env: UV_PRERELEASE=] [possible values: disallow, allow,
              if-necessary, explicit, if-necessary-or-explicit]
          --fork-strategy <FORK_STRATEGY>
              The strategy to use when selecting multiple versions of a given package across Python versions and platforms [env:
              UV_FORK_STRATEGY=] [possible values: fewest, requires-python]
          --exclude-newer <EXCLUDE_NEWER>
              Limit candidate packages to those that were uploaded prior to the given date [env: UV_EXCLUDE_NEWER=]
          --exclude-newer-package <EXCLUDE_NEWER_PACKAGE>
              Limit candidate packages for specific packages to those that were uploaded prior to the given date
          --no-sources
              Ignore the `tool.uv.sources` table when resolving dependencies. Used to lock against the standards-compliant,
              publishable package metadata, as opposed to using any workspace, Git, URL, or local path sources [env:
              UV_NO_SOURCES=]

    Installer options:
          --reinstall                              Reinstall all packages, regardless of whether they're already installed. Implies
                                                   `--refresh`
          --reinstall-package <REINSTALL_PACKAGE>  Reinstall a specific package, regardless of whether it's already installed.
                                                   Implies `--refresh-package`
          --link-mode <LINK_MODE>                  The method to use when installing packages from the global cache [env:
                                                   UV_LINK_MODE=] [possible values: clone, copy, hardlink, symlink]
          --compile-bytecode                       Compile Python files to bytecode after installation [env: UV_COMPILE_BYTECODE=]

    Build options:
      -C, --config-setting <CONFIG_SETTING>
              Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs
          --config-settings-package <CONFIG_SETTINGS_PACKAGE>
              Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs
          --no-build-isolation
              Disable isolation when building source distributions [env: UV_NO_BUILD_ISOLATION=]
          --no-build-isolation-package <NO_BUILD_ISOLATION_PACKAGE>
              Disable isolation when building source distributions for a specific package
          --no-build
              Don't build source distributions [env: UV_NO_BUILD=]
          --no-build-package <NO_BUILD_PACKAGE>
              Don't build source distributions for a specific package [env: UV_NO_BUILD_PACKAGE=]
          --no-binary
              Don't install pre-built wheels [env: UV_NO_BINARY=]
          --no-binary-package <NO_BINARY_PACKAGE>
              Don't install pre-built wheels for a specific package [env: UV_NO_BINARY_PACKAGE=]

    Cache options:
      -n, --no-cache                           Avoid reading from or writing to the cache, instead using a temporary directory for
                                               the duration of the operation [env: UV_NO_CACHE=]
          --cache-dir <CACHE_DIR>              Path to the cache directory [env: UV_CACHE_DIR=]
          --refresh                            Refresh all cached data
          --refresh-package <REFRESH_PACKAGE>  Refresh cached data for a specific package

    Python options:
      -p, --python <PYTHON>      The Python interpreter to use to build the run environment. [env: UV_PYTHON=]
          --managed-python       Require use of uv-managed Python versions [env: UV_MANAGED_PYTHON=]
          --no-managed-python    Disable use of uv-managed Python versions [env: UV_NO_MANAGED_PYTHON=]
          --no-python-downloads  Disable automatic downloads of Python. [env: "UV_PYTHON_DOWNLOADS=never"]

    Global options:
      -q, --quiet...
              Use quiet output
      -v, --verbose...
              Use verbose output
          --color <COLOR_CHOICE>
              Control the use of color in output [possible values: auto, always, never]
          --native-tls
              Whether to load TLS certificates from the platform's native certificate store [env: UV_NATIVE_TLS=]
          --offline
              Disable network access [env: UV_OFFLINE=]
          --allow-insecure-host <ALLOW_INSECURE_HOST>
              Allow insecure connections to a host [env: UV_INSECURE_HOST=]
          --no-progress
              Hide all progress outputs [env: UV_NO_PROGRESS=]
          --directory <DIRECTORY>
              Change to the given directory prior to running the command [env: UV_WORKING_DIR=]
          --project <PROJECT>
              Discover a project in the given directory [env: UV_PROJECT=]
          --config-file <CONFIG_FILE>
              The path to a `uv.toml` file to use for configuration [env: UV_CONFIG_FILE=]
          --no-config
              Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=]
      -h, --help
              Display the concise help for this command

    Use `uv help tool run` for more details.
    ```

### zsh shell completion

Add tab completion for uv to the Zsh resource configuration file.

```shell
echo 'eval "$(uv generate-shell-completion zsh)"' >> ~/.zshrc

I have my .zshrc in a different location (location set by a ~/.zshenv configuration file).

Configure zsh tab completion for uv - Practicalli setup

echo 'eval "$(uv generate-shell-completion zsh)"' >> ~/.config/zsh/.zshrc

Managing Python versionλ︎

uv can install a python version and also shows what is currently available, even when not installed via uv.

Which Python versions are available?
❯ uv python list
cpython-3.15.0a2-linux-x86_64-gnu                 <download available>
cpython-3.15.0a2+freethreaded-linux-x86_64-gnu    <download available>
cpython-3.14.2-linux-x86_64-gnu                   <download available>
cpython-3.14.2+freethreaded-linux-x86_64-gnu      <download available>
cpython-3.13.11-linux-x86_64-gnu                  <download available>
cpython-3.13.11+freethreaded-linux-x86_64-gnu     <download available>
cpython-3.13.5-linux-x86_64-gnu                   /usr/bin/python3.13
cpython-3.13.5-linux-x86_64-gnu                   /usr/bin/python3 -> python3.13
cpython-3.12.12-linux-x86_64-gnu                  <download available>
cpython-3.11.14-linux-x86_64-gnu                  <download available>
cpython-3.10.19-linux-x86_64-gnu                  <download available>
cpython-3.9.25-linux-x86_64-gnu                   <download available>
cpython-3.8.20-linux-x86_64-gnu                   <download available>
pypy-3.11.13-linux-x86_64-gnu                     <download available>
pypy-3.10.16-linux-x86_64-gnu                     <download available>
pypy-3.9.19-linux-x86_64-gnu                      <download available>
pypy-3.8.16-linux-x86_64-gnu                      <download available>
graalpy-3.12.0-linux-x86_64-gnu                   <download available>
graalpy-3.11.0-linux-x86_64-gnu                   <download available>
graalpy-3.10.0-linux-x86_64-gnu                   <download available>
graalpy-3.8.5-linux-x86_64-gnu                    <download available>

zensical installλ︎

Although the Zensical docs include Initialise a Python virtual environment and adding the Zensical package, this may be unnecessary if using uvx.

Creating the virtual environment and adding the zensical package seems to create a python project that is not required for the specific zensical project.

Initialise Python project with uv

uv init
Command Output
 ~/projects/practicalli/book-zensical/sustainable-life  ❯ uv init

Initialized project `sustainable-life`

 …/sustainable-life   v3.13.5   main ?  ❯ ls -a
.  ..  .git  .gitignore  main.py  pyproject.toml  .python-version  README.md

Add zensical with uv

uv add zensical
Command Output
❯ uv add zensical

Using CPython 3.13.5 interpreter at: /usr/bin/python3.13
Creating virtual environment at: .venv
Resolved 9 packages in 12ms
Installed 7 packages in 408ms
 + click==8.3.1
 + deepmerge==2.0
 + markdown==3.10
 + pygments==2.19.2
 + pymdown-extensions==10.19
 + pyyaml==6.0.3
 + zensical==0.0.11

Python Project config with Zensical

[project]
name = "sustainable-life"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "zensical>=0.0.11",
]

Create Zensical siteλ︎

Use UVX to run zensical new

uvx zensical new .

Cyclingλ︎

A 90mm carbon stem I bought from AliExpress for the Bianchi bike turned out to be faulty. The bolts at the bottom of the stem were protruding, preventing the stem gripping the handlebars sufficiently.

AliExpress has a 90 day returns policy, far better than the 30 days from Amazon. Luckily the stem was still in the returns window and there was a clear case for return.

I didnt need to return any other items from that specific order, so AliExpress cover the cost of the postage and I get a full return.

NOTE: if an item is less than a certain price (around 5 GBP I think), then AliExpress will give a refund without needing to return.


Thank you.

🌐 Practical.li Website

Practical.li GitHub Org practicalli-johnny profile

@practicalli@clj.social @practical_li