diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml deleted file mode 100644 index dd9b1931..00000000 --- a/.github/workflows/gh-pages.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Deploy Docs - -# yamllint disable-line rule:truthy -on: - push: - branches: - - main - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - run: pipx install poetry - - name: Set up Python - uses: actions/setup-python@v5 - with: - cache: poetry - - run: poetry install - - run: poetry run mkdocs gh-deploy --force diff --git a/Makefile b/Makefile index 1631c718..b2df73ac 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,11 @@ -.PHONY : install test serve-docs lint +.PHONY : install test lint POETRY := $(shell command -v poetry 2> /dev/null) -MKDOCS := $(shell command -v mkdocs 2> /dev/null) -all: install test serve-docs +all: install test install: ${POETRY} install test: ${POETRY} run pytest - -serve-docs: - poetry install - ${MKDOCS} serve diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..3b9dda49 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,38 @@ +--- +title: Strawberry Django docs +--- + +# Strawberry Django docs + +## General + +- [Index](./index.md) +- [Community Projects](./community-projects.md) +- [FAQ](./faq.md) + +## Guide + +- [Authentication](./guide/authentication.md) +- [Export Schema](./guide/export-schema.md) +- [Fields](./guide/fields.md) +- [Filters](./guide/filters.md) +- [Mutations](./guide/mutations.md) +- [Optimizer](./guide/optimizer.md) +- [Ordering](./guide/ordering.md) +- [Pagination](./guide/pagination.md) +- [Permissions](./guide/permissions.md) +- [Queries](./guide/queries.md) +- [Relay](./guide/relay.md) +- [Resolvers](./guide/resolvers.md) +- [Settings](./guide/settings.md) +- [Subscriptions](./guide/subscriptions.md) +- [Types](./guide/types.md) +- [Unit Testing](./guide/unit-testing.md) +- [Views](./guide/views.md) + +## Integrations + +- [Channels](./integrations/channels.md) +- [Choices Field](./integrations/choices-field.md) +- [Debug Toolbar](./integrations/debug-toolbar.md) +- [Guardian](./integrations/guardian.md) diff --git a/docs/community-projects.md b/docs/community-projects.md index f21718cb..71baa858 100644 --- a/docs/community-projects.md +++ b/docs/community-projects.md @@ -1,3 +1,7 @@ +--- +title: Community Projects +--- + # Community Projects Those are some community maintained projects worth mentioning: diff --git a/docs/contributing.md b/docs/contributing.md deleted file mode 100644 index 19fb84c2..00000000 --- a/docs/contributing.md +++ /dev/null @@ -1,37 +0,0 @@ ---- - -We use [poetry](https://github.com/sdispater/poetry) to manage dependencies, to -get started follow these steps: - -```shell -git clone https://github.com/strawberry-graphql/strawberry-django.git -cd strawberry_django -poetry install -poetry run pytest -``` - -This will install all the dependencies (including the dev ones) and run the tests. - -If the tests fail with `SpatiaLite requires SQLite to be configured to allow extension loading` error, -it means that your python interpreter is not built with `--enable-loadable-sqlite-extensions` flag. -For example, if you are using pyenv, it can be fixed like this: - -`PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" pyenv install 3.12.0` - -### Pre commit - -We have a configuration for -[pre-commit](https://github.com/pre-commit/pre-commit), to add the hook run the -following command: - -```shell -pre-commit install -``` - -### Docs setup and local server - -We use Material for MkDocs, you can read the documentation [here](https://squidfunk.github.io/mkdocs-material/) - -```shell -make serve-docs -``` diff --git a/docs/faq.md b/docs/faq.md index a4b08dc5..8c333566 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,3 +1,7 @@ +--- +title: Frequently Asked Questions +--- + # Frequently Asked Questions (FAQ) ## How to access Django request object in resolvers? diff --git a/docs/guide/authentication.md b/docs/guide/authentication.md index 51f5931e..e54db164 100644 --- a/docs/guide/authentication.md +++ b/docs/guide/authentication.md @@ -1,17 +1,20 @@ -# Authentication +--- +title: Authentication +--- -!!! warning +# Authentication - This solution is enough for web browsers, but will not work for clients that - doesn't have a way to store cookies in it (e.g. mobile apps). For those it is - recommended to use token authentication methods. JWT can be used with - [strawberry-django-jwt](https://github.com/KundaPanda/strawberry-django-jwt) - lib. +> [!WARNING] +> This solution is enough for web browsers, but will not work for clients that +> doesn't have a way to store cookies in it (e.g. mobile apps). For those it is +> recommended to use token authentication methods. JWT can be used with +> [strawberry-django-jwt](https://github.com/KundaPanda/strawberry-django-jwt) +> lib. `strawberry_django` provides mutations to get authentication going right away. The `auth.register` mutation performs password validation using Django's `validate_password` method. -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry import auto from django.contrib.auth import get_user_model @@ -27,7 +30,7 @@ class UserInput: password: auto ``` -```{.python title=schema.py} +```python title="schema.py" import strawberry import strawberry_django from .types import User, UserInput diff --git a/docs/guide/export-schema.md b/docs/guide/export-schema.md index 15b9e6c8..49f638b5 100644 --- a/docs/guide/export-schema.md +++ b/docs/guide/export-schema.md @@ -1,8 +1,11 @@ -# Export Schema +--- +title: Export Schema +--- -!!! info +# Export Schema - The `export_schema` management command provided here is specifically designed for use with `strawberry_django`. The [default Strawberry export command](https://strawberry.rocks/docs/guides/schema-export) won't work with `strawberry_django` schemas because `strawberry_django` extends the base functionality of Strawberry to integrate with Django models and queries. This command ensures proper schema export functionality. +> [!INFO] +> The `export_schema` management command provided here is specifically designed for use with `strawberry_django`. The [default Strawberry export command](https://strawberry.rocks/docs/guides/schema-export) won't work with `strawberry_django` schemas because `strawberry_django` extends the base functionality of Strawberry to integrate with Django models and queries. This command ensures proper schema export functionality. The `export_schema` management command allows you to export a GraphQL schema defined using the `strawberry_django` library. This command converts the schema definition to GraphQL schema definition language (SDL), which can then be saved to a file or printed to the console. diff --git a/docs/guide/fields.md b/docs/guide/fields.md index 4d8a4024..acf8796b 100644 --- a/docs/guide/fields.md +++ b/docs/guide/fields.md @@ -1,13 +1,16 @@ -# Defining Fields +--- +title: Defining Fields +--- -!!! tip +# Defining Fields - It is highly recommended to enable the [Query Optimizer Extension](optimizer.md) - for improved performance and avoid some common pitfalls (e.g. the `n+1` issue) +> [!TIP] +> It is highly recommended to enable the [Query Optimizer Extension](optimizer.md) +> for improved performance and avoid some common pitfalls (e.g. the `n+1` issue) Fields can be defined manually or `auto` type can be used for automatic type resolution. All basic field types and relation fields are supported out of the box. If you use a library that defines a custom field you will need to define an equivalent type such as `str`, `float`, `bool`, `int` or `id`. -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry import auto @@ -24,19 +27,18 @@ class Fruit2: name: str ``` -!!! tip - - For choices using - [Django's TextChoices/IntegerChoices](https://docs.djangoproject.com/en/4.2/ref/models/fields/#enumeration-types) - it is recommented using the [django-choices-field](/integrations/choices-field) integration - enum handling. +> [!TIP] +> For choices using +> [Django's TextChoices/IntegerChoices](https://docs.djangoproject.com/en/4.2/ref/models/fields/#enumeration-types) +> it is recommented using the [django-choices-field](/integrations/choices-field) integration +> enum handling. ## Relationships All one-to-one, one-to-many, many-to-one and many-to-many relationship types are supported, and the many-to-many relation is described using the `typing.List` annotation. The default resolver of `strawberry_django.fields()` resolves the relationship based on given type information. -```{.python title=types.py} +```python title="types.py" from typing import List @strawberry_django.type(models.Fruit) @@ -63,7 +65,7 @@ situations. All Django types are encoded using the `strawberry_django.field()` field type by default. Fields can be customized with various parameters. -```{.python title=types.py} +```python title="types.py" @strawberry_django.type(models.Color) class Color: another_name: auto = strawberry_django.field(field_name='name') @@ -120,9 +122,8 @@ field_type_map.update({ ## Including / excluding Django model fields by name -!!! warning - - These new keywords should be used with caution, as they may inadvertently lead to exposure of unwanted data. Especially with `fields="__all__"` or `exclude`, sensitive model attributes may be included and made available in the schema without your awareness. +> [!WARNING] +> These new keywords should be used with caution, as they may inadvertently lead to exposure of unwanted data. Especially with `fields="__all__"` or `exclude`, sensitive model attributes may be included and made available in the schema without your awareness. `strawberry_django.type` includes two optional keyword fields to help you populate fields from the Django model, `fields` and `exclude`. @@ -131,19 +132,19 @@ Valid values for `fields` are: - `__all__` to assign `strawberry.auto` as the field type for all model fields. - `[]` to assign `strawberry.auto` as the field type for the enumerated fields. These can be combined with manual type annotations if needed. -```{.python title="All Fields"} +```python title="All Fields" @strawberry_django.type(models.Fruit, fields="__all__") class FruitType: pass ``` -```{.python title="Enumerated Fields"} +```python title="Enumerated Fields" @strawberry_django.type(models.Fruit, fields=["name", "color"]) class FruitType: pass ``` -```{.python title="Overriden Fields"} +```python title="Overriden Fields" @strawberry_django.type(models.Fruit, fields=["color"]) class FruitType: name: str @@ -153,13 +154,13 @@ Valid values for `exclude` are: - `[]` to exclude from the fields list. All other Django model fields will included and have `strawberry.auto` as the field type. These can also be overriden if another field type should be assigned. An empty list is ignored. -```{.python title="Exclude Fields"} +```python title="Exclude Fields" @strawberry_django.type(models.Fruit, exclude=["name"]) class FruitType: pass ``` -```{.python title="Overriden Exclude Fields"} +```python title="Overriden Exclude Fields" @strawberry_django.type(models.Fruit, exclude=["name"]) class FruitType: color: int @@ -172,7 +173,7 @@ Note that `fields` has precedence over `exclude`, so if both are provided, then If in your project, you want to change/add some of the standard `strawberry_django.field()` behaviour, it is possible to use your own custom field class when decorating a `strawberry_django.type` with the `field_cls` argument, e.g. -```{.python title=types.py} +```python title="types.py" class CustomStrawberryDjangoField(StrawberryDjangoField): """Your custom behaviour goes here.""" diff --git a/docs/guide/filters.md b/docs/guide/filters.md index 3336e239..d0a5d44d 100644 --- a/docs/guide/filters.md +++ b/docs/guide/filters.md @@ -1,9 +1,13 @@ +--- +title: Filtering +--- + # Filtering It is possible to define filters for Django types, which will be converted into `.filter(...)` queries for the ORM: -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry import auto @@ -17,16 +21,15 @@ class Fruit: ... ``` -!!! tip - - In most cases filter fields should have `Optional` annotations and default value `strawberry.UNSET` like so: - `foo: Optional[SomeType] = strawberry.UNSET` - Above `auto` annotation is wrapped in `Optional` automatically. - `UNSET` is automatically used for fields without `field` or with `strawberry_django.filter_field`. +> [!TIP] +> In most cases filter fields should have `Optional` annotations and default value `strawberry.UNSET` like so: +> `foo: Optional[SomeType] = strawberry.UNSET` +> Above `auto` annotation is wrapped in `Optional` automatically. +> `UNSET` is automatically used for fields without `field` or with `strawberry_django.filter_field`. The code above would generate following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" input FruitFilter { id: ID name: String @@ -37,12 +40,11 @@ input FruitFilter { } ``` -!!! tip - - If you are using the [relay integration](relay.md) and working with types inheriting - from `relay.Node` and `GlobalID` for identifying objects, you might want to set - `MAP_AUTO_ID_AS_GLOBAL_ID=True` in your [strawberry django settings](../settings) - to make sure `auto` fields gets mapped to `GlobalID` on types and filters. +> [!TIP] +> If you are using the [relay integration](relay.md) and working with types inheriting +> from `relay.Node` and `GlobalID` for identifying objects, you might want to set +> `MAP_AUTO_ID_AS_GLOBAL_ID=True` in your [strawberry django settings](../settings) +> to make sure `auto` fields gets mapped to `GlobalID` on types and filters. ## AND, OR, NOT, DISTINCT ... @@ -66,7 +68,7 @@ To every filter `AND`, `OR`, `NOT` & `DISTINCT` fields are added to allow more c Lookups can be added to all fields with `lookups=True`, which will add more options to resolve each type. For example: -```{.python title=types.py} +```python title="types.py" @strawberry_django.filter(models.Fruit, lookups=True) class FruitFilter: id: auto @@ -75,7 +77,7 @@ class FruitFilter: The code above would generate the following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" input IDBaseFilterLookup { exact: ID isNull: Boolean @@ -109,7 +111,7 @@ input FruitFilter { Single-field lookup can be annotated with the `FilterLookup` generic type. -```{.python title=types.py} +```python title="types.py" from strawberry_django import FilterLookup @strawberry_django.filter(models.Fruit) @@ -119,7 +121,7 @@ class FruitFilter: ## Filtering over relationships -```{.python title=types.py} +```python title="types.py" @strawberry_django.filter(models.Color) class ColorFilter: id: auto @@ -134,7 +136,7 @@ class FruitFilter: The code above would generate following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" input ColorFilter { id: ID name: String @@ -157,7 +159,7 @@ input FruitFilter { You can define custom filter method by defining your own resolver. -```{.python title=types.py} +```python title="types.py" @strawberry_django.filter(models.Fruit) class FruitFilter: name: auto @@ -202,42 +204,42 @@ class FruitFilter: ) ``` -!!! warning - - It is discouraged to use `queryset.filter()` directly. When using more - complex filtering via `NOT`, `OR` & `AND` this might lead to undesired behaviour. - -!!! tip - - #### process_filters - - As seen above `strawberry_django.process_filters` function is exposed and can be - reused in custom methods. Above it's used to resolve fields lookups - - #### null values - - By default `null` value is ignored for all filters & lookups. This applies to custom - filter methods as well. Those won't even be called (you don't have to check for `None`). - This can be modified using - `strawberry_django.filter_field(filter_none=True)` - - This also means that built in `exact` & `iExact` lookups cannot be used to filter for `None` - and `isNull` have to be used explicitly. - - #### value resolution - - `value` parameter of type `relay.GlobalID` is resolved to its `node_id` attribute - - `value` parameter of type `Enum` is resolved to is's value - - above types are converted in `lists` as well - - resolution can modified via `strawberry_django.filter_field(resolve_value=...)` - - - True - always resolve - - False - never resolve - - UNSET (default) - resolves for filters without custom method only +> [!WARNING] +> It is discouraged to use `queryset.filter()` directly. When using more +> complex filtering via `NOT`, `OR` & `AND` this might lead to undesired behaviour. + +> [!TIP] +> +> #### process_filters +> +> As seen above `strawberry_django.process_filters` function is exposed and can be +> reused in custom methods. Above it's used to resolve fields lookups +> +> #### null values +> +> By default `null` value is ignored for all filters & lookups. This applies to custom +> filter methods as well. Those won't even be called (you don't have to check for `None`). +> This can be modified using +> `strawberry_django.filter_field(filter_none=True)` +> +> This also means that built in `exact` & `iExact` lookups cannot be used to filter for `None` +> and `isNull` have to be used explicitly. +> +> #### value resolution +> +> - `value` parameter of type `relay.GlobalID` is resolved to its `node_id` attribute +> - `value` parameter of type `Enum` is resolved to is's value +> - above types are converted in `lists` as well +> +> resolution can modified via `strawberry_django.filter_field(resolve_value=...)` +> +> - True - always resolve +> - False - never resolve +> - UNSET (default) - resolves for filters without custom method only The code above generates the following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" input FruitFilter { name: String lastName: String @@ -254,7 +256,7 @@ input FruitFilter { - Important for nested filtering - In code bellow custom filter `name` ends up filtering `Fruit` instead of `Color` without applying `prefix` -```{.python title="Why prefix?"} +```python title="Why prefix?" @strawberry_django.filter(models.Fruit) class FruitFilter: name: auto @@ -306,7 +308,7 @@ Works similar to field filter method, but: - argument `queryset` is **Required** - argument `value` is **Forbidden** -```{.python title=types.py} +```python title="types.py" @strawberry_django.filter(models.Fruit) class FruitFilter: def ordered( @@ -340,18 +342,17 @@ class FruitFilter: ) ``` -!!! tip - - As seen above `strawberry_django.process_filters` function is exposed and can be - reused in custom methods. - For filter method `filter` `skip_object_order_method` was used to avoid endless recursion. +> [!TIP] +> As seen above `strawberry_django.process_filters` function is exposed and can be +> reused in custom methods. +> For filter method `filter` `skip_object_order_method` was used to avoid endless recursion. ## Adding filters to types All fields and CUD mutations inherit filters from the underlying type by default. So, if you have a field like this: -```{.python title=types.py} +```python title="types.py" @strawberry_django.type(models.Fruit, filters=FruitFilter) class Fruit: ... @@ -368,7 +369,7 @@ if it was passed to the field. Filters added into a field override the default filters of this type. -```{.python title=schema.py} +```python title="schema.py" @strawberry.type class Query: fruits: list[Fruit] = strawberry_django.field(filters=FruitFilter) @@ -420,10 +421,9 @@ There is 7 already defined Generic Lookup `strawberry.input` classes importable The previous version of filters can be enabled via [**USE_DEPRECATED_FILTERS**](settings.md#strawberry_django) -!!! warning - - If **USE_DEPRECATED_FILTERS** is not set to `True` legacy custom filtering - methods will be _not_ be called. +> [!WARNING] +> If **USE_DEPRECATED_FILTERS** is not set to `True` legacy custom filtering +> methods will be _not_ be called. When using legacy filters it is important to use legacy `strawberry_django.filters.FilterLookup` lookups as well. diff --git a/docs/guide/mutations.md b/docs/guide/mutations.md index 0c1e87c2..e0d592d6 100644 --- a/docs/guide/mutations.md +++ b/docs/guide/mutations.md @@ -1,3 +1,7 @@ +--- +title: Mutations +--- + # Mutations ## Getting started @@ -20,7 +24,7 @@ Here are the differences between those: When defining a mutation you can pass `handle_django_errors=True` to make it handle common django errors, such as `ValidationError`, `PermissionDenied` and `ObjectDoesNotExist`: -```{.python title=types.py} +```python title="types.py" @strawberry.type class Mutation: @strawberry_django.mutation(handle_django_errors=True) @@ -36,7 +40,7 @@ class Mutation: The code above would generate following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" enum OperationMessageKind { INFO WARNING @@ -81,11 +85,10 @@ mutation { } ``` -!!! tip - - If all or most of your mutations use this behaviour, you can change the - default behaviour for `handle_django_errors` by setting - `MUTATIONS_DEFAULT_HANDLE_ERRORS=True` in your [strawberry django settings](../settings) +> [!TIP] +> If all or most of your mutations use this behaviour, you can change the +> default behaviour for `handle_django_errors` by setting +> `MUTATIONS_DEFAULT_HANDLE_ERRORS=True` in your [strawberry django settings](../settings) ## Input mutations @@ -105,7 +108,7 @@ The following CUD mutations are provided by this lib: A basic example would be: -```{.python title=types.py} +```python title="types.py" from strawberry import auto from strawberry_django import mutations, NodeInput from strawberry.relay import Node @@ -145,7 +148,7 @@ Some things to note here: see [partial input types](./types.md#input-types) documentation for examples. - I's also possible to update or delete model by using unique identifier other than id by providing `key_attr` property : -```{.python} +```python @strawberry_django.partial(SomeModel) class SomeModelInputPartial: unique_field: strawberry.auto @@ -164,17 +167,14 @@ class Mutation: ## Filtering -!!! danger - - This is totally discouraged as it allows for any issue with the filters - to be able to alter your whole model collection. - - **You have been warned!** +> [!CAUTION] +> This is totally discouraged as it allows for any issue with the filters +> to be able to alter your whole model collection. Filters can be added to update and delete mutations. More information in the [filtering](filters.md) section. -```{.python title=schema.py} +```python title="schema.py" import strawberry from strawberry_django import mutations diff --git a/docs/guide/optimizer.md b/docs/guide/optimizer.md index 4158e8e3..2abbd6b2 100644 --- a/docs/guide/optimizer.md +++ b/docs/guide/optimizer.md @@ -1,3 +1,7 @@ +--- +title: Query Optimizer +--- + # Query Optimizer ## Features @@ -23,7 +27,7 @@ Those are specially useful to avoid some common GraphQL pitfalls, like the famou The automatic optimization can be enabled by adding the `DjangoOptimizerExtension` to your strawberry's schema config. -```{.python title=schema.py} +```python title="schema.py" import strawberry from strawberry_django.optimizer import DjangoOptimizerExtension @@ -41,7 +45,7 @@ schema = strawberry.Schema( The optimizer will try to optimize all types automatically by introspecting it. Consider the following example: -```{.python title=models.py} +```python title="models.py" class Artist(models.Model): name = models.CharField() @@ -58,7 +62,7 @@ class Song(models.Model): album = models.ForeignKey("Album", related_name="songs") ``` -```{.python title=types.py} +```python title="types.py" from strawberry import auto import strawberry_django @@ -92,7 +96,7 @@ class Query: Querying for `artist` and `songs` like this: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" query { artist { id @@ -164,18 +168,17 @@ Song.objects.all().only( ) ``` -!!! note - - Even though `album__release_date` field was not selected here, it got selected - in the prefetch query later. Since Django caches known objects, we have to select it here or - else it would trigger extra queries latter. +> [!NOTE] +> Even though `album__release_date` field was not selected here, it got selected +> in the prefetch query later. Since Django caches known objects, we have to select it here or +> else it would trigger extra queries latter. ## Optimization hints Sometimes you will have a custom resolver which cannot be automatically optimized by the extension. Take this for example: -```{.python title=models.py} +```python title="models.py" class OrderItem(models.Model): price = models.DecimalField() quantity = models.IntegerField() @@ -185,7 +188,7 @@ class OrderItem(models.Model): return self.price * self.quantity ``` -```{.python title=types.py} +```python title="types.py" from strawberry import auto import strawberry_django @@ -203,7 +206,7 @@ by the optimizer. A solution in this case would be to "tell the optimizer" how to optimize that field: -```{.python title=types.py} +```python title="types.py" from strawberry import auto import strawberry_django @@ -218,7 +221,7 @@ class OrderItem: Or if you are using a custom resolver: -```{.python title=types.py} +```python title="types.py" import decimal from strawberry import auto @@ -265,7 +268,7 @@ For that this integration provides 2 decorators that can be used: The example in the previous section could be written using `@model_property` like this: -```{.python title=models.py} +```python title="models.py" from strawberry_django import model_property class OrderItem(models.Model): @@ -277,7 +280,7 @@ class OrderItem(models.Model): return self.price * self.quantity ``` -```{.python title=types.py} +```python title="types.py" from strawberry import auto import strawberry_django diff --git a/docs/guide/ordering.md b/docs/guide/ordering.md index 72f6b50e..6ddacea1 100644 --- a/docs/guide/ordering.md +++ b/docs/guide/ordering.md @@ -1,6 +1,10 @@ +--- +title: Ordering +--- + # Ordering -```{.python title=types.py} +```python title="types.py" @strawberry_django.order(models.Color) class ColorOrder: name: auto @@ -11,15 +15,14 @@ class FruitOrder: color: ColorOrder | None ``` -!!! tip - - In most cases order fields should have `Optional` annotations and default value `strawberry.UNSET`. - Above `auto` annotation is wrapped in `Optional` automatically. - `UNSET` is automatically used for fields without `field` or with `strawberry_django.order_field`. +> [!TIP] +> In most cases order fields should have `Optional` annotations and default value `strawberry.UNSET`. +> Above `auto` annotation is wrapped in `Optional` automatically. +> `UNSET` is automatically used for fields without `field` or with `strawberry_django.order_field`. The code above generates the following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" enum Ordering { ASC ASC_NULLS_FIRST @@ -43,7 +46,7 @@ input FruitOrder { You can define custom order method by defining your own resolver. -```{.python title=types.py} +```python title="types.py" @strawberry_django.order(models.Fruit) class FruitOrder: name: auto @@ -70,20 +73,17 @@ class FruitOrder: return queryset, [ordering] ``` -!!! warning - - Do not use `queryset.order_by()` directly. Due to `order_by` not being chainable - operation, changes applied this way would be overriden later. +> [!WARNING] +> Do not use `queryset.order_by()` directly. Due to `order_by` not being chainable +> operation, changes applied this way would be overriden later. -!!! tip - - `strawberry_django.Ordering` has convenient method `resolve` that can be used to - convert field's name to appropriate `F` object with correctly applied `asc()`, `desc()` method - with `nulls_first` and `nulls_last` arguments. +> [!TIP] > `strawberry_django.Ordering` has convenient method `resolve` that can be used to +> convert field's name to appropriate `F` object with correctly applied `asc()`, `desc()` method +> with `nulls_first` and `nulls_last` arguments. The code above generates the following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" enum Ordering { ASC ASC_NULLS_FIRST @@ -107,7 +107,7 @@ input FruitOrder { - Important for nested ordering - In code bellow custom order `name` ends up ordering `Fruit` instead of `Color` without applying `prefix` -```{.python title="Why prefix?"} +```python title="Why prefix?" @strawberry_django.order(models.Fruit) class FruitOrder: name: auto @@ -167,7 +167,7 @@ Works similar to field order method, but: - argument `value` is **Forbidden** - should probaly use `sequence` -```{.python title=types.py} +```python title="types.py" @strawberry_django.order(models.Fruit) class FruitOrder: name: auto @@ -208,18 +208,17 @@ class FruitOrder: ``` -!!! tip - - As seen above `strawberry_django.process_order` function is exposed and can be - reused in custom methods. - For order method `order` `skip_object_order_method` was used to avoid endless recursion. +> [!TIP] +> As seen above `strawberry_django.process_order` function is exposed and can be +> reused in custom methods. +> For order method `order` `skip_object_order_method` was used to avoid endless recursion. ## Adding orderings to types All fields and mutations inherit orderings from the underlying type by default. So, if you have a field like this: -```{.python title=types.py} +```python title="types.py" @strawberry_django.type(models.Fruit, order=FruitOrder) class Fruit: ... @@ -232,7 +231,7 @@ if it was passed to the field. Orderings added into a field override the default order of this type. -```{.python title=schema.py} +```python title="schema.py" @strawberry.type class Query: fruit: Fruit = strawberry_django.field(order=FruitOrder) diff --git a/docs/guide/pagination.md b/docs/guide/pagination.md index a02d8d1e..caa6fc22 100644 --- a/docs/guide/pagination.md +++ b/docs/guide/pagination.md @@ -1,16 +1,20 @@ +--- +title: Pagination +--- + # Pagination ## Default pagination An interface for limit/offset pagination can be use for basic pagination needs: -```{.python title=types.py} +```python title="types.py" @strawberry_django.type(models.Fruit, pagination=True) class Fruit: name: auto ``` -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" query { fruits(pagination: { offset: 0, limit: 2 }) { name diff --git a/docs/guide/permissions.md b/docs/guide/permissions.md index cf0fc1d0..35bccf3e 100644 --- a/docs/guide/permissions.md +++ b/docs/guide/permissions.md @@ -1,3 +1,7 @@ +--- +title: Permissions +--- + # Permissions This integration exposes a field extension to extend fields into using the @@ -32,7 +36,7 @@ graph TD ## Example -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry_django.permissions import ( IsAuthenticated, @@ -74,13 +78,12 @@ Available options are: will filter the return value, removing objects that fails the check (check below for more information regarding other possibilities). -!!! note - - The `HasSourcePerm` and `HasRetvalPerm` require having an - [authentication backend](https://docs.djangoproject.com/en/4.2/topics/auth/customizing/) - which supports resolving object permissions. This lib works out of the box with - [django-guardian](https://django-guardian.readthedocs.io/en/stable/), so if you are - using it you don't need to do anything else. +> [!NOTE] +> The `HasSourcePerm` and `HasRetvalPerm` require having an +> [authentication backend](https://docs.djangoproject.com/en/4.2/topics/auth/customizing/) +> which supports resolving object permissions. This lib works out of the box with +> [django-guardian](https://django-guardian.readthedocs.io/en/stable/), so if you are +> using it you don't need to do anything else. ## No Permission Handling diff --git a/docs/guide/queries.md b/docs/guide/queries.md index 23df6fa3..33de655c 100644 --- a/docs/guide/queries.md +++ b/docs/guide/queries.md @@ -1,3 +1,7 @@ +--- +title: Queries +--- + # Queries Queries can be written using `strawberry_django.field()` to load the fields defined in the `types.py` file. @@ -19,8 +23,7 @@ class Query: schema = strawberry.Schema(query=Query) ``` -!!! tip - - You must name your query class "Query" or decorate it with `@strawberry.type(name="Query")` for the single query default primary filter to work +> [!TIP] +> You must name your query class "Query" or decorate it with `@strawberry.type(name="Query")` for the single query default primary filter to work For the single queries (like `Fruit` above), Strawberry comes with a default primary key search filter in the GraphiQL interface. The query `Fruits` gets all the objects in the Fruits by default. To query specific sets of objects a filter need to be added in the `types.py` file. diff --git a/docs/guide/relay.md b/docs/guide/relay.md index 4d425c62..d4b794ec 100644 --- a/docs/guide/relay.md +++ b/docs/guide/relay.md @@ -1,9 +1,13 @@ +--- +title: Relay +--- + # Relay Support You can use the [official strawberry relay integration](https://strawberry.rocks/docs/guides/relay) directly with django types like this: -```{.python title=types.py} +```python title="types.py" import strawberry import strawberry_django from strawberry_django.relay import ListConnectionWithTotalCount @@ -51,12 +55,11 @@ Behind the scenes this extension is doing the following for you: You can also define your own `relay.NodeID` field and your resolve, in the same way as `some_model_conn_with_resolver` is doing. In those cases, they will not be overridden. -!!! tip - - If you are only working with types inheriting from `relay.Node` and `GlobalID` - for identifying objects, you might want to set `MAP_AUTO_ID_AS_GLOBAL_ID=True` - in your [strawberry django settings](../settings) to make sure `auto` fields gets - mapped to `GlobalID` on types and filters. +> [!TIP] +> If you are only working with types inheriting from `relay.Node` and `GlobalID` +> for identifying objects, you might want to set `MAP_AUTO_ID_AS_GLOBAL_ID=True` +> in your [strawberry django settings](../settings) to make sure `auto` fields gets +> mapped to `GlobalID` on types and filters. Also, this lib exposes a `strawberry_django.relay.ListConnectionWithTotalCount`, which works the same way as `strawberry.relay.ListConnection` does, but also exposes a diff --git a/docs/guide/resolvers.md b/docs/guide/resolvers.md index 666b0c84..2608c670 100644 --- a/docs/guide/resolvers.md +++ b/docs/guide/resolvers.md @@ -1,3 +1,7 @@ +--- +title: Resolvers +--- + # Custom Resolvers Basic resolvers are generated automatically once the types are declared. @@ -9,7 +13,7 @@ However it is possible to override them with custom resolvers. Sync resolvers can be used in both ASGI/WSGI and will be automatically wrapped in `sync_to_async` when running async. -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry import auto from typing import List @@ -29,7 +33,7 @@ class Color: Async resolvers can be used when running using ASGI. -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry import auto from typing import List @@ -60,7 +64,7 @@ It is important to note that overriding resolvers also removes default capabilit (e.g. `Pagination`, `Filter`), exception for [relay connections](relay.md). You can however still add those by hand and resolve them: -```{.python title=types.py} +```python title="types.py" import strawberry from strawberry import auto from strawberry.types import Info diff --git a/docs/guide/settings.md b/docs/guide/settings.md index f8131bd3..d8e41973 100644 --- a/docs/guide/settings.md +++ b/docs/guide/settings.md @@ -1,3 +1,7 @@ +--- +title: Settings +--- + # Django Settings Certain features of this library are configured using custom @@ -60,7 +64,7 @@ A dictionary with the following optional keys: These features can be enabled by adding this code to your `settings.py` file. -```{.python title=settings.py} +```python title="settings.py" STRAWBERRY_DJANGO = { "FIELD_DESCRIPTION_FROM_HELP_TEXT": True, "TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True, diff --git a/docs/guide/subscriptions.md b/docs/guide/subscriptions.md index 984dad24..93cfd9cf 100644 --- a/docs/guide/subscriptions.md +++ b/docs/guide/subscriptions.md @@ -1,3 +1,7 @@ +--- +title: Subscriptions +--- + # Subscriptions Subscriptions are supported using the diff --git a/docs/guide/types.md b/docs/guide/types.md index a46e8f48..6fe5c135 100644 --- a/docs/guide/types.md +++ b/docs/guide/types.md @@ -1,11 +1,14 @@ +--- +title: Defining Types +--- + # Defining Types ## Output types -!!! note - - It is highly recommended to enable the [Query Optimizer Extension](optimizer.md) - for improved performance and avoid some common pitfalls (e.g. the `n+1` issue) +> ![NOTE} +> It is highly recommended to enable the [Query Optimizer Extension](optimizer.md) +> for improved performance and avoid some common pitfalls (e.g. the `n+1` issue) Output types are generated from models. The `auto` type is used for field type auto resolution. Relational fields are described by referencing to other types generated from Django models. @@ -13,7 +16,7 @@ A many-to-many relation is described with the `typing.List` type annotation. `strawberry_django` will automatically generate resolvers for relational fields. More information about that can be read from [resolvers](resolvers.md) page. -```{.python title=types.py} +```python title="types.py" import strawberry_django from strawberry import auto @@ -37,7 +40,7 @@ class Color: Input types can be generated from Django models using the `strawberry_django.input` decorator. The first parameter is the model which the type is derived from. -```{.python title=types.py} +```python title="types.py" @strawberry_django.input(models.Fruit) class FruitInput: id: auto @@ -50,7 +53,7 @@ Partial input types can be generated from existing input types through class inh Non-`auto` type annotations will be respected—and therefore required—unless explicitly marked `Optional[]`. -```{.python title=types.py} +```python title="types.py" @strawberry_django.input(models.Color, partial=True) class FruitPartialInput(FruitInput): color: List["ColorPartialInput"] @@ -74,7 +77,7 @@ class ColorNameRequiredPartialInput: Django models can be converted to `strawberry` Types with the `strawberry_django.type` decorator. Custom descriptions can be added using the `description` keyword argument (See: [`strawberry.type` decorator API](https://strawberry.rocks/docs/types/object-types#api)). -```{.python title=types.py} +```python title="types.py" import strawberry_django @strawberry_django.type(models.Fruit, description="A tasty snack") @@ -89,17 +92,16 @@ on [How to define Fields](fields.md) for that. ### Customizing the returned `QuerySet` -!!! warning - - By doing this you are modifying all automatic `QuerySet` generation for any field - that returns this type. Ideally you will want to define your own [resolver](resolvers.md) - instead, which gives you more control over it. +> [!WARNING] +> By doing this you are modifying all automatic `QuerySet` generation for any field +> that returns this type. Ideally you will want to define your own [resolver](resolvers.md) +> instead, which gives you more control over it. By default, a `strawberry_django` type will get data from the default manager for its Django Model. You can implement a custom `get_queryset` classmethod to your type to do some extra processing to the default queryset, like filtering it further. -```{.python title=types.py} +```python title="types.py" @strawberry_django.type(models.Fruit) class Berry: @@ -114,7 +116,7 @@ a `strawberry` `Info` object containing details about the request. You can use that `info` parameter to, for example, limit access to results based on the current user in the request: -```{.python title=types.py} +```python title="types.py" from stawberry_django.auth.utils import get_current_user @strawberry_django.type(models.Fruit) @@ -129,10 +131,9 @@ class Berry: return queryset.filter(name__contains="berry") ``` -!!! note - - Another way of limiting this is by using the [PermissionExtension](permissions.md) - provided by this lib. +> [!NOTE] +> Another way of limiting this is by using the [PermissionExtension](permissions.md) +> provided by this lib. The `kwargs` dictionary can include other parameters that were added in a `@strawberry.django.type` definition like [filters](filters.md) or [pagination](pagination.md). diff --git a/docs/guide/unit-testing.md b/docs/guide/unit-testing.md index 7d096c2c..8e9ddcfb 100644 --- a/docs/guide/unit-testing.md +++ b/docs/guide/unit-testing.md @@ -1,3 +1,7 @@ +--- +title: Unit Testing +--- + # Unit testing Unit testing can be done by following the diff --git a/docs/guide/views.md b/docs/guide/views.md index 4ac0fcbd..81bd2d39 100644 --- a/docs/guide/views.md +++ b/docs/guide/views.md @@ -1,3 +1,7 @@ +--- +title: Views +--- + # Serving the API Strawberry works both with ASGI (async) and WSGI (sync). This integration @@ -12,7 +16,7 @@ you will be missing support for some interesting features, such as Expose the strawberry API when using ASGI by setting your urls.py like this: -```{.python title=urls.py} +```python title="urls.py" from django.urls import path from strawberry.django.views import AsyncGraphQLView @@ -27,7 +31,7 @@ urlpatterns = [ Expose the strawberry API when using WSGI by setting your urls.py like this: -```{.python title=urls.py} +```python title="urls.py" from django.urls import path from strawberry.django.views import GraphQLView diff --git a/docs/index.md b/docs/index.md index 3390026e..828c1663 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,41 +1,225 @@ - +--- +title: Quick Start +--- -![Logo](./images/logo.png){ align=center } -**Strawberry integration with Django** +# Quick Start ---- +In this Quick-Start, we will: -**WHAT:** A toolset for GraphQL schema generation from Django models. +- Set up a basic pair of models with a relation between them. +- Add them to a graphql schema and serve the graph API. +- Query the graph API for model contents. -**WHY:** To build better web apps more quickly and with less code. +For a more advanced example of a similar setup including a set of mutations and more queries, please check the [example app](https://github.com/strawberry-graphql/strawberry-django/tree/main/examples/django). -**HOW:** By providing django-specific methods for using the [strawberry GraphQL library](https://strawberry.rocks/). +## Installation ---- +```sh +poetry add strawberry-graphql-django +poetry add django-choices-field # Not required but recommended +``` + +(Not using poetry yet? `pip install strawberry-graphql-django` works fine too.) + +## Define your application models + +We'll build an example database of fruit and their colours. + +> [!TIP] +> You'll notice that for `Fruit.category`, we use `TextChoicesField` instead of `TextField(choices=...)`. +> This allows strawberry-django to automatically use an enum in the graphQL schema, instead of +> a string which would be the default behaviour for TextField. +> +> See the [choices-field integration](./integrations/choices-field.md) for more information. + +```python title="models.py" +from django.db import models +from django_choices_field import TextChoicesField + +class FruitCategory(models.TextChoices): + CITRUS = "citrus", "Citrus" + BERRY = "berry", "Berry" + +class Fruit(models.Model): + """A tasty treat""" + + name = models.CharField(max_length=20, help_text="The name of the fruit variety") + category = TextChoicesField(choices_enum=FruitCategory, help_text="The category of the fruit") + color = models.ForeignKey( + "Color", + on_delete=models.CASCADE, + related_name="fruits", + blank=True, + null=True, + help_text="The color of this kind of fruit", + ) + +class Color(models.Model): + """The hue of your tasty treat""" + + name = models.CharField( + max_length=20, + help_text="The color name", + ) +``` + +You'll need to make migrations then migrate: + +```sh +python manage.py makemigrations +python manage.py migrate +``` + +Now use the django shell, the admin, the loaddata command or whatever tool you like to load some fruits and colors. I've loaded a red strawberry (predictable, right?!) ready for later. + +## Define types + +Before creating queries, you have to define a `type` for each model. A `type` is a fundamental unit of the [schema](https://strawberry.rocks/docs/types/schema) +which describes the shape of the data that can be queried from the GraphQL server. Types can represent scalar values (like String, Int, Boolean, Float, and ID), enums, or complex objects that consist of many fields. + +> [!TIP] +> A key feature of `strawberry-graphql-django` is that it provides helpers to create types from django models, +> by automatically inferring types (and even documentation!!) from the model fields. +> +> See the [fields guide](./guide/fields.md) for more information. + +```python title="types.py" +import strawberry_django +from strawberry import auto + +from . import models + +@strawberry_django.type(models.Fruit) +class Fruit: + id: auto + name: auto + category: auto + color: "Color" # Strawberry will understand that this refers to the "Color" type that's defined below -[![CI](https://github.com/strawberry-graphql/strawberry-django/actions/workflows/main.yml/badge.svg)](https://github.com/strawberry-graphql/strawberry-django/actions/workflows/main.yml) -[![PyPI](https://img.shields.io/pypi/v/strawberry-graphql-django)](https://pypi.org/project/strawberry-graphql-django/) -[![Downloads](https://pepy.tech/badge/strawberry-graphql-django)](https://pepy.tech/project/strawberry-graphql-django) +@strawberry_django.type(models.Color) +class Color: + id: auto + name: auto + fruits: list[Fruit] # This tells strawberry about the ForeignKey to the Fruit model and how to represent the Fruit instances on that relation +``` -## Supported features +## Build the queries and schema -- [x] GraphQL type generation from models -- [x] Filtering, pagination and ordering -- [x] Basic create, retrieve, update and delete (CRUD) types and mutations -- [x] Basic Django auth support, current user query, login and logout mutations -- [x] Django sync and async views -- [x] Permission extension using django's permissioning system -- [x] Relay support with automatic resolvers generation -- [x] Query optimization to improve performance and avoid common pitfalls (e.g n+1) -- [x] Debug Toolbar integration with graphiql to display metrics like SQL queries -- [x] Unit test integration +Next we want to assemble the [schema](https://strawberry.rocks/docs/types/schema) from its building block types. -## Getting started +> [!WARNING] +> You'll notice a familiar statement, `fruits: list[Fruit]`. We already used this statement in the previous step in `types.py`. +> Seeing it twice can be a point of confusion when you're first getting to grips with graph and strawberry. +> +> The purpose here is similar but subtly different. Previously, the syntax defined that it was possible to make a query that **traverses** within the graph, from a Color to a list of Fruits. +> Here, the usage defines a [**root** query](https://strawberry.rocks/docs/general/queries) (a bit like an entrypoint into the graph). -Check out the [quick start](quick-start.md) for all the basics, then the [example app](https://github.com/strawberry-graphql/strawberry-django/tree/main/examples/django) for a slightly more complete setup +> [!TIP] +> We add the `DjangoOptimizerExtension` here. Don't worry about why for now, but you're almost certain to want it. +> +> See the [optimizer guide](./guide/optimizer.md) for more information. + +```python title="schema.py" +import strawberry +from strawberry_django.optimizer import DjangoOptimizerExtension + +from .types import Fruit + +@strawberry.type +class Query: + fruits: list[Fruit] = strawberry_django.field() + +schema = strawberry.Schema( + query=Query, + extensions=[ + DjangoOptimizerExtension, + ], ) +``` + +## Serving the API + +Now we're showing off. This isn't enabled by default, since existing django applications will likely +have model docstrings and help text that aren't user-oriented. But if you're starting clean (or overhauling +existing dosctrings and helptext), setting up the following is super useful for your API users. + +If you don't set these true, you can always provide user-oriented descriptions. See the + +```python title="settings.py" +STRAWBERRY_DJANGO = { + "FIELD_DESCRIPTION_FROM_HELP_TEXT": True, + "TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True, +} +``` + +```python title="urls.py" +from django.urls import include, path +from strawberry.django.views import AsyncGraphQLView + +from .schema import schema + +urlpatterns = [ + path('graphql', AsyncGraphQLView.as_view(schema=schema)), +] +``` + +This generates following schema: + +```graphql title="schema.graphql" +enum FruitCategory { + CITRUS + BERRY +} + +""" +A tasty treat +""" +type Fruit { + id: ID! + name: String! + category: FruitCategory! + color: Color +} + +type Color { + id: ID! + """ + field description + """ + name: String! + fruits: [Fruit!] +} + +type Query { + fruits: [Fruit!]! +} +``` + +## Using the API + +Start your server with: + +```sh +python manage.py runserver +``` + +Then visit [localhost:8000/graphql](http://localhost:8000/graphql) in your browser. You should see the graphql explorer being served by django. +Using the interactive query tool, you can query for the fruits you added earlier: + +![GraphiQL with fruit](./images/graphiql-with-fruit.png) + +## Next steps + +1. [Defining more Django Types](./guide/types.md) +2. [Define Fields inside those Types](./guide/fields.md) +3. [Serve your API using ASGI or WSGI](./guide/views.md) +4. [Define filters for your fields](./guide/filters.md) +5. [Define orderings for your fields](./guide/ordering.md) +6. [Define pagination for your fields](./guide/pagination.md) +7. [Define queries for your schema](./guide/queries.md) +8. [Define mutations for your schema](./guide/mutations.md) +9. [Define subscriptions for your schema](./guide/subscriptions.md) +10. [Enable the Query Optimizer extension for performance improvement](./guide/optimizer.md) +11. [Use the relay integration for advanced pagination and model refetching](./guide/relay.md) +12. [Protect your fields using the Permission Extension](./guide/permissions.md) +13. [Write unit tests for your schema](./guide/unit-testing.md) diff --git a/docs/integrations/channels.md b/docs/integrations/channels.md index 3c967f6e..90ad6252 100644 --- a/docs/integrations/channels.md +++ b/docs/integrations/channels.md @@ -1,3 +1,7 @@ +--- +title: Django Channels +--- + # django-channels Strawberry provides an integration for diff --git a/docs/integrations/choices-field.md b/docs/integrations/choices-field.md index 09d95ad9..21f95fc9 100644 --- a/docs/integrations/choices-field.md +++ b/docs/integrations/choices-field.md @@ -1,3 +1,7 @@ +--- +title: Django Choices Field +--- + # django-choices-field This lib provides integration for enum resolution for @@ -5,7 +9,7 @@ This lib provides integration for enum resolution for when defining the fields using the [django-choices-field](https://github.com/bellini666/django-choices-field) lib: -```{.python title=models.py} +```python title="models.py" from django.db import models from django_choices_field import TextChoicesField @@ -20,7 +24,7 @@ class Company(models.Model): ) ``` -```{.python title=types.py} +```python title="types.py" import strawberry import strawberry_django @@ -33,7 +37,7 @@ class Company: The code above would generate the following schema: -```{.graphql title=schema.graphql} +```graphql title="schema.graphql" enum Status { ACTIVE INACTIVE diff --git a/docs/integrations/debug-toolbar.md b/docs/integrations/debug-toolbar.md index 39f4cca2..bb03a603 100644 --- a/docs/integrations/debug-toolbar.md +++ b/docs/integrations/debug-toolbar.md @@ -1,3 +1,7 @@ +--- +title: Django Debug Toolbar +--- + # django-debug-toolbar This integration provides integration between the @@ -9,7 +13,7 @@ To use it, make sure you have the [Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) installed and configured, then change its middleware settings from: -```{.python title=settings.py} +```python title="settings.py" MIDDLEWARE = [ ... "debug_toolbar.middleware.DebugToolbarMiddleware", @@ -19,7 +23,7 @@ MIDDLEWARE = [ To: -```{.python title=settings.py} +```python title="settings.py" MIDDLEWARE = [ ... "strawberry_django.middlewares.debug_toolbar.DebugToolbarMiddleware", diff --git a/docs/integrations/guardian.md b/docs/integrations/guardian.md index 65c48be0..cb2bea33 100644 --- a/docs/integrations/guardian.md +++ b/docs/integrations/guardian.md @@ -1,3 +1,7 @@ +--- +title: django-guardian +--- + # django-guardian This lib provides integration for per-object-permissions using diff --git a/docs/quick-start.md b/docs/quick-start.md deleted file mode 100644 index bfe57ead..00000000 --- a/docs/quick-start.md +++ /dev/null @@ -1,227 +0,0 @@ -# Quick Start - -In this Quick-Start, we will: - -- Set up a basic pair of models with a relation between them. -- Add them to a graphql schema and serve the graph API. -- Query the graph API for model contents. - -For a more advanced example of a similar setup including a set of mutations and more queries, please check the [example app](https://github.com/strawberry-graphql/strawberry-django/tree/main/examples/django). - -## Installation - -```sh -poetry add strawberry-graphql-django -poetry add django-choices-field # Not required but recommended -``` - -(Not using poetry yet? `pip install strawberry-graphql-django` works fine too.) - -## Define your application models - -We'll build an example database of fruit and their colours. - -!!! tip - - You'll notice that for `Fruit.category`, we use `TextChoicesField` instead of `TextField(choices=...)`. - This allows strawberry-django to automatically use an enum in the graphQL schema, instead of - a string which would be the default behaviour for TextField. - - See the [choices-field integration](./integrations/choices-field.md) for more information. - -```{.python title=models.py} -from django.db import models -from django_choices_field import TextChoicesField - -class FruitCategory(models.TextChoices): - CITRUS = "citrus", "Citrus" - BERRY = "berry", "Berry" - -class Fruit(models.Model): - """A tasty treat""" - - name = models.CharField(max_length=20, help_text="The name of the fruit variety") - category = TextChoicesField(choices_enum=FruitCategory, help_text="The category of the fruit") - color = models.ForeignKey( - "Color", - on_delete=models.CASCADE, - related_name="fruits", - blank=True, - null=True, - help_text="The color of this kind of fruit", - ) - -class Color(models.Model): - """The hue of your tasty treat""" - - name = models.CharField( - max_length=20, - help_text="The color name", - ) -``` - -You'll need to make migrations then migrate: - -```sh -python manage.py makemigrations -python manage.py migrate -``` - -Now use the django shell, the admin, the loaddata command or whatever tool you like to load some fruits and colors. I've loaded a red strawberry (predictable, right?!) ready for later. - -## Define types - -Before creating queries, you have to define a `type` for each model. A `type` is a fundamental unit of the [schema](https://strawberry.rocks/docs/types/schema) -which describes the shape of the data that can be queried from the GraphQL server. Types can represent scalar values (like String, Int, Boolean, Float, and ID), enums, or complex objects that consist of many fields. - -!!! tip - - A key feature of `strawberry-graphql-django` is that it provides helpers to create types from django models, - by automatically inferring types (and even documentation!!) from the model fields. - - See the [fields guide](./guide/fields.md) for more information. - -```{.python title=types.py} -import strawberry_django -from strawberry import auto - -from . import models - -@strawberry_django.type(models.Fruit) -class Fruit: - id: auto - name: auto - category: auto - color: "Color" # Strawberry will understand that this refers to the "Color" type that's defined below - -@strawberry_django.type(models.Color) -class Color: - id: auto - name: auto - fruits: list[Fruit] # This tells strawberry about the ForeignKey to the Fruit model and how to represent the Fruit instances on that relation -``` - -## Build the queries and schema - -Next we want to assemble the [schema](https://strawberry.rocks/docs/types/schema) from its building block types. - -!!! warning - - You'll notice a familiar statement, `fruits: list[Fruit]`. We already used this statement in the previous step in `types.py`. - Seeing it twice can be a point of confusion when you're first getting to grips with graph and strawberry. - - The purpose here is similar but subtly different. Previously, the syntax defined that it was possible to make a query that **traverses** within the graph, from a Color to a list of Fruits. - Here, the usage defines a [**root** query](https://strawberry.rocks/docs/general/queries) (a bit like an entrypoint into the graph). - -!!! tip - - We add the `DjangoOptimizerExtension` here. Don't worry about why for now, but you're almost certain to want it. - - See the [optimizer guide](./guide/optimizer.md) for more information. - -```{.python title=schema.py} -import strawberry -from strawberry_django.optimizer import DjangoOptimizerExtension - -from .types import Fruit - -@strawberry.type -class Query: - fruits: list[Fruit] = strawberry_django.field() - -schema = strawberry.Schema( - query=Query, - extensions=[ - DjangoOptimizerExtension, - ], -) -``` - -## Serving the API - -Now we're showing off. This isn't enabled by default, since existing django applications will likely -have model docstrings and help text that aren't user-oriented. But if you're starting clean (or overhauling -existing dosctrings and helptext), setting up the following is super useful for your API users. - -If you don't set these true, you can always provide user-oriented descriptions. See the - -```{.python title=settings.py} -STRAWBERRY_DJANGO = { - "FIELD_DESCRIPTION_FROM_HELP_TEXT": True, - "TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True, -} -``` - -```{.python title=urls.py} -from django.urls import include, path -from strawberry.django.views import AsyncGraphQLView - -from .schema import schema - -urlpatterns = [ - path('graphql', AsyncGraphQLView.as_view(schema=schema)), -] -``` - -This generates following schema: - -```{.graphql title=schema.graphql} -enum FruitCategory { - CITRUS - BERRY -} - -""" -A tasty treat -""" -type Fruit { - id: ID! - name: String! - category: FruitCategory! - color: Color -} - -type Color { - id: ID! - """ - field description - """ - name: String! - fruits: [Fruit!] -} - -type Query { - fruits: [Fruit!]! -} -``` - -## Using the API - -Start your server with: - -```sh -python manage.py runserver -``` - -Then visit [localhost:8000/graphql](http://localhost:8000/graphql) in your browser. You should see the graphql explorer being served by django. -Using the interactive query tool, you can query for the fruits you added earlier: - -
- -
- -## Next steps - -1. [Defining more Django Types](./guide/types.md) -2. [Define Fields inside those Types](./guide/fields.md) -3. [Serve your API using ASGI or WSGI](./guide/views.md) -4. [Define filters for your fields](./guide/filters.md) -5. [Define orderings for your fields](./guide/ordering.md) -6. [Define pagination for your fields](./guide/pagination.md) -7. [Define queries for your schema](./guide/queries.md) -8. [Define mutations for your schema](./guide/mutations.md) -9. [Define subscriptions for your schema](./guide/subscriptions.md) -10. [Enable the Query Optimizer extension for performance improvement](./guide/optimizer.md) -11. [Use the relay integration for advanced pagination and model refetching](./guide/relay.md) -12. [Protect your fields using the Permission Extension](./guide/permissions.md) -13. [Write unit tests for your schema](./guide/unit-testing.md) diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 58322ea5..00000000 --- a/mkdocs.yml +++ /dev/null @@ -1,103 +0,0 @@ ---- -site_name: Strawberry Django -site_description: Strawberry integration with Django. -site_author: community -repo_name: strawberry-django -repo_url: https://github.com/strawberry-graphql/strawberry-django -edit_uri: edit/main/docs/ -dev_addr: 127.0.0.1:7000 - -theme: - name: material - language: en - palette: - - scheme: default - primary: red - accent: green - toggle: - icon: material/toggle-switch-off-outline - name: Switch to light mode - - scheme: slate - primary: green - accent: red - toggle: - icon: material/toggle-switch - name: Switch to dark mode - logo: images/logo.png - favicon: images/logo.png - features: - - content.code.annotate - - navigation.instant - -markdown_extensions: - - tables - - admonition - - codehilite - - attr_list - - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg - - pymdownx.highlight: - anchor_linenums: true - use_pygments: true - linenums: true - - pymdownx.superfences - - md_in_html - - pymdownx.tabbed: - alternate_style: true - - toc: - permalink: true - - pymdownx.caret - - pymdownx.betterem: - smart_enable: all - - pymdownx.details - - pymdownx.inlinehilite - - pymdownx.magiclink - - pymdownx.mark - - pymdownx.smartsymbols - - pymdownx.superfences: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format - - pymdownx.tasklist: - custom_checkbox: true - - pymdownx.tilde - -plugins: - - mkdocstrings: - - search - - minify: - minify_html: true - - markdownextradata: - data: docs/data - -nav: - - index.md - - quick-start.md - - Guide: - - guide/views.md - - guide/types.md - - guide/fields.md - - guide/resolvers.md - - guide/filters.md - - guide/ordering.md - - guide/pagination.md - - guide/optimizer.md - - guide/queries.md - - guide/mutations.md - - guide/subscriptions.md - - guide/permissions.md - - guide/relay.md - - guide/authentication.md - - guide/settings.md - - guide/unit-testing.md - - guide/export-schema.md - - Integrations: - - integrations/debug-toolbar.md - - integrations/guardian.md - - integrations/channels.md - - integrations/choices-field.md - - community-projects.md - - contributing.md - - FAQ: faq.md diff --git a/poetry.lock b/poetry.lock index 44de8b9f..5f9af47a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "asgiref" @@ -32,23 +32,6 @@ files = [ six = ">=1.6.1,<2.0" wheel = ">=0.23.0,<1.0" -[[package]] -name = "babel" -version = "2.15.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.8" -files = [ - {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, - {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, -] - -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - -[package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] - [[package]] name = "backports-zoneinfo" version = "0.2.1" @@ -77,17 +60,6 @@ files = [ [package.extras] tzdata = ["tzdata"] -[[package]] -name = "certifi" -version = "2024.7.4" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, -] - [[package]] name = "channels" version = "4.1.0" @@ -107,119 +79,6 @@ Django = ">=4.2" daphne = ["daphne (>=4.0.0)"] tests = ["async-timeout", "coverage (>=4.5,<5.0)", "pytest", "pytest-asyncio", "pytest-django"] -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" @@ -298,16 +157,6 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] -[[package]] -name = "csscompressor" -version = "0.9.5" -description = "A python port of YUI CSS Compressor" -optional = false -python-versions = "*" -files = [ - {file = "csscompressor-0.9.5.tar.gz", hash = "sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05"}, -] - [[package]] name = "django" version = "4.2.14" @@ -491,23 +340,6 @@ files = [ [package.dependencies] python-dateutil = ">=2.4" -[[package]] -name = "ghp-import" -version = "2.1.0" -description = "Copy your docs directly to the gh-pages branch." -optional = false -python-versions = "*" -files = [ - {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, - {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.1" - -[package.extras] -dev = ["flake8", "markdown", "twine", "wheel"] - [[package]] name = "graphql-core" version = "3.2.3" @@ -519,51 +351,15 @@ files = [ {file = "graphql_core-3.2.3-py3-none-any.whl", hash = "sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3"}, ] -[[package]] -name = "griffe" -version = "0.47.0" -description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." -optional = false -python-versions = ">=3.8" -files = [ - {file = "griffe-0.47.0-py3-none-any.whl", hash = "sha256:07a2fd6a8c3d21d0bbb0decf701d62042ccc8a576645c7f8799fe1f10de2b2de"}, - {file = "griffe-0.47.0.tar.gz", hash = "sha256:95119a440a3c932b13293538bdbc405bee4c36428547553dc6b327e7e7d35e5a"}, -] - -[package.dependencies] -astunparse = {version = ">=1.6", markers = "python_version < \"3.9\""} -colorama = ">=0.4" - -[[package]] -name = "htmlmin2" -version = "0.1.13" -description = "An HTML Minifier" -optional = false -python-versions = "*" -files = [ - {file = "htmlmin2-0.1.13-py3-none-any.whl", hash = "sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2"}, -] - -[[package]] -name = "idna" -version = "3.7" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - [[package]] name = "importlib-metadata" -version = "8.0.0" +version = "8.2.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, - {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, + {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"}, + {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"}, ] [package.dependencies] @@ -585,33 +381,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "jinja2" -version = "3.1.4" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jsmin" -version = "3.0.1" -description = "JavaScript minifier." -optional = false -python-versions = "*" -files = [ - {file = "jsmin-3.0.1.tar.gz", hash = "sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc"}, -] - [[package]] name = "markdown" version = "3.6" @@ -630,265 +399,6 @@ importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "mergedeep" -version = "1.3.4" -description = "A deep merge function for 🐍." -optional = false -python-versions = ">=3.6" -files = [ - {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, - {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, -] - -[[package]] -name = "mkdocs" -version = "1.6.0" -description = "Project documentation with Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"}, - {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} -ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} -jinja2 = ">=2.11.1" -markdown = ">=3.3.6" -markupsafe = ">=2.0.1" -mergedeep = ">=1.3.4" -mkdocs-get-deps = ">=0.2.0" -packaging = ">=20.5" -pathspec = ">=0.11.1" -pyyaml = ">=5.1" -pyyaml-env-tag = ">=0.1" -watchdog = ">=2.0" - -[package.extras] -i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] - -[[package]] -name = "mkdocs-autorefs" -version = "1.0.1" -description = "Automatically link across pages in MkDocs." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_autorefs-1.0.1-py3-none-any.whl", hash = "sha256:aacdfae1ab197780fb7a2dac92ad8a3d8f7ca8049a9cbe56a4218cd52e8da570"}, - {file = "mkdocs_autorefs-1.0.1.tar.gz", hash = "sha256:f684edf847eced40b570b57846b15f0bf57fb93ac2c510450775dcf16accb971"}, -] - -[package.dependencies] -Markdown = ">=3.3" -markupsafe = ">=2.0.1" -mkdocs = ">=1.1" - -[[package]] -name = "mkdocs-get-deps" -version = "0.2.0" -description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, - {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} -mergedeep = ">=1.3.4" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" - -[[package]] -name = "mkdocs-markdownextradata-plugin" -version = "0.2.5" -description = "A MkDocs plugin that injects the mkdocs.yml extra variables into the markdown template" -optional = false -python-versions = ">=2.7.9,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -files = [ - {file = "mkdocs-markdownextradata-plugin-0.2.5.tar.gz", hash = "sha256:9c562e8fe375647d5692d11dfe369a7bdd50302174d35995fce2aeca58036ec6"}, -] - -[package.dependencies] -mkdocs = "*" -pyyaml = "*" - -[[package]] -name = "mkdocs-material" -version = "9.5.29" -description = "Documentation that simply works" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material-9.5.29-py3-none-any.whl", hash = "sha256:afc1f508e2662ded95f0a35a329e8a5acd73ee88ca07ba73836eb6fcdae5d8b4"}, - {file = "mkdocs_material-9.5.29.tar.gz", hash = "sha256:3e977598ec15a4ddad5c4dfc9e08edab6023edb51e88f0729bd27be77e3d322a"}, -] - -[package.dependencies] -babel = ">=2.10,<3.0" -colorama = ">=0.4,<1.0" -jinja2 = ">=3.0,<4.0" -markdown = ">=3.2,<4.0" -mkdocs = ">=1.6,<2.0" -mkdocs-material-extensions = ">=1.3,<2.0" -paginate = ">=0.5,<1.0" -pygments = ">=2.16,<3.0" -pymdown-extensions = ">=10.2,<11.0" -regex = ">=2022.4" -requests = ">=2.26,<3.0" - -[package.extras] -git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] -imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] -recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -description = "Extension pack for Python Markdown and MkDocs Material." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, - {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, -] - -[[package]] -name = "mkdocs-minify-plugin" -version = "0.8.0" -description = "An MkDocs plugin to minify HTML, JS or CSS files prior to being written to disk" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs-minify-plugin-0.8.0.tar.gz", hash = "sha256:bc11b78b8120d79e817308e2b11539d790d21445eb63df831e393f76e52e753d"}, - {file = "mkdocs_minify_plugin-0.8.0-py3-none-any.whl", hash = "sha256:5fba1a3f7bd9a2142c9954a6559a57e946587b21f133165ece30ea145c66aee6"}, -] - -[package.dependencies] -csscompressor = ">=0.9.5" -htmlmin2 = ">=0.1.13" -jsmin = ">=3.0.1" -mkdocs = ">=1.4.1" - -[[package]] -name = "mkdocstrings" -version = "0.25.1" -description = "Automatic documentation from sources, for MkDocs." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocstrings-0.25.1-py3-none-any.whl", hash = "sha256:da01fcc2670ad61888e8fe5b60afe9fee5781017d67431996832d63e887c2e51"}, - {file = "mkdocstrings-0.25.1.tar.gz", hash = "sha256:c3a2515f31577f311a9ee58d089e4c51fc6046dbd9e9b4c3de4c3194667fe9bf"}, -] - -[package.dependencies] -click = ">=7.0" -importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} -Jinja2 = ">=2.11.1" -Markdown = ">=3.3" -MarkupSafe = ">=1.1" -mkdocs = ">=1.4" -mkdocs-autorefs = ">=0.3.1" -mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""} -platformdirs = ">=2.2.0" -pymdown-extensions = ">=6.3" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} - -[package.extras] -crystal = ["mkdocstrings-crystal (>=0.3.4)"] -python = ["mkdocstrings-python (>=0.5.2)"] -python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] - -[[package]] -name = "mkdocstrings-python" -version = "1.10.5" -description = "A Python handler for mkdocstrings." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocstrings_python-1.10.5-py3-none-any.whl", hash = "sha256:92e3c588ef1b41151f55281d075de7558dd8092e422cb07a65b18ee2b0863ebb"}, - {file = "mkdocstrings_python-1.10.5.tar.gz", hash = "sha256:acdc2a98cd9d46c7ece508193a16ca03ccabcb67520352b7449f84b57c162bdf"}, -] - -[package.dependencies] -griffe = ">=0.47" -mkdocstrings = ">=0.25" - [[package]] name = "packaging" version = "24.1" @@ -900,27 +410,6 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] -[[package]] -name = "paginate" -version = "0.5.6" -description = "Divides large result sets into pages for easier browsing" -optional = false -python-versions = "*" -files = [ - {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "pillow" version = "10.4.0" @@ -1018,22 +507,6 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa typing = ["typing-extensions"] xmp = ["defusedxml"] -[[package]] -name = "platformdirs" -version = "4.2.2" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] - [[package]] name = "pluggy" version = "1.5.0" @@ -1168,13 +641,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.8.1" +version = "10.9" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"}, - {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"}, + {file = "pymdown_extensions-10.9-py3-none-any.whl", hash = "sha256:d323f7e90d83c86113ee78f3fe62fc9dee5f56b54d912660703ea1816fed5626"}, + {file = "pymdown_extensions-10.9.tar.gz", hash = "sha256:6ff740bcd99ec4172a938970d42b96128bdc9d4b9bcad72494f29921dc69b753"}, ] [package.dependencies] @@ -1186,13 +659,13 @@ extra = ["pygments (>=2.12)"] [[package]] name = "pytest" -version = "8.2.2" +version = "8.3.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, - {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, + {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, + {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, ] [package.dependencies] @@ -1200,7 +673,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.5,<2.0" +pluggy = ">=1.5,<2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] @@ -1321,17 +794,6 @@ files = [ [package.dependencies] six = ">=1.5" -[[package]] -name = "pytz" -version = "2024.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - [[package]] name = "pyyaml" version = "6.0.1" @@ -1357,6 +819,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -1391,154 +854,31 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] -[[package]] -name = "pyyaml-env-tag" -version = "0.1" -description = "A custom YAML tag for referencing environment variables in YAML files. " -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, - {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, -] - -[package.dependencies] -pyyaml = "*" - -[[package]] -name = "regex" -version = "2024.5.15" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -files = [ - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, - {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, - {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, - {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, - {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, - {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, - {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, - {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, - {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, - {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, - {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, - {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - [[package]] name = "ruff" -version = "0.5.2" +version = "0.5.5" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.5.2-py3-none-linux_armv6l.whl", hash = "sha256:7bab8345df60f9368d5f4594bfb8b71157496b44c30ff035d1d01972e764d3be"}, - {file = "ruff-0.5.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1aa7acad382ada0189dbe76095cf0a36cd0036779607c397ffdea16517f535b1"}, - {file = "ruff-0.5.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:aec618d5a0cdba5592c60c2dee7d9c865180627f1a4a691257dea14ac1aa264d"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b62adc5ce81780ff04077e88bac0986363e4a3260ad3ef11ae9c14aa0e67ef"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dc42ebf56ede83cb080a50eba35a06e636775649a1ffd03dc986533f878702a3"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c15c6e9f88c67ffa442681365d11df38afb11059fc44238e71a9d9f1fd51de70"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d3de9a5960f72c335ef00763d861fc5005ef0644cb260ba1b5a115a102157251"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe5a968ae933e8f7627a7b2fc8893336ac2be0eb0aace762d3421f6e8f7b7f83"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a04f54a9018f75615ae52f36ea1c5515e356e5d5e214b22609ddb546baef7132"}, - {file = "ruff-0.5.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed02fb52e3741f0738db5f93e10ae0fb5c71eb33a4f2ba87c9a2fa97462a649"}, - {file = "ruff-0.5.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3cf8fe659f6362530435d97d738eb413e9f090e7e993f88711b0377fbdc99f60"}, - {file = "ruff-0.5.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:237a37e673e9f3cbfff0d2243e797c4862a44c93d2f52a52021c1a1b0899f846"}, - {file = "ruff-0.5.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2a2949ce7c1cbd8317432ada80fe32156df825b2fd611688814c8557824ef060"}, - {file = "ruff-0.5.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:481af57c8e99da92ad168924fd82220266043c8255942a1cb87958b108ac9335"}, - {file = "ruff-0.5.2-py3-none-win32.whl", hash = "sha256:f1aea290c56d913e363066d83d3fc26848814a1fed3d72144ff9c930e8c7c718"}, - {file = "ruff-0.5.2-py3-none-win_amd64.whl", hash = "sha256:8532660b72b5d94d2a0a7a27ae7b9b40053662d00357bb2a6864dd7e38819084"}, - {file = "ruff-0.5.2-py3-none-win_arm64.whl", hash = "sha256:73439805c5cb68f364d826a5c5c4b6c798ded6b7ebaa4011f01ce6c94e4d5583"}, - {file = "ruff-0.5.2.tar.gz", hash = "sha256:2c0df2d2de685433794a14d8d2e240df619b748fbe3367346baa519d8e6f1ca2"}, + {file = "ruff-0.5.5-py3-none-linux_armv6l.whl", hash = "sha256:605d589ec35d1da9213a9d4d7e7a9c761d90bba78fc8790d1c5e65026c1b9eaf"}, + {file = "ruff-0.5.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00817603822a3e42b80f7c3298c8269e09f889ee94640cd1fc7f9329788d7bf8"}, + {file = "ruff-0.5.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:187a60f555e9f865a2ff2c6984b9afeffa7158ba6e1eab56cb830404c942b0f3"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe26fc46fa8c6e0ae3f47ddccfbb136253c831c3289bba044befe68f467bfb16"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad25dd9c5faac95c8e9efb13e15803cd8bbf7f4600645a60ffe17c73f60779b"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f70737c157d7edf749bcb952d13854e8f745cec695a01bdc6e29c29c288fc36e"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:cfd7de17cef6ab559e9f5ab859f0d3296393bc78f69030967ca4d87a541b97a0"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a09b43e02f76ac0145f86a08e045e2ea452066f7ba064fd6b0cdccb486f7c3e7"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0b856cb19c60cd40198be5d8d4b556228e3dcd545b4f423d1ad812bfdca5884"}, + {file = "ruff-0.5.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3687d002f911e8a5faf977e619a034d159a8373514a587249cc00f211c67a091"}, + {file = "ruff-0.5.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ac9dc814e510436e30d0ba535f435a7f3dc97f895f844f5b3f347ec8c228a523"}, + {file = "ruff-0.5.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:af9bdf6c389b5add40d89b201425b531e0a5cceb3cfdcc69f04d3d531c6be74f"}, + {file = "ruff-0.5.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d40a8533ed545390ef8315b8e25c4bb85739b90bd0f3fe1280a29ae364cc55d8"}, + {file = "ruff-0.5.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cab904683bf9e2ecbbe9ff235bfe056f0eba754d0168ad5407832928d579e7ab"}, + {file = "ruff-0.5.5-py3-none-win32.whl", hash = "sha256:696f18463b47a94575db635ebb4c178188645636f05e934fdf361b74edf1bb2d"}, + {file = "ruff-0.5.5-py3-none-win_amd64.whl", hash = "sha256:50f36d77f52d4c9c2f1361ccbfbd09099a1b2ea5d2b2222c586ab08885cf3445"}, + {file = "ruff-0.5.5-py3-none-win_arm64.whl", hash = "sha256:3191317d967af701f1b73a31ed5788795936e423b7acce82a2b63e26eb3e89d6"}, + {file = "ruff-0.5.5.tar.gz", hash = "sha256:cc5516bdb4858d972fbc31d246bdb390eab8df1a26e2353be2dbc0c2d7f5421a"}, ] [[package]] @@ -1584,18 +924,18 @@ doc = ["sphinx"] [[package]] name = "strawberry-graphql" -version = "0.236.0" +version = "0.237.2" description = "A library for creating GraphQL APIs" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "strawberry_graphql-0.236.0-py3-none-any.whl", hash = "sha256:685f775be47c0753c39e0ef601d7f2b6f0e15dd4dfe5d57094d29a9cceb066f4"}, - {file = "strawberry_graphql-0.236.0.tar.gz", hash = "sha256:26dcae2c0b506330db60624194cdd0b49c1e773166791bd4f729126bf872b65c"}, + {file = "strawberry_graphql-0.237.2-py3-none-any.whl", hash = "sha256:0cab6ceb13d5d598faad7afc721a39cabae79e9bc801c2aac0b5bcd3402e4e10"}, + {file = "strawberry_graphql-0.237.2.tar.gz", hash = "sha256:ac419798303195547e3b286ee810ce957072d5aaac55e5f639cdc4bbb0d72c46"}, ] [package.dependencies] astunparse = {version = ">=1.6.3,<2.0.0", markers = "python_version < \"3.9\""} -graphql-core = ">=3.2.0,<3.3.0" +graphql-core = ">=3.2.0,<3.4.0" python-dateutil = ">=2.7.0,<3.0.0" typing-extensions = ">=4.5.0" @@ -1662,23 +1002,6 @@ files = [ {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, ] -[[package]] -name = "urllib3" -version = "2.2.2" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - [[package]] name = "watchdog" version = "4.0.1" @@ -1759,4 +1082,4 @@ enum = ["django-choices-field"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "da678e32dda1f80eee447008b7d5e118e3603b132b9af2a394c4c922e6ac6a75" +content-hash = "1a7cf88adca38c0e318cb890403b5c7b2904e967432620af8249bb05776d07f3" diff --git a/pyproject.toml b/pyproject.toml index 120cff1f..2c14ab03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,11 +48,6 @@ django-guardian = "^2.4.0" django-mptt = "^0.14.0" django-types = "^0.19.1" factory-boy = "^3.2.1" -mkdocs = "^1.4.2" -mkdocs-markdownextradata-plugin = "^0.2.5" -mkdocs-material = "^9.4.0" -mkdocs-minify-plugin = "^0.8.0" -mkdocstrings = { version = "^0.25.1", extras = ["python"] } pillow = "^10.2.0" pymdown-extensions = "^10.0.1" pytest = "^8.0.2"