From cd8074b06a37ccc8fd3387c81cabe0161fd5a6a1 Mon Sep 17 00:00:00 2001 From: DoctorJohn Date: Thu, 4 Jun 2020 20:46:53 +0200 Subject: [PATCH 1/3] Explicitly cast help_text used as description to str to resolve lazy translation Before graphql-core had issues processing descriptions generated from translatable help_text during schema generation. Involved graphql-core utilities expect descriptions to be of type `str`, however, the generated descriptions were of type `django.utils.functional.__proxy__` which caused concatination with actual strings to fail. --- graphene_django/converter.py | 28 ++++++++++++++-------------- graphene_django/filter/utils.py | 2 +- graphene_django/forms/converter.py | 20 ++++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/graphene_django/converter.py b/graphene_django/converter.py index b6106bdb0..5dc68e902 100644 --- a/graphene_django/converter.py +++ b/graphene_django/converter.py @@ -108,7 +108,7 @@ def convert_django_field_with_choices( if choices and convert_choices_to_enum: enum = convert_choice_field_to_enum(field) required = not (field.blank or field.null) - converted = enum(description=field.help_text, required=required) + converted = enum(description=str(field.help_text), required=required) else: converted = convert_django_field(field, registry) if registry is not None: @@ -132,17 +132,17 @@ def convert_django_field(field, registry=None): @convert_django_field.register(models.FileField) @convert_django_field.register(models.FilePathField) def convert_field_to_string(field, registry=None): - return String(description=field.help_text, required=not field.null) + return String(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.AutoField) def convert_field_to_id(field, registry=None): - return ID(description=field.help_text, required=not field.null) + return ID(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.UUIDField) def convert_field_to_uuid(field, registry=None): - return UUID(description=field.help_text, required=not field.null) + return UUID(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.PositiveIntegerField) @@ -151,35 +151,35 @@ def convert_field_to_uuid(field, registry=None): @convert_django_field.register(models.BigIntegerField) @convert_django_field.register(models.IntegerField) def convert_field_to_int(field, registry=None): - return Int(description=field.help_text, required=not field.null) + return Int(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.NullBooleanField) @convert_django_field.register(models.BooleanField) def convert_field_to_boolean(field, registry=None): - return Boolean(description=field.help_text, required=not field.null) + return Boolean(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.DecimalField) @convert_django_field.register(models.FloatField) @convert_django_field.register(models.DurationField) def convert_field_to_float(field, registry=None): - return Float(description=field.help_text, required=not field.null) + return Float(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.DateTimeField) def convert_datetime_to_string(field, registry=None): - return DateTime(description=field.help_text, required=not field.null) + return DateTime(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.DateField) def convert_date_to_string(field, registry=None): - return Date(description=field.help_text, required=not field.null) + return Date(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.TimeField) def convert_time_to_string(field, registry=None): - return Time(description=field.help_text, required=not field.null) + return Time(description=str(field.help_text), required=not field.null) @convert_django_field.register(models.OneToOneRel) @@ -250,7 +250,7 @@ def dynamic_type(): if not _type: return - return Field(_type, description=field.help_text, required=not field.null) + return Field(_type, description=str(field.help_text), required=not field.null) return Dynamic(dynamic_type) @@ -260,13 +260,13 @@ def convert_postgres_array_to_list(field, registry=None): base_type = convert_django_field(field.base_field) if not isinstance(base_type, (List, NonNull)): base_type = type(base_type) - return List(base_type, description=field.help_text, required=not field.null) + return List(base_type, description=str(field.help_text), required=not field.null) @convert_django_field.register(HStoreField) @convert_django_field.register(JSONField) def convert_postgres_field_to_string(field, registry=None): - return JSONString(description=field.help_text, required=not field.null) + return JSONString(description=str(field.help_text), required=not field.null) @convert_django_field.register(RangeField) @@ -274,7 +274,7 @@ def convert_postgres_range_to_string(field, registry=None): inner_type = convert_django_field(field.base_field) if not isinstance(inner_type, (List, NonNull)): inner_type = type(inner_type) - return List(inner_type, description=field.help_text, required=not field.null) + return List(inner_type, description=str(field.help_text), required=not field.null) # Register Django lazy()-wrapped values as GraphQL description/help_text. diff --git a/graphene_django/filter/utils.py b/graphene_django/filter/utils.py index ea4f8dc60..dda35d349 100644 --- a/graphene_django/filter/utils.py +++ b/graphene_django/filter/utils.py @@ -30,7 +30,7 @@ def get_filtering_args_from_filterset(filterset_class, type): form_field = filter_field.field field_type = convert_form_field(form_field).Argument() - field_type.description = filter_field.label + field_type.description = str(filter_field.label) args[name] = field_type return args diff --git a/graphene_django/forms/converter.py b/graphene_django/forms/converter.py index 077e9842e..a991d1e4b 100644 --- a/graphene_django/forms/converter.py +++ b/graphene_django/forms/converter.py @@ -25,39 +25,39 @@ def convert_form_field(field): @convert_form_field.register(forms.RegexField) @convert_form_field.register(forms.Field) def convert_form_field_to_string(field): - return String(description=field.help_text, required=field.required) + return String(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.UUIDField) def convert_form_field_to_uuid(field): - return UUID(description=field.help_text, required=field.required) + return UUID(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.IntegerField) @convert_form_field.register(forms.NumberInput) def convert_form_field_to_int(field): - return Int(description=field.help_text, required=field.required) + return Int(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.BooleanField) def convert_form_field_to_boolean(field): - return Boolean(description=field.help_text, required=field.required) + return Boolean(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.NullBooleanField) def convert_form_field_to_nullboolean(field): - return Boolean(description=field.help_text) + return Boolean(description=str(field.help_text)) @convert_form_field.register(forms.DecimalField) @convert_form_field.register(forms.FloatField) def convert_form_field_to_float(field): - return Float(description=field.help_text, required=field.required) + return Float(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.MultipleChoiceField) def convert_form_field_to_string_list(field): - return List(String, description=field.help_text, required=field.required) + return List(String, description=str(field.help_text), required=field.required) @convert_form_field.register(forms.ModelMultipleChoiceField) @@ -68,17 +68,17 @@ def convert_form_field_to_id_list(field): @convert_form_field.register(forms.DateField) def convert_form_field_to_date(field): - return Date(description=field.help_text, required=field.required) + return Date(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.DateTimeField) def convert_form_field_to_datetime(field): - return DateTime(description=field.help_text, required=field.required) + return DateTime(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.TimeField) def convert_form_field_to_time(field): - return Time(description=field.help_text, required=field.required) + return Time(description=str(field.help_text), required=field.required) @convert_form_field.register(forms.ModelChoiceField) From b725976c1d8211f3d677fdb2c650b05ca2331a83 Mon Sep 17 00:00:00 2001 From: DoctorJohn Date: Sat, 6 Jun 2020 16:08:09 +0200 Subject: [PATCH 2/3] Fix field description generation when help_text is None --- graphene_django/converter.py | 32 +++++++++++++++++------------- graphene_django/filter/utils.py | 2 +- graphene_django/forms/converter.py | 24 ++++++++++++---------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/graphene_django/converter.py b/graphene_django/converter.py index 5dc68e902..96d55cde9 100644 --- a/graphene_django/converter.py +++ b/graphene_django/converter.py @@ -108,7 +108,7 @@ def convert_django_field_with_choices( if choices and convert_choices_to_enum: enum = convert_choice_field_to_enum(field) required = not (field.blank or field.null) - converted = enum(description=str(field.help_text), required=required) + converted = enum(description=get_django_field_description(field), required=required) else: converted = convert_django_field(field, registry) if registry is not None: @@ -116,6 +116,10 @@ def convert_django_field_with_choices( return converted +def get_django_field_description(field): + return None if field.help_text is None else str(field.help_text) + + @singledispatch def convert_django_field(field, registry=None): raise Exception( @@ -132,17 +136,17 @@ def convert_django_field(field, registry=None): @convert_django_field.register(models.FileField) @convert_django_field.register(models.FilePathField) def convert_field_to_string(field, registry=None): - return String(description=str(field.help_text), required=not field.null) + return String(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.AutoField) def convert_field_to_id(field, registry=None): - return ID(description=str(field.help_text), required=not field.null) + return ID(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.UUIDField) def convert_field_to_uuid(field, registry=None): - return UUID(description=str(field.help_text), required=not field.null) + return UUID(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.PositiveIntegerField) @@ -151,35 +155,35 @@ def convert_field_to_uuid(field, registry=None): @convert_django_field.register(models.BigIntegerField) @convert_django_field.register(models.IntegerField) def convert_field_to_int(field, registry=None): - return Int(description=str(field.help_text), required=not field.null) + return Int(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.NullBooleanField) @convert_django_field.register(models.BooleanField) def convert_field_to_boolean(field, registry=None): - return Boolean(description=str(field.help_text), required=not field.null) + return Boolean(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.DecimalField) @convert_django_field.register(models.FloatField) @convert_django_field.register(models.DurationField) def convert_field_to_float(field, registry=None): - return Float(description=str(field.help_text), required=not field.null) + return Float(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.DateTimeField) def convert_datetime_to_string(field, registry=None): - return DateTime(description=str(field.help_text), required=not field.null) + return DateTime(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.DateField) def convert_date_to_string(field, registry=None): - return Date(description=str(field.help_text), required=not field.null) + return Date(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.TimeField) def convert_time_to_string(field, registry=None): - return Time(description=str(field.help_text), required=not field.null) + return Time(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(models.OneToOneRel) @@ -250,7 +254,7 @@ def dynamic_type(): if not _type: return - return Field(_type, description=str(field.help_text), required=not field.null) + return Field(_type, description=get_django_field_description(field), required=not field.null) return Dynamic(dynamic_type) @@ -260,13 +264,13 @@ def convert_postgres_array_to_list(field, registry=None): base_type = convert_django_field(field.base_field) if not isinstance(base_type, (List, NonNull)): base_type = type(base_type) - return List(base_type, description=str(field.help_text), required=not field.null) + return List(base_type, description=get_django_field_description(field), required=not field.null) @convert_django_field.register(HStoreField) @convert_django_field.register(JSONField) def convert_postgres_field_to_string(field, registry=None): - return JSONString(description=str(field.help_text), required=not field.null) + return JSONString(description=get_django_field_description(field), required=not field.null) @convert_django_field.register(RangeField) @@ -274,7 +278,7 @@ def convert_postgres_range_to_string(field, registry=None): inner_type = convert_django_field(field.base_field) if not isinstance(inner_type, (List, NonNull)): inner_type = type(inner_type) - return List(inner_type, description=str(field.help_text), required=not field.null) + return List(inner_type, description=get_django_field_description(field), required=not field.null) # Register Django lazy()-wrapped values as GraphQL description/help_text. diff --git a/graphene_django/filter/utils.py b/graphene_django/filter/utils.py index dda35d349..51111ef8e 100644 --- a/graphene_django/filter/utils.py +++ b/graphene_django/filter/utils.py @@ -30,7 +30,7 @@ def get_filtering_args_from_filterset(filterset_class, type): form_field = filter_field.field field_type = convert_form_field(form_field).Argument() - field_type.description = str(filter_field.label) + field_type.description = None if filter_field.label is None else str(filter_field.label) args[name] = field_type return args diff --git a/graphene_django/forms/converter.py b/graphene_django/forms/converter.py index a991d1e4b..3a004dcc8 100644 --- a/graphene_django/forms/converter.py +++ b/graphene_django/forms/converter.py @@ -8,6 +8,10 @@ from .forms import GlobalIDFormField, GlobalIDMultipleChoiceField +def get_form_field_description(field): + return None if field.help_text is None else str(field.help_text) + + @singledispatch def convert_form_field(field): raise ImproperlyConfigured( @@ -25,39 +29,39 @@ def convert_form_field(field): @convert_form_field.register(forms.RegexField) @convert_form_field.register(forms.Field) def convert_form_field_to_string(field): - return String(description=str(field.help_text), required=field.required) + return String(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.UUIDField) def convert_form_field_to_uuid(field): - return UUID(description=str(field.help_text), required=field.required) + return UUID(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.IntegerField) @convert_form_field.register(forms.NumberInput) def convert_form_field_to_int(field): - return Int(description=str(field.help_text), required=field.required) + return Int(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.BooleanField) def convert_form_field_to_boolean(field): - return Boolean(description=str(field.help_text), required=field.required) + return Boolean(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.NullBooleanField) def convert_form_field_to_nullboolean(field): - return Boolean(description=str(field.help_text)) + return Boolean(description=get_form_field_description(field)) @convert_form_field.register(forms.DecimalField) @convert_form_field.register(forms.FloatField) def convert_form_field_to_float(field): - return Float(description=str(field.help_text), required=field.required) + return Float(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.MultipleChoiceField) def convert_form_field_to_string_list(field): - return List(String, description=str(field.help_text), required=field.required) + return List(String, description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.ModelMultipleChoiceField) @@ -68,17 +72,17 @@ def convert_form_field_to_id_list(field): @convert_form_field.register(forms.DateField) def convert_form_field_to_date(field): - return Date(description=str(field.help_text), required=field.required) + return Date(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.DateTimeField) def convert_form_field_to_datetime(field): - return DateTime(description=str(field.help_text), required=field.required) + return DateTime(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.TimeField) def convert_form_field_to_time(field): - return Time(description=str(field.help_text), required=field.required) + return Time(description=get_form_field_description(field), required=field.required) @convert_form_field.register(forms.ModelChoiceField) From 1a0fed01305ad279162c27983fd9a9723fdc8540 Mon Sep 17 00:00:00 2001 From: DoctorJohn Date: Sat, 6 Jun 2020 16:15:01 +0200 Subject: [PATCH 3/3] Apply changes suggested by the black formatter --- graphene_django/converter.py | 54 +++++++++++++++++++++++------- graphene_django/filter/utils.py | 4 ++- graphene_django/forms/converter.py | 16 ++++++--- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/graphene_django/converter.py b/graphene_django/converter.py index 96d55cde9..d8d37db7b 100644 --- a/graphene_django/converter.py +++ b/graphene_django/converter.py @@ -108,7 +108,9 @@ def convert_django_field_with_choices( if choices and convert_choices_to_enum: enum = convert_choice_field_to_enum(field) required = not (field.blank or field.null) - converted = enum(description=get_django_field_description(field), required=required) + converted = enum( + description=get_django_field_description(field), required=required + ) else: converted = convert_django_field(field, registry) if registry is not None: @@ -136,7 +138,9 @@ def convert_django_field(field, registry=None): @convert_django_field.register(models.FileField) @convert_django_field.register(models.FilePathField) def convert_field_to_string(field, registry=None): - return String(description=get_django_field_description(field), required=not field.null) + return String( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.AutoField) @@ -146,7 +150,9 @@ def convert_field_to_id(field, registry=None): @convert_django_field.register(models.UUIDField) def convert_field_to_uuid(field, registry=None): - return UUID(description=get_django_field_description(field), required=not field.null) + return UUID( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.PositiveIntegerField) @@ -161,29 +167,39 @@ def convert_field_to_int(field, registry=None): @convert_django_field.register(models.NullBooleanField) @convert_django_field.register(models.BooleanField) def convert_field_to_boolean(field, registry=None): - return Boolean(description=get_django_field_description(field), required=not field.null) + return Boolean( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.DecimalField) @convert_django_field.register(models.FloatField) @convert_django_field.register(models.DurationField) def convert_field_to_float(field, registry=None): - return Float(description=get_django_field_description(field), required=not field.null) + return Float( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.DateTimeField) def convert_datetime_to_string(field, registry=None): - return DateTime(description=get_django_field_description(field), required=not field.null) + return DateTime( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.DateField) def convert_date_to_string(field, registry=None): - return Date(description=get_django_field_description(field), required=not field.null) + return Date( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.TimeField) def convert_time_to_string(field, registry=None): - return Time(description=get_django_field_description(field), required=not field.null) + return Time( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(models.OneToOneRel) @@ -254,7 +270,11 @@ def dynamic_type(): if not _type: return - return Field(_type, description=get_django_field_description(field), required=not field.null) + return Field( + _type, + description=get_django_field_description(field), + required=not field.null, + ) return Dynamic(dynamic_type) @@ -264,13 +284,19 @@ def convert_postgres_array_to_list(field, registry=None): base_type = convert_django_field(field.base_field) if not isinstance(base_type, (List, NonNull)): base_type = type(base_type) - return List(base_type, description=get_django_field_description(field), required=not field.null) + return List( + base_type, + description=get_django_field_description(field), + required=not field.null, + ) @convert_django_field.register(HStoreField) @convert_django_field.register(JSONField) def convert_postgres_field_to_string(field, registry=None): - return JSONString(description=get_django_field_description(field), required=not field.null) + return JSONString( + description=get_django_field_description(field), required=not field.null + ) @convert_django_field.register(RangeField) @@ -278,7 +304,11 @@ def convert_postgres_range_to_string(field, registry=None): inner_type = convert_django_field(field.base_field) if not isinstance(inner_type, (List, NonNull)): inner_type = type(inner_type) - return List(inner_type, description=get_django_field_description(field), required=not field.null) + return List( + inner_type, + description=get_django_field_description(field), + required=not field.null, + ) # Register Django lazy()-wrapped values as GraphQL description/help_text. diff --git a/graphene_django/filter/utils.py b/graphene_django/filter/utils.py index 51111ef8e..426bae28f 100644 --- a/graphene_django/filter/utils.py +++ b/graphene_django/filter/utils.py @@ -30,7 +30,9 @@ def get_filtering_args_from_filterset(filterset_class, type): form_field = filter_field.field field_type = convert_form_field(form_field).Argument() - field_type.description = None if filter_field.label is None else str(filter_field.label) + field_type.description = ( + None if filter_field.label is None else str(filter_field.label) + ) args[name] = field_type return args diff --git a/graphene_django/forms/converter.py b/graphene_django/forms/converter.py index 3a004dcc8..df3708f58 100644 --- a/graphene_django/forms/converter.py +++ b/graphene_django/forms/converter.py @@ -29,7 +29,9 @@ def convert_form_field(field): @convert_form_field.register(forms.RegexField) @convert_form_field.register(forms.Field) def convert_form_field_to_string(field): - return String(description=get_form_field_description(field), required=field.required) + return String( + description=get_form_field_description(field), required=field.required + ) @convert_form_field.register(forms.UUIDField) @@ -45,7 +47,9 @@ def convert_form_field_to_int(field): @convert_form_field.register(forms.BooleanField) def convert_form_field_to_boolean(field): - return Boolean(description=get_form_field_description(field), required=field.required) + return Boolean( + description=get_form_field_description(field), required=field.required + ) @convert_form_field.register(forms.NullBooleanField) @@ -61,7 +65,9 @@ def convert_form_field_to_float(field): @convert_form_field.register(forms.MultipleChoiceField) def convert_form_field_to_string_list(field): - return List(String, description=get_form_field_description(field), required=field.required) + return List( + String, description=get_form_field_description(field), required=field.required + ) @convert_form_field.register(forms.ModelMultipleChoiceField) @@ -77,7 +83,9 @@ def convert_form_field_to_date(field): @convert_form_field.register(forms.DateTimeField) def convert_form_field_to_datetime(field): - return DateTime(description=get_form_field_description(field), required=field.required) + return DateTime( + description=get_form_field_description(field), required=field.required + ) @convert_form_field.register(forms.TimeField)