From 58b0af8f71e5e668246bd3e175665bb2593911de Mon Sep 17 00:00:00 2001 From: Tarik Zegmott Date: Tue, 1 Sep 2026 13:57:54 -0400 Subject: [PATCH] build: reintroduced support for python 3.8+ --- README.md | 2 +- logging_loki/emitter.py | 7 +++---- logging_loki/handlers.py | 4 ++-- pyproject.toml | 3 +++ setup.py | 9 ++++++++- tox.ini | 15 +++++++++++++-- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b54f8c1..d9df49a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > Modern Python logging handler for Grafana Loki [![PyPI version](https://img.shields.io/pypi/v/python-logging-loki-v2.svg)](https://pypi.org/project/python-logging-loki-v2/) -[![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/) +[![Python](https://img.shields.io/badge/python-3.8.1+-blue.svg)](https://www.python.org/) ## Documented by Grafana: https://github.com/grafana/loki/pull/16397 diff --git a/logging_loki/emitter.py b/logging_loki/emitter.py index aeacea6..71f7419 100644 --- a/logging_loki/emitter.py +++ b/logging_loki/emitter.py @@ -4,7 +4,6 @@ import copy import functools import logging -import time from logging.config import ConvertingDict from typing import Any, Dict, List, Optional, Tuple @@ -26,7 +25,7 @@ class LokiEmitter(abc.ABC): label_replace_with = const.label_replace_with session_class = requests.Session - def __init__(self, url: str, tags: dict | None = None, auth: BasicAuth = None, headers: dict | None = None, verify_ssl: bool = True): + def __init__(self, url: str, tags: Optional[dict] = None, auth: BasicAuth = None, headers: Optional[dict] = None, verify_ssl: bool = True): """ Create new Loki emitter. @@ -47,7 +46,7 @@ def __init__(self, url: str, tags: dict | None = None, auth: BasicAuth = None, h #: Verify the host's ssl certificate self.verify_ssl = verify_ssl - self._session: requests.Session | None = None + self._session: Optional[requests.Session] = None def __call__(self, record: logging.LogRecord, line: str): """Send log record to Loki.""" @@ -149,7 +148,7 @@ class LokiEmitterV2(LokiEmitterV1): Enables passing additional headers to requests """ - def __init__(self, url: str, tags: dict | None = None, auth: BasicAuth = None, headers: dict = None, verify_ssl: bool = True): + def __init__(self, url: str, tags: Optional[dict] = None, auth: BasicAuth = None, headers: Optional[dict] = None, verify_ssl: bool = True): super().__init__(url, tags, auth, headers, verify_ssl) def __call__(self, record: logging.LogRecord, line: str): diff --git a/logging_loki/handlers.py b/logging_loki/handlers.py index 030aa2b..40ab368 100644 --- a/logging_loki/handlers.py +++ b/logging_loki/handlers.py @@ -4,7 +4,7 @@ import warnings from logging.handlers import QueueHandler, QueueListener from queue import Queue -from typing import Dict, Type +from typing import Dict, Optional, Type from logging_loki import const, emitter @@ -29,7 +29,7 @@ class LokiHandler(logging.Handler): emitters: Dict[str, Type[emitter.LokiEmitter]] = {"0": emitter.LokiEmitterV0, "1": emitter.LokiEmitterV1, "2": emitter.LokiEmitterV2} - def __init__(self, url: str, tags: dict | None = None, auth: emitter.BasicAuth | None = None, version: str | None = None, headers: dict | None = None, verify_ssl: bool = True): + def __init__(self, url: str, tags: Optional[dict] = None, auth: Optional[emitter.BasicAuth] = None, version: Optional[str] = None, headers: Optional[dict] = None, verify_ssl: bool = True): """ Create new Loki logging handler. diff --git a/pyproject.toml b/pyproject.toml index c05ed4d..571e3e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,9 @@ build-backend = "setuptools.build_meta" [tool.ruff] line-length = 200 +# Lowest supported interpreter; keeps pyupgrade rules from +# rewriting code into 3.9+ only syntax. +target-version = "py38" [tool.ruff.lint] # Enable flake8-style rules and more diff --git a/setup.py b/setup.py index 2aebd6d..688b410 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ author_email="cryos10@gmail.com", url="https://github.com/RomanR-dev/python-logging-loki", packages=setuptools.find_packages(exclude=("tests",)), - python_requires=">=3.11", + python_requires=">=3.8.1,<4.0", install_requires=["rfc3339>=6.1", "requests"], classifiers=[ "Development Status :: 5 - Production/Stable", @@ -24,7 +24,14 @@ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Logging", "Topic :: Internet :: WWW/HTTP", diff --git a/tox.ini b/tox.ini index 658ecc4..4e94982 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,19 @@ [tox] # List of Python versions to test against -envlist = py311,py312,ruff +envlist = py38,py39,py310,py311,py312,py313,ruff isolated_build = true +[gh-actions] +# Map the CI job's interpreter to the envs it should run, so each matrix +# entry runs its own testenv instead of skipping the rest of the envlist. +python = + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311, ruff + 3.12: py312 + 3.13: py313 + [testenv] setenv = LC_ALL = en_US.UTF-8 @@ -19,7 +30,7 @@ commands = [testenv:ruff] skip_install = true # Use whatever python3 is available on your system -basepython = python3.11 +basepython = python3 deps = ruff commands = # First fix auto-fixable issues