dynamicforms-fastapi-viewsets 0.12.0__tar.gz → 0.13.0__tar.gz
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.
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/PKG-INFO +1 -1
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/__init__.py +1 -1
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/route_viewset.py +5 -2
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mixins.py +79 -36
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/.gitignore +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/LICENSE +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/README.md +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/action_configuration.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/backends/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/backends/django_orm.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/collection_viewset.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/conf.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/context/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/context/auth/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/context/auth/django.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/context/auth/jwt.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/context/auth/static.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/cursor.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/build_schema.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/celery_viewset/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/celery_viewset/client.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/celery_viewset/payload.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/celery_viewset/result_reader.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/celery_viewset/server.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/conftest.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/lifecycle_runner.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/decorators/primary_key_model_helper.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/endpoint_docs.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/error_namespace.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/error_responses.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/authorizers.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/changes.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/conftest.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/delivery.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/event.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/lifecycle.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/redis.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/scopes.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/sources.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/store.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/topics.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/events/viewset.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/exceptions.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/filters/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/filters/base.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/filters/declaration.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/filters/operators.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/filters/registry.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/list_query.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/list_shapes.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/middleware/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/middleware/auth/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/middleware/auth/authorization.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/middleware/idempotency.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/middleware/rate_limiter.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mux_ws/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mux_ws/asgi.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mux_ws/protocol.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mux_ws/registry.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mux_ws/server.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/mux_ws/transports.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/py.typed +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/response_classes.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/routing.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/save_state/__init__.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/save_state/save_state.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/fastapi_viewsets/save_state/serialize_state.py +0 -0
- {dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: dynamicforms-fastapi-viewsets
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.0
|
|
4
4
|
Summary: Django REST Framework-style viewsets for FastAPI, with optional Celery-backed async execution and a Vue/TypeScript client counterpart.
|
|
5
5
|
Project-URL: Homepage, https://github.com/dynamicforms/fastapi-viewsets
|
|
6
6
|
Project-URL: Repository, https://github.com/dynamicforms/fastapi-viewsets
|
|
@@ -429,13 +429,16 @@ def route_viewset(
|
|
|
429
429
|
|
|
430
430
|
if is_schema_route(route):
|
|
431
431
|
# Two /schema routes on one path, one per transport, each answering with the
|
|
432
|
-
# endpoints published on its own transport
|
|
432
|
+
# endpoints published on its own transport, itself included: the TS client takes
|
|
433
|
+
# the viewset's base path in the document from the /schema path.
|
|
433
434
|
if on_rest:
|
|
434
435
|
rest_schema_kwargs = {**route_kwargs, "endpoint": openapi_endpoint(rest_routes)}
|
|
435
436
|
rest_routes.append(rest_schema_kwargs)
|
|
436
437
|
add_route(rest_schema_kwargs, {REST}, action_name)
|
|
437
438
|
if on_muxws_any:
|
|
438
|
-
|
|
439
|
+
muxws_schema_kwargs = {**route_kwargs, "endpoint": openapi_endpoint(muxws_routes)}
|
|
440
|
+
muxws_routes.append(muxws_schema_kwargs)
|
|
441
|
+
add_route(muxws_schema_kwargs, {MUXWS}, action_name)
|
|
439
442
|
continue
|
|
440
443
|
|
|
441
444
|
on_muxws = resolve_register_muxws(route.endpoint, register_muxws)
|
|
@@ -775,73 +775,116 @@ class LookupFilter(BaseModel):
|
|
|
775
775
|
|
|
776
776
|
|
|
777
777
|
TLookupFilter = TypeVar("TLookupFilter", default=LookupFilter)
|
|
778
|
+
TLookupItem = TypeVar("TLookupItem", default=LookupItem)
|
|
778
779
|
|
|
779
780
|
|
|
780
|
-
class LookupMixin(Generic[TLookupFilter], ABC):
|
|
781
|
+
class LookupMixin(Generic[TLookupFilter, TLookupItem], ABC):
|
|
781
782
|
"""
|
|
782
783
|
Lookup endpoint with optional search filtering.
|
|
783
784
|
|
|
784
|
-
Adds a GET /lookup endpoint that returns a list of
|
|
785
|
-
select/autocomplete widgets.
|
|
785
|
+
Adds a GET /lookup endpoint that returns a list of TLookupItem objects (default: LookupItem) -
|
|
786
|
+
useful for populating select/autocomplete widgets.
|
|
786
787
|
|
|
787
|
-
The
|
|
788
|
-
|
|
789
|
-
case-insensitive title match. Supply a custom filter model as a type argument to add extra
|
|
790
|
-
query parameters and override filter_lookup.
|
|
788
|
+
The fields of TLookupFilter (default: LookupFilter, a single `q`) are the endpoint's query
|
|
789
|
+
parameters. The request runs through the same stages as a list:
|
|
791
790
|
|
|
792
|
-
|
|
791
|
+
1. `perform_lookup(context)` returns the source, lazily or not.
|
|
792
|
+
2. `apply_lookup_filter(context, query, records)` narrows it. Override it to filter in the
|
|
793
|
+
backend and mark the stage applied (`query.mark_applied("filter")`); the default filters in
|
|
794
|
+
memory: by the declaration of a filter model built with `make_filter_model`, otherwise
|
|
795
|
+
through `filter_lookup`.
|
|
796
|
+
3. `to_lookup_item(raw)` converts each remaining row to TLookupItem.
|
|
793
797
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
2. Post-filter: filter_lookup is called after perform_lookup.
|
|
797
|
-
The default implementation filters by fltr.q (case-insensitive title match).
|
|
798
|
-
Override to customise in-memory filtering.
|
|
798
|
+
The filter travels in `query.fltr`, never on the viewset instance, which serves concurrent
|
|
799
|
+
requests under the default `singleton` lifecycle.
|
|
799
800
|
"""
|
|
800
801
|
|
|
801
802
|
__router = APIRouter()
|
|
802
803
|
|
|
803
804
|
@abstractmethod
|
|
804
|
-
async def perform_lookup(self, context: Context) ->
|
|
805
|
+
async def perform_lookup(self, context: Context) -> ListRecords:
|
|
805
806
|
"""
|
|
806
|
-
Subclasses
|
|
807
|
-
|
|
808
|
-
|
|
807
|
+
Subclasses implement this to return the lookup source.
|
|
808
|
+
|
|
809
|
+
A lazy source - a generator, an unevaluated QuerySet - is what an overridden
|
|
810
|
+
`apply_lookup_filter` pushes the filter into. Rows are TLookupItem once `to_lookup_item` has
|
|
811
|
+
run over them.
|
|
809
812
|
"""
|
|
810
813
|
raise NotImplementedError("Method 'perform_lookup' must be implemented.")
|
|
811
814
|
|
|
812
|
-
async def
|
|
815
|
+
async def get_lookup(self, context: Context, query: ListQuery) -> list[TLookupItem]:
|
|
816
|
+
"""The lookup pipeline: source, filter, conversion. Overridable as a whole."""
|
|
817
|
+
records = await self.perform_lookup(context)
|
|
818
|
+
records = await self.apply_lookup_filter(context, query, records)
|
|
819
|
+
return await self.land_lookup(query, records)
|
|
820
|
+
|
|
821
|
+
async def apply_lookup_filter(
|
|
822
|
+
self,
|
|
823
|
+
context: Context, # noqa: ARG002 - part of the hook signature, for overrides to use
|
|
824
|
+
query: ListQuery,
|
|
825
|
+
records: ListRecords,
|
|
826
|
+
) -> ListRecords:
|
|
813
827
|
"""
|
|
814
|
-
|
|
815
|
-
|
|
828
|
+
Narrows `records` to those the filter accepts. Override to filter in the backend; mark the
|
|
829
|
+
stage applied so this default does not redo the work:
|
|
830
|
+
|
|
831
|
+
async def apply_lookup_filter(self, context, query, records):
|
|
832
|
+
if query.has_filter:
|
|
833
|
+
records = records.filter(pk__in=query.fltr.ids)
|
|
834
|
+
query.mark_applied("filter")
|
|
835
|
+
return await super().apply_lookup_filter(context, query, records)
|
|
836
|
+
|
|
837
|
+
The default filters TLookupItem records in memory: by the declaration of a filter model built
|
|
838
|
+
with `make_filter_model`, otherwise through the `filter_lookup` hook.
|
|
816
839
|
"""
|
|
840
|
+
if not query.has_filter or not query.needs("filter"):
|
|
841
|
+
return records
|
|
817
842
|
|
|
818
|
-
|
|
843
|
+
items = await self.land_lookup(query, records)
|
|
844
|
+
declared = filters_from(query.fltr)
|
|
845
|
+
if declared is not None:
|
|
846
|
+
return declared.apply(items)
|
|
847
|
+
filtered = await self.filter_lookup(query.fltr, items)
|
|
848
|
+
return items if filtered is None else filtered
|
|
849
|
+
|
|
850
|
+
async def filter_lookup(self, fltr: TLookupFilter, items: list[TLookupItem]) -> list[TLookupItem]:
|
|
819
851
|
"""
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
Subclasses can override to change the filtering behaviour.
|
|
852
|
+
In-memory filter hook of a hand-written filter model, called with the converted items.
|
|
853
|
+
The default filters by `fltr.q`: a case-insensitive substring of the item's `title`.
|
|
823
854
|
"""
|
|
824
855
|
q = getattr(fltr, "q", None)
|
|
825
856
|
if q is None:
|
|
826
857
|
return items
|
|
827
|
-
|
|
858
|
+
needle = q.lower()
|
|
859
|
+
return [item for item in items if needle in str(getattr(item, "title", "")).lower()]
|
|
860
|
+
|
|
861
|
+
def to_lookup_item(self, raw: Any) -> TLookupItem:
|
|
862
|
+
"""
|
|
863
|
+
Converts one row of the source into TLookupItem. The default is identity, for a source that
|
|
864
|
+
already yields TLookupItem.
|
|
865
|
+
"""
|
|
866
|
+
return raw
|
|
867
|
+
|
|
868
|
+
async def land_lookup(self, query: ListQuery, records: ListRecords) -> list[TLookupItem]:
|
|
869
|
+
"""
|
|
870
|
+
Materialises the source and converts it with `to_lookup_item`. Idempotent: the conversion
|
|
871
|
+
runs once per request, whichever stage lands the source first.
|
|
872
|
+
"""
|
|
873
|
+
materialized = await materialize(records)
|
|
874
|
+
if query.needs("conversion"):
|
|
875
|
+
query.mark_applied("conversion")
|
|
876
|
+
if type(self).to_lookup_item is not LookupMixin.to_lookup_item:
|
|
877
|
+
return [self.to_lookup_item(row) for row in materialized]
|
|
878
|
+
return materialized
|
|
828
879
|
|
|
829
880
|
@final
|
|
830
881
|
@__router.get("lookup")
|
|
831
882
|
async def lookup(
|
|
832
|
-
self: "
|
|
883
|
+
self: "LookupMixin",
|
|
833
884
|
context: Context,
|
|
834
885
|
fltr: Annotated[TLookupFilter, Query()] = None,
|
|
835
|
-
) -> list[
|
|
836
|
-
|
|
837
|
-
fltr is not None and hasattr(fltr, "model_dump") and any(v is not None for v in fltr.model_dump().values())
|
|
838
|
-
)
|
|
839
|
-
if has_filter:
|
|
840
|
-
await self.setup_lookup_filter(fltr)
|
|
841
|
-
res = await self.perform_lookup(context)
|
|
842
|
-
if has_filter:
|
|
843
|
-
res = await self.filter_lookup(fltr, res)
|
|
844
|
-
return res
|
|
886
|
+
) -> list[TLookupItem]:
|
|
887
|
+
return await self.get_lookup(context, build_list_query(fltr, None))
|
|
845
888
|
|
|
846
889
|
|
|
847
890
|
###################################################################################################
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dynamicforms_fastapi_viewsets-0.12.0 → dynamicforms_fastapi_viewsets-0.13.0}/pyproject.toml
RENAMED
|
File without changes
|