We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: argument of type 'NoneType' is not iterable
### What are you trying to achieve?

Create a category with `null` passed as `seo` value in the input.

### Steps to reproduce the problem

1. Run the following mutation:
```graphql
mutation CreateCategory($input: CategoryInput!, $parentId: ID) {
  categoryCreate(input: $input, parent: $parentId) {
    errors {
      code
    }
    category {
      id
    }
  }
}
```

Variables:

```json
{
  "input": {
    "backgroundImage": null,
    "backgroundImageAlt": "Root",
    "description": "{\"blocks\":[{\"type\":\"paragraph\", \"data\":\"\"}]}",
    "metadata": null,
    "name": "Root",
    "privateMetadata": null,
    "seo": null,
    "slug": "root"
  },
  "parentId": null
}
```

2. It crashes with the following error:

```json
{
  "errors": [
    {
      "message": "argument of type 'NoneType' is not iterable",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "categoryCreate"
      ],
    }
  ],
  "data": {
    "categoryCreate": null
  },
}
```

API crashes in the `clean_seo_fields` function when `null` is passed as `seo` value. 



### What did you expect to happen?

In this case, the API shouldn't crash; it should ignore the SEO value and create the category without it.

### Logs

_No response_

### Environment

Saleor version: 3.14


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `saleor/graphql/core/validators/__init__.py`
Content:
```
1 from typing import TYPE_CHECKING, Optional
2 from uuid import UUID
3 
4 import graphene
5 from django.core.exceptions import ValidationError
6 from django_prices.utils.formatting import get_currency_fraction
7 from graphene.utils.str_converters import to_camel_case
8 from graphql.error import GraphQLError
9 
10 from ....core.utils import generate_unique_slug
11 from ....product.models import ProductVariantChannelListing
12 
13 if TYPE_CHECKING:
14     from decimal import Decimal
15 
16     from django.db.models import Model
17 
18 
19 def validate_one_of_args_is_in_mutation(*args, **kwargs):
20     try:
21         validate_one_of_args_is_in_query(*args, **kwargs)
22     except GraphQLError as e:
23         raise ValidationError(str(e), code="graphql_error")
24 
25 
26 def validate_one_of_args_is_in_query(*args, **kwargs):
27     # split args into a list with 2-element tuples:
28     # [(arg1_name, arg1_value), (arg2_name, arg2_value), ...]
29     splitted_args = [args[i : i + 2] for i in range(0, len(args), 2)]  # noqa: E203
30     # filter trueish values from each tuple
31     filter_args = list(filter(lambda item: bool(item[1]) is True, splitted_args))
32     use_camel_case = kwargs.get("use_camel_case")
33 
34     if len(filter_args) > 1:
35         if use_camel_case:
36             first_arg = to_camel_case(filter_args[0][0])
37             rest_args = ", ".join(
38                 [f"'{to_camel_case(item[0])}'" for item in filter_args[1:]]
39             )
40         else:
41             first_arg = filter_args[0][0]
42             rest_args = ", ".join([f"'{item[0]}'" for item in filter_args[1:]])
43         raise GraphQLError(
44             f"Argument '{first_arg}' cannot be combined with {rest_args}"
45         )
46 
47     if not filter_args:
48         if use_camel_case:
49             required_args = ", ".join(
50                 [f"'{to_camel_case(item[0])}'" for item in splitted_args]
51             )
52         else:
53             required_args = ", ".join([f"'{item[0]}'" for item in splitted_args])
54         raise GraphQLError(f"At least one of arguments is required: {required_args}.")
55 
56 
57 def validate_price_precision(
58     value: Optional["Decimal"],
59     currency: str,
60     currency_fractions=None,
61 ):
62     """Validate if price amount does not have too many decimal places.
63 
64     Price amount can't have more decimal places than currency allow to.
65     Works only with decimal created from a string.
66     """
67 
68     # check no needed when there is no value
69     if not value:
70         return
71 
72     if currency_fractions:
73         try:
74             currency_fraction = currency_fractions[currency][0]
75         except KeyError:
76             currency_fraction = currency_fractions["DEFAULT"][0]
77     else:
78         currency_fraction = get_currency_fraction(currency)
79 
80     value = value.normalize()
81     if value.as_tuple().exponent < -currency_fraction:
82         raise ValidationError(
83             f"Value cannot have more than {currency_fraction} decimal places."
84         )
85 
86 
87 def validate_decimal_max_value(value: "Decimal", max_value=10**9):
88     """Validate if price amount is not higher than the limit for precision field.
89 
90     Decimal fields in database have value limits.
91     By default its 10^9 for fields with precision 12.
92     """
93     if value >= max_value:
94         raise ValidationError(f"Value must be lower than {max_value}.")
95 
96 
97 def get_not_available_variants_in_channel(
98     variants_id: set, channel_id: int
99 ) -> tuple[set[int], set[str]]:
100     available_variants = ProductVariantChannelListing.objects.filter(
101         variant__id__in=variants_id,
102         channel_id=channel_id,
103         price_amount__isnull=False,
104     ).values_list("variant_id", flat=True)
105     not_available_variants = variants_id - set(available_variants)
106     not_available_graphql_ids = {
107         graphene.Node.to_global_id("ProductVariant", pk)
108         for pk in not_available_variants
109     }
110     return not_available_variants, not_available_graphql_ids
111 
112 
113 def validate_variants_available_in_channel(
114     variants_id: set,
115     channel_id: int,
116     error_code: str,
117 ):
118     """Validate available variants in specific channel."""
119     (
120         not_available_variants,
121         not_available_graphql_ids,
122     ) = get_not_available_variants_in_channel(variants_id, channel_id)
123     if not_available_variants:
124         raise ValidationError(
125             {
126                 "lines": ValidationError(
127                     "Cannot add lines with unavailable variants.",
128                     code=error_code,
129                     params={"variants": not_available_graphql_ids},
130                 )
131             }
132         )
133 
134 
135 def validate_end_is_after_start(start_date, end_date):
136     """Validate if the end date provided is after start date."""
137 
138     # check is not needed if no end date
139     if end_date is None:
140         return
141 
142     if start_date > end_date:
143         raise ValidationError("End date cannot be before the start date.")
144 
145 
146 def validate_slug_and_generate_if_needed(
147     instance: "Model",
148     slugable_field: str,
149     cleaned_input: dict,
150     slug_field_name: str = "slug",
151 ) -> dict:
152     """Validate slug from input and generate in create mutation if is not given."""
153 
154     # update mutation - just check if slug value is not empty
155     # _state.adding is True only when it's new not saved instance.
156     if not instance._state.adding:
157         validate_slug_value(cleaned_input)
158         return cleaned_input
159 
160     # create mutation - generate slug if slug value is empty
161     slug = cleaned_input.get(slug_field_name)
162     if not slug and slugable_field in cleaned_input:
163         slug = generate_unique_slug(instance, cleaned_input[slugable_field])
164         cleaned_input[slug_field_name] = slug
165     return cleaned_input
166 
167 
168 def validate_slug_value(cleaned_input, slug_field_name: str = "slug"):
169     if slug_field_name in cleaned_input:
170         slug = cleaned_input[slug_field_name]
171         if not slug:
172             raise ValidationError(
173                 f"{slug_field_name.capitalize()} value cannot be blank."
174             )
175 
176 
177 def clean_seo_fields(data):
178     """Extract and assign seo fields to given dictionary."""
179     seo_fields = data.pop("seo", {})
180 
181     if "title" in seo_fields:
182         data["seo_title"] = seo_fields["title"]
183 
184     if "description" in seo_fields:
185         data["seo_description"] = seo_fields["description"]
186 
187 
188 def validate_required_string_field(cleaned_input, field_name: str):
189     """Strip and validate field value."""
190     field_value = cleaned_input.get(field_name)
191     field_value = field_value.strip() if field_value else ""
192     if field_value:
193         cleaned_input[field_name] = field_value
194     else:
195         raise ValidationError(f"{field_name.capitalize()} is required.")
196     return cleaned_input
197 
198 
199 def validate_if_int_or_uuid(id):
200     result = True
201     try:
202         int(id)
203     except ValueError:
204         try:
205             UUID(id)
206         except (AttributeError, ValueError):
207             result = False
208     return result
209
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/saleor/graphql/core/validators/__init__.py b/saleor/graphql/core/validators/__init__.py
--- a/saleor/graphql/core/validators/__init__.py
+++ b/saleor/graphql/core/validators/__init__.py
@@ -178,11 +178,12 @@
     """Extract and assign seo fields to given dictionary."""
     seo_fields = data.pop("seo", {})
 
-    if "title" in seo_fields:
-        data["seo_title"] = seo_fields["title"]
+    if seo_fields:
+        if "title" in seo_fields:
+            data["seo_title"] = seo_fields["title"]
 
-    if "description" in seo_fields:
-        data["seo_description"] = seo_fields["description"]
+        if "description" in seo_fields:
+            data["seo_description"] = seo_fields["description"]
 
 
 def validate_required_string_field(cleaned_input, field_name: str):

{"golden_diff": "diff --git a/saleor/graphql/core/validators/__init__.py b/saleor/graphql/core/validators/__init__.py\n--- a/saleor/graphql/core/validators/__init__.py\n+++ b/saleor/graphql/core/validators/__init__.py\n@@ -178,11 +178,12 @@\n     \"\"\"Extract and assign seo fields to given dictionary.\"\"\"\n     seo_fields = data.pop(\"seo\", {})\n \n-    if \"title\" in seo_fields:\n-        data[\"seo_title\"] = seo_fields[\"title\"]\n+    if seo_fields:\n+        if \"title\" in seo_fields:\n+            data[\"seo_title\"] = seo_fields[\"title\"]\n \n-    if \"description\" in seo_fields:\n-        data[\"seo_description\"] = seo_fields[\"description\"]\n+        if \"description\" in seo_fields:\n+            data[\"seo_description\"] = seo_fields[\"description\"]\n \n \n def validate_required_string_field(cleaned_input, field_name: str):\n", "issue": "Bug: argument of type 'NoneType' is not iterable\n### What are you trying to achieve?\n\nCreate a category with `null` passed as `seo` value in the input.\n\n### Steps to reproduce the problem\n\n1. Run the following mutation:\r\n```graphql\r\nmutation CreateCategory($input: CategoryInput!, $parentId: ID) {\r\n  categoryCreate(input: $input, parent: $parentId) {\r\n    errors {\r\n      code\r\n    }\r\n    category {\r\n      id\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nVariables:\r\n\r\n```json\r\n{\r\n  \"input\": {\r\n    \"backgroundImage\": null,\r\n    \"backgroundImageAlt\": \"Root\",\r\n    \"description\": \"{\\\"blocks\\\":[{\\\"type\\\":\\\"paragraph\\\", \\\"data\\\":\\\"\\\"}]}\",\r\n    \"metadata\": null,\r\n    \"name\": \"Root\",\r\n    \"privateMetadata\": null,\r\n    \"seo\": null,\r\n    \"slug\": \"root\"\r\n  },\r\n  \"parentId\": null\r\n}\r\n```\r\n\r\n2. It crashes with the following error:\r\n\r\n```json\r\n{\r\n  \"errors\": [\r\n    {\r\n      \"message\": \"argument of type 'NoneType' is not iterable\",\r\n      \"locations\": [\r\n        {\r\n          \"line\": 2,\r\n          \"column\": 3\r\n        }\r\n      ],\r\n      \"path\": [\r\n        \"categoryCreate\"\r\n      ],\r\n    }\r\n  ],\r\n  \"data\": {\r\n    \"categoryCreate\": null\r\n  },\r\n}\r\n```\r\n\r\nAPI crashes in the `clean_seo_fields` function when `null` is passed as `seo` value. \r\n\r\n\n\n### What did you expect to happen?\n\nIn this case, the API shouldn't crash; it should ignore the SEO value and create the category without it.\n\n### Logs\n\n_No response_\n\n### Environment\n\nSaleor version: 3.14\r\n\n", "before_files": [{"content": "from typing import TYPE_CHECKING, Optional\nfrom uuid import UUID\n\nimport graphene\nfrom django.core.exceptions import ValidationError\nfrom django_prices.utils.formatting import get_currency_fraction\nfrom graphene.utils.str_converters import to_camel_case\nfrom graphql.error import GraphQLError\n\nfrom ....core.utils import generate_unique_slug\nfrom ....product.models import ProductVariantChannelListing\n\nif TYPE_CHECKING:\n    from decimal import Decimal\n\n    from django.db.models import Model\n\n\ndef validate_one_of_args_is_in_mutation(*args, **kwargs):\n    try:\n        validate_one_of_args_is_in_query(*args, **kwargs)\n    except GraphQLError as e:\n        raise ValidationError(str(e), code=\"graphql_error\")\n\n\ndef validate_one_of_args_is_in_query(*args, **kwargs):\n    # split args into a list with 2-element tuples:\n    # [(arg1_name, arg1_value), (arg2_name, arg2_value), ...]\n    splitted_args = [args[i : i + 2] for i in range(0, len(args), 2)]  # noqa: E203\n    # filter trueish values from each tuple\n    filter_args = list(filter(lambda item: bool(item[1]) is True, splitted_args))\n    use_camel_case = kwargs.get(\"use_camel_case\")\n\n    if len(filter_args) > 1:\n        if use_camel_case:\n            first_arg = to_camel_case(filter_args[0][0])\n            rest_args = \", \".join(\n                [f\"'{to_camel_case(item[0])}'\" for item in filter_args[1:]]\n            )\n        else:\n            first_arg = filter_args[0][0]\n            rest_args = \", \".join([f\"'{item[0]}'\" for item in filter_args[1:]])\n        raise GraphQLError(\n            f\"Argument '{first_arg}' cannot be combined with {rest_args}\"\n        )\n\n    if not filter_args:\n        if use_camel_case:\n            required_args = \", \".join(\n                [f\"'{to_camel_case(item[0])}'\" for item in splitted_args]\n            )\n        else:\n            required_args = \", \".join([f\"'{item[0]}'\" for item in splitted_args])\n        raise GraphQLError(f\"At least one of arguments is required: {required_args}.\")\n\n\ndef validate_price_precision(\n    value: Optional[\"Decimal\"],\n    currency: str,\n    currency_fractions=None,\n):\n    \"\"\"Validate if price amount does not have too many decimal places.\n\n    Price amount can't have more decimal places than currency allow to.\n    Works only with decimal created from a string.\n    \"\"\"\n\n    # check no needed when there is no value\n    if not value:\n        return\n\n    if currency_fractions:\n        try:\n            currency_fraction = currency_fractions[currency][0]\n        except KeyError:\n            currency_fraction = currency_fractions[\"DEFAULT\"][0]\n    else:\n        currency_fraction = get_currency_fraction(currency)\n\n    value = value.normalize()\n    if value.as_tuple().exponent < -currency_fraction:\n        raise ValidationError(\n            f\"Value cannot have more than {currency_fraction} decimal places.\"\n        )\n\n\ndef validate_decimal_max_value(value: \"Decimal\", max_value=10**9):\n    \"\"\"Validate if price amount is not higher than the limit for precision field.\n\n    Decimal fields in database have value limits.\n    By default its 10^9 for fields with precision 12.\n    \"\"\"\n    if value >= max_value:\n        raise ValidationError(f\"Value must be lower than {max_value}.\")\n\n\ndef get_not_available_variants_in_channel(\n    variants_id: set, channel_id: int\n) -> tuple[set[int], set[str]]:\n    available_variants = ProductVariantChannelListing.objects.filter(\n        variant__id__in=variants_id,\n        channel_id=channel_id,\n        price_amount__isnull=False,\n    ).values_list(\"variant_id\", flat=True)\n    not_available_variants = variants_id - set(available_variants)\n    not_available_graphql_ids = {\n        graphene.Node.to_global_id(\"ProductVariant\", pk)\n        for pk in not_available_variants\n    }\n    return not_available_variants, not_available_graphql_ids\n\n\ndef validate_variants_available_in_channel(\n    variants_id: set,\n    channel_id: int,\n    error_code: str,\n):\n    \"\"\"Validate available variants in specific channel.\"\"\"\n    (\n        not_available_variants,\n        not_available_graphql_ids,\n    ) = get_not_available_variants_in_channel(variants_id, channel_id)\n    if not_available_variants:\n        raise ValidationError(\n            {\n                \"lines\": ValidationError(\n                    \"Cannot add lines with unavailable variants.\",\n                    code=error_code,\n                    params={\"variants\": not_available_graphql_ids},\n                )\n            }\n        )\n\n\ndef validate_end_is_after_start(start_date, end_date):\n    \"\"\"Validate if the end date provided is after start date.\"\"\"\n\n    # check is not needed if no end date\n    if end_date is None:\n        return\n\n    if start_date > end_date:\n        raise ValidationError(\"End date cannot be before the start date.\")\n\n\ndef validate_slug_and_generate_if_needed(\n    instance: \"Model\",\n    slugable_field: str,\n    cleaned_input: dict,\n    slug_field_name: str = \"slug\",\n) -> dict:\n    \"\"\"Validate slug from input and generate in create mutation if is not given.\"\"\"\n\n    # update mutation - just check if slug value is not empty\n    # _state.adding is True only when it's new not saved instance.\n    if not instance._state.adding:\n        validate_slug_value(cleaned_input)\n        return cleaned_input\n\n    # create mutation - generate slug if slug value is empty\n    slug = cleaned_input.get(slug_field_name)\n    if not slug and slugable_field in cleaned_input:\n        slug = generate_unique_slug(instance, cleaned_input[slugable_field])\n        cleaned_input[slug_field_name] = slug\n    return cleaned_input\n\n\ndef validate_slug_value(cleaned_input, slug_field_name: str = \"slug\"):\n    if slug_field_name in cleaned_input:\n        slug = cleaned_input[slug_field_name]\n        if not slug:\n            raise ValidationError(\n                f\"{slug_field_name.capitalize()} value cannot be blank.\"\n            )\n\n\ndef clean_seo_fields(data):\n    \"\"\"Extract and assign seo fields to given dictionary.\"\"\"\n    seo_fields = data.pop(\"seo\", {})\n\n    if \"title\" in seo_fields:\n        data[\"seo_title\"] = seo_fields[\"title\"]\n\n    if \"description\" in seo_fields:\n        data[\"seo_description\"] = seo_fields[\"description\"]\n\n\ndef validate_required_string_field(cleaned_input, field_name: str):\n    \"\"\"Strip and validate field value.\"\"\"\n    field_value = cleaned_input.get(field_name)\n    field_value = field_value.strip() if field_value else \"\"\n    if field_value:\n        cleaned_input[field_name] = field_value\n    else:\n        raise ValidationError(f\"{field_name.capitalize()} is required.\")\n    return cleaned_input\n\n\ndef validate_if_int_or_uuid(id):\n    result = True\n    try:\n        int(id)\n    except ValueError:\n        try:\n            UUID(id)\n        except (AttributeError, ValueError):\n            result = False\n    return result\n", "path": "saleor/graphql/core/validators/__init__.py"}], "after_files": [{"content": "from typing import TYPE_CHECKING, Optional\nfrom uuid import UUID\n\nimport graphene\nfrom django.core.exceptions import ValidationError\nfrom django_prices.utils.formatting import get_currency_fraction\nfrom graphene.utils.str_converters import to_camel_case\nfrom graphql.error import GraphQLError\n\nfrom ....core.utils import generate_unique_slug\nfrom ....product.models import ProductVariantChannelListing\n\nif TYPE_CHECKING:\n    from decimal import Decimal\n\n    from django.db.models import Model\n\n\ndef validate_one_of_args_is_in_mutation(*args, **kwargs):\n    try:\n        validate_one_of_args_is_in_query(*args, **kwargs)\n    except GraphQLError as e:\n        raise ValidationError(str(e), code=\"graphql_error\")\n\n\ndef validate_one_of_args_is_in_query(*args, **kwargs):\n    # split args into a list with 2-element tuples:\n    # [(arg1_name, arg1_value), (arg2_name, arg2_value), ...]\n    splitted_args = [args[i : i + 2] for i in range(0, len(args), 2)]  # noqa: E203\n    # filter trueish values from each tuple\n    filter_args = list(filter(lambda item: bool(item[1]) is True, splitted_args))\n    use_camel_case = kwargs.get(\"use_camel_case\")\n\n    if len(filter_args) > 1:\n        if use_camel_case:\n            first_arg = to_camel_case(filter_args[0][0])\n            rest_args = \", \".join(\n                [f\"'{to_camel_case(item[0])}'\" for item in filter_args[1:]]\n            )\n        else:\n            first_arg = filter_args[0][0]\n            rest_args = \", \".join([f\"'{item[0]}'\" for item in filter_args[1:]])\n        raise GraphQLError(\n            f\"Argument '{first_arg}' cannot be combined with {rest_args}\"\n        )\n\n    if not filter_args:\n        if use_camel_case:\n            required_args = \", \".join(\n                [f\"'{to_camel_case(item[0])}'\" for item in splitted_args]\n            )\n        else:\n            required_args = \", \".join([f\"'{item[0]}'\" for item in splitted_args])\n        raise GraphQLError(f\"At least one of arguments is required: {required_args}.\")\n\n\ndef validate_price_precision(\n    value: Optional[\"Decimal\"],\n    currency: str,\n    currency_fractions=None,\n):\n    \"\"\"Validate if price amount does not have too many decimal places.\n\n    Price amount can't have more decimal places than currency allow to.\n    Works only with decimal created from a string.\n    \"\"\"\n\n    # check no needed when there is no value\n    if not value:\n        return\n\n    if currency_fractions:\n        try:\n            currency_fraction = currency_fractions[currency][0]\n        except KeyError:\n            currency_fraction = currency_fractions[\"DEFAULT\"][0]\n    else:\n        currency_fraction = get_currency_fraction(currency)\n\n    value = value.normalize()\n    if value.as_tuple().exponent < -currency_fraction:\n        raise ValidationError(\n            f\"Value cannot have more than {currency_fraction} decimal places.\"\n        )\n\n\ndef validate_decimal_max_value(value: \"Decimal\", max_value=10**9):\n    \"\"\"Validate if price amount is not higher than the limit for precision field.\n\n    Decimal fields in database have value limits.\n    By default its 10^9 for fields with precision 12.\n    \"\"\"\n    if value >= max_value:\n        raise ValidationError(f\"Value must be lower than {max_value}.\")\n\n\ndef get_not_available_variants_in_channel(\n    variants_id: set, channel_id: int\n) -> tuple[set[int], set[str]]:\n    available_variants = ProductVariantChannelListing.objects.filter(\n        variant__id__in=variants_id,\n        channel_id=channel_id,\n        price_amount__isnull=False,\n    ).values_list(\"variant_id\", flat=True)\n    not_available_variants = variants_id - set(available_variants)\n    not_available_graphql_ids = {\n        graphene.Node.to_global_id(\"ProductVariant\", pk)\n        for pk in not_available_variants\n    }\n    return not_available_variants, not_available_graphql_ids\n\n\ndef validate_variants_available_in_channel(\n    variants_id: set,\n    channel_id: int,\n    error_code: str,\n):\n    \"\"\"Validate available variants in specific channel.\"\"\"\n    (\n        not_available_variants,\n        not_available_graphql_ids,\n    ) = get_not_available_variants_in_channel(variants_id, channel_id)\n    if not_available_variants:\n        raise ValidationError(\n            {\n                \"lines\": ValidationError(\n                    \"Cannot add lines with unavailable variants.\",\n                    code=error_code,\n                    params={\"variants\": not_available_graphql_ids},\n                )\n            }\n        )\n\n\ndef validate_end_is_after_start(start_date, end_date):\n    \"\"\"Validate if the end date provided is after start date.\"\"\"\n\n    # check is not needed if no end date\n    if end_date is None:\n        return\n\n    if start_date > end_date:\n        raise ValidationError(\"End date cannot be before the start date.\")\n\n\ndef validate_slug_and_generate_if_needed(\n    instance: \"Model\",\n    slugable_field: str,\n    cleaned_input: dict,\n    slug_field_name: str = \"slug\",\n) -> dict:\n    \"\"\"Validate slug from input and generate in create mutation if is not given.\"\"\"\n\n    # update mutation - just check if slug value is not empty\n    # _state.adding is True only when it's new not saved instance.\n    if not instance._state.adding:\n        validate_slug_value(cleaned_input)\n        return cleaned_input\n\n    # create mutation - generate slug if slug value is empty\n    slug = cleaned_input.get(slug_field_name)\n    if not slug and slugable_field in cleaned_input:\n        slug = generate_unique_slug(instance, cleaned_input[slugable_field])\n        cleaned_input[slug_field_name] = slug\n    return cleaned_input\n\n\ndef validate_slug_value(cleaned_input, slug_field_name: str = \"slug\"):\n    if slug_field_name in cleaned_input:\n        slug = cleaned_input[slug_field_name]\n        if not slug:\n            raise ValidationError(\n                f\"{slug_field_name.capitalize()} value cannot be blank.\"\n            )\n\n\ndef clean_seo_fields(data):\n    \"\"\"Extract and assign seo fields to given dictionary.\"\"\"\n    seo_fields = data.pop(\"seo\", {})\n\n    if seo_fields:\n        if \"title\" in seo_fields:\n            data[\"seo_title\"] = seo_fields[\"title\"]\n\n        if \"description\" in seo_fields:\n            data[\"seo_description\"] = seo_fields[\"description\"]\n\n\ndef validate_required_string_field(cleaned_input, field_name: str):\n    \"\"\"Strip and validate field value.\"\"\"\n    field_value = cleaned_input.get(field_name)\n    field_value = field_value.strip() if field_value else \"\"\n    if field_value:\n        cleaned_input[field_name] = field_value\n    else:\n        raise ValidationError(f\"{field_name.capitalize()} is required.\")\n    return cleaned_input\n\n\ndef validate_if_int_or_uuid(id):\n    result = True\n    try:\n        int(id)\n    except ValueError:\n        try:\n            UUID(id)\n        except (AttributeError, ValueError):\n            result = False\n    return result\n", "path": "saleor/graphql/core/validators/__init__.py"}]}