Skip to content

Commit b3f2c5b

Browse files
authored
fix(picologging): better handle unsupported environments (#3918)
* fix(picologging): updates to handle unsupported environments (python 3.13, etc.) * fix: add ignores * fix: trim whitespace
1 parent 76632da commit b3f2c5b

File tree

5 files changed

+219
-85
lines changed

5 files changed

+219
-85
lines changed

litestar/logging/config.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,16 @@ def configure(self) -> GetLogger:
292292

293293
if self.logging_module == "picologging":
294294
try:
295-
from picologging import config, getLogger
295+
from picologging import ( # pyright: ignore[reportMissingImports,reportGeneralTypeIssues]
296+
config, # pyright: ignore[reportMissingImports,reportGeneralTypeIssues]
297+
getLogger, # pyright: ignore[reportMissingImports,reportGeneralTypeIssues]
298+
)
296299
except ImportError as e:
297300
raise MissingDependencyException("picologging") from e
298301

299302
excluded_fields.add("incremental")
300303
else:
301-
from logging import config, getLogger # type: ignore[no-redef, assignment]
304+
from logging import config, getLogger # type: ignore[no-redef,assignment,unused-ignore]
302305

303306
values = {
304307
_field.name: getattr(self, _field.name)

litestar/logging/picologging.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111

1212

1313
try:
14-
import picologging # noqa: F401
14+
import picologging # noqa: F401 # pyright: ignore[reportMissingImports]
1515
except ImportError as e:
1616
raise MissingDependencyException("picologging") from e
1717

18-
from picologging import StreamHandler
19-
from picologging.handlers import QueueHandler, QueueListener
18+
from picologging import StreamHandler # pyright: ignore[reportMissingImports]
19+
from picologging.handlers import QueueHandler, QueueListener # pyright: ignore[reportMissingImports]
2020

2121

22-
class QueueListenerHandler(QueueHandler):
22+
class QueueListenerHandler(QueueHandler): # type: ignore[misc,unused-ignore]
2323
"""Configure queue listener and handler to support non-blocking logging configuration."""
2424

2525
def __init__(self, handlers: list[Any] | None = None) -> None:
@@ -32,8 +32,8 @@ def __init__(self, handlers: list[Any] | None = None) -> None:
3232
- Requires ``picologging`` to be installed.
3333
"""
3434
super().__init__(Queue(-1))
35-
handlers = resolve_handlers(handlers) if handlers else [StreamHandler()]
36-
self.listener = QueueListener(self.queue, *handlers)
35+
handlers = resolve_handlers(handlers) if handlers else [StreamHandler()] # pyright: ignore[reportGeneralTypeIssues]
36+
self.listener = QueueListener(self.queue, *handlers) # pyright: ignore[reportGeneralTypeIssues]
3737
self.listener.start()
3838

3939
atexit.register(self.listener.stop)

pyproject.toml

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,21 @@ classifiers = [
3131
"Topic :: Software Development :: Libraries :: Python Modules",
3232
]
3333
dependencies = [
34-
"anyio>=3",
35-
"httpx>=0.22",
36-
"exceptiongroup; python_version < \"3.11\"",
37-
"importlib-metadata; python_version < \"3.10\"",
38-
"importlib-resources>=5.12.0; python_version < \"3.9\"",
39-
"msgspec>=0.18.2",
40-
"multidict>=6.0.2",
41-
"polyfactory>=2.6.3",
42-
"pyyaml",
43-
"typing-extensions",
44-
"click",
45-
"rich>=13.0.0",
46-
"rich-click",
47-
"multipart>=1.2.0",
48-
# default litestar plugins
34+
"anyio>=3",
35+
"httpx>=0.22",
36+
"exceptiongroup; python_version < \"3.11\"",
37+
"importlib-metadata; python_version < \"3.10\"",
38+
"importlib-resources>=5.12.0; python_version < \"3.9\"",
39+
"msgspec>=0.18.2",
40+
"multidict>=6.0.2",
41+
"polyfactory>=2.6.3",
42+
"pyyaml",
43+
"typing-extensions",
44+
"click",
45+
"rich>=13.0.0",
46+
"rich-click",
47+
"multipart>=1.2.0",
48+
# default litestar plugins
4949
"litestar-htmx>=0.4.0"
5050
]
5151
description = "Litestar - A production-ready, highly performant, extensible ASGI API Framework"
@@ -140,16 +140,16 @@ dev = [
140140
]
141141

142142
docs = [
143-
"sphinx>=7.1.2",
144-
"sphinx-autobuild>=2021.3.14",
145-
"sphinx-copybutton>=0.5.2",
146-
"sphinx-toolbox>=3.5.0",
147-
"sphinx-design>=0.5.0",
148-
"sphinx-click>=4.4.0",
149-
"sphinxcontrib-mermaid>=0.9.2",
150-
"auto-pytabs[sphinx]>=0.5.0",
151-
"litestar-sphinx-theme @ git+https://github.com/litestar-org/litestar-sphinx-theme.git",
152-
"sphinx-paramlinks>=0.6.0",
143+
"sphinx>=7.1.2",
144+
"sphinx-autobuild>=2021.3.14",
145+
"sphinx-copybutton>=0.5.2",
146+
"sphinx-toolbox>=3.5.0",
147+
"sphinx-design>=0.5.0",
148+
"sphinx-click>=4.4.0",
149+
"sphinxcontrib-mermaid>=0.9.2",
150+
"auto-pytabs[sphinx]>=0.5.0",
151+
"litestar-sphinx-theme @ git+https://github.com/litestar-org/litestar-sphinx-theme.git",
152+
"sphinx-paramlinks>=0.6.0",
153153
]
154154
linting = [
155155
"ruff>=0.2.1",
@@ -256,6 +256,10 @@ module = ["tests.examples.*", "tests.docker_service_fixtures"]
256256
module = ["tests.*"]
257257
disable_error_code = ["truthy-bool"]
258258

259+
[[tool.mypy.overrides]]
260+
disable_error_code = ["assignment"]
261+
module = ["tests.unit.test_logging.*"]
262+
259263
[[tool.mypy.overrides]]
260264
disallow_untyped_decorators = false
261265
module = ["tests.unit.test_kwargs.test_reserved_kwargs_injection"]
@@ -290,6 +294,7 @@ module = [
290294
"litestar.plugins.pydantic.*",
291295
"tests.unit.test_contrib.test_sqlalchemy",
292296
"tests.unit.test_contrib.test_pydantic.*",
297+
"tests.unit.test_logging.test_logging_config",
293298
"litestar.openapi.spec.base",
294299
"litestar.utils.helpers",
295300
"litestar.channels.plugin",

tests/helpers.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
from __future__ import annotations
22

33
import atexit
4+
import importlib.util
45
import inspect
56
import logging
67
import random
78
import sys
89
from contextlib import AbstractContextManager, contextmanager
10+
from pathlib import Path
911
from typing import Any, AsyncContextManager, Awaitable, ContextManager, Generator, TypeVar, cast, overload
1012

11-
import picologging
13+
import pytest
1214
from _pytest.logging import LogCaptureHandler, _LiveLoggingNullHandler
1315

1416
from litestar._openapi.schema_generation import SchemaCreator
@@ -90,9 +92,9 @@ def cleanup_logging_impl() -> Generator:
9092
# Don't interfere with PyTest handler config
9193
if not isinstance(std_handler, (_LiveLoggingNullHandler, LogCaptureHandler)):
9294
std_root_logger.removeHandler(std_handler)
93-
95+
picologging = pytest.importorskip("picologging")
9496
# Reset root logger (`picologging` module)
95-
pico_root_logger: picologging.Logger = picologging.getLogger()
97+
pico_root_logger: picologging.Logger = picologging.getLogger() # type: ignore[name-defined,unused-ignore] # pyright: ignore[reportPrivateUsage,reportGeneralTypeIssues,reportAssignmentType,reportInvalidTypeForm]
9698
for pico_handler in pico_root_logger.handlers:
9799
pico_root_logger.removeHandler(pico_handler)
98100

@@ -111,3 +113,10 @@ def cleanup_logging_impl() -> Generator:
111113
def not_none(val: T | None) -> T:
112114
assert val is not None
113115
return val
116+
117+
118+
def purge_module(module_names: list[str], path: str | Path) -> None:
119+
for name in module_names:
120+
if name in sys.modules:
121+
del sys.modules[name]
122+
Path(importlib.util.cache_from_source(path)).unlink(missing_ok=True) # type: ignore[arg-type]

0 commit comments

Comments
 (0)