fastapi-rtk 0.2.60__py3-none-any.whl → 1.0.18__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 (40) hide show
  1. fastapi_rtk/__init__.py +0 -1
  2. fastapi_rtk/_version.py +1 -0
  3. fastapi_rtk/api/model_rest_api.py +182 -87
  4. fastapi_rtk/auth/auth.py +0 -9
  5. fastapi_rtk/backends/sqla/db.py +32 -7
  6. fastapi_rtk/backends/sqla/filters.py +16 -0
  7. fastapi_rtk/backends/sqla/interface.py +11 -62
  8. fastapi_rtk/backends/sqla/model.py +16 -1
  9. fastapi_rtk/bases/db.py +20 -2
  10. fastapi_rtk/bases/file_manager.py +12 -0
  11. fastapi_rtk/bases/filter.py +1 -1
  12. fastapi_rtk/cli/cli.py +61 -0
  13. fastapi_rtk/cli/commands/security.py +6 -6
  14. fastapi_rtk/const.py +1 -1
  15. fastapi_rtk/db.py +3 -0
  16. fastapi_rtk/dependencies.py +110 -64
  17. fastapi_rtk/fastapi_react_toolkit.py +123 -172
  18. fastapi_rtk/file_managers/s3_file_manager.py +63 -32
  19. fastapi_rtk/lang/messages.pot +12 -12
  20. fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
  21. fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +12 -12
  22. fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
  23. fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +12 -12
  24. fastapi_rtk/manager.py +10 -14
  25. fastapi_rtk/schemas.py +6 -4
  26. fastapi_rtk/security/sqla/apis.py +20 -5
  27. fastapi_rtk/security/sqla/models.py +8 -23
  28. fastapi_rtk/security/sqla/security_manager.py +367 -10
  29. fastapi_rtk/utils/async_task_runner.py +119 -30
  30. fastapi_rtk/utils/csv_json_converter.py +242 -39
  31. fastapi_rtk/utils/hooks.py +7 -4
  32. fastapi_rtk/utils/self_dependencies.py +1 -1
  33. fastapi_rtk/version.py +6 -1
  34. fastapi_rtk-1.0.18.dist-info/METADATA +28 -0
  35. {fastapi_rtk-0.2.60.dist-info → fastapi_rtk-1.0.18.dist-info}/RECORD +38 -38
  36. {fastapi_rtk-0.2.60.dist-info → fastapi_rtk-1.0.18.dist-info}/WHEEL +1 -2
  37. fastapi_rtk-0.2.60.dist-info/METADATA +0 -25
  38. fastapi_rtk-0.2.60.dist-info/top_level.txt +0 -1
  39. {fastapi_rtk-0.2.60.dist-info → fastapi_rtk-1.0.18.dist-info}/entry_points.txt +0 -0
  40. {fastapi_rtk-0.2.60.dist-info → fastapi_rtk-1.0.18.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,15 @@
1
+ import abc
1
2
  import csv
2
3
  import enum
4
+ import inspect
3
5
  import json
4
6
  import typing
5
7
 
8
+ from .run_utils import safe_call
9
+
10
+ if typing.TYPE_CHECKING:
11
+ from ..bases import BasicModel
12
+
6
13
  __all__ = ["Line", "CSVJSONConverter"]
7
14
 
8
15
 
@@ -57,7 +64,7 @@ class CSVJSONConverter:
57
64
  @classmethod
58
65
  def json_to_csv(
59
66
  cls,
60
- data: dict[str, typing.Any] | list[dict[str, typing.Any]],
67
+ data: "dict[str, typing.Any] | list[dict[str, typing.Any]] | BasicModel | list[BasicModel]",
61
68
  /,
62
69
  *,
63
70
  list_columns: list[str],
@@ -71,8 +78,10 @@ class CSVJSONConverter:
71
78
  """
72
79
  Converts JSON data to CSV format.
73
80
 
81
+ - Data can also be a subclass of `BasicModel` or a list of subclasses of `BasicModel`.
82
+
74
83
  Args:
75
- data (dict[str, Any] | list[dict[str, Any]]): The JSON data to be converted.
84
+ data (dict[str, typing.Any] | list[dict[str, typing.Any]] | BasicModel | list[BasicModel]): The JSON data to be converted. Can also be a subclass of `BasicModel` or a list of subclasses of `BasicModel`.
76
85
  list_columns (list[str]): The list of columns to be included in the CSV.
77
86
  label_columns (dict[str, str]): The mapping of column names to labels.
78
87
  with_header (bool, optional): Whether to include the header in the CSV. Defaults to True.
@@ -93,11 +102,11 @@ class CSVJSONConverter:
93
102
  writer.writerow(header)
94
103
  csv_data = line.read()
95
104
 
96
- if isinstance(data, dict):
105
+ if not isinstance(data, list):
97
106
  data = [data]
98
107
 
99
108
  for item in data:
100
- row = cls._json_to_csv(
109
+ row = cls.json_to_csv_single(
101
110
  item,
102
111
  list_columns=list_columns,
103
112
  delimiter=delimiter,
@@ -110,9 +119,9 @@ class CSVJSONConverter:
110
119
  return csv_data.strip()
111
120
 
112
121
  @classmethod
113
- def _json_to_csv(
122
+ def json_to_csv_single(
114
123
  self,
115
- data: dict[str, typing.Any],
124
+ data: "dict[str, typing.Any] | BasicModel",
116
125
  /,
117
126
  *,
118
127
  list_columns: list[str],
@@ -123,8 +132,10 @@ class CSVJSONConverter:
123
132
  """
124
133
  Converts single JSON object to CSV format.
125
134
 
135
+ - Data can also be a subclass of `BasicModel`.
136
+
126
137
  Args:
127
- data (dict[str, Any]): The JSON data to be converted.
138
+ data (dict[str, typing.Any] | BasicModel): The JSON data to be converted. Can also be a subclass of `BasicModel`.
128
139
  list_columns (list[str]): The list of columns to be included in the CSV.
129
140
  delimiter (str, optional): The delimiter to use in the CSV. Defaults to ",".
130
141
  relation_separator (str, optional): The separator to use for nested keys. Defaults to ".".
@@ -134,40 +145,60 @@ class CSVJSONConverter:
134
145
  str: The CSV data as a string.
135
146
  """
136
147
  csv_data: list[str] = []
148
+ data_pipeline = DataPipeline()
149
+ data_pipeline.add_processor(ColumnProcessor(relation_separator))
150
+ data_pipeline.add_processor(ModelProcessor())
151
+ data_pipeline.add_processor(
152
+ ListProcessor(delimiter=delimiter, export_mode=export_mode)
153
+ )
154
+ data_pipeline.add_processor(EnumProcessor())
155
+ data_pipeline.add_processor(FallbackProcessor())
137
156
 
138
157
  for col in list_columns:
139
- sub_col = []
140
- if relation_separator in col:
141
- col, *sub_col = col.split(relation_separator)
142
- curr_val = data.get(col, "")
143
- for sub in sub_col:
144
- if isinstance(curr_val, dict):
145
- curr_val = curr_val.get(sub, "")
146
- else:
147
- curr_val = ""
148
-
149
- if isinstance(curr_val, dict):
150
- curr_val = curr_val.get("name_", curr_val)
151
- elif isinstance(curr_val, list):
152
- curr_val = [
153
- curr_val.get(
154
- "id_" if export_mode == "detailed" else "name_",
155
- json.dumps(curr_val),
156
- )
157
- for curr_val in curr_val
158
- ]
159
- array_separator = "," if delimiter == ";" else ";"
160
- curr_val = array_separator.join(curr_val)
161
- elif isinstance(curr_val, enum.Enum):
162
- curr_val = curr_val.value
163
- if curr_val is not None:
164
- if isinstance(curr_val, dict):
165
- curr_val = json.dumps(curr_val)
166
- else:
167
- curr_val = str(curr_val)
168
- else:
169
- curr_val = ""
170
- csv_data.append(curr_val)
158
+ value = data_pipeline.process(data, col)
159
+ csv_data.append(value)
160
+
161
+ return csv_data
162
+
163
+ @classmethod
164
+ async def ajson_to_csv_single(
165
+ cls,
166
+ data: "dict[str, typing.Any] | BasicModel",
167
+ /,
168
+ *,
169
+ list_columns: list[str],
170
+ delimiter=",",
171
+ relation_separator=".",
172
+ export_mode: ExportMode = "simplified",
173
+ ):
174
+ """
175
+ Asynchronously converts single JSON object to CSV format.
176
+
177
+ - Data can also be a `BasicModel`.
178
+
179
+ Args:
180
+ data (dict[str, typing.Any] | BasicModel): The JSON data to be converted. Can also be a `BasicModel`.
181
+ list_columns (list[str]): The list of columns to be included in the CSV.
182
+ delimiter (str, optional): The delimiter to use in the CSV. Defaults to ",".
183
+ relation_separator (str, optional): The separator to use for nested keys. Defaults to ".".
184
+ export_mode (ExportMode, optional): Export mode (simplified or detailed). Defaults to "simplified".
185
+
186
+ Returns:
187
+ str: The CSV data as a string.
188
+ """
189
+ csv_data: list[str] = []
190
+ data_pipeline = DataPipeline()
191
+ data_pipeline.add_processor(AsyncColumnProcessor(relation_separator))
192
+ data_pipeline.add_processor(ModelProcessor())
193
+ data_pipeline.add_processor(
194
+ ListProcessor(delimiter=delimiter, export_mode=export_mode)
195
+ )
196
+ data_pipeline.add_processor(EnumProcessor())
197
+ data_pipeline.add_processor(FallbackProcessor())
198
+
199
+ for col in list_columns:
200
+ value = await data_pipeline.aprocess(data, col)
201
+ csv_data.append(value)
171
202
 
172
203
  return csv_data
173
204
 
@@ -224,3 +255,175 @@ class CSVJSONConverter:
224
255
  value = value.split(list_delimiter)
225
256
  current[parts[-1]] = [item.strip() for item in value if item.strip()]
226
257
  return result
258
+
259
+
260
+ class DataPipeline:
261
+ def __init__(self):
262
+ self.processors = list[DataProcessor]()
263
+
264
+ def add_processor(self, processor: "DataProcessor"):
265
+ """
266
+ Adds a data processor to the pipeline.
267
+
268
+ Args:
269
+ processor (DataProcessor): The data processor to add.
270
+ """
271
+ self.processors.append(processor)
272
+
273
+ def process(self, data: typing.Any, col: str):
274
+ """
275
+ Processes the data through the pipeline.
276
+
277
+ Args:
278
+ data (typing.Any): The data to process.
279
+ col (str): The column to process.
280
+
281
+ Returns:
282
+ typing.Any: The processed data.
283
+ """
284
+ for processor in self.processors:
285
+ data, col, should_continue = processor.process(data, col)
286
+ if not should_continue:
287
+ break
288
+ return data
289
+
290
+ async def aprocess(self, data: typing.Any, col: str):
291
+ """
292
+ Asynchronously processes the data through the pipeline.
293
+
294
+ Args:
295
+ data (typing.Any): The data to process.
296
+ col (str): The column to process.
297
+
298
+ Returns:
299
+ typing.Any: The processed data.
300
+ """
301
+ for processor in self.processors:
302
+ data, col, should_continue = await safe_call(processor.process(data, col))
303
+ if not should_continue:
304
+ break
305
+ return data
306
+
307
+
308
+ class DataProcessor(abc.ABC):
309
+ @abc.abstractmethod
310
+ def process(self, data: typing.Any, col: str) -> tuple[typing.Any, str, bool]:
311
+ """
312
+ Processes the data for a specific column.
313
+
314
+ Args:
315
+ data (typing.Any): The data to process.
316
+ col (str): The column to process.
317
+
318
+ Returns:
319
+ tuple[typing.Any, str, bool]: The processed data, the column name, and a boolean indicating whether to continue processing.
320
+ """
321
+ raise NotImplementedError()
322
+
323
+
324
+ class ColumnProcessor(DataProcessor):
325
+ def __init__(self, relation_separator: str = "."):
326
+ super().__init__()
327
+ self.relation_separator = relation_separator
328
+
329
+ def process(self, data, col):
330
+ sub_col = []
331
+ if self.relation_separator in col:
332
+ col, *sub_col = col.split(self.relation_separator)
333
+ data = data.get(col, "") if isinstance(data, dict) else getattr(data, col, "")
334
+ for sub in sub_col:
335
+ data = (
336
+ data.get(sub, "") if isinstance(data, dict) else getattr(data, sub, "")
337
+ )
338
+ return data, col, True
339
+
340
+
341
+ class AsyncColumnProcessor(ColumnProcessor):
342
+ async def process(self, data, col):
343
+ data, col, continue_processing = super().process(data, col)
344
+ if inspect.iscoroutine(data):
345
+ data = await data
346
+ return data, col, continue_processing
347
+
348
+
349
+ class ModelProcessor(DataProcessor):
350
+ def __init__(self, attr="name_"):
351
+ super().__init__()
352
+ self.attr = attr
353
+
354
+ def process(self, data, col):
355
+ from ..bases import BasicModel
356
+
357
+ continue_processing = True
358
+
359
+ if isinstance(data, BasicModel):
360
+ data = getattr(data, self.attr, "")
361
+ continue_processing = False
362
+ return data, col, continue_processing
363
+
364
+
365
+ class DictProcessor(ModelProcessor):
366
+ def process(self, data, col):
367
+ continue_processing = True
368
+
369
+ if isinstance(data, dict):
370
+ data = data.get(self.attr, json.dumps(data))
371
+ continue_processing = False
372
+ return data, col, continue_processing
373
+
374
+
375
+ class ListProcessor(DataProcessor):
376
+ def __init__(
377
+ self,
378
+ delimiter=",",
379
+ export_mode: CSVJSONConverter.ExportMode = "simplified",
380
+ attr_detailed="id_",
381
+ attr_simplified="name_",
382
+ ):
383
+ super().__init__()
384
+ self.separator = "," if delimiter == ";" else ";"
385
+ self.export_mode = export_mode
386
+ self.model_processor = ModelProcessor(
387
+ attr_detailed if export_mode == "detailed" else attr_simplified
388
+ )
389
+ self.dict_processor = DictProcessor(
390
+ attr_detailed if export_mode == "detailed" else attr_simplified
391
+ )
392
+
393
+ def process(self, data, col):
394
+ from ..bases import BasicModel
395
+
396
+ continue_processing = True
397
+
398
+ if isinstance(data, list):
399
+ processed_list = []
400
+ for item in data:
401
+ if isinstance(item, dict):
402
+ item_processed, _, _ = self.dict_processor.process(item, col)
403
+ elif isinstance(item, BasicModel):
404
+ item_processed, _, _ = self.model_processor.process(item, col)
405
+ else:
406
+ item_processed = str(item)
407
+ processed_list.append(item_processed)
408
+ data = self.separator.join(processed_list)
409
+ continue_processing = False
410
+ return data, col, continue_processing
411
+
412
+
413
+ class EnumProcessor(DataProcessor):
414
+ def process(self, data, col):
415
+ continue_processing = True
416
+
417
+ if isinstance(data, enum.Enum):
418
+ data = data.value
419
+ continue_processing = False
420
+ return data, col, continue_processing
421
+
422
+
423
+ class FallbackProcessor(DataProcessor):
424
+ def process(self, data, col):
425
+ if data is None:
426
+ data = ""
427
+ else:
428
+ data = str(data)
429
+ return data, col, False
@@ -4,16 +4,19 @@ import typing
4
4
  __all__ = ["hooks"]
5
5
 
6
6
 
7
- def hooks(pre: typing.Callable = None, post: typing.Callable = None):
7
+ def hooks(
8
+ pre: typing.Callable[..., None] | None = None,
9
+ post: typing.Callable[..., None] | None = None,
10
+ ):
8
11
  """
9
12
  Decorator to add optional pre and post hook methods to a function.
10
13
 
11
14
  Args:
12
- pre (Callable): Function to run before the main function.
13
- post (Callable): Function to run after the main function.
15
+ pre (typing.Callable[..., None] | None): Function to run before the main function. Defaults to None.
16
+ post (typing.Callable[..., None] | None): Function to run after the main function. Defaults to None.
14
17
 
15
18
  Returns:
16
- Callable: The decorated function.
19
+ typing.Callable[..., typing.Any]: The decorated function.
17
20
  """
18
21
 
19
22
  def decorator(func):
@@ -1,6 +1,6 @@
1
1
  import fastapi
2
2
 
3
- __al__ = ["SelfDepends", "SelfType"]
3
+ __all__ = ["SelfDepends", "SelfType"]
4
4
 
5
5
 
6
6
  class BaseSelf:
fastapi_rtk/version.py CHANGED
@@ -1 +1,6 @@
1
- __version__ = "0.2.60"
1
+ __version__ = "0.0.0"
2
+ # Try to import the version from the generated _version.py file
3
+ try:
4
+ from ._version import __version__ # noqa: F401
5
+ except (ImportError, ModuleNotFoundError):
6
+ pass
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-rtk
3
+ Version: 1.0.18
4
+ Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
5
+ Project-URL: Homepage, https://codeberg.org/datatactics/fastapi-rtk
6
+ Project-URL: Issues, https://codeberg.org/datatactics/fastapi-rtk/issues
7
+ Author-email: Matthias Leinweber <m.leinweber@datatactics.de>, Agustinus Nicander Hery <a.hery@datatactics.de>
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: alembic>=1.17.0
18
+ Requires-Dist: beautifulsoup4>=4.14.2
19
+ Requires-Dist: fastapi-babel>=1.0.0
20
+ Requires-Dist: fastapi-users[oauth,sqlalchemy]>=14.0.1
21
+ Requires-Dist: fastapi[standard]>=0.119.1
22
+ Requires-Dist: jsonschema2md>=1.7.0
23
+ Requires-Dist: marshmallow-sqlalchemy>=1.4.2
24
+ Requires-Dist: polib>=1.2.0
25
+ Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0
26
+ Requires-Dist: secweb>=1.25.2
27
+ Requires-Dist: sqlalchemy-utils>=0.42.0
28
+ Requires-Dist: uvicorn==0.38.0
@@ -1,28 +1,29 @@
1
- fastapi_rtk/__init__.py,sha256=acLIihNMCZI3prFTq0cru1-k3kPjSZb2hhcqNrW7xJo,6203
1
+ fastapi_rtk/__init__.py,sha256=Lg6Er5blOMcbtQSRJMNWbRQ1VX4PWEPMVFm2ie5r8mA,6183
2
+ fastapi_rtk/_version.py,sha256=4Q9JfUgIQNLvUFicJMyEkNm8HoOBiK9BeIp9ImHf4Bg,23
2
3
  fastapi_rtk/apis.py,sha256=6X_Lhl98m7lKrDRybg2Oe24pLFLJ29eCOQSwCAvpKhY,172
3
4
  fastapi_rtk/config.py,sha256=9PZF9E5i1gxmnsZEprZZKxVHSk0dFEklJSplX9NEqdo,14036
4
- fastapi_rtk/const.py,sha256=huvh4Zor77fgUkhU4-x6LgkOglSxeKXOlXdhnai_5CQ,4905
5
- fastapi_rtk/db.py,sha256=nAPIibCCyaGm7Kw9updiVx5LWASkdfX01GxG5Gp12hM,24505
5
+ fastapi_rtk/const.py,sha256=sEj_cYeerj9pVwbCu0k5Sy1EYpdr1EHzUjqqbnporgc,4905
6
+ fastapi_rtk/db.py,sha256=4bNlpG_HqJzMkhgQ4c7kxm1AH82UVWRSD2ajexHp1Cs,24654
6
7
  fastapi_rtk/decorators.py,sha256=HqAFSiO0l5_M0idWs0IcY24FdzbAcDQDQoifM_WgZAQ,14515
7
- fastapi_rtk/dependencies.py,sha256=H31uMZRA0FdZZXmzIVS2j9gBAovJDYdb_5ZgmrKd9qc,6070
8
+ fastapi_rtk/dependencies.py,sha256=jlcsMrh83yrJsgXvpWJet_mjqwDP3nBZfPSg4Lq8KKE,7757
8
9
  fastapi_rtk/exceptions.py,sha256=P0qwd4VkeWFotgMVQHgmdT1NphFQaEznKLFIvJzW4Zs,2594
9
- fastapi_rtk/fastapi_react_toolkit.py,sha256=VaoU5zZ7V7R_t93jQSWsv3CiUDZKLsylzsUPUkkXgzc,31747
10
+ fastapi_rtk/fastapi_react_toolkit.py,sha256=lvtieBLzCAlozKQU9dkAUVoW7Ofi1ncri_hDyeHazF4,29803
10
11
  fastapi_rtk/filters.py,sha256=weCH3suCxpGJQYmwhj9D1iAqMPiRnmbRiN7stK0rhoE,181
11
12
  fastapi_rtk/globals.py,sha256=TcoMHCueM7sFwZ8iYorUe4q-3KpVFfV04RAPuMTYFKY,8863
12
- fastapi_rtk/manager.py,sha256=qZmOgVNt8oGQnB36hgUFk4hSo_u685eAvwXUBT9j3Fg,33852
13
+ fastapi_rtk/manager.py,sha256=F57aD0DApH98H7GPpnxrwKHz0nETuxQG2bax4FDfJgM,33737
13
14
  fastapi_rtk/middlewares.py,sha256=ycdaAdLIUaNEZ7KotczTHS6OOqy98Mn1_O7Hpe7Sma8,10325
14
15
  fastapi_rtk/mixins.py,sha256=78RqwrRJFOz6KAxf-GSNOmRdr7R3b-ws7OIENYlzRQQ,238
15
16
  fastapi_rtk/models.py,sha256=lQSqe-r0H7jWBVdqXjEi_bNL1cGQr0YWnyI1ToS_coc,178
16
17
  fastapi_rtk/routers.py,sha256=5gMGyH4Any9TwB3Fz23QDkmrX8MouzCxVgoAIcBqnTI,18988
17
- fastapi_rtk/schemas.py,sha256=zzzmf5qjSn6PtzrekD3Kll_WOn6XWR7h4AHQchW3GX8,17723
18
+ fastapi_rtk/schemas.py,sha256=mdIX93QRaQBLrQz-kBvG5wyKoi8H6OQpFuTBO9-mCK4,17894
18
19
  fastapi_rtk/setting.py,sha256=vpjnio0mp_yZhDajZaBl6uOFmrBYl-sqB0L_lSkBpfk,19529
19
20
  fastapi_rtk/types.py,sha256=-LPnTIbHvqJW81__gab3EWrhjNmznHhptz0BtXkEAHQ,3612
20
- fastapi_rtk/version.py,sha256=kup1SHkX0KaTSMwT4TfzIEO6OhzE6KCR_3icz2sPCnk,23
21
+ fastapi_rtk/version.py,sha256=D2cmQf2LNeHOiEfcNzVOOfcAmuLvPEmGEtZv5G54D0c,195
21
22
  fastapi_rtk/api/__init__.py,sha256=MwFR7HHppnhbjZGg3sOdQ6nqy9uxnHHXvicpswNFMNA,245
22
23
  fastapi_rtk/api/base_api.py,sha256=42I9v3b25lqxNAMDGEtajA5-btIDSyUWF0xMDgGkA8c,8078
23
- fastapi_rtk/api/model_rest_api.py,sha256=LGNCrMvhVOMloklTcD0kEC2F3uf_wMxV3Gngn2W8ed0,102409
24
+ fastapi_rtk/api/model_rest_api.py,sha256=cRjMg_v5TsXCare8Tg7b5qQssB6fGo7RpaoGWQvdoO8,106572
24
25
  fastapi_rtk/auth/__init__.py,sha256=iX7O41NivBYDfdomEaqm4lUx9KD17wI4g3EFLF6kUTw,336
25
- fastapi_rtk/auth/auth.py,sha256=MZmuueioiMbSHjd_F3frKEqCA3yjtanRWyKOy6CnOd0,20994
26
+ fastapi_rtk/auth/auth.py,sha256=F2qZoR7go_7FnvVJrDxUCd6vtRz5XW8yyOv143MWPts,20664
26
27
  fastapi_rtk/auth/hashers/__init__.py,sha256=uBThFj2VPPSMSioxYTktNiM4-mVgtDAjTpKA3ZzWxxs,110
27
28
  fastapi_rtk/auth/hashers/pbkdf2.py,sha256=EeusoypVDHVuxneoPP2aXOPpyCwxx_5O22qMeDW51b0,919
28
29
  fastapi_rtk/auth/hashers/scrypt.py,sha256=CPGe6vzj7hlKTl_MKDGSgKQW927EpPkgpGM7mVO5MW0,902
@@ -44,11 +45,11 @@ fastapi_rtk/backends/generic/model.py,sha256=olRvHD57CCKnZoyia7EcvecZfXjN-ku17gx
44
45
  fastapi_rtk/backends/generic/session.py,sha256=J8OJSuGcFkZiOg7SJIbkKnMUlo_njQjRJ1vNl4k8Ve4,19053
45
46
  fastapi_rtk/backends/sqla/__init__.py,sha256=p4TRI65-R6TM6G_-OAnwYV7Hk9WVkKsnhN2sFta1-cU,1795
46
47
  fastapi_rtk/backends/sqla/column.py,sha256=KutGcyFr3ZeHFTL8c313I4CNxosGq54neLLB7N53GZs,240
47
- fastapi_rtk/backends/sqla/db.py,sha256=hnE1jQFZai96IaQ7jWqAsiEK0PXnGpMgvgZIGSlPBsM,17245
48
+ fastapi_rtk/backends/sqla/db.py,sha256=kVipLr8C1XoeNV65IJpB-XGKde13nb_YDG-h5R8dfAs,18469
48
49
  fastapi_rtk/backends/sqla/exceptions.py,sha256=rRtvgXyDwGSbjvJIPJIOjOBYytvNv9VXkZOBy6p2J80,61
49
- fastapi_rtk/backends/sqla/filters.py,sha256=H2eholy7VTfVwcBTAV0BWO6NXJYA-eDp_YvptLFKO3E,20927
50
- fastapi_rtk/backends/sqla/interface.py,sha256=7JQ1hK49PDd2_E8KeEiivbWot3zP7ZiZifmVI7-eYZY,30058
51
- fastapi_rtk/backends/sqla/model.py,sha256=dkhnVvpKAqYAqtRYl9JsARCqEqmhc6wgGy9JHj4TNdQ,6612
50
+ fastapi_rtk/backends/sqla/filters.py,sha256=bqdt3ojlF_elAj7TJxkVq4WgkrNeV0LTR6Ojkc1H5R0,21395
51
+ fastapi_rtk/backends/sqla/interface.py,sha256=mnlCxSvWIuTrVzE8KMjZyI7Tdhk041MUF3F2ZLdhYs8,27824
52
+ fastapi_rtk/backends/sqla/model.py,sha256=N0fxuAHbw_RCfFPRw-cjWQdBEanfogLRXOUEPqZ1Qac,7168
52
53
  fastapi_rtk/backends/sqla/session.py,sha256=di52RhRWzUchcquWMU9KKd0F1N5te1GfAtcfCnekiwI,412
53
54
  fastapi_rtk/backends/sqla/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
55
  fastapi_rtk/backends/sqla/extensions/audit/__init__.py,sha256=CaVc9fV584PVazvGGMOKwX4xC3OvIae9kXBx6xQAj5g,131
@@ -58,21 +59,21 @@ fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py,sha256=d8ODg17-NEPq
58
59
  fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py,sha256=L1WgO7UzWuAgsf93iK7mmsL89DMUaRGUCEKX7CM7kz8,3846
59
60
  fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py,sha256=sckNoxPE8ApKCLgBZzE_2dokXrM6mIXvMguHZvyJzIM,3891
60
61
  fastapi_rtk/bases/__init__.py,sha256=v3tMVuX20UbvjI_mTWpDAePWAA38e3pjlYEiICgY4j8,440
61
- fastapi_rtk/bases/db.py,sha256=T0XozwU17WWwkP3J0j_sxA3Zfql2OT0HKcxoiTsJTUY,17903
62
- fastapi_rtk/bases/file_manager.py,sha256=d1ZZaY-OgDxjSWQ49DNQNSDHKznzr-03wki_eR2iU2A,8230
63
- fastapi_rtk/bases/filter.py,sha256=b9DNgW9M6pLv0eMTnaGUaYpPX1ZSloo6OCvdxGpCNNE,1837
62
+ fastapi_rtk/bases/db.py,sha256=D27BhF89J0OaLHjALDCa85eNf35lBaTz6VV7EDa4wuM,18711
63
+ fastapi_rtk/bases/file_manager.py,sha256=n6yRY0jh60itXZt0R3oaSN-2Q_CTRswX1BghE7GN4Sk,8791
64
+ fastapi_rtk/bases/filter.py,sha256=XmWTcLaIcBj9pKF1PMAKdwSnZNpdT8Df3uLeUIOGUDE,1840
64
65
  fastapi_rtk/bases/interface.py,sha256=Cq9Duxa3w-tw342P424h88fc0_X1DoxCdTa3rAN-6jM,45380
65
66
  fastapi_rtk/bases/model.py,sha256=nUZf0AVs0Mzqh2u_ALiRNYN1bfOU9PzYLvEFHDQ57Y0,1692
66
67
  fastapi_rtk/bases/session.py,sha256=Q92cRW0nI5IYSsBXLkTJjK5ztMSBNRt-olMwxTIeel0,173
67
68
  fastapi_rtk/cli/__init__.py,sha256=q0W_4aUfKI_FzoSdadTfFODvDq8L0R4TmBCiNyxlA58,46
68
- fastapi_rtk/cli/cli.py,sha256=z_jKgmdOEkQQeM6vpVpM6AJwto4sDv2UYnSM0MCIImc,918
69
+ fastapi_rtk/cli/cli.py,sha256=obejTHiXMiNICU_i76BmbRniA1vBmb8YpfvpQfQx_ts,3085
69
70
  fastapi_rtk/cli/const.py,sha256=VrHZLKH6bJncOFpUnsWBtBgVzcR1zehI-nbl3Mf7mcA,138
70
71
  fastapi_rtk/cli/decorators.py,sha256=nIFp6LufGnOLTW6oDUxMVRQvaCw9frK5mddvLFOyvqo,1118
71
72
  fastapi_rtk/cli/types.py,sha256=ezJjljcofwSI4HlDz2JWe0oVY9IA6hVvgx7IEWBkyRQ,1364
72
73
  fastapi_rtk/cli/utils.py,sha256=v7sfL1-S3XYSQ40WTD-CYcH77EfJTcKhuD3jaAImYc8,6285
73
74
  fastapi_rtk/cli/commands/__init__.py,sha256=iFkU03MOUgHoAmmyF5FmUxA6wD1YN59JqqP4WD5n6Dk,524
74
75
  fastapi_rtk/cli/commands/export.py,sha256=4OuFyljUxSvdyZc0bYzzLfnahJvSYN38fxAUPopoH4M,17572
75
- fastapi_rtk/cli/commands/security.py,sha256=oP1sfQxhgrpNoRmlB-lvbt1dAoGlNXeBEQQXQihAF_k,8916
76
+ fastapi_rtk/cli/commands/security.py,sha256=tZOUVSbsgBFXjH7_vfH6GMKH5pKkRuhVl8TTh7V8plA,8880
76
77
  fastapi_rtk/cli/commands/translate.py,sha256=v6s0XentYi5wLzPEd7qc6QUjgdn6wt89dvTbWzUPeOY,10508
77
78
  fastapi_rtk/cli/commands/db/__init__.py,sha256=2clkGMUpGY0czSUaBql8fFSd8YrSJ0oGlzkpBZejjd0,14128
78
79
  fastapi_rtk/cli/commands/db/templates/fastapi/README,sha256=dNsmYPHI9RJkhAIE18JqVmXhdJ21OCeQs8GP5DyA8Yo,47
@@ -86,48 +87,47 @@ fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako,sha256=o02U
86
87
  fastapi_rtk/file_managers/__init__.py,sha256=RZzSSUDq_cIv4MeVePRBGR0mbEiJua7WKccfE6IAawk,198
87
88
  fastapi_rtk/file_managers/file_manager.py,sha256=YJzKWtwVOiIYS4-W0CfadYhhWLydNRJ7D_T9vdzcIdU,2612
88
89
  fastapi_rtk/file_managers/image_manager.py,sha256=S2mcBuXOzXWlPhmq1in76kRmNKGYrIeEqDMs-c5KXo8,573
89
- fastapi_rtk/file_managers/s3_file_manager.py,sha256=3brXewQ1d3Fx9EVTvc24EFdzqE1DIlhNARWjCWKMeR8,3635
90
+ fastapi_rtk/file_managers/s3_file_manager.py,sha256=wjSyAoNrpDa5-SS__hK6Grajm1ZLOQZX9mXptjPd4lY,5538
90
91
  fastapi_rtk/file_managers/s3_image_manager.py,sha256=YLPARdmffA_prMPmm5Mzupaz0IakxWgWL7hWaLSznm0,352
91
92
  fastapi_rtk/lang/__init__.py,sha256=zJejpbIXx1O-nSuWwrCYgr5f5EtwjYW6kh8jRy_Yo0U,68
92
93
  fastapi_rtk/lang/babel.cfg,sha256=ahkzg8wUKyl9G9UqkgAyWEtRlCnaWkjStM5c4FhKuUE,18
93
94
  fastapi_rtk/lang/lazy_text.py,sha256=UnCBmauuIQe5_hDoEnItyl3u6Hz5NnXAV-AAU3GpfKU,3888
94
- fastapi_rtk/lang/messages.pot,sha256=fGMvpq_loG3Tnt1IRA5pCcE08SOFuOyFVQM7OjpZGlw,5650
95
+ fastapi_rtk/lang/messages.pot,sha256=kJFwHKaDgk0On6rION9mxJwbkqukIBcVWHgKJaGlGsg,5650
95
96
  fastapi_rtk/lang/babel/__init__.py,sha256=Pa1gbGSJbeMBcEMsPjvvtjl28cVy0VzWYiCSf5RsYzQ,101
96
97
  fastapi_rtk/lang/babel/cli.py,sha256=YyjguB--oPEKYP_i3FdEour1gT9AgvkXODgGrpLTWCY,1105
97
98
  fastapi_rtk/lang/babel/config.py,sha256=aKXlIRjDo0mg05widqRBA25ZgUXT5ECbxJV23jHaCOI,382
98
- fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo,sha256=zgBWcIjOwOU6-rVBpv3dkDKizcm9jMHzROpMveEtjic,2976
99
- fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po,sha256=PJsSXwrxsQ9Aw3ulLVWYIs7VX5Kh3qRPMRiSaz8SzEQ,7023
100
- fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo,sha256=vB5MQ4GKI0L-WT9nCF4eDFwdCe-T0nrQ1RifhfTr4xE,2782
101
- fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po,sha256=wWBoF6Fe8M278ntpaGzAcwcjMW3YHLLZKcR-b5MuGXA,6781
99
+ fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo,sha256=HhU9aLPhvtuXhziG4jGlAjHet7HW5xVmgmH3R6PH7Tw,2976
100
+ fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po,sha256=kj04JGVwjWrRBz132184hSeaDg_xlByvKJjk0ZAITvA,7023
101
+ fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo,sha256=Oi0vH4JgE6QmBcbhcgiU8t4yUTWbRX1jrvncp3fGmnQ,2782
102
+ fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po,sha256=GcgnXbNEQyhPM_E1urhOyhsZJxfSl2JMjMC7rBbMzas,6781
102
103
  fastapi_rtk/security/__init__.py,sha256=XkYZ_GO2opdyQS_LJwbCH1C6SUkNfLUvLkpFhcO7ZlI,86
103
104
  fastapi_rtk/security/sqla/__init__.py,sha256=qKh1mGQezDtMzvRzxzfHZRyKVaks-O7PXrOx16ekSZA,88
104
- fastapi_rtk/security/sqla/apis.py,sha256=J3BCqSnaX-w9raTA5LHa7muW24kA09nAm9kN6b3N5PU,10170
105
- fastapi_rtk/security/sqla/models.py,sha256=dwIZHNU-6b1r0M2swlYyRtSgI1e1hnvav6d6jdmffM8,8096
106
- fastapi_rtk/security/sqla/security_manager.py,sha256=p5RDZ_0vjI2kyYcOTdoA2Hvp3d7BmEcyeC4yQ9Pki2Q,17365
105
+ fastapi_rtk/security/sqla/apis.py,sha256=8Qtd1G73i2TaA9Euo63naaB8d_I9r4EHL8DWtWNJEfs,10699
106
+ fastapi_rtk/security/sqla/models.py,sha256=rEXpbljTMlTkiDp0VIxRXant8xN-WTjpqgQkr-ElXeM,7865
107
+ fastapi_rtk/security/sqla/security_manager.py,sha256=ui0g2cH8Z-YjDuqszcstyj6Li8U4IpuVV4bAVaD69Lc,31395
107
108
  fastapi_rtk/utils/__init__.py,sha256=0X4BwrVDl4S3mB7DLyHaZVednefMjRIjBIDT3yv_CHM,1875
108
- fastapi_rtk/utils/async_task_runner.py,sha256=PNo0vdKQAUOZ3HqGzU7E232qV8V218hKB7q8_uwx2dM,12653
109
+ fastapi_rtk/utils/async_task_runner.py,sha256=HzykQSdeAmNjZfVB5vUDVwrSCVFr8__67ACQk60pSsk,15545
109
110
  fastapi_rtk/utils/class_factory.py,sha256=jlVw8yCh-tYsMnR5Hm8fgxtL0kvXwnhe6DPJA1sUh7k,598
110
- fastapi_rtk/utils/csv_json_converter.py,sha256=S0j73joqFw4a2xqhqR53vOMCO2s6Q-eiGubTBysy0kU,7459
111
+ fastapi_rtk/utils/csv_json_converter.py,sha256=7szrPiB7DrK5S-s2GaHVCmEP9_OXk9RFwbZmRtAKM5A,14036
111
112
  fastapi_rtk/utils/deep_merge.py,sha256=PHtKJgXfCngOBGVliX9aVlEFcwCxr-GlzU-w6vjgAIs,2426
112
113
  fastapi_rtk/utils/extender_mixin.py,sha256=eu22VAZJIf-r_uD-zVn_2IzvknfuUkmEHn9oo-0KU0k,1388
113
114
  fastapi_rtk/utils/flask_appbuilder_utils.py,sha256=nPLQIczDZgKElMtqBRSo_aPJZMOnPs7fRyjqKUtPDbo,2276
114
- fastapi_rtk/utils/hooks.py,sha256=9DO8Y6vj0Drjkh064bTf31nSgLiCqkA-XCUOgzLB_V4,744
115
+ fastapi_rtk/utils/hooks.py,sha256=iGE8HTfDDVfQm7yeD3WqPB8_I1FXFGpBdl3ngyjaRbY,901
115
116
  fastapi_rtk/utils/lazy.py,sha256=SlVYQ-RHRcp6pGmcslVNc5lKs5GOSjqLcRsQsSWIB0s,10352
116
117
  fastapi_rtk/utils/merge_schema.py,sha256=AStYAS_t2idD63_YQri8sBcRM1jaq0kapjYUpI27syg,1398
117
118
  fastapi_rtk/utils/multiple_async_contexts.py,sha256=-juAliUeG4XI1J-p31KknsJvzvM5vX0gXVXst_xZUIo,557
118
119
  fastapi_rtk/utils/prettify_dict.py,sha256=VKve-52fE9usIzflD3mNtvql_p5F2jq9HYBTJF_1MX0,662
119
120
  fastapi_rtk/utils/pydantic.py,sha256=c4TGu6fP5qmsMJcEerhgq3R1iTpJn_1oA91d43GaVlo,2408
120
121
  fastapi_rtk/utils/run_utils.py,sha256=2aieVAGp4e7vByzkwnmXk5c-crLl-Ia1rwdHl6LRQ34,6237
121
- fastapi_rtk/utils/self_dependencies.py,sha256=ZTpJZFFnh3MhhS5PwsgJ9TeVgcV6gwSS962c7udLzds,4101
122
+ fastapi_rtk/utils/self_dependencies.py,sha256=SjX8BOC3UvuLxfElo1MMgugCX8ZEgsCgLy0g011a4UU,4102
122
123
  fastapi_rtk/utils/smartdefaultdict.py,sha256=UdA_N1eQ3TooE9_ci0O_5QKUjGkQfo-c2BwEX5OkXfY,645
123
124
  fastapi_rtk/utils/sqla.py,sha256=To4PhsO5orPJVqjdLh5C9y_xPgiy8-zhrJdSqhR_tsc,690
124
125
  fastapi_rtk/utils/timezone.py,sha256=62S0pPWuDFFXxV1YTFCsc4uKiSP_Ba36Fv7S3gYjfhs,570
125
126
  fastapi_rtk/utils/update_signature.py,sha256=PIzZgNpGEwvDNgQ3G51Zi-QhVV3mbxvUvSwDwf_-yYs,2209
126
127
  fastapi_rtk/utils/use_default_when_none.py,sha256=H2HqhKy_8eYk3i1xijEjuaKak0oWkMIkrdz6T7DK9QU,469
127
128
  fastapi_rtk/utils/werkzeug.py,sha256=1Gv-oyqSmhVGrmNbB9fDqpqJzPpANOzWf4zMMrhW9UA,3245
128
- fastapi_rtk-0.2.60.dist-info/licenses/LICENSE,sha256=NDrWi4Qwcxal3u1r2lBWGA6TVh3OeW7yMan098mQz98,1073
129
- fastapi_rtk-0.2.60.dist-info/METADATA,sha256=fPTU_b6UmU5ANlZ1FNGqHfBT3LifgusqOF94WLTj4f4,1011
130
- fastapi_rtk-0.2.60.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
131
- fastapi_rtk-0.2.60.dist-info/entry_points.txt,sha256=UuTkxSVIokSlVN28TMhoxzRRUaPxlVRSH3Gsx6yip60,53
132
- fastapi_rtk-0.2.60.dist-info/top_level.txt,sha256=Wr00iKHxOevS1Ce82ujInrg78jENrtSPWvBAkY1rm_Y,12
133
- fastapi_rtk-0.2.60.dist-info/RECORD,,
129
+ fastapi_rtk-1.0.18.dist-info/METADATA,sha256=XV1b_3Enq1nruSbQvf1nOb9ufulbPMFKoV0Oz-08x5w,1302
130
+ fastapi_rtk-1.0.18.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
131
+ fastapi_rtk-1.0.18.dist-info/entry_points.txt,sha256=UuTkxSVIokSlVN28TMhoxzRRUaPxlVRSH3Gsx6yip60,53
132
+ fastapi_rtk-1.0.18.dist-info/licenses/LICENSE,sha256=NDrWi4Qwcxal3u1r2lBWGA6TVh3OeW7yMan098mQz98,1073
133
+ fastapi_rtk-1.0.18.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1,25 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: fastapi-rtk
3
- Version: 0.2.60
4
- Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
5
- Author-email: Matthias Leinweber <m.leinweber@datatactics.de>, Agustinus Nicander Hery <a.hery@datatactics.de>
6
- Project-URL: Homepage, https://github.com/dttctcs/fastapi-rtk
7
- Project-URL: Issues, https://github.com/dttctcs/fastapi-rtk/issues
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.10
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: fastapi[standard]
15
- Requires-Dist: fastapi-users[oauth,sqlalchemy]
16
- Requires-Dist: sqlalchemy_utils
17
- Requires-Dist: alembic
18
- Requires-Dist: prometheus-fastapi-instrumentator
19
- Requires-Dist: marshmallow-sqlalchemy
20
- Requires-Dist: jsonschema2md
21
- Requires-Dist: Secweb
22
- Requires-Dist: beautifulsoup4
23
- Requires-Dist: fastapi_babel
24
- Requires-Dist: polib
25
- Dynamic: license-file
@@ -1 +0,0 @@
1
- fastapi_rtk