From ffa86a87c65105df2f6eac9c4c8f088c0f40598f Mon Sep 17 00:00:00 2001 From: Daniel Gallagher Date: Mon, 21 May 2018 22:03:49 -0700 Subject: [PATCH] Add pre-commit tool to repository, and run on all files. --- .gitignore | 1 + .pre-commit-config.yaml | 18 +++++++++++++ README.md | 6 ++--- graphql/error/tests/test_base.py | 2 +- graphql/execution/executor.py | 2 +- graphql/execution/tests/test_abstract.py | 2 +- graphql/execution/tests/test_dataloader.py | 25 ++++++++----------- graphql/execution/tests/test_executor.py | 1 - graphql/execution/tests/test_located_error.py | 2 +- graphql/execution/tests/test_resolve.py | 2 +- graphql/execution/tests/test_variables.py | 3 ++- graphql/language/printer.py | 2 +- graphql/type/definition.py | 2 ++ graphql/type/tests/test_schema.py | 3 ++- graphql/type/typemap.py | 2 +- graphql/utils/tests/test_ast_to_code.py | 3 ++- .../utils/tests/test_build_client_schema.py | 2 +- graphql/utils/tests/test_quoted_or_list.py | 4 +++ .../rules/overlapping_fields_can_be_merged.py | 4 +-- scripts/casing.py | 1 + scripts/generate_ast.py | 4 +-- tox.ini | 10 +++++++- 22 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.gitignore b/.gitignore index 74b41897..af2acb26 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ htmlcov/ nosetests.xml coverage.xml *,cover +.pytest_cache/ # Translations *.mo diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..cb67b545 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +- repo: git://github.com/pre-commit/pre-commit-hooks + sha: v0.8.0 + hooks: + - id: autopep8-wrapper + args: + - -i + - --ignore=E128,E309,E501 + exclude: ^docs/.*$ + - id: check-json + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + exclude: ^docs/.*$ + - id: trailing-whitespace + - id: pretty-format-json + args: + - --autofix + - --indent=4 diff --git a/README.md b/README.md index dd765980..04d66456 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,13 @@ For questions, ask [Stack Overflow](http://stackoverflow.com/questions/tagged/gr ## Getting Started -An overview of the GraphQL language is available in the +An overview of the GraphQL language is available in the [README](https://github.com/facebook/graphql/blob/master/README.md) for the -[Specification for GraphQL](https://github.com/facebook/graphql). +[Specification for GraphQL](https://github.com/facebook/graphql). The overview describes a simple set of GraphQL examples that exist as [tests](https://github.com/graphql-python/graphql-core/tree/master/tests/) in this repository. A good way to get started is to walk through that README and the corresponding tests -in parallel. +in parallel. ### Using graphql-core diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index d51848b3..c686a0f6 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -39,7 +39,7 @@ def resolver(context, *_): formatted_tb = [row[2:] for row in extracted] if formatted_tb[2][0] == 'reraise': formatted_tb[2:] = formatted_tb[3:] - + assert formatted_tb == [ ('test_reraise', 'result.errors[0].reraise()'), ('reraise', 'six.reraise(type(self), self, self.stack)'), diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index 31428ee6..32525190 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -233,7 +233,7 @@ def resolve_field(exe_context, parent_type, source, field_asts, parent_info): operation=exe_context.operation, variable_values=exe_context.variable_values, context=context, - path=parent_info.path+[field_name] if parent_info else [field_name] + path=parent_info.path + [field_name] if parent_info else [field_name] ) executor = exe_context.executor diff --git a/graphql/execution/tests/test_abstract.py b/graphql/execution/tests/test_abstract.py index 0b745bc3..dedd6e44 100644 --- a/graphql/execution/tests/test_abstract.py +++ b/graphql/execution/tests/test_abstract.py @@ -25,7 +25,7 @@ def __init__(self, name): self.name = name -is_type_of = lambda type: lambda obj, info: isinstance(obj, type) +def is_type_of(type): return lambda obj, info: isinstance(obj, type) def make_type_resolver(types): diff --git a/graphql/execution/tests/test_dataloader.py b/graphql/execution/tests/test_dataloader.py index aaa01b0c..7fd4611e 100644 --- a/graphql/execution/tests/test_dataloader.py +++ b/graphql/execution/tests/test_dataloader.py @@ -28,7 +28,6 @@ def test_batches_correctly(executor): schema = GraphQLSchema(query=Query) - doc = ''' { business1: getBusiness(id: "1") { @@ -41,9 +40,8 @@ def test_batches_correctly(executor): ''' doc_ast = parse(doc) - load_calls = [] - + class BusinessDataLoader(DataLoader): def batch_load_fn(self, keys): load_calls.append(keys) @@ -52,7 +50,6 @@ def batch_load_fn(self, keys): class Context(object): business_data_loader = BusinessDataLoader() - result = execute(schema, doc_ast, None, context_value=Context(), executor=executor) assert not result.errors assert result.data == { @@ -63,7 +60,7 @@ class Context(object): 'id': '2' }, } - assert load_calls == [['1','2']] + assert load_calls == [['1', '2']] @pytest.mark.parametrize("executor", [ @@ -78,8 +75,11 @@ def test_batches_multiple_together(executor): Business = GraphQLObjectType('Business', lambda: { 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), - 'location': GraphQLField(Location, - resolver=lambda root, info, **args: info.context.location_data_loader.load('location-{}'.format(root)) + 'location': GraphQLField( + Location, + resolver=lambda root, info, **args: info.context.location_data_loader.load( + 'location-{}'.format(root) + ) ), }) @@ -94,7 +94,6 @@ def test_batches_multiple_together(executor): schema = GraphQLSchema(query=Query) - doc = ''' { business1: getBusiness(id: "1") { @@ -113,16 +112,15 @@ def test_batches_multiple_together(executor): ''' doc_ast = parse(doc) - business_load_calls = [] - + class BusinessDataLoader(DataLoader): def batch_load_fn(self, keys): business_load_calls.append(keys) return Promise.resolve(keys) location_load_calls = [] - + class LocationDataLoader(DataLoader): def batch_load_fn(self, keys): location_load_calls.append(keys) @@ -132,7 +130,6 @@ class Context(object): business_data_loader = BusinessDataLoader() location_data_loader = LocationDataLoader() - result = execute(schema, doc_ast, None, context_value=Context(), executor=executor) assert not result.errors assert result.data == { @@ -149,5 +146,5 @@ class Context(object): } }, } - assert business_load_calls == [['1','2']] - assert location_load_calls == [['location-1','location-2']] + assert business_load_calls == [['1', '2']] + assert location_load_calls == [['location-1', 'location-2']] diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py index cc107362..897e4fc7 100644 --- a/graphql/execution/tests/test_executor.py +++ b/graphql/execution/tests/test_executor.py @@ -812,4 +812,3 @@ def resolve(self, _next, root, info, *args, **kwargs): ['feed', 1, 'author', 'id'], ['feed', 1, 'author', 'name'] ] - diff --git a/graphql/execution/tests/test_located_error.py b/graphql/execution/tests/test_located_error.py index 0ff9530f..df61f257 100644 --- a/graphql/execution/tests/test_located_error.py +++ b/graphql/execution/tests/test_located_error.py @@ -20,4 +20,4 @@ def resolver(context, *_): }) result = execute(GraphQLSchema(Type), ast) - assert isinstance(result.errors[0], GraphQLLocatedError) \ No newline at end of file + assert isinstance(result.errors[0], GraphQLLocatedError) diff --git a/graphql/execution/tests/test_resolve.py b/graphql/execution/tests/test_resolve.py index 0ae7fc0f..5850063d 100644 --- a/graphql/execution/tests/test_resolve.py +++ b/graphql/execution/tests/test_resolve.py @@ -8,6 +8,7 @@ GraphQLObjectType, GraphQLSchema, GraphQLString) from promise import Promise + class CustomPromise(Promise): @classmethod def fulfilled(cls, x): @@ -150,7 +151,6 @@ def test_maps_argument_out_names_well_with_input(): def resolver(source, info, **args): return json.dumps([source, args], separators=(',', ':')) - TestInputObject = GraphQLInputObjectType('TestInputObject', lambda: OrderedDict([ ('inputOne', GraphQLInputObjectField(GraphQLString, out_name="input_one")), ('inputRecursive', GraphQLInputObjectField(TestInputObject, out_name="input_recursive")), diff --git a/graphql/execution/tests/test_variables.py b/graphql/execution/tests/test_variables.py index f50cbb5b..7f001caa 100644 --- a/graphql/execution/tests/test_variables.py +++ b/graphql/execution/tests/test_variables.py @@ -35,7 +35,8 @@ class my_special_dict(dict): ('a', GraphQLInputObjectField(GraphQLString)), ]), container_type=my_special_dict) -stringify = lambda obj: json.dumps(obj, sort_keys=True) + +def stringify(obj): return json.dumps(obj, sort_keys=True) def input_to_json(obj, info, **args): diff --git a/graphql/language/printer.py b/graphql/language/printer.py index 638d9b3a..e136b7d1 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -116,7 +116,7 @@ def leave_SchemaDefinition(self, node, *args): 'schema', join(node.directives, ' '), block(node.operation_types), - ], ' ') + ], ' ') def leave_OperationTypeDefinition(self, node, *args): return '{}: {}'.format(node.operation, node.type) diff --git a/graphql/type/definition.py b/graphql/type/definition.py index eb1a8764..5c62a75f 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -161,6 +161,7 @@ class GraphQLObjectType(GraphQLType): 'bestFriend': GraphQLField(PersonType) }) """ + def __init__(self, name, fields, interfaces=None, is_type_of=None, description=None): assert name, 'Type must be named.' assert_valid_name(name) @@ -513,6 +514,7 @@ class GeoPoint(GraphQLInputObjectType): default_value=0) } """ + def __init__(self, name, fields, description=None, container_type=None): assert name, 'Type must be named.' self.name = name diff --git a/graphql/type/tests/test_schema.py b/graphql/type/tests/test_schema.py index ff592222..166cf123 100644 --- a/graphql/type/tests/test_schema.py +++ b/graphql/type/tests/test_schema.py @@ -9,7 +9,7 @@ 'field_name': GraphQLField( type=GraphQLString, resolver=lambda *_: implementing_type - ) + ) } ) @@ -31,6 +31,7 @@ ) ) + def test_throws_human_readable_error_if_schematypes_not_defined(): with raises(AssertionError) as exci: schema.is_possible_type(interface_type, implementing_type) diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index 619043be..1bad09c1 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -41,7 +41,7 @@ def is_possible_type(self, abstract_type, possible_type): 'Could not find possible implementing types for ${} in ' + 'schema. Check that schema.types is defined and is an array of' + 'all possible types in the schema.' - ).format(abstract_type) + ).format(abstract_type) if not self._possible_type_map[abstract_type.name]: self._possible_type_map[abstract_type.name].update([p.name for p in possible_types]) diff --git a/graphql/utils/tests/test_ast_to_code.py b/graphql/utils/tests/test_ast_to_code.py index 98de219f..e86a4ee7 100644 --- a/graphql/utils/tests/test_ast_to_code.py +++ b/graphql/utils/tests/test_ast_to_code.py @@ -10,7 +10,8 @@ def test_ast_to_code_using_kitchen_sink(): doc = parse(fixtures.KITCHEN_SINK) code_ast = ast_to_code(doc) source = Source(fixtures.KITCHEN_SINK) - loc = lambda start, end: Loc(start, end, source) + + def loc(start, end): return Loc(start, end, source) parsed_code_ast = eval(code_ast, {}, {'ast': ast, 'loc': loc}) assert doc == parsed_code_ast diff --git a/graphql/utils/tests/test_build_client_schema.py b/graphql/utils/tests/test_build_client_schema.py index c2248cd7..a3650830 100644 --- a/graphql/utils/tests/test_build_client_schema.py +++ b/graphql/utils/tests/test_build_client_schema.py @@ -619,7 +619,7 @@ def test_succeds_on_smaller_equals_than_7_deep_lists(): GraphQLNonNull(GraphQLList(GraphQLNonNull( GraphQLList(GraphQLNonNull(GraphQLString)) )) - ))) + ))) ) } ) diff --git a/graphql/utils/tests/test_quoted_or_list.py b/graphql/utils/tests/test_quoted_or_list.py index 7ac13fbd..201aade1 100644 --- a/graphql/utils/tests/test_quoted_or_list.py +++ b/graphql/utils/tests/test_quoted_or_list.py @@ -7,14 +7,18 @@ def test_does_not_accept_an_empty_list(): with raises(StopIteration): quoted_or_list([]) + def test_returns_single_quoted_item(): assert quoted_or_list(['A']) == '"A"' + def test_returns_two_item_list(): assert quoted_or_list(['A', 'B']) == '"A" or "B"' + def test_returns_comma_separated_many_item_list(): assert quoted_or_list(['A', 'B', 'C']) == '"A", "B" or "C"' + def test_limits_to_five_items(): assert quoted_or_list(['A', 'B', 'C', 'D', 'E', 'F']) == '"A", "B", "C", "D" or "E"' diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index bc7f51ac..2dbca1cd 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -161,7 +161,7 @@ def _find_conflicts_within_selection_set(context, cached_fields_and_fragment_nam # selection set to collect conflicts within fragments spread together. # This compares each item in the list of fragment names to every other item # in that same list (except for itself). - for other_fragment_name in fragment_names[i+1:]: + for other_fragment_name in fragment_names[i + 1:]: _collect_conflicts_between_fragments( context, conflicts, @@ -304,7 +304,7 @@ def _collect_conflicts_within(context, conflicts, cached_fields_and_fragment_nam # (except to itself). If the list only has one item, nothing needs to # be compared. for i, field in enumerate(fields): - for other_field in fields[i+1:]: + for other_field in fields[i + 1:]: # within one collection is never mutually exclusive conflict = _find_conflict(context, cached_fields_and_fragment_names, compared_fragments, False, response_name, field, other_field) diff --git a/scripts/casing.py b/scripts/casing.py index 324e6e70..ff74030b 100644 --- a/scripts/casing.py +++ b/scripts/casing.py @@ -5,6 +5,7 @@ # LICENSE file in the root directory of this source tree. An additional grant # of patent rights can be found in the PATENTS file in the same directory. + def title(s): '''Capitalize the first character of s.''' return s[0].capitalize() + s[1:] diff --git a/scripts/generate_ast.py b/scripts/generate_ast.py index 4be8d5a6..9a23a15c 100644 --- a/scripts/generate_ast.py +++ b/scripts/generate_ast.py @@ -20,6 +20,7 @@ 'ArrayValue': 'ListValue', } + def remap_type(typename): return REMAP_TYPES.get(typename, typename) @@ -101,7 +102,7 @@ def _print_copy(self, typename): [field for field in self._fields if not field[2]] + [field for field in self._fields if field[2]]) args = '\n'.join(''' self.{},'''.format(snake(name)) for (type, name, nullable, plural) in fields) - print (''' + print(''' def __copy__(self): return type(self)( {} @@ -139,4 +140,3 @@ def union_option(self, option): def end_union(self, name): self._current_union = None - diff --git a/tox.ini b/tox.ini index 215e2656..a4534498 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = flake8,isort,py27,py33,py34,py35,pypy,docs +envlist = flake8,isort,py27,py33,py34,py35,pre-commit,pypy,docs [testenv] deps = @@ -13,6 +13,14 @@ commands = py{27,33,34,py}: py.test graphql tests {posargs} py35: py.test graphql tests tests_py35 {posargs} +[testenv:pre-commit] +basepython=python3.6 +deps = + pre-commit>0.12.0 +setenv = + LC_CTYPE=en_US.UTF-8 +commands = + pre-commit {posargs:run --all-files} [testenv:flake8] deps = flake8