diff --git a/examples/cookbook-plain/cookbook/ingredients/migrations/0001_initial.py b/examples/cookbook-plain/cookbook/ingredients/migrations/0001_initial.py index 0494923..ee8cadd 100644 --- a/examples/cookbook-plain/cookbook/ingredients/migrations/0001_initial.py +++ b/examples/cookbook-plain/cookbook/ingredients/migrations/0001_initial.py @@ -10,24 +10,46 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Category', + name="Category", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), ], ), migrations.CreateModel( - name='Ingredient', + name="Ingredient", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('notes', models.TextField()), - ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='ingredients.Category')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), + ("notes", models.TextField()), + ( + "category", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="ingredients", + to="ingredients.Category", + ), + ), ], ), ] diff --git a/examples/cookbook-plain/cookbook/ingredients/migrations/0002_auto_20161104_0050.py b/examples/cookbook-plain/cookbook/ingredients/migrations/0002_auto_20161104_0050.py index 359d4fc..40c7f2b 100644 --- a/examples/cookbook-plain/cookbook/ingredients/migrations/0002_auto_20161104_0050.py +++ b/examples/cookbook-plain/cookbook/ingredients/migrations/0002_auto_20161104_0050.py @@ -7,14 +7,12 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('ingredients', '0001_initial'), - ] + dependencies = [("ingredients", "0001_initial")] operations = [ migrations.AlterField( - model_name='ingredient', - name='notes', + model_name="ingredient", + name="notes", field=models.TextField(blank=True, null=True), - ), + ) ] diff --git a/examples/cookbook-plain/cookbook/ingredients/migrations/0003_auto_20181018_1746.py b/examples/cookbook-plain/cookbook/ingredients/migrations/0003_auto_20181018_1746.py index 184e79e..3648299 100644 --- a/examples/cookbook-plain/cookbook/ingredients/migrations/0003_auto_20181018_1746.py +++ b/examples/cookbook-plain/cookbook/ingredients/migrations/0003_auto_20181018_1746.py @@ -5,13 +5,10 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('ingredients', '0002_auto_20161104_0050'), - ] + dependencies = [("ingredients", "0002_auto_20161104_0050")] operations = [ migrations.AlterModelOptions( - name='category', - options={'verbose_name_plural': 'Categories'}, - ), + name="category", options={"verbose_name_plural": "Categories"} + ) ] diff --git a/examples/cookbook-plain/cookbook/recipes/migrations/0001_initial.py b/examples/cookbook-plain/cookbook/recipes/migrations/0001_initial.py index 338c71a..9ce12f2 100644 --- a/examples/cookbook-plain/cookbook/recipes/migrations/0001_initial.py +++ b/examples/cookbook-plain/cookbook/recipes/migrations/0001_initial.py @@ -10,27 +10,61 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ('ingredients', '0001_initial'), - ] + dependencies = [("ingredients", "0001_initial")] operations = [ migrations.CreateModel( - name='Recipe', + name="Recipe", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('instructions', models.TextField()), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=100)), + ("instructions", models.TextField()), ], ), migrations.CreateModel( - name='RecipeIngredient', + name="RecipeIngredient", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('amount', models.FloatField()), - ('unit', models.CharField(choices=[('kg', 'Kilograms'), ('l', 'Litres'), ('', 'Units')], max_length=20)), - ('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to='ingredients.Ingredient')), - ('recipes', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='amounts', to='recipes.Recipe')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("amount", models.FloatField()), + ( + "unit", + models.CharField( + choices=[("kg", "Kilograms"), ("l", "Litres"), ("", "Units")], + max_length=20, + ), + ), + ( + "ingredient", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="used_by", + to="ingredients.Ingredient", + ), + ), + ( + "recipes", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="amounts", + to="recipes.Recipe", + ), + ), ], ), ] diff --git a/examples/cookbook-plain/cookbook/recipes/migrations/0002_auto_20161104_0106.py b/examples/cookbook-plain/cookbook/recipes/migrations/0002_auto_20161104_0106.py index f135392..fb32282 100644 --- a/examples/cookbook-plain/cookbook/recipes/migrations/0002_auto_20161104_0106.py +++ b/examples/cookbook-plain/cookbook/recipes/migrations/0002_auto_20161104_0106.py @@ -7,19 +7,23 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('recipes', '0001_initial'), - ] + dependencies = [("recipes", "0001_initial")] operations = [ migrations.RenameField( - model_name='recipeingredient', - old_name='recipes', - new_name='recipe', + model_name="recipeingredient", old_name="recipes", new_name="recipe" ), migrations.AlterField( - model_name='recipeingredient', - name='unit', - field=models.CharField(choices=[(b'unit', b'Units'), (b'kg', b'Kilograms'), (b'l', b'Litres'), (b'st', b'Shots')], max_length=20), + model_name="recipeingredient", + name="unit", + field=models.CharField( + choices=[ + (b"unit", b"Units"), + (b"kg", b"Kilograms"), + (b"l", b"Litres"), + (b"st", b"Shots"), + ], + max_length=20, + ), ), ] diff --git a/examples/cookbook-plain/cookbook/recipes/migrations/0003_auto_20181018_1728.py b/examples/cookbook-plain/cookbook/recipes/migrations/0003_auto_20181018_1728.py index 7a8df49..05fed05 100644 --- a/examples/cookbook-plain/cookbook/recipes/migrations/0003_auto_20181018_1728.py +++ b/examples/cookbook-plain/cookbook/recipes/migrations/0003_auto_20181018_1728.py @@ -5,14 +5,20 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('recipes', '0002_auto_20161104_0106'), - ] + dependencies = [("recipes", "0002_auto_20161104_0106")] operations = [ migrations.AlterField( - model_name='recipeingredient', - name='unit', - field=models.CharField(choices=[('unit', 'Units'), ('kg', 'Kilograms'), ('l', 'Litres'), ('st', 'Shots')], max_length=20), - ), + model_name="recipeingredient", + name="unit", + field=models.CharField( + choices=[ + ("unit", "Units"), + ("kg", "Kilograms"), + ("l", "Litres"), + ("st", "Shots"), + ], + max_length=20, + ), + ) ] diff --git a/examples/cookbook/cookbook/ingredients/migrations/0001_initial.py b/examples/cookbook/cookbook/ingredients/migrations/0001_initial.py index 0494923..ee8cadd 100644 --- a/examples/cookbook/cookbook/ingredients/migrations/0001_initial.py +++ b/examples/cookbook/cookbook/ingredients/migrations/0001_initial.py @@ -10,24 +10,46 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Category', + name="Category", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), ], ), migrations.CreateModel( - name='Ingredient', + name="Ingredient", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('notes', models.TextField()), - ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='ingredients.Category')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), + ("notes", models.TextField()), + ( + "category", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="ingredients", + to="ingredients.Category", + ), + ), ], ), ] diff --git a/examples/cookbook/cookbook/ingredients/migrations/0002_auto_20161104_0050.py b/examples/cookbook/cookbook/ingredients/migrations/0002_auto_20161104_0050.py index 359d4fc..40c7f2b 100644 --- a/examples/cookbook/cookbook/ingredients/migrations/0002_auto_20161104_0050.py +++ b/examples/cookbook/cookbook/ingredients/migrations/0002_auto_20161104_0050.py @@ -7,14 +7,12 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('ingredients', '0001_initial'), - ] + dependencies = [("ingredients", "0001_initial")] operations = [ migrations.AlterField( - model_name='ingredient', - name='notes', + model_name="ingredient", + name="notes", field=models.TextField(blank=True, null=True), - ), + ) ] diff --git a/examples/cookbook/cookbook/recipes/migrations/0001_initial.py b/examples/cookbook/cookbook/recipes/migrations/0001_initial.py index 338c71a..9ce12f2 100644 --- a/examples/cookbook/cookbook/recipes/migrations/0001_initial.py +++ b/examples/cookbook/cookbook/recipes/migrations/0001_initial.py @@ -10,27 +10,61 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ('ingredients', '0001_initial'), - ] + dependencies = [("ingredients", "0001_initial")] operations = [ migrations.CreateModel( - name='Recipe', + name="Recipe", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('instructions', models.TextField()), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=100)), + ("instructions", models.TextField()), ], ), migrations.CreateModel( - name='RecipeIngredient', + name="RecipeIngredient", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('amount', models.FloatField()), - ('unit', models.CharField(choices=[('kg', 'Kilograms'), ('l', 'Litres'), ('', 'Units')], max_length=20)), - ('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by', to='ingredients.Ingredient')), - ('recipes', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='amounts', to='recipes.Recipe')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("amount", models.FloatField()), + ( + "unit", + models.CharField( + choices=[("kg", "Kilograms"), ("l", "Litres"), ("", "Units")], + max_length=20, + ), + ), + ( + "ingredient", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="used_by", + to="ingredients.Ingredient", + ), + ), + ( + "recipes", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="amounts", + to="recipes.Recipe", + ), + ), ], ), ] diff --git a/examples/cookbook/cookbook/recipes/migrations/0002_auto_20161104_0106.py b/examples/cookbook/cookbook/recipes/migrations/0002_auto_20161104_0106.py index f135392..fb32282 100644 --- a/examples/cookbook/cookbook/recipes/migrations/0002_auto_20161104_0106.py +++ b/examples/cookbook/cookbook/recipes/migrations/0002_auto_20161104_0106.py @@ -7,19 +7,23 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('recipes', '0001_initial'), - ] + dependencies = [("recipes", "0001_initial")] operations = [ migrations.RenameField( - model_name='recipeingredient', - old_name='recipes', - new_name='recipe', + model_name="recipeingredient", old_name="recipes", new_name="recipe" ), migrations.AlterField( - model_name='recipeingredient', - name='unit', - field=models.CharField(choices=[(b'unit', b'Units'), (b'kg', b'Kilograms'), (b'l', b'Litres'), (b'st', b'Shots')], max_length=20), + model_name="recipeingredient", + name="unit", + field=models.CharField( + choices=[ + (b"unit", b"Units"), + (b"kg", b"Kilograms"), + (b"l", b"Litres"), + (b"st", b"Shots"), + ], + max_length=20, + ), ), ] diff --git a/graphene_django/fields.py b/graphene_django/fields.py index 0f018ee..f865ca5 100644 --- a/graphene_django/fields.py +++ b/graphene_django/fields.py @@ -122,15 +122,16 @@ class DjangoConnectionField(ConnectionField): @classmethod def connection_resolver( - cls, - resolver, - connection, - default_manager, - max_limit, - enforce_first_or_last, - root, - info, - **kwargs): + cls, + resolver, + connection, + default_manager, + max_limit, + enforce_first_or_last, + root, + info, + **kwargs + ): # By current `connection_from_list_slice` implementation, # `last` means last N items in the selection, @@ -140,26 +141,34 @@ class DjangoConnectionField(ConnectionField): last = kwargs.get("last") if first is not None and first <= 0: raise ValueError( - "`first` argument must be positive, got `{first}`".format(first=first)) + "`first` argument must be positive, got `{first}`".format(first=first) + ) if last is not None and last <= 0: raise ValueError( - "`last` argument must be positive, got `{last}`".format(last=last)) + "`last` argument must be positive, got `{last}`".format(last=last) + ) if enforce_first_or_last and not (first or last): raise ValueError( "You must provide a `first` or `last` value " - "to properly paginate the `{info.field_name}` connection.".format(info=info)) + "to properly paginate the `{info.field_name}` connection.".format( + info=info + ) + ) if not max_limit: pass elif first is None and last is None: - kwargs['first'] = max_limit + kwargs["first"] = max_limit else: count = min(i for i in (first, last) if i) if count > max_limit: - raise ValueError(("Requesting {count} records " - "on the `{info.field_name}` connection " - "exceeds the limit of {max_limit} records.").format( - count=count, info=info, max_limit=max_limit)) + raise ValueError( + ( + "Requesting {count} records " + "on the `{info.field_name}` connection " + "exceeds the limit of {max_limit} records." + ).format(count=count, info=info, max_limit=max_limit) + ) iterable = resolver(root, info, **kwargs) queryset = cls.resolve_queryset(connection, default_manager, info, kwargs) diff --git a/graphene_django/filter/tests/test_fields.py b/graphene_django/filter/tests/test_fields.py index d5e0c6f..f949579 100644 --- a/graphene_django/filter/tests/test_fields.py +++ b/graphene_django/filter/tests/test_fields.py @@ -2,13 +2,11 @@ from datetime import datetime import pytest -from graphene import (Argument, Boolean, Field, Float, ObjectType, Schema, - String) +from graphene import Argument, Boolean, Field, Float, ObjectType, Schema, String from graphene.relay import Node from graphene_django import DjangoObjectType -from graphene_django.forms import (GlobalIDFormField, - GlobalIDMultipleChoiceField) +from graphene_django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField from graphene_django.tests.models import Article, Pet, Reporter from graphene_django.utils import DJANGO_FILTER_INSTALLED @@ -769,6 +767,7 @@ def test_annotation_is_perserved(): assert not result.errors assert result.data == expected + def test_filter_with_union(): class ReporterType(DjangoObjectType): class Meta: @@ -783,7 +782,6 @@ def test_filter_with_union(): def resolve_all_reporters(cls, root, info, **kwargs): ret = Reporter.objects.none() | Reporter.objects.filter(first_name="John") - Reporter.objects.create(first_name="John", last_name="Doe") schema = Schema(query=Query) diff --git a/graphene_django/tests/test_query.py b/graphene_django/tests/test_query.py index f4f48f9..71f0f87 100644 --- a/graphene_django/tests/test_query.py +++ b/graphene_django/tests/test_query.py @@ -805,6 +805,7 @@ def test_should_error_if_negative_last(): assert str(result.errors[0]) == "`last` argument must be positive, got `-100`" assert result.data == expected + def test_max_limit_is_zero(): graphene_settings.RELAY_CONNECTION_MAX_LIMIT = 0 @@ -841,6 +842,7 @@ def test_max_limit_is_zero(): graphene_settings.RELAY_CONNECTION_MAX_LIMIT = 100 + def test_max_limit_is_none(): graphene_settings.RELAY_CONNECTION_MAX_LIMIT = None @@ -877,6 +879,7 @@ def test_max_limit_is_none(): graphene_settings.RELAY_CONNECTION_MAX_LIMIT = 100 + def test_should_query_promise_connectionfields(): from promise import Promise