mirror of
https://github.com/kristoferssolo/bunyan-formatter.git
synced 2025-10-21 17:20:35 +00:00
commit
725dd8e624
26
.github/workflows/publish.yaml
vendored
Normal file
26
.github/workflows/publish.yaml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Publish Python Package
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build
|
||||
- name: Build package
|
||||
run: python -m build
|
||||
- name: Publish package
|
||||
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
26
.github/workflows/tox.yaml
vendored
Normal file
26
.github/workflows/tox.yaml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Run Tox
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
jobs:
|
||||
test:
|
||||
name: Test with ${{ matrix.python-version }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install tox tox-gh-actions
|
||||
- name: Run Tox
|
||||
env:
|
||||
TOXENV: py${{ matrix.python-version }}
|
||||
run: tox
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ build/
|
||||
dist/
|
||||
wheels/
|
||||
*.egg-info
|
||||
.tox/
|
||||
|
||||
# venv
|
||||
.venv
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
[project]
|
||||
name = "bunyan-formatter"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
description = "Bunyan Formatter for Python"
|
||||
dependencies = []
|
||||
readme = "README.md"
|
||||
requires-python = ">= 3.8"
|
||||
requires-python = ">=3.9"
|
||||
authors = [{ name = "Kristofers Solo", email = "dev@kristofers.xyz" }]
|
||||
|
||||
[build-system]
|
||||
@ -13,7 +13,13 @@ build-backend = "hatchling.build"
|
||||
|
||||
[tool.rye]
|
||||
managed = true
|
||||
dev-dependencies = ["mypy~=1.11", "ruff~=0.6", "pre-commit~=3.8", "pytest~=8.3"]
|
||||
dev-dependencies = [
|
||||
"mypy~=1.11",
|
||||
"ruff~=0.6",
|
||||
"pre-commit~=3.8",
|
||||
"pytest~=8.3",
|
||||
"tox~=4.18",
|
||||
]
|
||||
|
||||
[tool.hatch.metadata]
|
||||
allow-direct-references = true
|
||||
@ -25,7 +31,7 @@ packages = ["src/bunyan_formatter"]
|
||||
show-fixes = true
|
||||
line-length = 120
|
||||
indent-width = 4
|
||||
target-version = "py38"
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = [
|
||||
|
||||
@ -10,11 +10,18 @@
|
||||
# universal: false
|
||||
|
||||
-e file:.
|
||||
cachetools==5.5.0
|
||||
# via tox
|
||||
cfgv==3.4.0
|
||||
# via pre-commit
|
||||
chardet==5.2.0
|
||||
# via tox
|
||||
colorama==0.4.6
|
||||
# via tox
|
||||
distlib==0.3.8
|
||||
# via virtualenv
|
||||
filelock==3.16.0
|
||||
# via tox
|
||||
# via virtualenv
|
||||
identify==2.6.0
|
||||
# via pre-commit
|
||||
@ -26,17 +33,25 @@ mypy-extensions==1.0.0
|
||||
nodeenv==1.9.1
|
||||
# via pre-commit
|
||||
packaging==24.1
|
||||
# via pyproject-api
|
||||
# via pytest
|
||||
# via tox
|
||||
platformdirs==4.3.2
|
||||
# via tox
|
||||
# via virtualenv
|
||||
pluggy==1.5.0
|
||||
# via pytest
|
||||
# via tox
|
||||
pre-commit==3.8.0
|
||||
pyproject-api==1.7.1
|
||||
# via tox
|
||||
pytest==8.3.3
|
||||
pyyaml==6.0.2
|
||||
# via pre-commit
|
||||
ruff==0.6.4
|
||||
tox==4.18.1
|
||||
typing-extensions==4.12.2
|
||||
# via mypy
|
||||
virtualenv==20.26.4
|
||||
# via pre-commit
|
||||
# via tox
|
||||
|
||||
@ -1,25 +1,28 @@
|
||||
import json
|
||||
import logging
|
||||
from logging import LogRecord
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from bunyan_formatter import BunyanFormatter
|
||||
|
||||
|
||||
class TestBunyanFormatter(TestCase):
|
||||
def setUp(self):
|
||||
def setUp(self) -> None:
|
||||
self.project_name = "test_project"
|
||||
self.project_root = Path("/path/to/project")
|
||||
self.formatter = BunyanFormatter(self.project_name, self.project_root)
|
||||
|
||||
def create_log_record(self, level, msg, pathname):
|
||||
return logging.LogRecord(
|
||||
name="test_logger", level=level, pathname=pathname, lineno=42, msg=msg, args=(), exc_info=None
|
||||
)
|
||||
def create_log_record(self, level: int, msg: str, pathname: str) -> LogRecord:
|
||||
return LogRecord(name="test_logger", level=level, pathname=pathname, lineno=42, msg=msg, args=(), exc_info=None)
|
||||
|
||||
@patch("socket.gethostname")
|
||||
def test_format_basic(self, mock_gethostname):
|
||||
def test_format_basic(self, mock_gethostname: Optional[Mock]) -> None:
|
||||
if mock_gethostname is None:
|
||||
raise ValueError("mock_gethostname should not be None")
|
||||
|
||||
mock_gethostname.return_value = "test_host"
|
||||
record = self.create_log_record(logging.INFO, "Test message", "/path/to/project/test.py")
|
||||
|
||||
@ -36,25 +39,27 @@ class TestBunyanFormatter(TestCase):
|
||||
assert log_entry["line"] == 42
|
||||
assert log_entry["file"] == "test.py"
|
||||
|
||||
def test_format_different_levels(self):
|
||||
def test_format_different_levels(self) -> None:
|
||||
levels = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]
|
||||
expected_levels = [20, 30, 40, 50, 60]
|
||||
|
||||
for level, expected in zip(levels, expected_levels):
|
||||
for level, expected in zip(levels, expected_levels, strict=False):
|
||||
record = self.create_log_record(level, f"Test {logging.getLevelName(level)}", "/path/to/project/test.py")
|
||||
formatted = self.formatter.format(record)
|
||||
log_entry = json.loads(formatted)
|
||||
assert log_entry["level"] == expected
|
||||
assert log_entry["levelname"] == logging.getLevelName(level)
|
||||
|
||||
def test_format_file_outside_project(self):
|
||||
def test_format_file_outside_project(self) -> None:
|
||||
record = self.create_log_record(logging.INFO, "Test message", "/path/outside/project/test.py")
|
||||
formatted = self.formatter.format(record)
|
||||
log_entry = json.loads(formatted)
|
||||
assert log_entry["file"] == "/path/outside/project/test.py"
|
||||
|
||||
@patch("socket.gethostname")
|
||||
def test_format_hostname_consistency(self, mock_gethostname):
|
||||
def test_format_hostname_consistency(self, mock_gethostname: Optional[Mock]) -> None:
|
||||
if mock_gethostname is None:
|
||||
raise ValueError("mock_gethostname should not be None")
|
||||
mock_gethostname.return_value = "test_host"
|
||||
record1 = self.create_log_record(logging.INFO, "Message 1", "/path/to/project/test1.py")
|
||||
record2 = self.create_log_record(logging.INFO, "Message 2", "/path/to/project/test2.py")
|
||||
@ -67,7 +72,7 @@ class TestBunyanFormatter(TestCase):
|
||||
|
||||
assert log_entry1["hostname"] == log_entry2["hostname"]
|
||||
|
||||
def test_format_time(self):
|
||||
def test_format_time(self) -> None:
|
||||
record = self.create_log_record(logging.INFO, "Test message", "/path/to/project/test.py")
|
||||
formatted = self.formatter.format(record)
|
||||
log_entry = json.loads(formatted)
|
||||
|
||||
28
tox.ini
Normal file
28
tox.ini
Normal file
@ -0,0 +1,28 @@
|
||||
[tox]
|
||||
envlist = py39, py310, py311, py312, format, lint, type, test
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
hatchling
|
||||
-rrequirements-dev.lock
|
||||
|
||||
[testenv:format]
|
||||
description = Run ruff to format the code
|
||||
skip_install = true
|
||||
deps = ruff
|
||||
commands = ruff format
|
||||
|
||||
[testenv:lint]
|
||||
description = Run ruff to lint the code
|
||||
skip_install = true
|
||||
deps = ruff
|
||||
commands = ruff check --fix
|
||||
|
||||
[testenv:type]
|
||||
description = Run mypy to check type annotations
|
||||
commands = mypy .
|
||||
|
||||
[testenv:test]
|
||||
description = Run pytest to execute the tests
|
||||
commands = pytest
|
||||
Loading…
Reference in New Issue
Block a user