diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f1787ef..db99378 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,18 +1,50 @@ # https://github.com/devcontainers/images/tree/main/src/python -FROM mcr.microsoft.com/devcontainers/python:1-3.12-bookworm +#FROM mcr.microsoft.com/devcontainers/python:1-3.13-bookworm +FROM python:3.13-slim-bookworm + +# https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Create the user +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME --shell /bin/bash \ + # [Optional] Add sudo support. Omit if you don't need to install software after connecting. + && apt-get update \ + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME # Install additional packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends \ -# \ -# && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends \ + git \ + make \ + openssh-client \ + && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 \ + UV_LINK_MODE=copy # Install UV / UVX COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ -ENV UV_COMPILE_BYTECODE=1 -ENV UV_LINK_MODE=copy # Install project dependencies -RUN --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - --mount=type=bind,source=uv.lock,target=uv.lock \ - uv sync --frozen --no-install-project --all-extras +COPY pyproject.toml uv.lock ./ +RUN uv sync --frozen --no-install-project --all-groups \ + && rm pyproject.toml uv.lock \ + && chown -R $USERNAME:$USERNAME /app + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# HACK: https://github.com/sphinx-doc/sphinx/issues/11739 +ENV LC_ALL=C.UTF-8 + +# [Optional] Set the default user. Omit if you want to keep the default as root. +USER $USERNAME diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ebe2148 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +# Exclude the project virtual environment from image builds +.venv \ No newline at end of file diff --git a/.github/workflows/docker-build-publish.yml b/.github/workflows/docker-build-publish.yml index 69734ab..3559b42 100644 --- a/.github/workflows/docker-build-publish.yml +++ b/.github/workflows/docker-build-publish.yml @@ -5,16 +5,16 @@ on: branches: - main paths: - - Pipfile - - Pipfile.lock - .devcontainer/Dockerfile + - pyproject.toml + - uv.lock pull_request: branches: - main paths: - - Pipfile - - Pipfile.lock - .devcontainer/Dockerfile + - pyproject.toml + - uv.lock workflow_dispatch: jobs: diff --git a/pyproject.toml b/pyproject.toml index da77cf6..22c064f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,8 +9,8 @@ build-backend = "setuptools.build_meta" [project] name = "python_training_project" authors = [ - {name = "Andreas", email = "andreas@devminds.ch"}, - {name = "Thomas", email = "thomas@devminds.ch"}, + {name = "Andreas Nussberger", email = "andreas@devminds.ch"}, + {name = "Thomas Keller", email = "thomas@devminds.ch"}, ] description = "Python Training Project by devminds GmbH" readme = "README.md" @@ -33,8 +33,8 @@ dynamic = ["version"] [project.scripts] python_training_project = "python_training_project.__main__:cli" -[tool.uv] -dev-dependencies = [ +[dependency-groups] +dev = [ "coverage", "flake8", "mypy", @@ -54,6 +54,9 @@ write_to = "src/python_training_project/version.py" [tool.pytest.ini_options] minversion = "6.0" addopts = "--cov --cov-report term --cov-report xml --junitxml=build/test-report.xml" +pythonpath = [ + "src", +] testpaths = [ "tests", ] @@ -79,3 +82,8 @@ include = [ "tests/**/*.py" ] output-format = "pylint" + +[tool.pylint.main] +ignore = [ + "version.py" +] diff --git a/src/python_training_project/__main__.py b/src/python_training_project/__main__.py index a3cc794..b374114 100644 --- a/src/python_training_project/__main__.py +++ b/src/python_training_project/__main__.py @@ -7,7 +7,7 @@ import click -from python_training_project.calculate import sum +from python_training_project.calculate import calc_sum log = logging.getLogger(__name__) @@ -28,7 +28,7 @@ def cli(): @click.argument("b", type=float) def cli_sum(a: float, b: float): """Show the sum of two numbers on the console.""" - log.info("Sum of %f and %f is %f", a, b, sum(a, b)) + log.info("Sum of %f and %f is %f", a, b, calc_sum(a, b)) if __name__ == "__main__": diff --git a/src/python_training_project/calculate.py b/src/python_training_project/calculate.py index 38e024d..f85432e 100644 --- a/src/python_training_project/calculate.py +++ b/src/python_training_project/calculate.py @@ -3,7 +3,7 @@ """ -def sum(a: float, b: float) -> float: +def calc_sum(a: float, b: float) -> float: """Calculate the sum of two numbers.""" return a + b diff --git a/tests/test_calculate.py b/tests/test_calculate.py index 5ebefb7..e18c5b1 100644 --- a/tests/test_calculate.py +++ b/tests/test_calculate.py @@ -1,13 +1,13 @@ -from python_training_project.calculate import sum +from python_training_project.calculate import calc_sum -def test_sum(): - assert sum(1, 1) == 2 - assert sum(2, 1) == 3 - assert sum(1, 2) == 3 +def test_calc_sum(): + assert calc_sum(1, 1) == 2 + assert calc_sum(2, 1) == 3 + assert calc_sum(1, 2) == 3 def test_sum_negative(): - assert sum(1, -1) == 0 - assert sum(-1, 1) == 0 - assert sum(-1, -1) == -2 + assert calc_sum(1, -1) == 0 + assert calc_sum(-1, 1) == 0 + assert calc_sum(-1, -1) == -2 diff --git a/tools/build-docs.sh b/tools/build-docs.sh index 0ec04a9..b4cc9ae 100755 --- a/tools/build-docs.sh +++ b/tools/build-docs.sh @@ -8,6 +8,6 @@ pushd "${REPO_ROOT}" 2>&1 > /dev/null echo "Building documentation..." mkdir -p build cd docs -uv run --all-extras make html +make html popd 2>&1 > /dev/null diff --git a/tools/lint-package.sh b/tools/lint-package.sh index ada8352..ce76b9d 100755 --- a/tools/lint-package.sh +++ b/tools/lint-package.sh @@ -11,31 +11,31 @@ STATUS=0 set +e echo "Running flake8..." -uv run --all-extras flake8 src/python_training_project --format=pylint > build/flake8.txt +flake8 src/python_training_project --format=pylint > build/flake8.txt if [ $? -ne 0 ]; then STATUS=1 fi echo "Running mypy..." -uv run --all-extras mypy src/python_training_project > build/mypy.txt +mypy src/python_training_project > build/mypy.txt if [ $? -ne 0 ]; then STATUS=1 fi echo "Running pylint..." -uv run --all-extras pylint src/python_training_project --msg-template="{path}:{line}: [{msg_id}, {obj}] {msg} ({symbol})" > build/pylint.txt +pylint src/python_training_project --msg-template="{path}:{line}: [{msg_id}, {obj}] {msg} ({symbol})" > build/pylint.txt if [ $? -ne 0 ]; then STATUS=1 fi echo "Running ruff check..." -uv run --all-extras ruff check > build/ruff.txt +ruff check > build/ruff.txt if [ $? -ne 0 ]; then STATUS=1 fi echo "Running ruff format..." -uv run --all-extras ruff format --check +ruff format --check if [ $? -ne 0 ]; then STATUS=1 fi diff --git a/tools/test-package.sh b/tools/test-package.sh index 1b00b41..df59698 100755 --- a/tools/test-package.sh +++ b/tools/test-package.sh @@ -8,6 +8,6 @@ pushd "${REPO_ROOT}" 2>&1 > /dev/null mkdir -p build echo "Running tests..." -uv run --all-extras pytest +pytest popd 2>&1 > /dev/null diff --git a/uv.lock b/uv.lock index 2abbb11..2c92a16 100644 --- a/uv.lock +++ b/uv.lock @@ -119,7 +119,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -574,7 +574,6 @@ wheels = [ [[package]] name = "python-training-project" -version = "0.1.dev50+g3436a05.d20241101" source = { editable = "." } dependencies = [ { name = "click" },