fastapi-rtk 0.2.27__py3-none-any.whl → 1.0.13__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.
Files changed (98) hide show
  1. fastapi_rtk/__init__.py +39 -35
  2. fastapi_rtk/_version.py +1 -0
  3. fastapi_rtk/api/model_rest_api.py +476 -221
  4. fastapi_rtk/auth/auth.py +0 -9
  5. fastapi_rtk/backends/generic/__init__.py +6 -0
  6. fastapi_rtk/backends/generic/column.py +21 -12
  7. fastapi_rtk/backends/generic/db.py +42 -7
  8. fastapi_rtk/backends/generic/filters.py +21 -16
  9. fastapi_rtk/backends/generic/interface.py +14 -8
  10. fastapi_rtk/backends/generic/model.py +19 -11
  11. fastapi_rtk/backends/sqla/__init__.py +1 -0
  12. fastapi_rtk/backends/sqla/db.py +77 -17
  13. fastapi_rtk/backends/sqla/extensions/audit/audit.py +401 -189
  14. fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +15 -12
  15. fastapi_rtk/backends/sqla/filters.py +50 -21
  16. fastapi_rtk/backends/sqla/interface.py +96 -34
  17. fastapi_rtk/backends/sqla/model.py +56 -39
  18. fastapi_rtk/bases/__init__.py +20 -0
  19. fastapi_rtk/bases/db.py +94 -7
  20. fastapi_rtk/bases/file_manager.py +47 -3
  21. fastapi_rtk/bases/filter.py +22 -0
  22. fastapi_rtk/bases/interface.py +49 -5
  23. fastapi_rtk/bases/model.py +3 -0
  24. fastapi_rtk/bases/session.py +2 -0
  25. fastapi_rtk/cli/cli.py +62 -9
  26. fastapi_rtk/cli/commands/__init__.py +23 -0
  27. fastapi_rtk/cli/{db.py → commands/db/__init__.py} +107 -50
  28. fastapi_rtk/cli/{templates → commands/db/templates}/fastapi/env.py +2 -3
  29. fastapi_rtk/cli/{templates → commands/db/templates}/fastapi-multidb/env.py +10 -9
  30. fastapi_rtk/cli/{templates → commands/db/templates}/fastapi-multidb/script.py.mako +3 -1
  31. fastapi_rtk/cli/{export.py → commands/export.py} +12 -10
  32. fastapi_rtk/cli/{security.py → commands/security.py} +73 -7
  33. fastapi_rtk/cli/commands/translate.py +299 -0
  34. fastapi_rtk/cli/decorators.py +9 -4
  35. fastapi_rtk/cli/utils.py +46 -0
  36. fastapi_rtk/config.py +41 -1
  37. fastapi_rtk/const.py +29 -1
  38. fastapi_rtk/db.py +76 -40
  39. fastapi_rtk/decorators.py +1 -1
  40. fastapi_rtk/dependencies.py +134 -62
  41. fastapi_rtk/exceptions.py +51 -1
  42. fastapi_rtk/fastapi_react_toolkit.py +186 -171
  43. fastapi_rtk/file_managers/file_manager.py +8 -6
  44. fastapi_rtk/file_managers/s3_file_manager.py +69 -33
  45. fastapi_rtk/globals.py +22 -12
  46. fastapi_rtk/lang/__init__.py +3 -0
  47. fastapi_rtk/lang/babel/__init__.py +4 -0
  48. fastapi_rtk/lang/babel/cli.py +40 -0
  49. fastapi_rtk/lang/babel/config.py +17 -0
  50. fastapi_rtk/lang/babel.cfg +1 -0
  51. fastapi_rtk/lang/lazy_text.py +120 -0
  52. fastapi_rtk/lang/messages.pot +238 -0
  53. fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
  54. fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +248 -0
  55. fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
  56. fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +244 -0
  57. fastapi_rtk/manager.py +355 -37
  58. fastapi_rtk/mixins.py +12 -0
  59. fastapi_rtk/routers.py +208 -72
  60. fastapi_rtk/schemas.py +142 -39
  61. fastapi_rtk/security/sqla/apis.py +39 -13
  62. fastapi_rtk/security/sqla/models.py +8 -23
  63. fastapi_rtk/security/sqla/security_manager.py +369 -11
  64. fastapi_rtk/setting.py +446 -88
  65. fastapi_rtk/types.py +94 -27
  66. fastapi_rtk/utils/__init__.py +8 -0
  67. fastapi_rtk/utils/async_task_runner.py +286 -61
  68. fastapi_rtk/utils/csv_json_converter.py +243 -40
  69. fastapi_rtk/utils/hooks.py +34 -0
  70. fastapi_rtk/utils/merge_schema.py +3 -3
  71. fastapi_rtk/utils/multiple_async_contexts.py +21 -0
  72. fastapi_rtk/utils/pydantic.py +46 -1
  73. fastapi_rtk/utils/run_utils.py +31 -1
  74. fastapi_rtk/utils/self_dependencies.py +1 -1
  75. fastapi_rtk/utils/use_default_when_none.py +1 -1
  76. fastapi_rtk/version.py +6 -1
  77. fastapi_rtk-1.0.13.dist-info/METADATA +28 -0
  78. fastapi_rtk-1.0.13.dist-info/RECORD +133 -0
  79. {fastapi_rtk-0.2.27.dist-info → fastapi_rtk-1.0.13.dist-info}/WHEEL +1 -2
  80. fastapi_rtk/backends/gremlinpython/__init__.py +0 -108
  81. fastapi_rtk/backends/gremlinpython/column.py +0 -208
  82. fastapi_rtk/backends/gremlinpython/db.py +0 -228
  83. fastapi_rtk/backends/gremlinpython/exceptions.py +0 -34
  84. fastapi_rtk/backends/gremlinpython/filters.py +0 -461
  85. fastapi_rtk/backends/gremlinpython/interface.py +0 -734
  86. fastapi_rtk/backends/gremlinpython/model.py +0 -364
  87. fastapi_rtk/backends/gremlinpython/session.py +0 -23
  88. fastapi_rtk/cli/commands.py +0 -295
  89. fastapi_rtk-0.2.27.dist-info/METADATA +0 -23
  90. fastapi_rtk-0.2.27.dist-info/RECORD +0 -126
  91. fastapi_rtk-0.2.27.dist-info/top_level.txt +0 -1
  92. /fastapi_rtk/cli/{templates → commands/db/templates}/fastapi/README +0 -0
  93. /fastapi_rtk/cli/{templates → commands/db/templates}/fastapi/alembic.ini.mako +0 -0
  94. /fastapi_rtk/cli/{templates → commands/db/templates}/fastapi/script.py.mako +0 -0
  95. /fastapi_rtk/cli/{templates → commands/db/templates}/fastapi-multidb/README +0 -0
  96. /fastapi_rtk/cli/{templates → commands/db/templates}/fastapi-multidb/alembic.ini.mako +0 -0
  97. {fastapi_rtk-0.2.27.dist-info → fastapi_rtk-1.0.13.dist-info}/entry_points.txt +0 -0
  98. {fastapi_rtk-0.2.27.dist-info → fastapi_rtk-1.0.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,228 +0,0 @@
1
- import contextlib
2
-
3
- import fastapi
4
- import gremlin_python.driver.driver_remote_connection
5
- import gremlin_python.process.anonymous_traversal
6
- import gremlin_python.process.graph_traversal
7
- import gremlin_python.process.traversal
8
-
9
- from ...bases.db import AbstractQueryBuilder
10
- from ...const import logger
11
- from ...setting import Setting
12
- from ...utils import lazy
13
- from .model import UNSPECIFIED_LABEL
14
-
15
- try:
16
- import janusgraph_python.driver.serializer
17
-
18
- serializer = janusgraph_python.driver.serializer
19
- except ImportError:
20
- logger.warning(
21
- "janusgraph_python is not installed. Some Gremlin features may not work as expected."
22
- )
23
- serializer = None
24
-
25
- __all__ = ["GremlinQueryBuilder", "graph_db"]
26
-
27
-
28
- class GremlinQueryBuilder(
29
- AbstractQueryBuilder[gremlin_python.process.graph_traversal.GraphTraversal]
30
- ):
31
- """
32
- A class that builds Gremlin queries for a graph database.
33
- """
34
-
35
- build_steps = list(reversed(AbstractQueryBuilder.DEFAULT_BUILD_STEPS))
36
-
37
- def __init__(self, datamodel, statement=None):
38
- try:
39
- super().__init__(datamodel, statement)
40
- except RuntimeError:
41
- pass
42
-
43
- def apply_list_columns(self, statement, list_columns):
44
- list_columns = list(
45
- dict.fromkeys(
46
- x.split(".")[0]
47
- for x in list_columns
48
- if x != self.datamodel.obj.__mapper__.pk
49
- and x != self.datamodel.obj.__mapper__.lk
50
- and x not in self.datamodel.get_property_column_list()
51
- )
52
- )
53
- relation_columns = [
54
- x for x in self.datamodel.get_relation_columns() if x in list_columns
55
- ]
56
- list_columns = [x for x in list_columns if x not in relation_columns]
57
-
58
- statement = statement.project(
59
- self.datamodel.obj.__label__ or UNSPECIFIED_LABEL, *relation_columns
60
- ).by(gremlin_python.process.graph_traversal.__.valueMap(True, *list_columns))
61
-
62
- for rel_col in relation_columns:
63
- direction = self.datamodel.list_properties[rel_col].direction
64
- sub_statement = gremlin_python.process.graph_traversal.__
65
- match direction:
66
- case "in":
67
- sub_statement = sub_statement.inE
68
- case "out":
69
- sub_statement = sub_statement.outE
70
- case "both":
71
- sub_statement = sub_statement.bothE
72
- if self.datamodel.list_properties[rel_col].name:
73
- sub_statement = sub_statement(
74
- self.datamodel.list_properties[rel_col].name
75
- )
76
- else:
77
- sub_statement = sub_statement()
78
- if self.datamodel.list_properties[rel_col].properties:
79
- for key, value in self.datamodel.list_properties[
80
- rel_col
81
- ].properties.items():
82
- sub_statement = sub_statement.has(key, value)
83
- sub_other_v_statement = (
84
- sub_statement.otherV()
85
- if not self.datamodel.list_properties[rel_col].with_edge
86
- else gremlin_python.process.graph_traversal.__.otherV()
87
- )
88
- if self.datamodel.list_properties[rel_col].obj_properties:
89
- for key, value in self.datamodel.list_properties[
90
- rel_col
91
- ].obj_properties.items():
92
- sub_other_v_statement = sub_other_v_statement.has(key, value)
93
- sub_other_v_statement = sub_other_v_statement.valueMap(True)
94
- if self.datamodel.list_properties[rel_col].with_edge:
95
- sub_statement = (
96
- sub_statement.project("edge", rel_col)
97
- .by(gremlin_python.process.graph_traversal.__.valueMap(True))
98
- .by(sub_other_v_statement)
99
- )
100
- else:
101
- sub_statement = sub_other_v_statement
102
- sub_statement = sub_statement.fold()
103
- statement = statement.by(sub_statement)
104
-
105
- return statement
106
-
107
- def apply_pagination(self, statement, page, page_size):
108
- lower_range = page_size * (page or 0)
109
- return statement.range_(lower_range, lower_range + page_size)
110
-
111
- def apply_order_by(self, statement, order_column, order_direction):
112
- return statement.order().by(
113
- order_column,
114
- gremlin_python.process.traversal.Order.asc
115
- if order_direction == "asc"
116
- else gremlin_python.process.traversal.Order.desc,
117
- )
118
-
119
- def apply_where(self, statement, column, value):
120
- args = [column, value]
121
- func = statement.has
122
- if column.lower() == self.datamodel.obj.__mapper__.pk:
123
- func = statement.hasId
124
- args = args[1:]
125
- elif column.lower() == self.datamodel.obj.__mapper__.lk:
126
- func = statement.hasLabel
127
- args = args[1:]
128
- return func(*args)
129
-
130
- def apply_where_in(self, statement, column, values):
131
- args = [column, gremlin_python.process.traversal.within(values)]
132
- func = statement.has
133
- if column.lower() == self.datamodel.obj.__mapper__.pk:
134
- func = statement.hasId
135
- args = args[1:]
136
- elif column.lower() == self.datamodel.obj.__mapper__.lk:
137
- func = statement.hasLabel
138
- args = args[1:]
139
- return func(*args)
140
-
141
- def apply_filter(self, statement, filter):
142
- filter_classes = self.datamodel.filters.get(filter.col)
143
- filter_class = None
144
- for f in filter_classes:
145
- if f.arg_name == filter.opr:
146
- filter_class = f
147
- break
148
- if not filter_class:
149
- raise fastapi.HTTPException(
150
- status_code=400, detail=f"Invalid filter opr: {filter.opr}"
151
- )
152
-
153
- col = filter.col
154
- value = filter.value
155
-
156
- return self.apply_filter_class(statement, col, filter_class, value)
157
-
158
- def apply_filter_class(self, statement, col, filter_class, value):
159
- return filter_class.apply(statement, col, value)
160
-
161
- def apply_global_filter(self, statement, columns, global_filter):
162
- return super().apply_global_filter(statement, columns, global_filter)
163
-
164
-
165
- class GremlinDatabaseSessionManager:
166
- gremlin_connection = lazy(lambda: Setting.GREMLIN_CONNECTION)
167
-
168
- @contextlib.contextmanager
169
- def connect(self, bind: str | None = None, keep_open=False):
170
- """
171
- Establishes a connection to the graph database.
172
-
173
- Args:
174
- bind (str | None, optional): The bind key to retrieve the connection for. If None, the default connection is returned. Defaults to None. UNUSED FOR NOW.
175
- keep_open (bool, optional): Whether to keep the connection open after use. Defaults to False.
176
-
177
- Yields:
178
- gremlin_python.driver.driver_remote_connection.DriverRemoteConnection: The graph database connection.
179
- """
180
- url, graph_object = self.gremlin_connection
181
- connection = (
182
- gremlin_python.driver.driver_remote_connection.DriverRemoteConnection(
183
- url,
184
- graph_object,
185
- # session=True, #! When true, can not add Edge
186
- message_serializer=serializer.JanusGraphSONSerializersV3d0()
187
- if serializer
188
- else None,
189
- **Setting.GREMLIN_CONNECTION_OPTIONS,
190
- )
191
- )
192
- try:
193
- if keep_open:
194
- logger.warning(
195
- f"Connection {connection} is kept open. Make sure to close it manually when done."
196
- )
197
- yield connection
198
- except Exception:
199
- connection.rollback()
200
- raise
201
- finally:
202
- if keep_open:
203
- return
204
- connection.close()
205
-
206
- @contextlib.contextmanager
207
- def session(self, bind: str | None = None, keep_open=False):
208
- """
209
- Provides a graph database session for performing database operations.
210
-
211
- Args:
212
- bind (str | None, optional): The bind key to retrieve the session for. If None, the default session is returned. Defaults to None. UNUSED FOR NOW.
213
- keep_open (bool, optional): Whether to keep the connection open after use. Defaults to False.
214
-
215
- Yields:
216
- gremlin_python.process.graph_traversal.GraphTraversal: A graph traversal object for executing queries.
217
- """
218
- with self.connect(bind, keep_open) as connection:
219
- traversal = (
220
- gremlin_python.process.anonymous_traversal.traversal().withRemote(
221
- connection
222
- )
223
- )
224
- traversal.remote_connection = connection
225
- yield traversal
226
-
227
-
228
- graph_db = GremlinDatabaseSessionManager()
@@ -1,34 +0,0 @@
1
- __all__ = ["GremlinMissingLabelException", "LKMultipleException"]
2
-
3
-
4
- class BaseGremlinException(Exception):
5
- """
6
- Base exception for all Gremlin-related errors.
7
- """
8
-
9
-
10
- class GremlinMissingLabelException(BaseGremlinException):
11
- """
12
- Exception raised when a Gremlin model is missing a label.
13
- """
14
-
15
- def __init__(self, model_name: str):
16
- super().__init__(f"Model {model_name} is missing a label.")
17
- self.model_name = model_name
18
-
19
- def __repr__(self):
20
- return f"Gremlin model '{self.model_name}' must have a label defined."
21
-
22
-
23
- class LKMultipleException(BaseGremlinException):
24
- """
25
- Exception raised when a Gremlin model has multiple label keys defined.
26
- """
27
-
28
- def __init__(self, model_name: str, message: str):
29
- super().__init__(f"{model_name}: {message}")
30
- self.model_name = model_name
31
- self.message = message
32
-
33
- def __repr__(self):
34
- return f"Gremlin model '{self.model_name}' has multiple label keys defined: {self.message}"