Skip to content

Commit 56cfe3a

Browse files
committed
feat: add Ruff linting workflow and update dependencies for improved code quality
1 parent 2643ba1 commit 56cfe3a

21 files changed

Lines changed: 163 additions & 61 deletions
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
name: UV Build - Pylint Lint
1+
name: UV Build - Ruff Lint
22

33
on:
44
pull_request:
55
branches:
66
- '*'
77

88
jobs:
9-
pylint-lint:
9+
ruff-lint:
1010
runs-on: ubuntu-latest
1111
permissions:
1212
contents: read
@@ -40,10 +40,10 @@ jobs:
4040
- name: Install dependencies
4141
run: uv sync
4242

43-
- name: Run pylint
43+
- name: Run Ruff
4444
run: |
45-
uv run -- pylint src
46-
uv run -- pylint tests
45+
uv run ruff check src
46+
uv run ruff check tests
4747
4848
- name: Save uv caches
4949
if: steps.cache-restore.outputs.cache-hit != 'true'

pyproject.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ dependencies = [
1515
"pydantic-extra-types>=2.11.0",
1616
"pydantic-settings>=2.12.0",
1717
"pyfiglet>=1.0.4",
18-
"pylint>=4.0.4",
1918
"pylint-pydantic>=0.4.1",
2019
"pytest>=9.0.2",
2120
"rich>=14.3.2",
21+
"ruff>=0.15.1",
2222
]
2323

2424
[project.optional-dependencies]
@@ -45,3 +45,14 @@ source = ["src"]
4545

4646
[tool.coverage.report]
4747
omit = ["tests/*"]
48+
49+
[tool.ruff]
50+
line-length = 88
51+
exclude = ["__pycache__", "build", "dist", ".venv"]
52+
53+
[tool.ruff.lint]
54+
select = ["E", "F", "W", "C", "B", "I", "N", "D", "UP", "T", "A"]
55+
ignore = []
56+
57+
[tool.ruff.lint.per-file-ignores]
58+
"tests/*" = ["F401"]

src/sample_python_app/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Sample Python app package initialization."""

src/sample_python_app/core/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
"""
2-
Export core modules for use in other modules.
3-
"""
1+
"""Export core modules for use in other modules."""
42

53
from sample_python_app.core.config import settings, weather_settings
64
from sample_python_app.core.data_loader import fetch_astronomical_data_from_api

src/sample_python_app/core/config.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
"""
2-
Main configuration file for the API
3-
"""
1+
"""Main configuration file for the API."""
42

53
from zoneinfo import ZoneInfo
64

@@ -35,6 +33,7 @@ class Settings(BaseSettings):
3533

3634
@property
3735
def tz(self) -> ZoneInfo:
36+
"""Return the configured timezone info."""
3837
return ZoneInfo(self.TIMEZONE)
3938

4039

src/sample_python_app/core/data_loader.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
"""
2-
Handles loading and validating weather.gov astronomical data from file.
3-
"""
1+
"""Handles loading and validating weather.gov astronomical data from file."""
42

53
import httpx
64
from pydantic import ValidationError
@@ -10,6 +8,20 @@
108

119

1210
def fetch_astronomical_data_from_api(lat: float, lon: float):
11+
"""Fetch and validate astronomical data from weather.gov API for given coordinates.
12+
13+
Args:
14+
lat (float): Latitude of the location.
15+
lon (float): Longitude of the location.
16+
17+
Returns:
18+
AstronomicalData: Validated astronomical data from API response.
19+
20+
Raises:
21+
ValidationError: If the API response fails validation.
22+
httpx.HTTPError: If the API request fails.
23+
24+
"""
1325
logger = setup_logger(mode="silent")
1426
url = f"https://api.weather.gov/points/{lat},{lon}"
1527
headers = {"User-Agent": "(myweatherapp.com, contact@myweatherapp.com)"}

src/sample_python_app/core/display.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
"""
2-
Handles formatting and displaying astronomical data using rich and pyfiglet.
3-
"""
1+
"""Handles formatting and displaying astronomical data using rich and pyfiglet."""
42

53
from pyfiglet import Figlet
64
from rich.console import Console
@@ -10,6 +8,15 @@
108

119

1210
def display_astronomical_data(astro):
11+
"""Format and display astronomical data using rich and pyfiglet.
12+
13+
Args:
14+
astro: AstronomicalData object containing sunrise, sunset, and formatted values.
15+
16+
Returns:
17+
None
18+
19+
"""
1320
logger = setup_logger(mode="silent")
1421
console = Console()
1522
header = Figlet(font="small", width=100).renderText("Astronomical Data")

src/sample_python_app/core/logging.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
"""
2-
Loguru logger configuration for python-app-template.
3-
"""
1+
"""Loguru logger configuration for python-app-template."""
2+
3+
import sys
44

55
from loguru import logger
66

@@ -13,8 +13,22 @@
1313

1414

1515
def setup_logger(mode="normal"):
16+
"""Configure and return a Loguru logger instance.
17+
18+
Args:
19+
mode (str, optional): Logging mode. "normal" for console and file logging,
20+
"silent" for file logging only. Defaults to "normal".
21+
22+
Returns:
23+
logger: Configured Loguru logger instance.
24+
25+
"""
1626
logger.remove()
1727
if mode == "silent":
28+
# Log errors to the console even in silent mode
29+
logger.add(
30+
sink=lambda msg: sys.stdout.write(msg), format=log_format, level="ERROR"
31+
)
1832
logger.add(
1933
"app.log",
2034
format=log_format,
@@ -24,7 +38,9 @@ def setup_logger(mode="normal"):
2438
compression="zip",
2539
)
2640
else:
27-
logger.add(sink=lambda msg: print(msg, end=""), format=log_format, level="INFO")
41+
logger.add(
42+
sink=lambda msg: sys.stdout.write(msg), format=log_format, level="INFO"
43+
)
2844
logger.add(
2945
"app.log",
3046
format=log_format,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""Custom exceptions package for sample_python_app."""
2+
3+
from sample_python_app.exceptions.custom import (
4+
AppError,
5+
)
6+
7+
__all__ = ["AppError"]

0 commit comments

Comments
 (0)