fastapi-rtk 1.0.6__py3-none-any.whl → 1.0.8__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_rtk/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.0.6"
1
+ __version__ = "1.0.8"
@@ -1,5 +1,4 @@
1
1
  import asyncio
2
- import copy
3
2
  import csv
4
3
  import enum
5
4
  import re
@@ -256,9 +255,7 @@ class ModelRestApi(BaseApi):
256
255
 
257
256
  Example:
258
257
  ```python
259
- opr_filters = [
260
- [FilterEqualOnNameAndAge],
261
- ]
258
+ opr_filters = [FilterEqualOnNameAndAge]
262
259
  ```
263
260
  """
264
261
  label_columns = lazy(lambda: dict[str, str]())
@@ -2331,6 +2328,7 @@ class ModelRestApi(BaseApi):
2331
2328
  )
2332
2329
 
2333
2330
  if self.datamodel.is_files(key) or self.datamodel.is_images(key):
2331
+ value = [x for x in value if x] # Remove None values
2334
2332
  old_filenames = (
2335
2333
  [x for x in value if isinstance(x, str)] if value else []
2336
2334
  )
@@ -2591,12 +2589,18 @@ class ModelRestApi(BaseApi):
2591
2589
  Returns:
2592
2590
  dict: The generated JSONForms schema.
2593
2591
  """
2594
- jsonforms_schema = schema.model_json_schema()
2592
+ cache_key = f"jsonforms_schema_{schema.__name__}"
2593
+ jsonforms_schema = self.cache.get(cache_key)
2594
+ if not jsonforms_schema:
2595
+ self.cache[cache_key] = jsonforms_schema = schema.model_json_schema()
2595
2596
 
2596
2597
  # Remove unused vars
2597
2598
  jsonforms_schema.pop("$defs", None)
2598
2599
 
2599
- for key, value in jsonforms_schema["properties"].items():
2600
+ result = jsonforms_schema.copy()
2601
+ result["properties"] = jsonforms_schema["properties"].copy()
2602
+ for key, value in result["properties"].items():
2603
+ value = value.copy()
2600
2604
  label = self.label_columns.get(key)
2601
2605
  if label:
2602
2606
  value["title"] = label
@@ -2621,7 +2625,7 @@ class ModelRestApi(BaseApi):
2621
2625
  ]
2622
2626
  value["contentMediaType"] = ", ".join(allowed_extensions)
2623
2627
  if self.datamodel.is_files(key) or self.datamodel.is_images(key):
2624
- current_value = copy.deepcopy(value)
2628
+ current_value = value.copy()
2625
2629
  value["type"] = "array"
2626
2630
  value["items"] = current_value
2627
2631
  elif self.datamodel.is_boolean(key):
@@ -2688,9 +2692,9 @@ class ModelRestApi(BaseApi):
2688
2692
  if key in g.sensitive_data.get(self.datamodel.obj.__name__, []):
2689
2693
  value["format"] = "password"
2690
2694
 
2691
- jsonforms_schema["properties"][key] = value
2695
+ result["properties"][key] = value
2692
2696
 
2693
- return jsonforms_schema
2697
+ return result
2694
2698
 
2695
2699
  async def _export_data(
2696
2700
  self,
@@ -34,6 +34,7 @@ LOAD_TYPE_MAPPING = {
34
34
 
35
35
  class LoadColumn(typing.TypedDict):
36
36
  statement: Select[tuple[T]] | _AbstractLoad
37
+ statement_type: typing.Literal["select", "joinedload", "selectinload"] | None
37
38
  type: typing.Literal["defer", "some", "all"]
38
39
  columns: list[str]
39
40
  related_columns: collections.defaultdict[str, "LoadColumn"]
@@ -42,6 +43,7 @@ class LoadColumn(typing.TypedDict):
42
43
  def create_load_column(statement: Select[tuple[T]] | _AbstractLoad | None = None):
43
44
  return LoadColumn(
44
45
  statement=statement,
46
+ statement_type=None,
45
47
  type="defer",
46
48
  columns=[],
47
49
  related_columns=collections.defaultdict(create_load_column),
@@ -104,7 +106,7 @@ class SQLAQueryBuilder(AbstractQueryBuilder[Select[tuple[T]]]):
104
106
  statement = statement.options(cache_option)
105
107
  return statement
106
108
 
107
- load_column = self._load_columns_recursively(statement, list_columns)
109
+ load_column = self._load_columns_recursively(statement, "select", list_columns)
108
110
  logger.debug(f"Load Column:\n{prettify_dict(load_column)}")
109
111
  return self._load_columns_from_dictionary(statement, load_column, list_columns)
110
112
 
@@ -365,27 +367,32 @@ class SQLAQueryBuilder(AbstractQueryBuilder[Select[tuple[T]]]):
365
367
  return statement
366
368
 
367
369
  def _load_columns_recursively(
368
- self, statement: Select[tuple[T]] | _AbstractLoad, columns: list[str]
370
+ self,
371
+ statement: Select[tuple[T]] | _AbstractLoad,
372
+ statement_type: typing.Literal["select", "joinedload", "selectinload"],
373
+ columns: list[str],
369
374
  ):
370
375
  """
371
376
  Load specified columns into the given SQLAlchemy statement. This returns a dictionary that can be used with the `load_columns_from_dictionary` method.
372
377
 
373
378
  Args:
374
379
  statement (Select[tuple[T]] | _AbstractLoad): The SQLAlchemy statement to which the columns will be loaded.
380
+ statement_type (typing.Literal["select", "joinedload", "selectinload"]): The type of statement to use for loading.
375
381
  columns (list[str]): A list of column names to be loaded.
376
382
 
377
383
  Returns:
378
384
  dict: A dictionary that can be used with the `load_columns_from_dictionary` method.
379
385
  """
380
386
  load_column = create_load_column(statement)
387
+ load_column["statement_type"] = statement_type
381
388
  for col in columns:
382
389
  sub_col = ""
383
390
  if "." in col:
384
391
  col, sub_col = col.split(".", 1)
385
392
 
386
- # If it is not a relation, load only the column if it is in the user column list, else skip
393
+ # If it is not a relation, load only the column if it is in the column list, else skip
387
394
  if not self.datamodel.is_relation(col):
388
- if col in self.datamodel.get_user_column_list():
395
+ if col in self.datamodel.get_column_list():
389
396
  load_column["columns"].append(col)
390
397
  load_column["type"] = "some"
391
398
  continue
@@ -393,10 +400,18 @@ class SQLAQueryBuilder(AbstractQueryBuilder[Select[tuple[T]]]):
393
400
  if self.datamodel.is_relation_one_to_one(
394
401
  col
395
402
  ) or self.datamodel.is_relation_many_to_one(col):
403
+ load_column["related_columns"][col]["statement_type"] = (
404
+ load_column["related_columns"][col]["statement_type"]
405
+ or "joinedload"
406
+ )
396
407
  load_column["related_columns"][col]["statement"] = load_column[
397
408
  "related_columns"
398
409
  ][col]["statement"] or joinedload(self.datamodel.obj.load_options(col))
399
410
  else:
411
+ load_column["related_columns"][col]["statement_type"] = (
412
+ load_column["related_columns"][col]["statement_type"]
413
+ or "selectinload"
414
+ )
400
415
  load_column["related_columns"][col]["statement"] = load_column[
401
416
  "related_columns"
402
417
  ][col]["statement"] or selectinload(
@@ -410,7 +425,9 @@ class SQLAQueryBuilder(AbstractQueryBuilder[Select[tuple[T]]]):
410
425
  load_column["related_columns"][col] = deep_merge(
411
426
  load_column["related_columns"][col],
412
427
  interface.query._load_columns_recursively(
413
- load_column["related_columns"][col]["statement"], [sub_col]
428
+ load_column["related_columns"][col]["statement"],
429
+ load_column["related_columns"][col]["statement_type"],
430
+ [sub_col],
414
431
  ),
415
432
  rules={
416
433
  "type": lambda x1, x2: LOAD_TYPE_MAPPING[x2]
@@ -427,8 +444,8 @@ class SQLAQueryBuilder(AbstractQueryBuilder[Select[tuple[T]]]):
427
444
  load_column["related_columns"][col]["type"] = "all"
428
445
  continue
429
446
 
430
- # Skip if the sub column is not in the user column list or if it is a relation
431
- if sub_col not in interface.get_user_column_list() or interface.is_relation(
447
+ # Skip if the sub column is not in the column list or if it is a relation
448
+ if sub_col not in interface.get_column_list() or interface.is_relation(
432
449
  sub_col
433
450
  ):
434
451
  continue
@@ -437,3 +454,11 @@ class SQLAQueryBuilder(AbstractQueryBuilder[Select[tuple[T]]]):
437
454
  load_column["related_columns"][col]["type"] = "some"
438
455
 
439
456
  return load_column
457
+
458
+ def _convert_id_into_dict(self, id):
459
+ # Cast the id into the right type based on the pk column type
460
+ pk_dict = super()._convert_id_into_dict(id)
461
+ for pk in pk_dict:
462
+ col_type = self.datamodel.list_columns[pk].type.python_type
463
+ pk_dict[pk] = col_type(pk_dict[pk])
464
+ return pk_dict
@@ -617,6 +617,22 @@ class SQLAFilterConverter:
617
617
  FilterIn,
618
618
  ],
619
619
  ),
620
+ (
621
+ "is_files",
622
+ [
623
+ FilterTextContains,
624
+ # TODO: Make compatible filters
625
+ # FilterEqual,
626
+ # FilterNotEqual,
627
+ # FilterStartsWith,
628
+ # FilterNotStartsWith,
629
+ # FilterEndsWith,
630
+ # FilterNotEndsWith,
631
+ # FilterContains,
632
+ # FilterNotContains,
633
+ # FilterIn,
634
+ ],
635
+ ),
620
636
  (
621
637
  "is_integer",
622
638
  [
@@ -255,7 +255,12 @@ class SQLAInterface(AbstractInterface[ModelType, Session | AsyncSession, Column]
255
255
  unique_order_columns.update(
256
256
  [f"{col_name}.{sub_col}" for sub_col in sub_order_columns]
257
257
  )
258
- elif self.is_property(col_name) and not self.is_hybrid_property(col_name):
258
+ elif (
259
+ self.is_property(col_name)
260
+ and not self.is_hybrid_property(col_name)
261
+ or self.is_files(col_name)
262
+ or self.is_images(col_name)
263
+ ):
259
264
  continue
260
265
 
261
266
  # Allow the column to be used for ordering by default
@@ -353,14 +358,12 @@ class SQLAInterface(AbstractInterface[ModelType, Session | AsyncSession, Column]
353
358
  ]
354
359
  elif self.is_file(col) or self.is_image(col):
355
360
  value_type = fastapi.UploadFile
361
+ annotated_str_type = typing.Annotated[
362
+ str | None, BeforeValidator(lambda x: None if x == "null" else x)
363
+ ]
356
364
  if self.is_files(col) or self.is_images(col):
357
- value_type = list[value_type | str]
358
- return (
359
- value_type
360
- | typing.Annotated[
361
- str | None, BeforeValidator(lambda x: None if x == "null" else x)
362
- ]
363
- )
365
+ value_type = list[value_type | annotated_str_type]
366
+ return value_type | annotated_str_type
364
367
  elif self.is_date(col):
365
368
  return date
366
369
  elif self.is_datetime(col):
@@ -125,16 +125,18 @@ class Model(sqlalchemy.ext.asyncio.AsyncAttrs, BasicModel, DeclarativeBase):
125
125
  def get_pk_attrs(cls):
126
126
  return [col.name for col in cls.__mapper__.primary_key]
127
127
 
128
- async def load(self, cols: list[str] | str):
128
+ async def load(self, *cols: list[str] | str):
129
129
  """
130
- Asynchronously load the specified columns for the current instance.
130
+ Asynchronously loads the specified columns of the model instance.
131
131
 
132
132
  Args:
133
- cols (list[str] | str): A list of column names to load or a single column name.
133
+ *cols (list[str] | str): The columns to load. Can be a list of strings or individual string arguments.
134
134
  """
135
+ cols = [
136
+ item for col in cols for item in (col if isinstance(col, list) else [col])
137
+ ]
138
+
135
139
  async with AsyncTaskRunner() as runner:
136
- if isinstance(cols, str):
137
- cols = [cols]
138
140
  for col in cols:
139
141
  runner.add_task(getattr(self.awaitable_attrs, col))
140
142
 
@@ -51,7 +51,7 @@ class AbstractBaseOprFilter(AbstractBaseFilter[T]):
51
51
  """
52
52
 
53
53
  @abc.abstractmethod
54
- def apply(self, statement, value) -> T:
54
+ def apply(self, statement: T, value) -> T:
55
55
  """
56
56
  Apply the filter to the given SQLAlchemy Select statement.
57
57
 
fastapi_rtk/const.py CHANGED
@@ -76,7 +76,7 @@ DEFAULT_COOKIE_NAME = "dataTactics"
76
76
  DEFAULT_BASEDIR = "app"
77
77
  DEFAULT_STATIC_FOLDER = DEFAULT_BASEDIR + "/static"
78
78
  DEFAULT_TEMPLATE_FOLDER = DEFAULT_BASEDIR + "/templates"
79
- DEFAULT_PROFILER_FOLDER = DEFAULT_STATIC_FOLDER + "/profiles"
79
+ DEFAULT_PROFILER_FOLDER = DEFAULT_STATIC_FOLDER + "/profiler"
80
80
  DEFAULT_LANG_FOLDER = DEFAULT_BASEDIR + "/lang"
81
81
  DEFAULT_LANGUAGES = "en,de"
82
82
  DEFAULT_TRANSLATIONS_KEY = "translations"
@@ -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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-rtk
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
5
5
  Project-URL: Homepage, https://codeberg.org/datatactics/fastapi-rtk
6
6
  Project-URL: Issues, https://codeberg.org/datatactics/fastapi-rtk/issues
@@ -1,8 +1,8 @@
1
1
  fastapi_rtk/__init__.py,sha256=acLIihNMCZI3prFTq0cru1-k3kPjSZb2hhcqNrW7xJo,6203
2
- fastapi_rtk/_version.py,sha256=mqMuQB3aqJVPrHHqJMLjqiMKUiJjozc7EPLcX5DpKHg,22
2
+ fastapi_rtk/_version.py,sha256=NND_6JDYnYnGzN3-RTpS5F7wzv62vDf7hAxiyTSBJfE,22
3
3
  fastapi_rtk/apis.py,sha256=6X_Lhl98m7lKrDRybg2Oe24pLFLJ29eCOQSwCAvpKhY,172
4
4
  fastapi_rtk/config.py,sha256=9PZF9E5i1gxmnsZEprZZKxVHSk0dFEklJSplX9NEqdo,14036
5
- fastapi_rtk/const.py,sha256=huvh4Zor77fgUkhU4-x6LgkOglSxeKXOlXdhnai_5CQ,4905
5
+ fastapi_rtk/const.py,sha256=sEj_cYeerj9pVwbCu0k5Sy1EYpdr1EHzUjqqbnporgc,4905
6
6
  fastapi_rtk/db.py,sha256=nAPIibCCyaGm7Kw9updiVx5LWASkdfX01GxG5Gp12hM,24505
7
7
  fastapi_rtk/decorators.py,sha256=HqAFSiO0l5_M0idWs0IcY24FdzbAcDQDQoifM_WgZAQ,14515
8
8
  fastapi_rtk/dependencies.py,sha256=H31uMZRA0FdZZXmzIVS2j9gBAovJDYdb_5ZgmrKd9qc,6070
@@ -21,7 +21,7 @@ fastapi_rtk/types.py,sha256=-LPnTIbHvqJW81__gab3EWrhjNmznHhptz0BtXkEAHQ,3612
21
21
  fastapi_rtk/version.py,sha256=D2cmQf2LNeHOiEfcNzVOOfcAmuLvPEmGEtZv5G54D0c,195
22
22
  fastapi_rtk/api/__init__.py,sha256=MwFR7HHppnhbjZGg3sOdQ6nqy9uxnHHXvicpswNFMNA,245
23
23
  fastapi_rtk/api/base_api.py,sha256=42I9v3b25lqxNAMDGEtajA5-btIDSyUWF0xMDgGkA8c,8078
24
- fastapi_rtk/api/model_rest_api.py,sha256=PQwR_ya4rrzlZlHDl8lr3z7y1SH8mRbgiVRX2TrjsGk,104924
24
+ fastapi_rtk/api/model_rest_api.py,sha256=R-zdfDK6QiVb8u6EBTpZt7cqvH4kP86udNMxdJRiphQ,105254
25
25
  fastapi_rtk/auth/__init__.py,sha256=iX7O41NivBYDfdomEaqm4lUx9KD17wI4g3EFLF6kUTw,336
26
26
  fastapi_rtk/auth/auth.py,sha256=MZmuueioiMbSHjd_F3frKEqCA3yjtanRWyKOy6CnOd0,20994
27
27
  fastapi_rtk/auth/hashers/__init__.py,sha256=uBThFj2VPPSMSioxYTktNiM4-mVgtDAjTpKA3ZzWxxs,110
@@ -45,11 +45,11 @@ fastapi_rtk/backends/generic/model.py,sha256=olRvHD57CCKnZoyia7EcvecZfXjN-ku17gx
45
45
  fastapi_rtk/backends/generic/session.py,sha256=J8OJSuGcFkZiOg7SJIbkKnMUlo_njQjRJ1vNl4k8Ve4,19053
46
46
  fastapi_rtk/backends/sqla/__init__.py,sha256=p4TRI65-R6TM6G_-OAnwYV7Hk9WVkKsnhN2sFta1-cU,1795
47
47
  fastapi_rtk/backends/sqla/column.py,sha256=KutGcyFr3ZeHFTL8c313I4CNxosGq54neLLB7N53GZs,240
48
- fastapi_rtk/backends/sqla/db.py,sha256=hnE1jQFZai96IaQ7jWqAsiEK0PXnGpMgvgZIGSlPBsM,17245
48
+ fastapi_rtk/backends/sqla/db.py,sha256=kVipLr8C1XoeNV65IJpB-XGKde13nb_YDG-h5R8dfAs,18469
49
49
  fastapi_rtk/backends/sqla/exceptions.py,sha256=rRtvgXyDwGSbjvJIPJIOjOBYytvNv9VXkZOBy6p2J80,61
50
- fastapi_rtk/backends/sqla/filters.py,sha256=H2eholy7VTfVwcBTAV0BWO6NXJYA-eDp_YvptLFKO3E,20927
51
- fastapi_rtk/backends/sqla/interface.py,sha256=9I2JiShqmyakfgdXE-DA5TW35xdvMs_-pDDccKnX5cA,27678
52
- fastapi_rtk/backends/sqla/model.py,sha256=GqWJyb4uq7AK58_zZw5jx4BQ6xWi5thwNqr8WGfnJ6o,7099
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
53
53
  fastapi_rtk/backends/sqla/session.py,sha256=di52RhRWzUchcquWMU9KKd0F1N5te1GfAtcfCnekiwI,412
54
54
  fastapi_rtk/backends/sqla/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  fastapi_rtk/backends/sqla/extensions/audit/__init__.py,sha256=CaVc9fV584PVazvGGMOKwX4xC3OvIae9kXBx6xQAj5g,131
@@ -61,7 +61,7 @@ fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py,sha256=sc
61
61
  fastapi_rtk/bases/__init__.py,sha256=v3tMVuX20UbvjI_mTWpDAePWAA38e3pjlYEiICgY4j8,440
62
62
  fastapi_rtk/bases/db.py,sha256=D27BhF89J0OaLHjALDCa85eNf35lBaTz6VV7EDa4wuM,18711
63
63
  fastapi_rtk/bases/file_manager.py,sha256=d1ZZaY-OgDxjSWQ49DNQNSDHKznzr-03wki_eR2iU2A,8230
64
- fastapi_rtk/bases/filter.py,sha256=b9DNgW9M6pLv0eMTnaGUaYpPX1ZSloo6OCvdxGpCNNE,1837
64
+ fastapi_rtk/bases/filter.py,sha256=XmWTcLaIcBj9pKF1PMAKdwSnZNpdT8Df3uLeUIOGUDE,1840
65
65
  fastapi_rtk/bases/interface.py,sha256=Cq9Duxa3w-tw342P424h88fc0_X1DoxCdTa3rAN-6jM,45380
66
66
  fastapi_rtk/bases/model.py,sha256=nUZf0AVs0Mzqh2u_ALiRNYN1bfOU9PzYLvEFHDQ57Y0,1692
67
67
  fastapi_rtk/bases/session.py,sha256=Q92cRW0nI5IYSsBXLkTJjK5ztMSBNRt-olMwxTIeel0,173
@@ -119,15 +119,15 @@ fastapi_rtk/utils/multiple_async_contexts.py,sha256=-juAliUeG4XI1J-p31KknsJvzvM5
119
119
  fastapi_rtk/utils/prettify_dict.py,sha256=VKve-52fE9usIzflD3mNtvql_p5F2jq9HYBTJF_1MX0,662
120
120
  fastapi_rtk/utils/pydantic.py,sha256=c4TGu6fP5qmsMJcEerhgq3R1iTpJn_1oA91d43GaVlo,2408
121
121
  fastapi_rtk/utils/run_utils.py,sha256=2aieVAGp4e7vByzkwnmXk5c-crLl-Ia1rwdHl6LRQ34,6237
122
- fastapi_rtk/utils/self_dependencies.py,sha256=ZTpJZFFnh3MhhS5PwsgJ9TeVgcV6gwSS962c7udLzds,4101
122
+ fastapi_rtk/utils/self_dependencies.py,sha256=SjX8BOC3UvuLxfElo1MMgugCX8ZEgsCgLy0g011a4UU,4102
123
123
  fastapi_rtk/utils/smartdefaultdict.py,sha256=UdA_N1eQ3TooE9_ci0O_5QKUjGkQfo-c2BwEX5OkXfY,645
124
124
  fastapi_rtk/utils/sqla.py,sha256=To4PhsO5orPJVqjdLh5C9y_xPgiy8-zhrJdSqhR_tsc,690
125
125
  fastapi_rtk/utils/timezone.py,sha256=62S0pPWuDFFXxV1YTFCsc4uKiSP_Ba36Fv7S3gYjfhs,570
126
126
  fastapi_rtk/utils/update_signature.py,sha256=PIzZgNpGEwvDNgQ3G51Zi-QhVV3mbxvUvSwDwf_-yYs,2209
127
127
  fastapi_rtk/utils/use_default_when_none.py,sha256=H2HqhKy_8eYk3i1xijEjuaKak0oWkMIkrdz6T7DK9QU,469
128
128
  fastapi_rtk/utils/werkzeug.py,sha256=1Gv-oyqSmhVGrmNbB9fDqpqJzPpANOzWf4zMMrhW9UA,3245
129
- fastapi_rtk-1.0.6.dist-info/METADATA,sha256=M9gJt_FXPypoq_6Q-U2L6mE9m-9Y_MZpqcorsYAy9iI,1270
130
- fastapi_rtk-1.0.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
131
- fastapi_rtk-1.0.6.dist-info/entry_points.txt,sha256=UuTkxSVIokSlVN28TMhoxzRRUaPxlVRSH3Gsx6yip60,53
132
- fastapi_rtk-1.0.6.dist-info/licenses/LICENSE,sha256=NDrWi4Qwcxal3u1r2lBWGA6TVh3OeW7yMan098mQz98,1073
133
- fastapi_rtk-1.0.6.dist-info/RECORD,,
129
+ fastapi_rtk-1.0.8.dist-info/METADATA,sha256=BtLiGBfKiNshhahz5dAFunO6FJip5cxTRFkWZ4_zibI,1270
130
+ fastapi_rtk-1.0.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
131
+ fastapi_rtk-1.0.8.dist-info/entry_points.txt,sha256=UuTkxSVIokSlVN28TMhoxzRRUaPxlVRSH3Gsx6yip60,53
132
+ fastapi_rtk-1.0.8.dist-info/licenses/LICENSE,sha256=NDrWi4Qwcxal3u1r2lBWGA6TVh3OeW7yMan098mQz98,1073
133
+ fastapi_rtk-1.0.8.dist-info/RECORD,,