diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index e09c6408..a0744cbc 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -65,7 +65,7 @@ jobs: # FIXME ? # os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest] - python-version: ["3.8", "3.9", "3.11", "3.12", "3.13", "pypy3.10"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "pypy3.10"] steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 011e6da4..92e53298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ Features: Refactoring: -- None +- `[dev]` Python 3.14 Default Development Target +- `[dev]` Remove Support for Python 3.8 (EOL) Misc: diff --git a/Dockerfile b/Dockerfile index 4dc633c3..c4e13e11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.13-alpine +FROM python:3.14-alpine LABEL MAINTAINER="BJ Dierkes " ENV PS1="\[\e[0;33m\]|> cement <| \[\e[1;35m\]\W\[\e[0m\] \[\e[0m\]# " ENV PATH="${PATH}:/root/.local/bin" diff --git a/Makefile b/Makefile index 300f7623..fe013063 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,11 @@ dev: docker compose up -d docker compose exec cement pdm install - docker compose exec cement-py38 pdm install docker compose exec cement-py39 pdm install docker compose exec cement-py310 pdm install docker compose exec cement-py311 pdm install docker compose exec cement-py312 pdm install + docker compose exec cement-py313 pdm install docker compose exec cement /bin/bash test: comply diff --git a/README.md b/README.md index 83346ed3..78afe916 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Cement core features include (but are not limited to): - 100% PEP8 compliance (`ruff`) - Type annotation compliance (`mypy`) - Extensive API Reference (`sphinx`) -- Tested on Python 3.8+ +- Tested on Python 3.9+ ## Optional Extensions @@ -92,17 +92,17 @@ All execution is done *inside the docker containers*. **Testing Alternative Versions of Python** -The latest stable version of Python 3 is the default, and target version accessible as the `cement` container within Docker Compose. For testing against alternative versions of python, additional containers are created (ex: `cement-py38`, `cement-py39`, etc). You can access these containers via: +The latest stable version of Python 3 is the default, and target version accessible as the `cement` container within Docker Compose. For testing against alternative versions of python, additional containers are created (ex: `cement-py39`, `cement-py310`, etc). You can access these containers via: ``` $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------- -cement_cement-py38_1 /bin/bash Up cement_cement-py39_1 /bin/bash Up cement_cement-py310_1 /bin/bash Up cement_cement-py311_1 /bin/bash Up cement_cement-py312_1 /bin/bash Up +cement_cement-py313_1 /bin/bash Up cement_cement_1 /bin/bash Up cement_memcached_1 docker-entrypoint.sh memcached Up 11211/tcp cement_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp diff --git a/cement/ext/ext_plugin.py b/cement/ext/ext_plugin.py index 701859ee..efdbe91e 100644 --- a/cement/ext/ext_plugin.py +++ b/cement/ext/ext_plugin.py @@ -5,7 +5,6 @@ Cement plugin extension module. from __future__ import annotations import os import sys -import importlib import importlib.util import importlib.machinery import re diff --git a/devbox.json b/devbox.json index 51c65de8..d90ec690 100644 --- a/devbox.json +++ b/devbox.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.14.0/.schema/devbox.schema.json", "packages": { - "python": "3.13", + "python": "3.14", "pdm": "latest", "libmemcached": "latest", "zlib": { diff --git a/devbox.lock b/devbox.lock index 8b84fadc..02a965e4 100644 --- a/devbox.lock +++ b/devbox.lock @@ -212,60 +212,60 @@ } } }, - "python@3.13": { - "last_modified": "2025-05-16T20:19:48Z", + "python@3.14": { + "last_modified": "2025-10-08T01:30:28Z", "plugin_version": "0.0.4", - "resolved": "github:NixOS/nixpkgs/12a55407652e04dcf2309436eb06fef0d3713ef3#python313", + "resolved": "github:NixOS/nixpkgs/8b5c9dd8856f0c0cf46cc91f2c21c106a9d42e25#python314", "source": "devbox-search", - "version": "3.13.3", + "version": "3.14.0", "systems": { "aarch64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/1a8xg8l3m67hxinxzzcsak9736qm9vsf-python3-3.13.3", + "path": "/nix/store/2sqv05h8017f38w5rvppb2f5wbbisnwp-python3-3.14.0", "default": true } ], - "store_path": "/nix/store/1a8xg8l3m67hxinxzzcsak9736qm9vsf-python3-3.13.3" + "store_path": "/nix/store/2sqv05h8017f38w5rvppb2f5wbbisnwp-python3-3.14.0" }, "aarch64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/yy0xvc2rydhrs0h1v8d7r3sql347xzz5-python3-3.13.3", + "path": "/nix/store/zlph3shgrkfmrhkxbgmi6qa26gfzl58q-python3-3.14.0", "default": true }, { "name": "debug", - "path": "/nix/store/42bxfqfrh8cwspl7szr0cw8739xv8qlq-python3-3.13.3-debug" + "path": "/nix/store/3zmfrpjfpqaxcl68hlg5nfzvx49awjks-python3-3.14.0-debug" } ], - "store_path": "/nix/store/yy0xvc2rydhrs0h1v8d7r3sql347xzz5-python3-3.13.3" + "store_path": "/nix/store/zlph3shgrkfmrhkxbgmi6qa26gfzl58q-python3-3.14.0" }, "x86_64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/gbrigjhghz9v2p0zf9b2fnvs0g0yx7q4-python3-3.13.3", + "path": "/nix/store/bq9ss2vlr05zdrhcfmvclm0gsrc7i6xb-python3-3.14.0", "default": true } ], - "store_path": "/nix/store/gbrigjhghz9v2p0zf9b2fnvs0g0yx7q4-python3-3.13.3" + "store_path": "/nix/store/bq9ss2vlr05zdrhcfmvclm0gsrc7i6xb-python3-3.14.0" }, "x86_64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/2mab9iiwhcqwk75qwvp3zv0bvbiaq6cs-python3-3.13.3", + "path": "/nix/store/76lchhz5hhik0j5hjy6lwwn3ik0x54aa-python3-3.14.0", "default": true }, { "name": "debug", - "path": "/nix/store/9z6k8ijl2md0y2n95yprbjj4vxbfsi15-python3-3.13.3-debug" + "path": "/nix/store/rjm597f2d9bjllyjnv3y20261bwxd108-python3-3.14.0-debug" } ], - "store_path": "/nix/store/2mab9iiwhcqwk75qwvp3zv0bvbiaq6cs-python3-3.13.3" + "store_path": "/nix/store/76lchhz5hhik0j5hjy6lwwn3ik0x54aa-python3-3.14.0" } } }, diff --git a/docker-compose.yml b/docker-compose.yml index b5e945e0..692f1bca 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -53,20 +53,13 @@ services: - memcached - mailpit - cement-py38: - <<: *DEFAULTS - image: "cement:dev-py38" - build: - context: . - dockerfile: docker/Dockerfile.dev-py38 - cement-py39: <<: *DEFAULTS image: "cement:dev-py39" build: context: . dockerfile: docker/Dockerfile.dev-py39 - + cement-py310: <<: *DEFAULTS image: "cement:dev-py310" @@ -87,3 +80,10 @@ services: build: context: . dockerfile: docker/Dockerfile.dev-py312 + + cement-py313: + <<: *DEFAULTS + image: "cement:dev-py313" + build: + context: . + dockerfile: docker/Dockerfile.dev-py313 diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index 490e9545..8f1424a2 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -1,6 +1,6 @@ -FROM python:3.13-alpine +FROM python:3.14-alpine LABEL MAINTAINER="BJ Dierkes " -ENV PS1="\[\e[0;33m\]|> cement-py313 <| \[\e[1;35m\]\W\[\e[0m\] \[\e[0m\]# " +ENV PS1="\[\e[0;33m\]|> cement-py314 <| \[\e[1;35m\]\W\[\e[0m\] \[\e[0m\]# " ENV PATH="${PATH}:/root/.local/bin" WORKDIR /src diff --git a/docker/Dockerfile.dev-py313 b/docker/Dockerfile.dev-py313 index b6b8e482..5cc230b8 100644 --- a/docker/Dockerfile.dev-py313 +++ b/docker/Dockerfile.dev-py313 @@ -1,4 +1,4 @@ -FROM python:3.13-rc-alpine +FROM python:3.13-alpine LABEL MAINTAINER="BJ Dierkes " ENV PS1="\[\e[0;33m\]|> cement-py313 <| \[\e[1;35m\]\W\[\e[0m\] \[\e[0m\]# " ENV PATH="${PATH}:/root/.local/bin" diff --git a/docker/Dockerfile.dev-py38 b/docker/Dockerfile.dev-py314 similarity index 74% rename from docker/Dockerfile.dev-py38 rename to docker/Dockerfile.dev-py314 index 6dba3572..b2e190b7 100644 --- a/docker/Dockerfile.dev-py38 +++ b/docker/Dockerfile.dev-py314 @@ -1,6 +1,6 @@ -FROM python:3.8-alpine +FROM python:3.14-alpine LABEL MAINTAINER="BJ Dierkes " -ENV PS1="\[\e[0;33m\]|> cement-py38 <| \[\e[1;35m\]\W\[\e[0m\] \[\e[0m\]# " +ENV PS1="\[\e[0;33m\]|> cement-py314 <| \[\e[1;35m\]\W\[\e[0m\] \[\e[0m\]# " ENV PATH="${PATH}:/root/.local/bin" WORKDIR /src @@ -22,7 +22,7 @@ RUN apk update \ && ln -sf /usr/bin/vim /usr/bin/vi RUN pipx install pdm COPY . /src -COPY docker/vimrc /root/.vimrc -COPY docker/bashrc /root/.bashrc +COPY ./docker/vimrc /root/.vimrc +COPY ./docker/bashrc /root/.bashrc RUN pdm install CMD ["/bin/bash"] diff --git a/pdm.lock b/pdm.lock index 3c3935c0..0e39ecc1 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,10 +5,10 @@ groups = ["default", "alarm", "argparse", "cli", "colorlog", "configparser", "daemon", "dev", "docs", "dummy", "generate", "jinja2", "json", "logging", "memcached", "mustache", "plugin", "print", "redis", "scrub", "smtp", "tabulate", "watchdog", "yaml"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:edb453570d1f7e2dcd14a71e866fa1814be1c5341a716c96164858feae2e3662" +content_hash = "sha256:88e91afb3db1d8d71ebff4abd3d4d3e29b3415592657bd9fe104948d542d1ee5" [[metadata.targets]] -requires_python = ">=3.8" +requires_python = ">=3.9" [[package]] name = "alabaster" @@ -55,7 +55,7 @@ name = "certifi" version = "2024.2.2" requires_python = ">=3.6" summary = "Python package for providing Mozilla's CA Bundle." -groups = ["docs"] +groups = ["dev", "docs"] files = [ {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, @@ -66,7 +66,7 @@ name = "charset-normalizer" version = "3.3.2" requires_python = ">=3.7.0" summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -groups = ["docs"] +groups = ["dev", "docs"] files = [ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, @@ -380,7 +380,7 @@ name = "idna" version = "3.6" requires_python = ">=3.5" summary = "Internationalized Domain Names in Applications (IDNA)" -groups = ["docs"] +groups = ["dev", "docs"] files = [ {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, @@ -702,17 +702,6 @@ files = [ {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] -[[package]] -name = "pytz" -version = "2024.1" -summary = "World timezone definitions, modern and historical" -groups = ["docs"] -marker = "python_version < \"3.9\"" -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - [[package]] name = "pyyaml" version = "6.0.3" @@ -814,7 +803,7 @@ name = "requests" version = "2.31.0" requires_python = ">=3.7" summary = "Python HTTP for Humans." -groups = ["docs"] +groups = ["dev", "docs"] dependencies = [ "certifi>=2017.4.17", "charset-normalizer<4,>=2", @@ -1054,7 +1043,7 @@ name = "urllib3" version = "2.2.1" requires_python = ">=3.8" summary = "HTTP library with thread-safe connection pooling, file post, and more." -groups = ["docs"] +groups = ["dev", "docs"] files = [ {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, diff --git a/pyproject.toml b/pyproject.toml index 2e3aa9c2..ef7e4b1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ dynamic = ["version", "README"] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [] [project.optional-dependencies] @@ -69,7 +69,7 @@ precision = 2 [tool.ruff] -target-version = "py38" +target-version = "py39" line-length = 100 indent-width = 4 exclude = [ @@ -107,7 +107,7 @@ unfixable = [] # ignore_missing_imports = true [tool.mypy] -python_version = "3.8" +python_version = "3.9" disallow_untyped_calls = true disallow_untyped_defs = true disallow_any_unimported = false diff --git a/scripts/cli-smoke-test.sh b/scripts/cli-smoke-test.sh index 82c42af6..2e9f3a9d 100755 --- a/scripts/cli-smoke-test.sh +++ b/scripts/cli-smoke-test.sh @@ -2,7 +2,7 @@ set -e [ -z "$CEMENT_VERSION" ] && CEMENT_VERSION="3.0" -[ -z "$PYTHON_VERSIONS" ] && PYTHON_VERSIONS="3.8 3.9 3.10 3.11 3.12 3.13" +[ -z "$PYTHON_VERSIONS" ] && PYTHON_VERSIONS="3.9 3.10 3.11 3.12 3.13 3.14" function smoke-test { pyver=$1