fastapi-voyager 0.7.6__py3-none-any.whl → 0.8.2__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.
fastapi_voyager/render.py CHANGED
@@ -104,7 +104,7 @@ class Renderer:
104
104
  inner_nodes = [
105
105
  f'''
106
106
  "{r.id}" [
107
- label = " {r.name} "
107
+ label = " {r.name}: {r.response_schema} "
108
108
  margin="0.5,0.1"
109
109
  shape = "record"
110
110
  ];''' for r in mod.routes
fastapi_voyager/server.py CHANGED
@@ -33,6 +33,7 @@ class Payload(BaseModel):
33
33
  show_fields: str = 'object'
34
34
  show_meta: bool = False
35
35
  brief: bool = False
36
+ hide_primitive_route: bool = False
36
37
 
37
38
  def create_route(
38
39
  target_app: FastAPI,
@@ -65,6 +66,7 @@ def create_route(
65
66
 
66
67
  @router.post("/dot", response_class=PlainTextResponse)
67
68
  def get_filtered_dot(payload: Payload) -> str:
69
+ print(payload)
68
70
  voyager = Voyager(
69
71
  include_tags=payload.tags,
70
72
  schema=payload.schema_name,
@@ -73,6 +75,7 @@ def create_route(
73
75
  module_color=module_color,
74
76
  route_name=payload.route_name,
75
77
  load_meta=False,
78
+ hide_primitive_route=payload.hide_primitive_route,
76
79
  )
77
80
  voyager.analysis(target_app)
78
81
  if payload.brief:
fastapi_voyager/type.py CHANGED
@@ -24,6 +24,8 @@ class Route(NodeBase):
24
24
  module: str
25
25
  source_code: str = ''
26
26
  vscode_link: str = '' # optional vscode deep link
27
+ response_schema: str = ''
28
+ is_primitive: bool = True
27
29
 
28
30
  @dataclass
29
31
  class ModuleRoute:
@@ -276,6 +276,12 @@ def is_generic_container(cls):
276
276
  return (hasattr(cls, '__bases__') and Generic in cls.__bases__ and (hasattr(cls, '__parameters__') and bool(cls.__parameters__)))
277
277
  except (TypeError, AttributeError):
278
278
  return False
279
+
280
+ def is_non_pydantic_type(tp):
281
+ for schema in get_core_types(tp):
282
+ if schema and issubclass(schema, BaseModel):
283
+ return False
284
+ return True
279
285
 
280
286
  if __name__ == "__main__":
281
287
  from tests.demo_anno import PageSprint, PageOverall
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.7.6"
2
+ __version__ = "0.8.2"
@@ -8,7 +8,9 @@ from fastapi_voyager.type_helper import (
8
8
  get_pydantic_fields,
9
9
  get_vscode_link,
10
10
  get_source,
11
- update_forward_refs
11
+ get_type_name,
12
+ update_forward_refs,
13
+ is_non_pydantic_type
12
14
  )
13
15
  from pydantic import BaseModel
14
16
  from fastapi_voyager.type import Route, SchemaNode, Link, Tag, LinkType, FieldType, PK, CoreData
@@ -26,6 +28,7 @@ class Voyager:
26
28
  include_tags: list[str] | None = None,
27
29
  module_color: dict[str, str] | None = None,
28
30
  route_name: str | None = None,
31
+ hide_primitive_route: bool = False,
29
32
  load_meta: bool = False
30
33
  ):
31
34
 
@@ -48,6 +51,7 @@ class Voyager:
48
51
  self.module_color = module_color or {}
49
52
  self.route_name = route_name
50
53
  self.load_meta = load_meta
54
+ self.hide_primitive_route = hide_primitive_route
51
55
 
52
56
 
53
57
  def _get_available_route(self, app: FastAPI):
@@ -89,28 +93,36 @@ class Voyager:
89
93
  if self.route_name is not None and route_id != self.route_name:
90
94
  continue
91
95
 
96
+ is_primitive_response = is_non_pydantic_type(route.response_model)
97
+ # filter primitive route if needed
98
+ if self.hide_primitive_route and is_primitive_response:
99
+ continue
100
+
101
+ self.links.append(Link(
102
+ source=tag_id,
103
+ source_origin=tag_id,
104
+ target=route_id,
105
+ target_origin=route_id,
106
+ type='tag_route'
107
+ ))
108
+
92
109
  route_obj = Route(
93
110
  id=route_id,
94
111
  name=route_name,
95
112
  module=route_module,
96
113
  vscode_link=get_vscode_link(route.endpoint) if self.load_meta else '',
97
- source_code=inspect.getsource(route.endpoint) if self.load_meta else ''
114
+ source_code=inspect.getsource(route.endpoint) if self.load_meta else '',
115
+ response_schema=get_type_name(route.response_model),
116
+ is_primitive=is_primitive_response
98
117
  )
99
-
100
118
  self.routes.append(route_obj)
101
119
  # add route into current tag
102
120
  self.tag_set[tag_id].routes.append(route_obj)
103
- self.links.append(Link(
104
- source=tag_id,
105
- source_origin=tag_id,
106
- target=route_id,
107
- target_origin=route_id,
108
- type='tag_route'
109
- ))
110
121
 
111
122
  # add response_models and create links from route -> response_model
112
123
  for schema in get_core_types(route.response_model):
113
124
  if schema and issubclass(schema, BaseModel):
125
+ is_primitive_response = False
114
126
  target_name = full_class_name(schema)
115
127
  self.links.append(Link(
116
128
  source=route_id,
@@ -274,7 +286,6 @@ class Voyager:
274
286
  return renderer.render_dot(_tags, _routes, _nodes, _links)
275
287
 
276
288
  def render_brief_dot(self, module_prefix: str | None = None):
277
- print(module_prefix)
278
289
  _tags, _routes, _nodes, _links = filter_subgraph(
279
290
  module_prefix=module_prefix,
280
291
  tags=self.tags,
@@ -104,9 +104,6 @@
104
104
  </div>
105
105
  </div>
106
106
 
107
- <div class="col-auto">
108
- <q-toggle class="q-ml-md" v-model="state.brief" label="Brief Mode" title="config module_prefix to enable it" dense />
109
- </div>
110
107
 
111
108
  <!-- <div class="col-auto">
112
109
  <q-btn-dropdown
@@ -129,6 +126,10 @@
129
126
  </div> -->
130
127
 
131
128
  <div class="col-auto q-ml-auto">
129
+ <q-toggle class="q-ml-md" v-model="state.brief" label="Brief Mode" title="config module_prefix to enable it" dense />
130
+ <q-toggle class="q-ml-md" v-model="state.hidePrimitiveRoute" label="Hide Primitive Routes" title="" dense />
131
+ </div>
132
+ <div class="col-auto">
132
133
  <q-btn outline @click="onReset" title="may be very slow" label="Show All" />
133
134
  </div>
134
135
  <div class="col-auto">
@@ -200,7 +201,7 @@
200
201
 
201
202
  <q-list separator>
202
203
  <q-item
203
- v-for="route in (tag.routes || [])"
204
+ v-for="route in (state.hidePrimitiveRoute ? tag.routes.filter(r => !r.is_primitive) :tag.routes || [])"
204
205
  :key="route.id"
205
206
  clickable
206
207
  v-ripple
@@ -209,8 +210,8 @@
209
210
  @click="selectRoute(route.id)"
210
211
  >
211
212
  <q-item-section>
212
- <span class="q-ml-sm"> {{ route.name }} </span>
213
- </q-item-section>
213
+ <span class="q-ml-sm"> <span style="font-weight: bold;">⋅</span> &nbsp; {{ route.name }}</span>
214
+ </q-item-section>
214
215
  </q-item>
215
216
  <q-item v-if="!tag.routes || tag.routes.length === 0" dense>
216
217
  <q-item-section class="text-grey-6">No routes</q-item-section>
@@ -23,6 +23,7 @@ const app = createApp({
23
23
  { label: "All fields", value: "all" },
24
24
  ],
25
25
  brief: false,
26
+ hidePrimitiveRoute: false,
26
27
  generating: false,
27
28
  rawTags: [], // [{ name, routes: [{ id, name }] }]
28
29
  rawSchemas: [], // [{ name, fullname }]
@@ -123,6 +124,7 @@ const app = createApp({
123
124
  route_name: state.routeId || null,
124
125
  show_fields: state.showFields,
125
126
  brief: state.brief,
127
+ hide_primitive_route: state.hidePrimitiveRoute
126
128
  };
127
129
 
128
130
  const res = await fetch("dot", {
@@ -243,7 +245,11 @@ const app = createApp({
243
245
  }
244
246
 
245
247
  function selectRoute(routeId) {
246
- state.routeId = routeId
248
+ if (state.routeId === routeId) {
249
+ state.routeId = ''
250
+ } else {
251
+ state.routeId = routeId
252
+ }
247
253
  onGenerate()
248
254
  }
249
255
 
@@ -276,6 +282,15 @@ const app = createApp({
276
282
  }
277
283
  );
278
284
 
285
+ watch(
286
+ () => state.hidePrimitiveRoute,
287
+ () => {
288
+ if (!state.initializing) {
289
+ onGenerate();
290
+ }
291
+ }
292
+ );
293
+
279
294
  onMounted(async () => {
280
295
  await loadInitial();
281
296
  });
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.7.6
3
+ Version: 0.8.2
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
@@ -108,7 +108,10 @@ from fastapi import FastAPI
108
108
  from fastapi_voyager.server import create_app_with_fastapi
109
109
  from tests.demo import app
110
110
 
111
- app.mount('/voyager', create_app_with_fastapi(app))
111
+ app.mount('/voyager', create_app_with_fastapi(
112
+ app,
113
+ module_color={"tests.service": "red"},
114
+ module_prefix="tests.service"))
112
115
  ```
113
116
 
114
117
  more about [sub application](https://fastapi.tiangolo.com/advanced/sub-applications/?h=sub)
@@ -198,6 +201,8 @@ features:
198
201
  - [x] export voyager core data into json (for better debugging)
199
202
  - [x] add api to rebuild core data from json, and render it
200
203
  - [x] fix Generic case `test_generic.py`
204
+ - [ ] show tips for routes not return pydantic type.
205
+ - [ ] add http method for route
201
206
 
202
207
  bugs & non feature:
203
208
  - [x] fix duplicated link from class and parent class, it also break clicking highlight
@@ -220,6 +225,11 @@ TODO: ...
220
225
 
221
226
  ## Changelog
222
227
 
228
+ - 0.8:
229
+ - 0.8.2
230
+ - fix silly typo.
231
+ - 0.8.1
232
+ - add feature: hide primitive routes
223
233
  - 0.7:
224
234
  - 0.7.5
225
235
  - fix show all display issue
@@ -2,19 +2,19 @@ fastapi_voyager/__init__.py,sha256=E5WTV_sYs2LK8I6jzA7AuvFU5a8_vjnDseC3DMha0iQ,1
2
2
  fastapi_voyager/cli.py,sha256=2eixX7mtPsZvukc4vrwQOt6XTPJgHUKIGLBy3IIC2jE,11127
3
3
  fastapi_voyager/filter.py,sha256=2Yt37o8mhqSqleafO4YRrumh_ExYUqzXFOxQRPuTbAc,8078
4
4
  fastapi_voyager/module.py,sha256=Z2QHNmiLk6ZAJlm2nSmO875Q33TweSg8UxZSzIpU9zY,3499
5
- fastapi_voyager/render.py,sha256=rOJEKqiIAPowa3kZheRIgZMnbNzHQz9QoJM5aWUfXXs,7744
6
- fastapi_voyager/server.py,sha256=UT-fHggdqicIo5m3uUX86-XFhAVDLXpXBsBQwd1HdIg,4001
7
- fastapi_voyager/type.py,sha256=nad4WNxTcZFi7Mskw6p2W7v2Gs4f0giVLNoFjZlKmbA,1778
8
- fastapi_voyager/type_helper.py,sha256=f2Gy5r3Zi6a2wTkbqU9W-AkvcetajEYCfroACzcIcVY,9064
9
- fastapi_voyager/version.py,sha256=Oq-SkiGLvgSaGMuxFQNR6zCOQtBkYc1PpxNgDXQBXrg,48
10
- fastapi_voyager/voyager.py,sha256=uOQEzrs3o6UUUswvHGRKELNWYUH1ix0Z7SbzMHwm320,10709
5
+ fastapi_voyager/render.py,sha256=qy3g1Rz1s8XkuR_6n1Q1YPwy_oMOjWjNswTHQjdz4N0,7765
6
+ fastapi_voyager/server.py,sha256=Q9-f0frKHC4d0vN8ZasZyw6AsWKwLRB0P7z8dZ0lzjQ,4108
7
+ fastapi_voyager/type.py,sha256=k62cDofqmy-2q5rInW5LydLaRuDpKLsdbapps8Osqys,1838
8
+ fastapi_voyager/type_helper.py,sha256=hjBC4E0tgBpQDlYxGg74uK07SXjsrAgictEETJfIpYM,9231
9
+ fastapi_voyager/version.py,sha256=yVKW8UNsBx7oBKPkkSearnWpjZ_4I3OjOtDJSd778OY,48
10
+ fastapi_voyager/voyager.py,sha256=Tz-cJW1Pg9Ei6zX2CPCdAnkTqErp2OIIhhxeeDd6Nss,11221
11
11
  fastapi_voyager/web/graph-ui.js,sha256=eEjDnJVMvk35LdRoxcqX_fZxLFS9_bUrGAZL6K2O5C0,4176
12
12
  fastapi_voyager/web/graphviz.svg.css,sha256=zDCjjpT0Idufu5YOiZI76PL70-avP3vTyzGPh9M85Do,1563
13
13
  fastapi_voyager/web/graphviz.svg.js,sha256=lvAdbjHc-lMSk4GQp-iqYA2PCFX4RKnW7dFaoe0LUHs,16005
14
- fastapi_voyager/web/index.html,sha256=VZGdmFtNbZ4qdqb1763lbWW8Ta44ND_uNxyJyWOYsDc,12523
14
+ fastapi_voyager/web/index.html,sha256=iv4Fd0RsX854ZWrfSnVn-369_ky9ubFlK36vLiAbd0w,12760
15
15
  fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
16
16
  fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
17
- fastapi_voyager/web/vue-main.js,sha256=GLBePxcTIwFKwAA5WwujtxSpr4o2SmlgTVBgEvrPLto,9200
17
+ fastapi_voyager/web/vue-main.js,sha256=f4re2Hys0FOli3R_AZ_byUd08YLScDZ01xf1hXeoHCA,9529
18
18
  fastapi_voyager/web/component/render-graph.js,sha256=e8Xgh2Kl-nYU0P1gstEmAepCgFnk2J6UdxW8TlMafGs,2322
19
19
  fastapi_voyager/web/component/route-code-display.js,sha256=NECC1OGcPCdDfbghtRJEnmFM6HmH5J3win2ibapWPeA,2649
20
20
  fastapi_voyager/web/component/schema-code-display.js,sha256=oOusgTvCaWGnoKb-NBwu0SXqJJf2PTUtp3lUczokTBM,5515
@@ -26,8 +26,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
26
26
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
27
27
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
28
28
  fastapi_voyager/web/icon/site.webmanifest,sha256=ep4Hzh9zhmiZF2At3Fp1dQrYQuYF_3ZPZxc1KcGBvwQ,263
29
- fastapi_voyager-0.7.6.dist-info/METADATA,sha256=Q9qB67ItP5pcNEGbM0Rp2n_Aji4PS-R1h7CSvPQyeP4,7810
30
- fastapi_voyager-0.7.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- fastapi_voyager-0.7.6.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
32
- fastapi_voyager-0.7.6.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
33
- fastapi_voyager-0.7.6.dist-info/RECORD,,
29
+ fastapi_voyager-0.8.2.dist-info/METADATA,sha256=yLmyNrBFAkmFtX1EiHUf_m_2n7uM56Q9vK1s8MV_RNM,8082
30
+ fastapi_voyager-0.8.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
+ fastapi_voyager-0.8.2.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
32
+ fastapi_voyager-0.8.2.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
33
+ fastapi_voyager-0.8.2.dist-info/RECORD,,