diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 56059d2..12bc3b3 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v3 diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 34ae0fa..9c3d3eb 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -20,9 +20,8 @@ def show_toolbar(request: Request, settings: DebugToolbarSettings) -> bool: - if settings.ALLOWED_IPS is not None: - remote_addr, _ = request["client"] - return request.app.debug and remote_addr in settings.ALLOWED_IPS + if request.client is not None and settings.ALLOWED_HOSTS is not None: + return request.app.debug and request.client.host in settings.ALLOWED_HOSTS return request.app.debug diff --git a/debug_toolbar/panels/sqlalchemy.py b/debug_toolbar/panels/sqlalchemy.py index 5db9312..e3de433 100644 --- a/debug_toolbar/panels/sqlalchemy.py +++ b/debug_toolbar/panels/sqlalchemy.py @@ -1,8 +1,8 @@ import typing as t +from contextlib import AsyncExitStack from time import perf_counter from fastapi import Request, Response -from fastapi.concurrency import AsyncExitStack from fastapi.dependencies.utils import solve_dependencies from sqlalchemy import event from sqlalchemy.engine import Connection, Engine, ExecutionContext @@ -52,6 +52,7 @@ async def add_engines(self, request: Request): request=request, dependant=route.dependant, dependency_overrides_provider=route.dependency_overrides_provider, + async_exit_stack=AsyncExitStack(), ) for value in solved_result[0].values(): if isinstance(value, Session): diff --git a/debug_toolbar/panels/versions.py b/debug_toolbar/panels/versions.py index 7c45e82..a3f0883 100644 --- a/debug_toolbar/panels/versions.py +++ b/debug_toolbar/panels/versions.py @@ -1,4 +1,5 @@ import typing as t +from importlib import metadata from fastapi import Request, Response, __version__ @@ -21,13 +22,8 @@ def scripts(self) -> t.List[str]: return scripts async def generate_stats(self, request: Request, response: Response) -> Stats: - try: - import pkg_resources - except ImportError: - packages = [] - else: - packages = sorted( - pkg_resources.working_set, - key=lambda pkg: pkg.project_name.lower(), - ) + packages = sorted( + metadata.distributions(), + key=lambda dist: dist.metadata["name"].lower(), + ) return {"packages": packages} diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index 7012947..dc7f7d4 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -2,7 +2,7 @@ from jinja2 import BaseLoader, ChoiceLoader, Environment, PackageLoader from jinja2.ext import Extension -from pydantic import Field, IPvAnyAddress, model_validator +from pydantic import Field, model_validator from pydantic_extra_types.color import Color from pydantic_settings import BaseSettings, SettingsConfigDict @@ -45,11 +45,11 @@ class DebugToolbarSettings(BaseSettings): "want disabled (but still displayed) by default." ), ) - ALLOWED_IPS: t.Optional[t.Sequence[IPvAnyAddress]] = Field( + ALLOWED_HOSTS: t.Optional[t.Sequence[str]] = Field( None, description=( "If it's set, the Debug Toolbar is shown only " - "if your IP address is listed." + "if the request host is listed." ), ) JINJA_ENV: Environment = Field( diff --git a/debug_toolbar/templates/panels/versions.html b/debug_toolbar/templates/panels/versions.html index 40c66e8..7464b4f 100644 --- a/debug_toolbar/templates/panels/versions.html +++ b/debug_toolbar/templates/panels/versions.html @@ -15,8 +15,8 @@ {% for package in packages %} - - {{ package.project_name }} + + {{ package.metadata.name }} {{ package.version }} diff --git a/pyproject.toml b/pyproject.toml index 5394f93..d7e3521 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "fastapi-debug-toolbar" description = "A debug toolbar for FastAPI." readme = "README.md" license = "BSD-3-Clause" -requires-python = ">=3.7" +requires-python = ">=3.8" dynamic = ["version"] authors = [ { name = "Dani", email = "dani@domake.io" } @@ -26,11 +26,11 @@ classifiers = [ "Typing :: Typed", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "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", "Topic :: Software Development", "Topic :: Software Development :: Debuggers", "Topic :: Software Development :: Libraries", @@ -42,7 +42,7 @@ classifiers = [ ] dependencies = [ - "fastapi >=0.70.0", + "fastapi >=0.106.0", "anyio >=3.0.0", "Jinja2 >=2.9", "pydantic >=2.0", diff --git a/tests/test_api.py b/tests/test_api.py index 76ab3a2..3bb57fc 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,6 +1,6 @@ from fastapi import status -from .mark import override_panels, override_settings +from .mark import override_panels from .testclient import TestClient @@ -19,12 +19,3 @@ def test_invalid_store_id(client: TestClient) -> None: assert response.status_code == status.HTTP_200_OK assert not response.json()["scripts"] - - -@override_settings( - panels=["debug_toolbar.panels.timer.TimerPanel"], - allowed_ips=[], -) -def test_not_allowed(client: TestClient) -> None: - response = client.render_panel(store_id="", panel_id="TimerPanel") - assert response.status_code == status.HTTP_404_NOT_FOUND