fastapi-voyager 0.16.0a1__py3-none-any.whl → 0.16.0a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,11 +5,7 @@ This module provides the FastAPI-specific implementation of the voyager server.
5
5
  """
6
6
  from typing import Any, Literal
7
7
 
8
- from fastapi import APIRouter, FastAPI
9
- from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
10
- from fastapi.staticfiles import StaticFiles
11
8
  from pydantic import BaseModel
12
- from starlette.middleware.gzip import GZipMiddleware
13
9
 
14
10
  from fastapi_voyager.adapters.base import VoyagerAdapter
15
11
  from fastapi_voyager.adapters.common import STATIC_FILES_PATH, VoyagerContext
@@ -98,8 +94,14 @@ class FastAPIAdapter(VoyagerAdapter):
98
94
  )
99
95
  self.gzip_minimum_size = gzip_minimum_size
100
96
 
101
- def create_app(self) -> FastAPI:
97
+ def create_app(self) -> Any:
102
98
  """Create and return a FastAPI application with voyager endpoints."""
99
+ # Lazy import FastAPI to avoid import errors when framework is not installed
100
+ from fastapi import APIRouter, FastAPI
101
+ from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
102
+ from fastapi.staticfiles import StaticFiles
103
+ from starlette.middleware.gzip import GZipMiddleware
104
+
103
105
  router = APIRouter(tags=["fastapi-voyager"])
104
106
 
105
107
  @router.post("/er-diagram", response_class=PlainTextResponse)
@@ -5,9 +5,6 @@ This module provides the Litestar-specific implementation of the voyager server.
5
5
  """
6
6
  from typing import Any
7
7
 
8
- from litestar import Litestar, MediaType, Request, Response, get, post
9
- from litestar.static_files import create_static_files_router
10
-
11
8
  from fastapi_voyager.adapters.base import VoyagerAdapter
12
9
  from fastapi_voyager.adapters.common import STATIC_FILES_PATH, WEB_DIR, VoyagerContext
13
10
  from fastapi_voyager.type import CoreData, SchemaNode, Tag
@@ -47,8 +44,11 @@ class LitestarAdapter(VoyagerAdapter):
47
44
  )
48
45
  self.gzip_minimum_size = gzip_minimum_size
49
46
 
50
- def create_app(self) -> Litestar:
47
+ def create_app(self) -> Any:
51
48
  """Create and return a Litestar application with voyager endpoints."""
49
+ # Lazy import Litestar to avoid import errors when framework is not installed
50
+ from litestar import Litestar, MediaType, Request, Response, get, post
51
+ from litestar.static_files import create_static_files_router
52
52
 
53
53
  @get("/er-diagram")
54
54
  async def get_er_diagram(request: Request) -> str:
fastapi_voyager/cli.py CHANGED
@@ -5,17 +5,19 @@ import importlib.util
5
5
  import logging
6
6
  import os
7
7
  import sys
8
-
9
- from fastapi import FastAPI
8
+ from typing import TYPE_CHECKING
10
9
 
11
10
  from fastapi_voyager import server as viz_server
12
11
  from fastapi_voyager.version import __version__
13
12
  from fastapi_voyager.voyager import Voyager
14
13
 
14
+ if TYPE_CHECKING:
15
+ from fastapi import FastAPI
16
+
15
17
  logger = logging.getLogger(__name__)
16
18
 
17
19
 
18
- def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> FastAPI | None:
20
+ def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> "FastAPI | None":
19
21
  """Load FastAPI app from a Python module file."""
20
22
  try:
21
23
  # Convert relative path to absolute path
@@ -35,6 +37,8 @@ def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> FastA
35
37
  # Get the FastAPI app instance
36
38
  if hasattr(module, app_name):
37
39
  app = getattr(module, app_name)
40
+ # Lazy import to avoid import errors when FastAPI is not installed
41
+ from fastapi import FastAPI
38
42
  if isinstance(app, FastAPI):
39
43
  return app
40
44
  logger.error(f"'{app_name}' is not a FastAPI instance")
@@ -47,7 +51,7 @@ def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> FastA
47
51
  return None
48
52
 
49
53
 
50
- def load_fastapi_app_from_module(module_name: str, app_name: str = "app") -> FastAPI | None:
54
+ def load_fastapi_app_from_module(module_name: str, app_name: str = "app") -> "FastAPI | None":
51
55
  """Load FastAPI app from a Python module name."""
52
56
  try:
53
57
  # Temporarily add the current working directory to sys.path
@@ -65,6 +69,8 @@ def load_fastapi_app_from_module(module_name: str, app_name: str = "app") -> Fas
65
69
  # Get the FastAPI app instance
66
70
  if hasattr(module, app_name):
67
71
  app = getattr(module, app_name)
72
+ # Lazy import to avoid import errors when FastAPI is not installed
73
+ from fastapi import FastAPI
68
74
  if isinstance(app, FastAPI):
69
75
  return app
70
76
  logger.error(f"'{app_name}' is not a FastAPI instance")
@@ -85,7 +91,7 @@ def load_fastapi_app_from_module(module_name: str, app_name: str = "app") -> Fas
85
91
 
86
92
 
87
93
  def generate_visualization(
88
- app: FastAPI,
94
+ app: "FastAPI",
89
95
  output_file: str = "router_viz.dot", tags: list[str] | None = None,
90
96
  schema: str | None = None,
91
97
  show_fields: bool = False,
@@ -4,11 +4,13 @@ FastAPI implementation of the AppIntrospector interface.
4
4
  This module provides the adapter that allows fastapi-voyager to work with FastAPI applications.
5
5
  """
6
6
  from collections.abc import Iterator
7
-
8
- from fastapi import FastAPI, routing
7
+ from typing import TYPE_CHECKING, Any
9
8
 
10
9
  from fastapi_voyager.introspectors.base import AppIntrospector, RouteInfo
11
10
 
11
+ if TYPE_CHECKING:
12
+ from fastapi import FastAPI
13
+
12
14
 
13
15
  class FastAPIIntrospector(AppIntrospector):
14
16
  """
@@ -18,7 +20,7 @@ class FastAPIIntrospector(AppIntrospector):
18
20
  and converts it to the framework-agnostic RouteInfo format.
19
21
  """
20
22
 
21
- def __init__(self, app: FastAPI, swagger_url: str | None = None):
23
+ def __init__(self, app: "FastAPI", swagger_url: str | None = None):
22
24
  """
23
25
  Initialize the FastAPI introspector.
24
26
 
@@ -26,6 +28,12 @@ class FastAPIIntrospector(AppIntrospector):
26
28
  app: The FastAPI application instance
27
29
  swagger_url: Optional custom URL to Swagger documentation
28
30
  """
31
+ # Lazy import to avoid import errors when FastAPI is not installed
32
+ from fastapi import FastAPI
33
+
34
+ if not isinstance(app, FastAPI):
35
+ raise TypeError(f"Expected FastAPI instance, got {type(app)}")
36
+
29
37
  self.app = app
30
38
  self.swagger_url = swagger_url or "/docs"
31
39
 
@@ -36,6 +44,9 @@ class FastAPIIntrospector(AppIntrospector):
36
44
  Yields:
37
45
  RouteInfo: Standardized route information for each API route
38
46
  """
47
+ # Lazy import routing to avoid import errors when FastAPI is not installed
48
+ from fastapi import routing
49
+
39
50
  for route in self.app.routes:
40
51
  # Only process APIRoute instances (not static files, etc.)
41
52
  if isinstance(route, routing.APIRoute):
@@ -66,7 +77,7 @@ class FastAPIIntrospector(AppIntrospector):
66
77
  """
67
78
  return self.swagger_url
68
79
 
69
- def _get_route_id(self, route: routing.APIRoute) -> str:
80
+ def _get_route_id(self, route: Any) -> str:
70
81
  """
71
82
  Generate a unique identifier for the route.
72
83
 
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.16.0alpha-1"
2
+ __version__ = "0.16.0alpha-2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.16.0a1
3
+ Version: 0.16.0a2
4
4
  Summary: Visualize FastAPI application's routing tree and dependencies
5
5
  Project-URL: Homepage, https://github.com/allmonday/fastapi-voyager
6
6
  Project-URL: Source, https://github.com/allmonday/fastapi-voyager
@@ -20,15 +20,33 @@ Classifier: Programming Language :: Python :: 3.14
20
20
  Requires-Python: >=3.10
21
21
  Requires-Dist: jinja2>=3.0.0
22
22
  Requires-Dist: pydantic-resolve>=2.4.3
23
+ Provides-Extra: all
24
+ Requires-Dist: django-ninja>=1.5.3; extra == 'all'
25
+ Requires-Dist: django>=4.2; extra == 'all'
26
+ Requires-Dist: fastapi>=0.110; extra == 'all'
27
+ Requires-Dist: httpx; extra == 'all'
28
+ Requires-Dist: litestar>=2.19.0; extra == 'all'
29
+ Requires-Dist: pydantic>=2.0; extra == 'all'
30
+ Requires-Dist: pytest; extra == 'all'
31
+ Requires-Dist: pytest-asyncio; extra == 'all'
32
+ Requires-Dist: ruff; extra == 'all'
33
+ Requires-Dist: uvicorn; extra == 'all'
23
34
  Provides-Extra: dev
24
- Requires-Dist: django-ninja; extra == 'dev'
25
- Requires-Dist: fastapi>=0.110; extra == 'dev'
26
35
  Requires-Dist: httpx; extra == 'dev'
27
- Requires-Dist: litestar; extra == 'dev'
28
36
  Requires-Dist: pytest; extra == 'dev'
29
37
  Requires-Dist: pytest-asyncio; extra == 'dev'
30
38
  Requires-Dist: ruff; extra == 'dev'
31
- Requires-Dist: uvicorn; extra == 'dev'
39
+ Provides-Extra: django-ninja
40
+ Requires-Dist: django-ninja>=1.5.3; extra == 'django-ninja'
41
+ Requires-Dist: django>=4.2; extra == 'django-ninja'
42
+ Requires-Dist: uvicorn; extra == 'django-ninja'
43
+ Provides-Extra: fastapi
44
+ Requires-Dist: fastapi>=0.110; extra == 'fastapi'
45
+ Requires-Dist: uvicorn; extra == 'fastapi'
46
+ Provides-Extra: litestar
47
+ Requires-Dist: litestar>=2.19.0; extra == 'litestar'
48
+ Requires-Dist: pydantic>=2.0; extra == 'litestar'
49
+ Requires-Dist: uvicorn; extra == 'litestar'
32
50
  Description-Content-Type: text/markdown
33
51
 
34
52
  [![pypi](https://img.shields.io/pypi/v/fastapi-voyager.svg)](https://pypi.python.org/pypi/fastapi-voyager)
@@ -1,5 +1,5 @@
1
1
  fastapi_voyager/__init__.py,sha256=1IdDy6JUMgQqQo33qUe2znX9YeI7S35pjVrbt0QLOzY,228
2
- fastapi_voyager/cli.py,sha256=td3yIIigEomhSdDO-Xkh-CgpEwCafwlwnpvxnT9QsBo,10488
2
+ fastapi_voyager/cli.py,sha256=1o0areaN302fOoBprn-zXPnDFfCFbF81MatFTR1FHrU,10795
3
3
  fastapi_voyager/er_diagram.py,sha256=4Ba5u-T7XmVmk9MltVMe-m-18mUAHMTybTdE-zNZLrU,7860
4
4
  fastapi_voyager/filter.py,sha256=AN_HIu8-DtKisIq5mFt7CnqRHtxKewedNGyyaI82hSY,11529
5
5
  fastapi_voyager/module.py,sha256=h9YR3BpS-CAcJW9WCdVkF4opqwY32w9T67g9GfdLytk,3425
@@ -9,19 +9,19 @@ fastapi_voyager/render_style.py,sha256=1y3aRhBSJSWU-JuSgjn9il_xFEqjv6mJCoUzImLQT
9
9
  fastapi_voyager/server.py,sha256=sgUUscbt736VNB6CN2J_6rJ6fpWO4vJFW7oP7FmAjvA,6739
10
10
  fastapi_voyager/type.py,sha256=zluWvh5vpnjXJ9aAmyNJTSmXZPjAHCvgRT5oQRAjHrg,2104
11
11
  fastapi_voyager/type_helper.py,sha256=5HYUHdghTISZ44NvVsrMWlRGD5C9-xrGeNKuLYDMA6s,10209
12
- fastapi_voyager/version.py,sha256=0KZ1gUzWpAnbQTYDMdcLc-qEsyVlYlG265SEa7S4Ij4,56
12
+ fastapi_voyager/version.py,sha256=BzQ3H9QQr3tEif7581G5jfiOo26aX4wMpelAXUnXzF0,56
13
13
  fastapi_voyager/voyager.py,sha256=S0cCMLFv_wPfEMVdp4cYqbc-Y207SjCTSmsYdqzIDHg,15307
14
14
  fastapi_voyager/adapters/__init__.py,sha256=a95rBvV4QVcX_yAzjuJQKOW-EbJ79R--YjUJ3BGkC3k,517
15
15
  fastapi_voyager/adapters/base.py,sha256=m-E74LlNgYCpj-gqfYsKl2mzWW5iFiaDTjiBri_5cfo,1283
16
16
  fastapi_voyager/adapters/common.py,sha256=DXVLsjLn65U3RR7YyKL_ELV74mnINWmZ4hQ6zISdV0E,9684
17
17
  fastapi_voyager/adapters/django_ninja_adapter.py,sha256=tl1rMcotAhOwBxT8poG8rTXm1v3wn_cpaoda79NEFxE,11424
18
- fastapi_voyager/adapters/fastapi_adapter.py,sha256=-VvCXdMRsV_zZzEkplOGK8HjQ9ICoTyapG3ZluQ1Nvk,5870
19
- fastapi_voyager/adapters/litestar_adapter.py,sha256=-ILD8jIb82_JKV87p4IfV9IXvhUJ6RSic6i_iHapo5w,6812
18
+ fastapi_voyager/adapters/fastapi_adapter.py,sha256=attD4uuKXElFXk7JT7W-JW5B4S7a-qHzYVToHKBwTqk,5984
19
+ fastapi_voyager/adapters/litestar_adapter.py,sha256=9AfWuLtHHqzKj-VySJaOEtb7HWefRfJSobCQ_Y03ytU,6908
20
20
  fastapi_voyager/introspectors/__init__.py,sha256=HbmoUyM-BSwd4Rg2ptd9u-qvZSD3UykKyHYVoRg03OM,917
21
21
  fastapi_voyager/introspectors/base.py,sha256=hMfka9gVXr-E8MA1rKSSmYk0OppqgiFPWavfgAkPmQI,2131
22
22
  fastapi_voyager/introspectors/detector.py,sha256=rmlpQARJMrFXPty6OUdjmFRTtBYErGDH4l7Tivnu_FQ,3910
23
23
  fastapi_voyager/introspectors/django_ninja.py,sha256=Ytneh_kpsakTo_Njv1e4nvqfErjT1PrYelLZ-8xX5Gg,4052
24
- fastapi_voyager/introspectors/fastapi.py,sha256=SyWGKAH8cM3CENY-Uu3YY6e8kFM5BE-jEBBZLoIF--A,2696
24
+ fastapi_voyager/introspectors/fastapi.py,sha256=TGr1VPO0f6y-w3ZvQpI15o4Jq5L7VcN_twqzY_33fz4,3085
25
25
  fastapi_voyager/introspectors/litestar.py,sha256=QXnaT0-hCa_0sByKJoUWuu0vIzRpCCKLokCBDTtv_s4,6100
26
26
  fastapi_voyager/templates/dot/cluster.j2,sha256=I2z9KkfCzmAtqXe0gXBnxnOfBXUSpdlATs3uf-O8_B8,307
27
27
  fastapi_voyager/templates/dot/cluster_container.j2,sha256=2tH1mOJvPoVKE_aHVMR3t06TfH_dYa9OeH6DBqSHt_A,204
@@ -55,8 +55,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
55
55
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
56
56
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
57
57
  fastapi_voyager/web/icon/site.webmanifest,sha256=GRozZ5suTykYcPMap1QhjrAB8PLW0mbT_phhzw_utvQ,316
58
- fastapi_voyager-0.16.0a1.dist-info/METADATA,sha256=pGOq7n96lV1BKAXvCKPXUU8BvXN89HzgAMI90dmnH_Y,12943
59
- fastapi_voyager-0.16.0a1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
60
- fastapi_voyager-0.16.0a1.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
61
- fastapi_voyager-0.16.0a1.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
62
- fastapi_voyager-0.16.0a1.dist-info/RECORD,,
58
+ fastapi_voyager-0.16.0a2.dist-info/METADATA,sha256=SskYV4bCVQW96Q5CYbgZQEVt_ajQWPG1BO0uzKnxKmA,13701
59
+ fastapi_voyager-0.16.0a2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
60
+ fastapi_voyager-0.16.0a2.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
61
+ fastapi_voyager-0.16.0a2.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
62
+ fastapi_voyager-0.16.0a2.dist-info/RECORD,,