Skip to content

Commit

Permalink
Switched to ruff, dropped black, added doc strings
Browse files Browse the repository at this point in the history
  • Loading branch information
max-pfeiffer committed Mar 24, 2024
1 parent c87a6d5 commit 3645305
Show file tree
Hide file tree
Showing 41 changed files with 518 additions and 93 deletions.
12 changes: 4 additions & 8 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ jobs:
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: |
poetry install --no-interaction --no-root
- name: Run pylint and black
- name: Run pre-commit hooks
run: |
source .venv/bin/activate
pylint build tests
black --check .
poetry run pre-commit run -a
run-build-image-tests:
needs: code-quality
Expand Down Expand Up @@ -71,8 +69,7 @@ jobs:
OS_VARIANT: ${{ matrix.os_variant }}
POETRY_VERSION: ${{ matrix.poetry_version }}
run: |
source .venv/bin/activate
pytest tests/build_image --cov --cov-report=xml:build_image_coverage_report.xml
poetry run pytest tests/build_image --cov --cov-report=xml:build_image_coverage_report.xml
- name: Upload coverage report to artifactory
uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -119,8 +116,7 @@ jobs:
OS_VARIANT: ${{ matrix.os_variant }}
POETRY_VERSION: ${{ matrix.poetry_version }}
run: |
source .venv/bin/activate
pytest tests/publish_image --cov --cov-report=xml:publish_image_coverage_report.xml
poetry run pytest tests/publish_image --cov --cov-report=xml:publish_image_coverage_report.xml
- name: Upload coverage report to artifactory
uses: actions/upload-artifact@v3
with:
Expand Down
19 changes: 6 additions & 13 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,10 @@ repos:
- id: check-merge-conflict
- id: detect-private-key
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 23.12.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
hooks:
- id: black
- repo: local
hooks:
- id: pylint
name: pylint
entry: .venv/bin/pylint
language: system
types: [python]
args:
- build
- tests
- id: ruff
args: ["--fix", "--config", "pyproject.toml", "."]
- id: ruff-format
args: ["--config", "pyproject.toml", "."]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![codecov](https://codecov.io/gh/max-pfeiffer/uvicorn-poetry/branch/main/graph/badge.svg?token=WQI2SJJLZN)](https://codecov.io/gh/max-pfeiffer/uvicorn-poetry)
![pipeline workflow](https://github.com/max-pfeiffer/uvicorn-poetry/actions/workflows/pipeline.yml/badge.svg)
![Docker Image Size (latest semver)](https://img.shields.io/docker/image-size/pfeiffermax/uvicorn-poetry?sort=semver)
Expand Down
1 change: 1 addition & 0 deletions build/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Image build."""
2 changes: 2 additions & 0 deletions build/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Constants for image build."""

# As we are running the server with an unprivileged user, we need to use
# a high port.
APPLICATION_SERVER_PORT: str = "8000"
Expand Down
34 changes: 21 additions & 13 deletions build/publish.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"""Image publishing."""

from os import getenv
from pathlib import Path

import click
from build.constants import PLATFORMS, APPLICATION_SERVER_PORT
from python_on_whales import Builder, DockerClient

from build.constants import APPLICATION_SERVER_PORT, PLATFORMS
from build.utils import (
get_context,
get_image_reference,
get_python_poetry_image_reference,
)
from pathlib import Path
from python_on_whales import DockerClient, Builder
from os import getenv


@click.command()
Expand All @@ -21,9 +25,7 @@
envvar="DOCKER_HUB_PASSWORD",
help="Docker Hub password",
)
@click.option(
"--version-tag", envvar="GIT_TAG_NAME", required=True, help="Version tag"
)
@click.option("--version-tag", envvar="GIT_TAG_NAME", required=True, help="Version tag")
@click.option(
"--python-version",
envvar="PYTHON_VERSION",
Expand All @@ -47,6 +49,16 @@ def main(
os_variant: str,
registry: str,
) -> None:
"""Build Docker image.
:param docker_hub_username:
:param docker_hub_password:
:param version_tag:
:param python_version:
:param os_variant:
:param registry:
:return:
"""
github_ref_name: str = getenv("GITHUB_REF_NAME")
context: Path = get_context()
image_reference: str = get_image_reference(
Expand All @@ -55,9 +67,7 @@ def main(
cache_scope: str = f"{python_version}-{os_variant}"

if github_ref_name:
cache_to: str = (
f"type=gha,mode=max,scope={github_ref_name}-{cache_scope}"
)
cache_to: str = f"type=gha,mode=max,scope={github_ref_name}-{cache_scope}"
cache_from: str = f"type=gha,scope={github_ref_name}-{cache_scope}"
else:
cache_to = f"type=local,mode=max,dest=/tmp,scope={cache_scope}"
Expand All @@ -77,9 +87,7 @@ def main(
docker_client.buildx.build(
context_path=context,
build_args={
"BASE_IMAGE": get_python_poetry_image_reference(
python_version, os_variant
),
"BASE_IMAGE": get_python_poetry_image_reference(python_version, os_variant),
"APPLICATION_SERVER_PORT": APPLICATION_SERVER_PORT,
},
tags=image_reference,
Expand Down
30 changes: 28 additions & 2 deletions build/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
"""Utilities for image publishing."""

from pathlib import Path


def get_context() -> Path:
"""Return Docker build context.
:return:
"""
return Path(__file__).parent.resolve()


Expand All @@ -11,13 +17,33 @@ def get_image_reference(
python_version: str,
os_variant: str,
) -> str:
reference: str = f"{registry}/pfeiffermax/uvicorn-poetry:{image_version}-python{python_version}-{os_variant}"
"""Return image reference.
:param registry:
:param image_version:
:param python_version:
:param os_variant:
:return:
"""
reference: str = (
f"{registry}/pfeiffermax/uvicorn-poetry:{image_version}"
f"-python{python_version}-{os_variant}"
)
return reference


def get_python_poetry_image_reference(
python_version: str,
os_variant: str,
) -> str:
reference: str = f"pfeiffermax/python-poetry:1.8.0-poetry1.7.1-python{python_version}-{os_variant}"
"""Return image reference for base image.
:param python_version:
:param os_variant:
:return:
"""
reference: str = (
f"pfeiffermax/python-poetry:1.8.0-poetry1.7.1-python"
f"{python_version}-{os_variant}"
)
return reference
1 change: 1 addition & 0 deletions examples/fast_api_multistage_build/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Application."""
15 changes: 15 additions & 0 deletions examples/fast_api_multistage_build/app/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module."""

from typing import Dict

from fastapi import FastAPI
Expand All @@ -10,13 +12,26 @@

@app.get("/")
def read_root():
"""Root endpoint.
:return:
"""
return HELLO_WORLD


@app.get("/items/{item_id}")
def read_item(item_id: str):
"""Items.
:param item_id:
:return:
"""
return ITEMS[item_id]


def get_app():
"""Return app.
:return:
"""
return app
1 change: 1 addition & 0 deletions examples/fast_api_multistage_build/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests."""
6 changes: 6 additions & 0 deletions examples/fast_api_multistage_build/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
"""Test fixtures."""

import pytest
from app.main import app
from fastapi.testclient import TestClient


@pytest.fixture(scope="module")
def test_client() -> TestClient:
"""Fixture for providing test client.
:return:
"""
return TestClient(app)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""API tests."""
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Tests for API endpoints."""

import random

from app.main import HELLO_WORLD, ITEMS
Expand All @@ -6,13 +8,23 @@


def test_root(test_client):
"""Test for root endpoint.
:param test_client:
:return:
"""
response: Response = test_client.get("/")

assert response.status_code == status.HTTP_200_OK
assert response.json() == HELLO_WORLD


def test_items(test_client):
"""Test for items endpoint.
:param test_client:
:return:
"""
key, value = random.choice(list(ITEMS.items()))

response: Response = test_client.get(f"/items/{key}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Application."""
15 changes: 15 additions & 0 deletions examples/fast_api_multistage_build_with_json_logging/app/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module."""

from typing import Dict

from fastapi import FastAPI
Expand All @@ -10,13 +12,26 @@

@app.get("/")
def read_root():
"""Root endpoint.
:return:
"""
return HELLO_WORLD


@app.get("/items/{item_id}")
def read_item(item_id: str):
"""Items endpoint.
:param item_id:
:return:
"""
return ITEMS[item_id]


def get_app():
"""Return application.
:return:
"""
return app
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests."""
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
"""Fixtures for tests."""

import pytest
from app.main import app
from fastapi.testclient import TestClient


@pytest.fixture(scope="module")
def test_client() -> TestClient:
"""Fixture for providing a test client.
:return:
"""
return TestClient(app)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests."""
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
"""Tests for API endpoints."""

import random

from app.main import HELLO_WORLD, ITEMS
from requests import Response
from starlette import status


def test_root(test_client):
def test_root(test_client) -> None:
"""Test for root endpoint.
:param test_client:
:return:
"""
response: Response = test_client.get("/")

assert response.status_code == status.HTTP_200_OK
assert response.json() == HELLO_WORLD


def test_items(test_client):
"""Test for items endpoint.
:param test_client:
:return:
"""
key, value = random.choice(list(ITEMS.items()))

response: Response = test_client.get(f"/items/{key}")
Expand Down
1 change: 1 addition & 0 deletions examples/fast_api_singlestage_build/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Application."""
15 changes: 15 additions & 0 deletions examples/fast_api_singlestage_build/app/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module."""

from typing import Dict

from fastapi import FastAPI
Expand All @@ -10,13 +12,26 @@

@app.get("/")
def read_root():
"""Root endpoint.
:return:
"""
return HELLO_WORLD


@app.get("/items/{item_id}")
def read_item(item_id: str):
"""Items endpoint.
:param item_id:
:return:
"""
return ITEMS[item_id]


def get_app():
"""Return application.
:return:
"""
return app
Loading

0 comments on commit 3645305

Please sign in to comment.