fastapi-voyager 0.13.1__py3-none-any.whl → 0.13.3__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.
@@ -70,7 +70,7 @@ class DiagramRenderer:
70
70
  def render_link(self, link: Link) -> str:
71
71
  h = self._handle_schema_anchor
72
72
  if link.type == 'schema':
73
- return f"""{h(link.source)}:e -> {h(link.target)}:w [style = "solid", label = "{link.label}", minlen=3];"""
73
+ return f"""{h(link.source)}:e -> {h(link.target)}:w [style = "{link.style}", label = "{link.label}", minlen=3];"""
74
74
  else:
75
75
  raise ValueError(f'Unknown link type: {link.type}')
76
76
 
@@ -154,6 +154,7 @@ class VoyagerErDiagram:
154
154
  er_diagram: ErDiagram,
155
155
  show_fields: FieldType = 'single',
156
156
  show_module: bool = False):
157
+
157
158
  self.er_diagram = er_diagram
158
159
  self.nodes: list[SchemaNode] = []
159
160
  self.node_set: dict[str, SchemaNode] = {}
@@ -186,7 +187,9 @@ class VoyagerErDiagram:
186
187
  target=self.generate_node_head(full_class_name(anno)),
187
188
  target_origin=full_class_name(anno),
188
189
  type='schema',
189
- label=get_type_name(relationship.target_kls))
190
+ label=get_type_name(relationship.target_kls),
191
+ style='solid' if relationship.loader else 'solid, dashed'
192
+ )
190
193
 
191
194
  elif isinstance(relationship, MultipleRelationship):
192
195
  for link in relationship.links:
@@ -197,7 +200,8 @@ class VoyagerErDiagram:
197
200
  target_origin=full_class_name(anno),
198
201
  type='schema',
199
202
  biz=link.biz,
200
- label=f'{get_type_name(relationship.target_kls)} / {link.biz} '
203
+ label=f'{get_type_name(relationship.target_kls)} / {link.biz} ',
204
+ style='solid' if link.loader else 'solid, dashed'
201
205
  )
202
206
 
203
207
  def add_to_node_set(self, schema, fk_set: set[str] | None = None) -> str:
@@ -226,6 +230,7 @@ class VoyagerErDiagram:
226
230
  target_origin: str,
227
231
  type: LinkType,
228
232
  label: str,
233
+ style: str,
229
234
  biz: str | None = None
230
235
  ) -> bool:
231
236
  """
@@ -241,7 +246,8 @@ class VoyagerErDiagram:
241
246
  target=target,
242
247
  target_origin=target_origin,
243
248
  type=type,
244
- label=label
249
+ label=label,
250
+ style=style
245
251
  ))
246
252
  return result
247
253
 
fastapi_voyager/type.py CHANGED
@@ -16,6 +16,7 @@ class FieldInfo:
16
16
  from_base: bool = False
17
17
  is_object: bool = False
18
18
  is_exclude: bool = False
19
+ desc: str = ''
19
20
 
20
21
  @dataclass
21
22
  class Tag(NodeBase):
@@ -68,6 +69,7 @@ class Link:
68
69
  target_origin: str
69
70
  type: LinkType
70
71
  label: str | None = None
72
+ style: str | None = None
71
73
 
72
74
  FieldType = Literal['single', 'object', 'all']
73
75
  PK = "PK"
@@ -182,7 +182,8 @@ def get_pydantic_fields(schema: type[BaseModel], bases_fields: set[str]) -> list
182
182
  name=k,
183
183
  from_base=k in bases_fields,
184
184
  type_name=get_type_name(anno),
185
- is_exclude=bool(v.exclude)
185
+ is_exclude=bool(v.exclude),
186
+ desc=v.description or ''
186
187
  ))
187
188
  return fields
188
189
 
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.13.1"
2
+ __version__ = "0.13.3"
@@ -179,6 +179,7 @@ export default defineComponent({
179
179
  <tr>
180
180
  <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Field</th>
181
181
  <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Type</th>
182
+ <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Description</th>
182
183
  <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Inherited</th>
183
184
  </tr>
184
185
  </thead>
@@ -186,6 +187,7 @@ export default defineComponent({
186
187
  <tr v-for="f in fields" :key="f.name">
187
188
  <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0;">{{ f.name }}</td>
188
189
  <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0; white-space:nowrap;">{{ f.type_name }}</td>
190
+ <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0; max-width: 200px;">{{ f.desc }}</td>
189
191
  <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0; text-align:left;">{{ f.from_base ? '✔︎' : '' }}</td>
190
192
  </tr>
191
193
  <tr v-if="!fields.length">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.13.1
3
+ Version: 0.13.3
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
@@ -35,11 +35,12 @@ Visualize your FastAPI endpoints, and explore them interactively.
35
35
 
36
36
  > This repo is still in early stage, it supports pydantic v2 only
37
37
 
38
- [live demo](https://www.newsyeah.fun/voyager/) of project: [composition oriented development pattern](https://github.com/allmonday/composition-oriented-development-pattern)
38
+ visit [live demo](https://www.newsyeah.fun/voyager/)
39
+ source code:[composition oriented development pattern](https://github.com/allmonday/composition-oriented-development-pattern)
39
40
 
40
- <img width="1600" height="986" alt="image" src="https://github.com/user-attachments/assets/8829cda0-f42d-4c84-be2f-b019bb5fe7e1" />
41
+ <img width="1597" height="933" alt="image" src="https://github.com/user-attachments/assets/020bf5b2-6c69-44bf-ba1f-39389d388d27" />
41
42
 
42
- with configuration:
43
+ with simple configuration it can be embedded into FastAPI.
43
44
 
44
45
  ```python
45
46
  app.mount('/voyager',
@@ -67,6 +68,8 @@ pip install fastapi-voyager
67
68
  uv add fastapi-voyager
68
69
  ```
69
70
 
71
+ run with cli:
72
+
70
73
  ```shell
71
74
  voyager -m path.to.your.app.module --server
72
75
  ```
@@ -77,47 +80,81 @@ voyager -m path.to.your.app.module --server
77
80
  voyager -m path.to.your.app.module --server --app api
78
81
  ```
79
82
 
80
- ## Mount into project
81
-
82
- ```python
83
- from fastapi import FastAPI
84
- from fastapi_voyager import create_voyager
85
- from tests.demo import app
86
-
87
- app.mount('/voyager', create_voyager(
88
- app,
89
- module_color={"tests.service": "red"},
90
- module_prefix="tests.service"),
91
- swagger_url="/docs")
92
- ```
93
83
 
94
84
  ## Features
95
85
 
96
86
  For scenarios of using FastAPI as internal API integration endpoints, `fastapi-voyager` helps to visualize the dependencies.
97
87
 
98
- It is also an architecture inspection tool that can identify issues in data relationships during design phase before turly implemtatioin.
88
+ It is also an architecture tool that can identify issues inside implementation, finding out wrong relationships, overfetchs, or anything else.
89
+
90
+ **If the process of building the view model follows the ER model**, the full potential of fastapi-voyager can be realized. It allows for quick identification of APIs that use entities, as well as which entities are used by a specific API
99
91
 
100
- If the process of building the view model follows the ER model, the full potential of fastapi-voyager can be realized. It allows for quick identification of APIs that use entities, as well as which entities are used by a specific API
92
+ Given ErDiagram defined by pydantic-resolve, application level entity relationship diagram can be visualized too.
101
93
 
102
94
  ### highlight nodes and links
103
95
  click a node to highlight it's upperstream and downstream nodes. figure out the related models of one page, or homw many pages are related with one model.
104
96
 
105
-
106
97
  <img width="1100" height="700" alt="image" src="https://github.com/user-attachments/assets/3e0369ea-5fa4-469a-82c1-ed57d407e53d" />
107
98
 
108
- ### focus on nodes
109
-
110
- Double click a node, and then toggle focus to hide irrelevant nodes.
111
-
112
- <img width="1061" height="937" alt="image" src="https://github.com/user-attachments/assets/79709b02-7571-43fc-abc9-17a287a97515" />
113
-
114
99
  ### view source code
115
100
 
116
101
  double click a node or route to show source code or open file in vscode.
117
102
 
118
103
  <img width="1297" height="940" alt="image" src="https://github.com/user-attachments/assets/c8bb2e7d-b727-42a6-8c9e-64dce297d2d8" />
119
104
 
120
- <img width="1132" height="824" alt="image" src="https://github.com/user-attachments/assets/b706e879-e4fc-48dd-ace1-99bf97e3ed6a" />
105
+ ### quick search
106
+
107
+ seach schemas by name and dispaly it's upstream and downstreams.
108
+
109
+ shift + click can quickly search current one
110
+
111
+ <img width="1587" height="873" alt="image" src="https://github.com/user-attachments/assets/ee4716f3-233d-418f-bc0e-3b214d1498f7" />
112
+
113
+ ### display ER diagram
114
+
115
+ ER diagram is a new feature from pydantic-resolve which provide a solid expression for business descritpions.
116
+
117
+ ```python
118
+ diagram = ErDiagram(
119
+ configs=[
120
+ Entity(
121
+ kls=Team,
122
+ relationships=[
123
+ Relationship( field='id', target_kls=list[Sprint], loader=sprint_loader.team_to_sprint_loader),
124
+ Relationship( field='id', target_kls=list[User], loader=user_loader.team_to_user_loader)
125
+ ]
126
+ ),
127
+ Entity(
128
+ kls=Sprint,
129
+ relationships=[
130
+ Relationship( field='id', target_kls=list[Story], loader=story_loader.sprint_to_story_loader)
131
+ ]
132
+ ),
133
+ Entity(
134
+ kls=Story,
135
+ relationships=[
136
+ Relationship( field='id', target_kls=list[Task], loader=task_loader.story_to_task_loader),
137
+ Relationship( field='owner_id', target_kls=User, loader=user_loader.user_batch_loader)
138
+ ]
139
+ ),
140
+ Entity(
141
+ kls=Task,
142
+ relationships=[
143
+ Relationship( field='owner_id', target_kls=User, loader=user_loader.user_batch_loader)
144
+ ]
145
+ )
146
+ ]
147
+ )
148
+
149
+ # display in voyager
150
+ app.mount('/voyager',
151
+ create_voyager(
152
+ app,
153
+ er_diagram=diagram)
154
+ ```
155
+
156
+ <img width="1276" height="613" alt="image" src="https://github.com/user-attachments/assets/ea0091bb-ee11-4f71-8be3-7129d956c910" />
157
+
121
158
 
122
159
 
123
160
  ## Command Line Usage
@@ -1,13 +1,13 @@
1
1
  fastapi_voyager/__init__.py,sha256=kqwzThE1YhmQ_7jPKGlnWvqRGC-hFrRqq_lKhKaleYU,229
2
2
  fastapi_voyager/cli.py,sha256=td3yIIigEomhSdDO-Xkh-CgpEwCafwlwnpvxnT9QsBo,10488
3
- fastapi_voyager/er_diagram.py,sha256=I-Fo03FMHu5INYeeycsdECN0oh7LroDHD88YlHwwUGA,10136
3
+ fastapi_voyager/er_diagram.py,sha256=cMiNKk4ufSM147ldvvfdqfv34Q5mj533VcELsp4Gwwc,10384
4
4
  fastapi_voyager/filter.py,sha256=AN_HIu8-DtKisIq5mFt7CnqRHtxKewedNGyyaI82hSY,11529
5
5
  fastapi_voyager/module.py,sha256=h9YR3BpS-CAcJW9WCdVkF4opqwY32w9T67g9GfdLytk,3425
6
6
  fastapi_voyager/render.py,sha256=O_HR8ypOrFhjejkBpKIH_8foB78DgzH0hvO-CWeYt0w,9976
7
7
  fastapi_voyager/server.py,sha256=UZi-VdsurjDnqDgf3l5LfgWfZ4OxzilC_A_Ju6x9jQc,8592
8
- fastapi_voyager/type.py,sha256=uniDpmNSf6r-5qoGVkOP6-k0kxxJyUvXsEBgW5sDFKg,1779
9
- fastapi_voyager/type_helper.py,sha256=UTCFWluFeGdGkJX3wiE_bZ2EgZsu4JkmqHjsJVdG81Q,9953
10
- fastapi_voyager/version.py,sha256=XPQT-MiS5izc8d6XhjxYtP7l6JRWW4h0BgwR0e2ndGo,49
8
+ fastapi_voyager/type.py,sha256=SPKEe0CrD4B4iB-lFQ9-wP6jXrO4rSMoU4p5uxbGcU4,1827
9
+ fastapi_voyager/type_helper.py,sha256=hRk1ssjimZwETQ-rRII1-4ReJO_vpsnQtamcZKOA2Gg,9991
10
+ fastapi_voyager/version.py,sha256=G1nfVjtIW-gYs-xjE2TKGW-IoBvxU-80bK_VtkMtqE8,49
11
11
  fastapi_voyager/voyager.py,sha256=iWt-_QsoKavhb9ZawhU3W8gv3vTwn8PWTevg8BooyV8,13923
12
12
  fastapi_voyager/web/graph-ui.js,sha256=hTsZO1Ly1JuoRg0kZWQ62jeLiD2kbnzACfbSPd0F95U,6634
13
13
  fastapi_voyager/web/graphviz.svg.css,sha256=zDCjjpT0Idufu5YOiZI76PL70-avP3vTyzGPh9M85Do,1563
@@ -20,7 +20,7 @@ fastapi_voyager/web/vue-main.js,sha256=BqFfjKRj1b2_nmR0Jmd2pL59Zk6qesrTNjRPpDRYM
20
20
  fastapi_voyager/web/component/demo.js,sha256=bQb16Un4XZ3Mf8qL6gvyrXe_mmA3V3mSIRMQAWg2MNk,352
21
21
  fastapi_voyager/web/component/render-graph.js,sha256=e8Xgh2Kl-nYU0P1gstEmAepCgFnk2J6UdxW8TlMafGs,2322
22
22
  fastapi_voyager/web/component/route-code-display.js,sha256=8NJPPjNRUC21gjpY8XYEQs4RBbhX1pCiqEhJp39ku6k,3678
23
- fastapi_voyager/web/component/schema-code-display.js,sha256=qKUMV2RFQzR8deof2iC4vyp65UaWadtVsDAXjY-i3vE,7042
23
+ fastapi_voyager/web/component/schema-code-display.js,sha256=E4XiX0ahPxQhvPhZxe_uAbm5FdZYJiml3UAfvIRyrBw,7269
24
24
  fastapi_voyager/web/icon/android-chrome-192x192.png,sha256=35sBy6jmUFJCcquStaafHH1qClZIbd-X3PIKSeLkrNo,37285
25
25
  fastapi_voyager/web/icon/android-chrome-512x512.png,sha256=eb2eDjCwIruc05029_0L9hcrkVkv8KceLn1DJMYU0zY,210789
26
26
  fastapi_voyager/web/icon/apple-touch-icon.png,sha256=gnWK46tPnvSw1-oYZjgI02wpoO4OrIzsVzGHC5oKWO0,33187
@@ -28,8 +28,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
28
28
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
29
29
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
30
30
  fastapi_voyager/web/icon/site.webmanifest,sha256=ep4Hzh9zhmiZF2At3Fp1dQrYQuYF_3ZPZxc1KcGBvwQ,263
31
- fastapi_voyager-0.13.1.dist-info/METADATA,sha256=9MgyRS-Az5198n87XhUnHLF6xgkghGxBeCM6TRmCitE,6521
32
- fastapi_voyager-0.13.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
- fastapi_voyager-0.13.1.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
34
- fastapi_voyager-0.13.1.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
35
- fastapi_voyager-0.13.1.dist-info/RECORD,,
31
+ fastapi_voyager-0.13.3.dist-info/METADATA,sha256=1jDBavGvAX72SPLnwkZKTlf9G0rv-gkN6J5bCVImAWQ,7777
32
+ fastapi_voyager-0.13.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
+ fastapi_voyager-0.13.3.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
34
+ fastapi_voyager-0.13.3.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
35
+ fastapi_voyager-0.13.3.dist-info/RECORD,,