8000 Correctly detect required/optional args/fields · graphql-python/graphql-core@a3be3d1 · GitHub
[go: up one dir, main page]

Skip to content

Commit a3be3d1

Browse files
committed
Correctly detect required/optional args/fields
Replicates graphql/graphql-js@0adece9
1 parent 046da17 commit a3be3d1

File tree

2 files changed

+58
-50
lines changed

2 files changed

+58
-50
lines changed

graphql/utilities/find_breaking_changes.py

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
GraphQLInterfaceType, GraphQLList, GraphQLNamedType, GraphQLNonNull,
99
GraphQLObjectType, GraphQLSchema, GraphQLType, GraphQLUnionType,
1010
is_enum_type, is_input_object_type, is_interface_type, is_list_type,
11-
is_named_type, is_non_null_type, is_object_type, is_scalar_type,
12-
is_union_type)
11+
is_named_type, is_required_argument, is_required_input_field,
12+
is_non_null_type, is_object_type, is_scalar_type, is_union_type)
1313

1414
__all__ = [
1515
'BreakingChange', 'BreakingChangeType',
@@ -36,22 +36,22 @@ class BreakingChangeType(Enum):
3636
VALUE_REMOVED_FROM_ENUM = 30
3737
ARG_REMOVED = 40
3838
ARG_CHANGED_KIND = 41
39-
NON_NULL_ARG_ADDED = 50
40-
NON_NULL_INPUT_FIELD_ADDED = 51
39+
REQUIRED_ARG_ADDED = 50
40+
REQUIRED_INPUT_FIELD_ADDED = 51
4141
INTERFACE_REMOVED_FROM_OBJECT = 60
4242
DIRECTIVE_REMOVED = 70
4343
DIRECTIVE_ARG_REMOVED = 71
4444
DIRECTIVE_LOCATION_REMOVED = 72
45-
NON_NULL_DIRECTIVE_ARG_ADDED = 73
45+
REQUIRED_DIRECTIVE_ARG_ADDED = 73
4646

4747

4848
class DangerousChangeType(Enum):
4949
ARG_DEFAULT_VALUE_CHANGE = 42
5050
VALUE_ADDED_TO_ENUM = 31
5151
INTERFACE_ADDED_TO_OBJECT = 61
5252
TYPE_ADDED_TO_UNION = 23
53-
NULLABLE_INPUT_FIELD_ADDED = 52
54-
NULLABLE_ARG_ADDED = 53
53+
OPTIONAL_INPUT_FIELD_ADDED = 52
54+
OPTIONAL_ARG_ADDED = 53
5555

5656

5757
class BreakingChange(NamedTuple):
@@ -214,20 +214,20 @@ def find_arg_changes(
214214
f'{old_type.name}.{field_name} arg'
215215
f' {arg_name} has changed defaultValue'))
216216

217-
# Check if a non-null arg was added to the field
217+
# Check if arg was added to the field
218218
for arg_name in new_args:
219219
if arg_name not in old_args:
220-
new_arg = new_args[arg_name]
221-
if is_non_null_type(new_arg.type):
220+
new_arg_def = new_args[arg_name]
221+
if is_required_argument(new_arg_def):
222222
breaking_changes.append(BreakingChange(
223-
BreakingChangeType.NON_NULL_ARG_ADDED,
224-
f'A non-null arg {arg_name} on'
225-
f' {new_type.name}.{field_name} was added'))
223+
BreakingChangeType.REQUIRED_ARG_ADDED,
224+
f'A required arg {arg_name} on'
225+
f' {type_name}.{field_name} was added'))
226226
else:
227227
dangerous_changes.append(DangerousChange(
228-
DangerousChangeType.NULLABLE_ARG_ADDED,
229-
f'A nullable arg {arg_name} on'
230-
f' {new_type.name}.{field_name} was added'))
228+
DangerousChangeType.OPTIONAL_ARG_ADDED,
229+
f'An optional arg {arg_name} on'
230+
f' {type_name}.{field_name} was added'))
231231

232232
return BreakingAndDangerousChanges(breaking_changes, dangerous_changes)
233233

@@ -343,16 +343,16 @@ def find_fields_that_changed_type_on_input_object_types(
343343
# Check if a field was added to the input object type
344344
for field_name in new_type_fields_def:
345345
if field_name not in old_type_fields_def:
346-
if is_non_null_type(new_type_fields_def[field_name].type):
346+
if is_required_input_field(new_type_fields_def[field_name]):
347347
breaking_changes.append(BreakingChange(
348-
BreakingChangeType.NON_NULL_INPUT_FIELD_ADDED,
349-
f'A non-null field {field_name} on'
350-
f' input type {new_type.name} was added.'))
348+
BreakingChangeType.REQUIRED_INPUT_FIELD_ADDED,
349+
f'A required field {field_name} on'
350+
f' input type {type_name} was added.'))
351351
else:
352352
dangerous_changes.append(DangerousChange(
353-
DangerousChangeType.NULLABLE_INPUT_FIELD_ADDED,
354-
f'A nullable field {field_name} on'
355-
f' input type {new_type.name} was added.'))
353+
DangerousChangeType.OPTIONAL_INPUT_FIELD_ADDED,
354+
f'An optional field {field_name} on'
355+
f' input type {type_name} was added.'))
356356

357357
return BreakingAndDangerousChanges(breaking_changes, dangerous_changes)
358358

@@ -651,13 +651,11 @@ def find_added_non_null_directive_args(
651651

652652
for arg_name, arg in find_added_args_for_directive(
653653
old_directive, new_directive).items():
654-
if not is_non_null_type(arg.type):
655-
continue
656-
657-
added_non_nullable_args.append(BreakingChange(
658-
BreakingChangeType.NON_NULL_DIRECTIVE_ARG_ADDED,
659-
f'A non-null arg {arg_name} on directive'
660-
f' {new_directive.name} was added'))
654+
if is_required_argument(arg):
655+
added_non_nullable_args.append(BreakingChange(
656+
BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED,
657+
f'A required arg {arg_name} on directive'
658+
f' {new_directive.name} was added'))
661659

662660
return added_non_nullable_args
663661

tests/utilities/test_find_breaking_changes.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ def should_detect_if_fields_on_input_types_changed_kind_or_were_removed():
244244
assert find_fields_that_changed_type_on_input_object_types(
245245
old_schema, new_schema).breaking_changes == expected_field_changes
246246

247-
def should_detect_if_a_non_null_field_is_added_to_an_input_type():
247+
def should_detect_if_a_required_field_is_added_to_an_input_type():
248248
old_schema = build_schema("""
249249
input InputType1 {
250250
field1: String
@@ -259,7 +259,8 @@ def should_detect_if_a_non_null_field_is_added_to_an_input_type():
259259
input InputType1 {
260260
field1: String
261261
requiredField: Int!
262-
optionalField: Boolean
262+
optionalField1: Boolean
263+
optionalField2: Boolean! = false
263264
}
264265
265266
type Query {
@@ -268,8 +269,8 @@ def should_detect_if_a_non_null_field_is_added_to_an_input_type():
268269
""")
269270

270271
expected_field_changes = [
271-
(BreakingChangeType.NON_NULL_INPUT_FIELD_ADDED,
272-
'A non-null field requiredField on input type'
272+
(BreakingChangeType.REQUIRED_INPUT_FIELD_ADDED,
273+
'A required field requiredField on input type'
273274
' InputType1 was added.')]
274275

275276
assert find_fields_that_changed_type_on_input_object_types(
@@ -462,7 +463,7 @@ def should_detect_if_a_field_argument_has_changed_type():
462463
'Type1.field1 arg arg15 has changed type from [[Int]!]'
463464
' to [[Int!]!]')]
464465

465-
def should_detect_if_a_non_null_field_argument_was_added():
466+
def should_detect_if_a_required_field_argument_was_added():
466467
old_schema = build_schema("""
467468
type Type1 {
468469
field1(arg1: String): String
@@ -475,7 +476,12 @@ def should_detect_if_a_non_null_field_argument_was_added():
475476

476477
new_schema = build_schema("""
477478
type Type1 {
478-
field1(arg1: String, newRequiredArg: String!, newOptionalArg: Int): String
479+
field1(
480+
arg1: String,
481+
newRequiredArg: String!
482+
newOptionalArg1: Int
483+
newOptionalArg2: Int! = 0
484+
): String
479485
}
480486
481487
type Query {
@@ -484,8 +490,8 @@ def should_detect_if_a_non_null_field_argument_was_added():
484490
""") # noqa
485491

486492
assert find_arg_changes(old_schema, new_schema).breaking_changes == [
487-
(BreakingChangeType.NON_NULL_ARG_ADDED,
488-
'A non-null arg newRequiredArg on Type1.field1 was added')]
493+
(BreakingChangeType.REQUIRED_ARG_ADDED,
494+
'A required arg newRequiredArg on Type1.field1 was added')]
489495

490496
def should_not_flag_args_with_the_same_type_signature_as_breaking():
491497
old_schema = build_schema("""
@@ -700,8 +706,8 @@ def should_detect_all_breaking_changes():
700706
'DirectiveThatIsRemoved was removed'),
701707
(BreakingChangeType.DIRECTIVE_ARG_REMOVED,
702708
'arg1 was removed from DirectiveThatRemovesArg'),
703-
(BreakingChangeType.NON_NULL_DIRECTIVE_ARG_ADDED,
704-
'A non-null arg arg1 on directive'
709+
(BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED,
710+
'A required arg arg1 on directive'
705711
' NonNullDirectiveAdded was added'),
706712
(BreakingChangeType.DIRECTIVE_LOCATION_REMOVED,
707713
'QUERY was removed from DirectiveName')]
@@ -746,18 +752,22 @@ def should_detect_if_a_directive_argument_was_removed():
746752
(BreakingChangeType.DIRECTIVE_ARG_REMOVED,
747753
'arg1 was removed from DirectiveWithArg')]
748754

749-
def should_detect_if_a_non_nullable_directive_argument_was_added():
755+
def should_detect_if_an_optional_directive_argument_was_added():
750756
old_schema = build_schema("""
751757
directive @DirectiveName on FIELD_DEFINITION
752758
""")
753759

754760
new_schema = build_schema("""
755-
directive @DirectiveName(arg1: Boolean!) on FIELD_DEFINITION
761+
directive @DirectiveName(
762+
newRequiredArg: String!
763+
newOptionalArg1: Int
764+
newOptionalArg2: Int! = 0
765+
) on FIELD_DEFINITION
756766
""")
757767

758768
assert find_added_non_null_directive_args(old_schema, new_schema) == [
759-
(BreakingChangeType.NON_NULL_DIRECTIVE_ARG_ADDED,
760-
'A non-null arg arg1 on directive DirectiveName was added')]
769+
(BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED, 'A required arg'
770+
' newRequiredArg on directive DirectiveName was added')]
761771

762772
def should_detect_locations_removed_from_a_directive():
763773
d1 = GraphQLDirective('Directive Name', locations=[
@@ -904,7 +914,7 @@ def should_detect_if_a_type_was_added_to_a_union_type():
904914
(DangerousChangeType.TYPE_ADDED_TO_UNION,
905915
'Type2 was added to union type UnionType1.')]
906916

907-
def should_detect_if_a_nullable_field_was_added_to_an_input():
917+
def should_detect_if_an_optional_field_was_added_to_an_input():
908918
old_schema = build_schema("""
909919
input InputType1 {
910920
field1: String
@@ -927,8 +937,8 @@ def should_detect_if_a_nullable_field_was_added_to_an_input():
927937
""")
928938

929939
expected_field_changes = [
930-
(DangerousChangeType.NULLABLE_INPUT_FIELD_ADDED,
931-
'A nullable field field2 on input type InputType1 was added.')]
940+
(DangerousChangeType.OPTIONAL_INPUT_FIELD_ADDED,
941+
'An optional field field2 on input type InputType1 was added.')]
932942

933943
assert find_fields_that_changed_type_on_input_object_types(
934944
old_schema, new_schema).dangerous_changes == expected_field_changes
@@ -1007,7 +1017,7 @@ def should_find_all_dangerous_changes():
10071017
assert find_dangerous_changes(
10081018
old_schema, new_schema) == expected_dangerous_changes
10091019

1010-
def should_detect_if_a_nullable_field_argument_was_added():
1020+
def should_detect_if_an_optional_field_argument_was_added():
10111021
old_schema = build_schema("""
10121022
type Type1 {
10131023
field1(arg1: String): String
@@ -1029,5 +1039,5 @@ def should_detect_if_a_nullable_field_argument_was_added():
10291039
""")
10301040

10311041
assert find_arg_changes(old_schema, new_schema). 1CF5 dangerous_changes == [
1032-
(DangerousChangeType.NULLABLE_ARG_ADDED,
1033-
'A nullable arg arg2 on Type1.field1 was added')]
1042+
(DangerousChangeType.OPTIONAL_ARG_ADDED,
1043+
'An optional arg arg2 on Type1.field1 was added')]

0 commit comments

Comments
 (0)
0