diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb67b545..f30010f9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,18 +1,23 @@ +repos: - repo: git://github.com/pre-commit/pre-commit-hooks - sha: v0.8.0 + rev: v1.3.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 + exclude: README.md - id: pretty-format-json args: - --autofix - - --indent=4 +- repo: https://github.com/asottile/pyupgrade + rev: v1.4.0 + hooks: + - id: pyupgrade +- repo: https://github.com/ambv/black + rev: 18.6b4 + hooks: + - id: black + language_version: python3.6 diff --git a/conftest.py b/conftest.py index a36e6ba1..6b916378 100644 --- a/conftest.py +++ b/conftest.py @@ -4,11 +4,13 @@ try: import pyannotate_runtime + PYANOTATE_PRESENT = True except ImportError: PYANOTATE_PRESENT = False if PYANOTATE_PRESENT: + def pytest_collection_finish(session): """Handle the pytest collection finish hook: configure pyannotate. Explicitly delay importing `collect_types` until all tests have @@ -16,15 +18,18 @@ def pytest_collection_finish(session): world before importing pyannotate. """ from pyannotate_runtime import collect_types + collect_types.init_types_collection() @pytest.fixture(autouse=True) def collect_types_fixture(): from pyannotate_runtime import collect_types + collect_types.resume() yield collect_types.pause() def pytest_sessionfinish(session, exitstatus): from pyannotate_runtime import collect_types + collect_types.dump_stats("type_info.json") diff --git a/docs/conf.py b/docs/conf.py index dab2d99b..d5c9947c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,51 +19,51 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('..')) +sys.path.insert(0, os.path.abspath("..")) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'graphqllib' -copyright = u'2015, Taeho Kim' -author = u'Taeho Kim' +project = u"graphqllib" +copyright = u"2015, Taeho Kim" +author = u"Taeho Kim" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.1' +version = "0.1" # The full version, including alpha/beta/rc tags. -release = '0.1a0' +release = "0.1a0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -74,37 +74,37 @@ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -114,156 +114,149 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] +# html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'graphqllibdoc' +htmlhelp_basename = "graphqllibdoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # 'preamble': '', + # Latex figure (float) alignment + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'graphqllib.tex', u'graphqllib Documentation', - u'Taeho Kim', 'manual'), + (master_doc, "graphqllib.tex", u"graphqllib Documentation", u"Taeho Kim", "manual") ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'graphqllib', u'graphqllib Documentation', - [author], 1) -] +man_pages = [(master_doc, "graphqllib", u"graphqllib Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -272,23 +265,29 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'graphqllib', u'graphqllib Documentation', - author, 'graphqllib', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "graphqllib", + u"graphqllib Documentation", + author, + "graphqllib", + "One line description of project.", + "Miscellaneous", + ) ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {"https://docs.python.org/": None} diff --git a/graphql/backend/quiver_cloud.py b/graphql/backend/quiver_cloud.py index 280f23d9..2c6796b6 100644 --- a/graphql/backend/quiver_cloud.py +++ b/graphql/backend/quiver_cloud.py @@ -49,7 +49,7 @@ def __init__(self, dsn, python_options=None, **options): else: path = "" - self.api_url = "%s://%s%s" % (url.scheme.rsplit("+", 1)[-1], netloc, path) + self.api_url = "{}://{}{}".format(url.scheme.rsplit("+", 1)[-1], netloc, path) self.public_key = url.username self.secret_key = url.password self.extra_namespace = {} diff --git a/graphql/execution/tests/test_located_error.py b/graphql/execution/tests/test_located_error.py index 26773804..b5bec97f 100644 --- a/graphql/execution/tests/test_located_error.py +++ b/graphql/execution/tests/test_located_error.py @@ -1,8 +1,14 @@ # type: ignore # coding: utf-8 -from graphql import (GraphQLField, GraphQLObjectType, GraphQLSchema, - GraphQLString, execute, parse) +from graphql import ( + GraphQLField, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + execute, + parse, +) from graphql.error import GraphQLLocatedError diff --git a/graphql/language/lexer.py b/graphql/language/lexer.py index a017dbce..a60bc6e2 100644 --- a/graphql/language/lexer.py +++ b/graphql/language/lexer.py @@ -372,7 +372,7 @@ def read_string(source, start): position += 1 if code == 92: # \ - append(body[chunk_start: position - 1]) + append(body[chunk_start : position - 1]) code = char_code_at(body, position) escaped = ESCAPED_CHAR_CODES.get(code) # type: ignore @@ -392,7 +392,7 @@ def read_string(source, start): source, position, u"Invalid character escape sequence: \\u{}.".format( - body[position + 1: position + 5] + body[position + 1 : position + 5] ), ) diff --git a/graphql/pyutils/default_ordered_dict.py b/graphql/pyutils/default_ordered_dict.py index 2408cb43..61f8d67c 100644 --- a/graphql/pyutils/default_ordered_dict.py +++ b/graphql/pyutils/default_ordered_dict.py @@ -42,7 +42,6 @@ def __deepcopy__(self, memo): return self.__class__(self.default_factory, copy.deepcopy(list(self.items()))) def __repr__(self): - return "DefaultOrderedDict(%s, %s)" % ( - self.default_factory, - OrderedDict.__repr__(self)[19:-1], + return "DefaultOrderedDict({}, {})".format( + self.default_factory, OrderedDict.__repr__(self)[19:-1] ) diff --git a/graphql/type/definition.py b/graphql/type/definition.py index ce9dffb5..b4e769ca 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -625,12 +625,13 @@ class GeoPoint(GraphQLInputObjectType): } """ - def __init__(self, - name, # type: str - fields, # type: Union[Callable[[], Dict[str, GraphQLInputObjectField]], Dict[str, GraphQLInputObjectField]] - description=None, # type: Optional[str] - container_type=None, # type: Type[Dict[str, Any]] - ): + def __init__( + self, + name, # type: str + fields, # type: Union[Callable[[], Dict[str, GraphQLInputObjectField]], Dict[str, GraphQLInputObjectField]] + description=None, # type: Optional[str] + container_type=None, # type: Type[Dict[str, Any]] + ): # type: (...) -> None assert name, "Type must be named." self.name = name diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index 4cba7ca2..8506e2cd 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -207,7 +207,7 @@ def _find_conflicts_within_selection_set( # 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, @@ -444,7 +444,7 @@ def _collect_conflicts_within( # (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, diff --git a/scripts/ast.ast b/scripts/ast.ast index e4ff87ee..7b9aa677 100644 --- a/scripts/ast.ast +++ b/scripts/ast.ast @@ -117,7 +117,7 @@ S Type type T NonNullType # JS version prohibits nesting nonnull in nonnull, we can't because we # can't support multiple unions. Fix? -S Type type +S Type type T Name S string value diff --git a/scripts/casing.py b/scripts/casing.py index ff74030b..53c6040f 100644 --- a/scripts/casing.py +++ b/scripts/casing.py @@ -7,23 +7,23 @@ def title(s): - '''Capitalize the first character of s.''' + """Capitalize the first character of s.""" return s[0].capitalize() + s[1:] def camel(s): - '''Lowercase the first character of s.''' + """Lowercase the first character of s.""" return s[0].lower() + s[1:] def snake(s): - '''Convert from title or camelCase to snake_case.''' + """Convert from title or camelCase to snake_case.""" if len(s) < 2: return s.lower() out = s[0].lower() for c in s[1:]: if c.isupper(): - out += '_' + out += "_" c = c.lower() out += c return out diff --git a/scripts/fb_ast.py b/scripts/fb_ast.py index 4093f1eb..f91f2aed 100644 --- a/scripts/fb_ast.py +++ b/scripts/fb_ast.py @@ -19,44 +19,44 @@ def print_ast(lang_module, input_file): while line: line = line.strip() - if line.startswith('#') or not line: + if line.startswith("#") or not line: line = input_file.readline() continue code, rest = line.split(None, 1) - if code[0] == 'T': + if code[0] == "T": lang_module.start_type(rest) field_line = input_file.readline().strip() while field_line: - if field_line.startswith('#'): + if field_line.startswith("#"): field_line = input_file.readline().strip() continue field_kind, field_type, field_name = field_line.split() - nullable = len(field_kind) > 1 and field_kind[1] == '?' + nullable = len(field_kind) > 1 and field_kind[1] == "?" - if field_kind[0] == 'S': + if field_kind[0] == "S": plural = False - elif field_kind[0] == 'P': + elif field_kind[0] == "P": plural = True else: - raise Exception('Unknown field kind: ' + field_kind) + raise Exception("Unknown field kind: " + field_kind) lang_module.field(field_type, field_name, nullable, plural) field_line = input_file.readline().strip() lang_module.end_type(rest) - elif code[0] == 'U': + elif code[0] == "U": lang_module.start_union(rest) field_line = input_file.readline().strip() while field_line: option_code, option_type = field_line.split() - if option_code != 'O': - raise Exception('Unknown code in union: ' + option_code) + if option_code != "O": + raise Exception("Unknown code in union: " + option_code) lang_module.union_option(option_type) field_line = input_file.readline().strip() @@ -68,7 +68,7 @@ def print_ast(lang_module, input_file): lang_module.end_file() -if __name__ == '__main__': +if __name__ == "__main__": import sys lang = sys.argv[1] @@ -76,4 +76,4 @@ def print_ast(lang_module, input_file): lang_module = load_lang(lang) - print_ast(lang_module, open(filename, 'r')) + print_ast(lang_module, open(filename, "r")) diff --git a/scripts/generate_ast.py b/scripts/generate_ast.py index 9a23a15c..06e098a2 100644 --- a/scripts/generate_ast.py +++ b/scripts/generate_ast.py @@ -1,14 +1,15 @@ -if __name__ == '__main__': +if __name__ == "__main__": import os.path import sys import subprocess - project_root = os.path.join(os.path.dirname(__file__), '..') - with open(os.path.join(project_root, 'graphql/core/language/ast.py'), 'w') as fp: + + project_root = os.path.join(os.path.dirname(__file__), "..") + with open(os.path.join(project_root, "graphql/core/language/ast.py"), "w") as fp: process = subprocess.Popen( - ['python', './fb_ast.py', 'generate_ast', './ast.ast'], + ["python", "./fb_ast.py", "generate_ast", "./ast.ast"], stdout=fp, - cwd=os.path.join(project_root, 'scripts'), - env={'PYTHONPATH': '.'} + cwd=os.path.join(project_root, "scripts"), + env={"PYTHONPATH": "."}, ) sys.exit(process.wait()) @@ -16,9 +17,7 @@ from casing import snake # Fix inconsistencies between libgraphqlparser and graphql-js -REMAP_TYPES = { - 'ArrayValue': 'ListValue', -} +REMAP_TYPES = {"ArrayValue": "ListValue"} def remap_type(typename): @@ -32,22 +31,28 @@ def __init__(self): self._fields = [] def start_file(self): - print('''# This is autogenerated code. DO NOT change this manually. + print( + """# This is autogenerated code. DO NOT change this manually. # Run scripts/generate_ast.py to generate this file. class Node(object): - __slots__ = ()''') + __slots__ = ()""" + ) def end_file(self): pass def start_type(self, name): name = remap_type(name) - parent_type = self._parent_types.get(name, 'Node') - print(''' + parent_type = self._parent_types.get(name, "Node") + print( + """ -class {name}({parent_type}):'''.format(name=name, parent_type=parent_type)) +class {name}({parent_type}):""".format( + name=name, parent_type=parent_type + ) + ) def field(self, type, name, nullable, plural): type = remap_type(type) @@ -65,74 +70,111 @@ def end_type(self, typename): self._fields = [] def _print_fields(self): - fields = ', '.join("'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields) - print(''' _fields = ({},)'''.format(fields)) + fields = ", ".join( + "'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields + ) + print(""" _fields = ({},)""".format(fields)) def _print_slots(self): - slots = ', '.join("'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields) - print(''' __slots__ = ('loc', {slots},)'''.format(slots=slots)) + slots = ", ".join( + "'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields + ) + print(""" __slots__ = ('loc', {slots},)""".format(slots=slots)) def _print_ctor(self): - fields = ( - [field for field in self._fields if not field[2]] + - [field for field in self._fields if field[2]]) - ctor_args = ', '.join(snake(name) + ('=None' if nullable else '') for (type, name, nullable, plural) in fields) - print(''' + fields = [field for field in self._fields if not field[2]] + [ + field for field in self._fields if field[2] + ] + ctor_args = ", ".join( + snake(name) + ("=None" if nullable else "") + for (type, name, nullable, plural) in fields + ) + print( + """ def __init__(self, {ctor_args}, loc=None): - self.loc = loc'''.format(ctor_args=ctor_args)) + self.loc = loc""".format( + ctor_args=ctor_args + ) + ) for type, name, nullable, plural in self._fields: - print(''' self.{name} = {name}'''.format(name=snake(name))) + print(""" self.{name} = {name}""".format(name=snake(name))) def _print_comparator(self, typename): - print(''' + print( + """ def __eq__(self, other): return ( self is other or ( isinstance(other, {typename}) and - self.loc == other.loc and'''.format(typename=typename)) - print(' and\n'.join( - ''' self.{name} == other.{name}'''.format(name=snake(name)) - for type, name, nullable, plural in self._fields - )) - print(' )') - print(' )') + self.loc == other.loc and""".format( + typename=typename + ) + ) + print( + " and\n".join( + """ self.{name} == other.{name}""".format( + name=snake(name) + ) + for type, name, nullable, plural in self._fields + ) + ) + print(" )") + print(" )") def _print_copy(self, typename): - fields = ( - [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(''' + fields = [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( + """ def __copy__(self): return type(self)( {} self.loc - )'''.format(args)) + )""".format( + args + ) + ) def _print_repr(self, typename): - print(''' + print( + """ def __repr__(self): - return ('{typename}(' '''.rstrip().format(typename=typename)) + return ('{typename}(' """.rstrip().format( + typename=typename + ) + ) first = True for type, name, nullable, plural in self._fields: - print(" '{comma}{name}={{self.{name}!r}}'".format( - comma=', ' if not first else '', - name=snake(name) - )) + print( + " '{comma}{name}={{self.{name}!r}}'".format( + comma=", " if not first else "", name=snake(name) + ) + ) first = False - print(''' ')').format(self=self)''') + print(""" ')').format(self=self)""") def _print_hash(self): - print(''' + print( + """ def __hash__(self): - return id(self)''') + return id(self)""" + ) def start_union(self, name): self._current_union = name - print(''' + print( + """ class {name}(Node): - __slots__ = ()'''.format(name=name)) + __slots__ = ()""".format( + name=name + ) + ) def union_option(self, option): option = remap_type(option) diff --git a/setup.py b/setup.py index 5edde148..ea36046d 100644 --- a/setup.py +++ b/setup.py @@ -4,89 +4,80 @@ import ast import re -_version_re = re.compile(r'VERSION\s+=\s+(.*)') +_version_re = re.compile(r"VERSION\s+=\s+(.*)") -with open('graphql/__init__.py', 'rb') as f: - version = ast.literal_eval(_version_re.search( - f.read().decode('utf-8')).group(1)) +with open("graphql/__init__.py", "rb") as f: + version = ast.literal_eval(_version_re.search(f.read().decode("utf-8")).group(1)) path_copy = sys.path[:] -sys.path.append('graphql') +sys.path.append("graphql") try: from pyutils.version import get_version + version = get_version(version) except Exception: version = ".".join([str(v) for v in version]) sys.path[:] = path_copy -install_requires = [ - 'six>=1.10.0', - 'promise>=2.1', - 'rx>=1.6.0', -] +install_requires = ["six>=1.10.0", "promise>=2.1", "rx>=1.6.0"] tests_requires = [ - 'pytest==3.0.2', - 'pytest-django==2.9.1', - 'pytest-cov==2.3.1', - 'coveralls', - 'gevent==1.1rc1', - 'six>=1.10.0', - 'pytest-benchmark==3.0.0', - 'pytest-mock==1.2', + "pytest==3.0.2", + "pytest-django==2.9.1", + "pytest-cov==2.3.1", + "coveralls", + "gevent==1.1rc1", + "six>=1.10.0", + "pytest-benchmark==3.0.0", + "pytest-mock==1.2", ] class PyTest(TestCommand): def finalize_options(self): TestCommand.finalize_options(self) - self.test_args = ['graphql', '-vrsx'] + self.test_args = ["graphql", "-vrsx"] self.test_suite = True def run_tests(self): # import here, cause outside the eggs aren't loaded import pytest + errno = pytest.main(self.test_args) sys.exit(errno) setup( - name='graphql-core', + name="graphql-core", version=version, - description='GraphQL implementation for Python', - url='https://github.com/graphql-python/graphql-core', - download_url='https://github.com/graphql-python/graphql-core/releases', - author='Syrus Akbary, Jake Heinz, Taeho Kim', - author_email='me@syrusakbary.com', - license='MIT', + description="GraphQL implementation for Python", + url="https://github.com/graphql-python/graphql-core", + download_url="https://github.com/graphql-python/graphql-core/releases", + author="Syrus Akbary, Jake Heinz, Taeho Kim", + author_email="me@syrusakbary.com", + license="MIT", classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Libraries', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: Implementation :: PyPy', - 'License :: OSI Approved :: MIT License', - 'Topic :: Database :: Front-Ends', - 'Topic :: Internet :: WWW/HTTP', + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: Implementation :: PyPy", + "License :: OSI Approved :: MIT License", + "Topic :: Database :: Front-Ends", + "Topic :: Internet :: WWW/HTTP", ], - keywords='api graphql protocol rest', - packages=find_packages( - exclude=['tests', 'tests_py35', 'tests.*', 'tests_py35.*']), + keywords="api graphql protocol rest", + packages=find_packages(exclude=["tests", "tests_py35", "tests.*", "tests_py35.*"]), install_requires=install_requires, tests_require=tests_requires, - cmdclass={'test': PyTest}, - extras_require={ - 'gevent': [ - 'gevent==1.1rc1' - ], - 'test': tests_requires - } + cmdclass={"test": PyTest}, + extras_require={"gevent": ["gevent==1.1rc1"], "test": tests_requires}, ) diff --git a/tests/starwars/starwars_fixtures.py b/tests/starwars/starwars_fixtures.py index 51f29a59..9007b1a5 100644 --- a/tests/starwars/starwars_fixtures.py +++ b/tests/starwars/starwars_fixtures.py @@ -1,77 +1,64 @@ from collections import namedtuple -Human = namedtuple('Human', 'id name friends appearsIn homePlanet') +Human = namedtuple("Human", "id name friends appearsIn homePlanet") luke = Human( - id='1000', - name='Luke Skywalker', - friends=['1002', '1003', '2000', '2001'], + id="1000", + name="Luke Skywalker", + friends=["1002", "1003", "2000", "2001"], appearsIn=[4, 5, 6], - homePlanet='Tatooine', + homePlanet="Tatooine", ) vader = Human( - id='1001', - name='Darth Vader', - friends=['1004'], + id="1001", + name="Darth Vader", + friends=["1004"], appearsIn=[4, 5, 6], - homePlanet='Tatooine', + homePlanet="Tatooine", ) han = Human( - id='1002', - name='Han Solo', - friends=['1000', '1003', '2001'], + id="1002", + name="Han Solo", + friends=["1000", "1003", "2001"], appearsIn=[4, 5, 6], homePlanet=None, ) leia = Human( - id='1003', - name='Leia Organa', - friends=['1000', '1002', '2000', '2001'], + id="1003", + name="Leia Organa", + friends=["1000", "1002", "2000", "2001"], appearsIn=[4, 5, 6], - homePlanet='Alderaan', + homePlanet="Alderaan", ) tarkin = Human( - id='1004', - name='Wilhuff Tarkin', - friends=['1001'], - appearsIn=[4], - homePlanet=None, + id="1004", name="Wilhuff Tarkin", friends=["1001"], appearsIn=[4], homePlanet=None ) -humanData = { - '1000': luke, - '1001': vader, - '1002': han, - '1003': leia, - '1004': tarkin, -} +humanData = {"1000": luke, "1001": vader, "1002": han, "1003": leia, "1004": tarkin} -Droid = namedtuple('Droid', 'id name friends appearsIn primaryFunction') +Droid = namedtuple("Droid", "id name friends appearsIn primaryFunction") threepio = Droid( - id='2000', - name='C-3PO', - friends=['1000', '1002', '1003', '2001'], + id="2000", + name="C-3PO", + friends=["1000", "1002", "1003", "2001"], appearsIn=[4, 5, 6], - primaryFunction='Protocol', + primaryFunction="Protocol", ) artoo = Droid( - id='2001', - name='R2-D2', - friends=['1000', '1002', '1003'], + id="2001", + name="R2-D2", + friends=["1000", "1002", "1003"], appearsIn=[4, 5, 6], - primaryFunction='Astromech', + primaryFunction="Astromech", ) -droidData = { - '2000': threepio, - '2001': artoo, -} +droidData = {"2000": threepio, "2001": artoo} def getCharacter(id): diff --git a/tests/starwars/starwars_schema.py b/tests/starwars/starwars_schema.py index 74bf4364..a5c2a6f0 100644 --- a/tests/starwars/starwars_schema.py +++ b/tests/starwars/starwars_schema.py @@ -1,145 +1,128 @@ -from graphql.type import (GraphQLArgument, GraphQLEnumType, GraphQLEnumValue, - GraphQLField, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) from .starwars_fixtures import getDroid, getFriends, getHero, getHuman episodeEnum = GraphQLEnumType( - 'Episode', - description='One of the films in the Star Wars Trilogy', + "Episode", + description="One of the films in the Star Wars Trilogy", values={ - 'NEWHOPE': GraphQLEnumValue( - 4, - description='Released in 1977.', - ), - 'EMPIRE': GraphQLEnumValue( - 5, - description='Released in 1980.', - ), - 'JEDI': GraphQLEnumValue( - 6, - description='Released in 1983.', - ) - } + "NEWHOPE": GraphQLEnumValue(4, description="Released in 1977."), + "EMPIRE": GraphQLEnumValue(5, description="Released in 1980."), + "JEDI": GraphQLEnumValue(6, description="Released in 1983."), + }, ) characterInterface = GraphQLInterfaceType( - 'Character', - description='A character in the Star Wars Trilogy', + "Character", + description="A character in the Star Wars Trilogy", fields=lambda: { - 'id': GraphQLField( - GraphQLNonNull(GraphQLString), - description='The id of the character.' + "id": GraphQLField( + GraphQLNonNull(GraphQLString), description="The id of the character." ), - 'name': GraphQLField( - GraphQLString, - description='The name of the character.' - ), - 'friends': GraphQLField( + "name": GraphQLField(GraphQLString, description="The name of the character."), + "friends": GraphQLField( GraphQLList(characterInterface), - description='The friends of the character, or an empty list if they have none.' + description="The friends of the character, or an empty list if they have none.", ), - 'appearsIn': GraphQLField( - GraphQLList(episodeEnum), - description='Which movies they appear in.' + "appearsIn": GraphQLField( + GraphQLList(episodeEnum), description="Which movies they appear in." ), }, - resolve_type=lambda character, info: humanType if getHuman(character.id) else droidType, + resolve_type=lambda character, info: humanType + if getHuman(character.id) + else droidType, ) humanType = GraphQLObjectType( - 'Human', - description='A humanoid creature in the Star Wars universe.', + "Human", + description="A humanoid creature in the Star Wars universe.", fields=lambda: { - 'id': GraphQLField( - GraphQLNonNull(GraphQLString), - description='The id of the human.', - ), - 'name': GraphQLField( - GraphQLString, - description='The name of the human.', + "id": GraphQLField( + GraphQLNonNull(GraphQLString), description="The id of the human." ), - 'friends': GraphQLField( + "name": GraphQLField(GraphQLString, description="The name of the human."), + "friends": GraphQLField( GraphQLList(characterInterface), - description='The friends of the human, or an empty list if they have none.', + description="The friends of the human, or an empty list if they have none.", resolver=lambda human, *_: getFriends(human), ), - 'appearsIn': GraphQLField( - GraphQLList(episodeEnum), - description='Which movies they appear in.', + "appearsIn": GraphQLField( + GraphQLList(episodeEnum), description="Which movies they appear in." ), - 'homePlanet': GraphQLField( + "homePlanet": GraphQLField( GraphQLString, - description='The home planet of the human, or null if unknown.', - ) + description="The home planet of the human, or null if unknown.", + ), }, - interfaces=[characterInterface] + interfaces=[characterInterface], ) droidType = GraphQLObjectType( - 'Droid', - description='A mechanical creature in the Star Wars universe.', + "Droid", + description="A mechanical creature in the Star Wars universe.", fields=lambda: { - 'id': GraphQLField( - GraphQLNonNull(GraphQLString), - description='The id of the droid.', - ), - 'name': GraphQLField( - GraphQLString, - description='The name of the droid.', + "id": GraphQLField( + GraphQLNonNull(GraphQLString), description="The id of the droid." ), - 'friends': GraphQLField( + "name": GraphQLField(GraphQLString, description="The name of the droid."), + "friends": GraphQLField( GraphQLList(characterInterface), - description='The friends of the droid, or an empty list if they have none.', + description="The friends of the droid, or an empty list if they have none.", resolver=lambda droid, info, **args: getFriends(droid), ), - 'appearsIn': GraphQLField( - GraphQLList(episodeEnum), - description='Which movies they appear in.', + "appearsIn": GraphQLField( + GraphQLList(episodeEnum), description="Which movies they appear in." + ), + "primaryFunction": GraphQLField( + GraphQLString, description="The primary function of the droid." ), - 'primaryFunction': GraphQLField( - GraphQLString, - description='The primary function of the droid.', - ) }, - interfaces=[characterInterface] + interfaces=[characterInterface], ) queryType = GraphQLObjectType( - 'Query', + "Query", fields=lambda: { - 'hero': GraphQLField( + "hero": GraphQLField( characterInterface, args={ - 'episode': GraphQLArgument( - description='If omitted, returns the hero of the whole saga. If ' - 'provided, returns the hero of that particular episode.', + "episode": GraphQLArgument( + description="If omitted, returns the hero of the whole saga. If " + "provided, returns the hero of that particular episode.", type=episodeEnum, ) }, - resolver=lambda root, info, **args: getHero(args.get('episode')), + resolver=lambda root, info, **args: getHero(args.get("episode")), ), - 'human': GraphQLField( + "human": GraphQLField( humanType, args={ - 'id': GraphQLArgument( - description='id of the human', - type=GraphQLNonNull(GraphQLString), + "id": GraphQLArgument( + description="id of the human", type=GraphQLNonNull(GraphQLString) ) }, - resolver=lambda root, info, **args: getHuman(args['id']), + resolver=lambda root, info, **args: getHuman(args["id"]), ), - 'droid': GraphQLField( + "droid": GraphQLField( droidType, args={ - 'id': GraphQLArgument( - description='id of the droid', - type=GraphQLNonNull(GraphQLString), + "id": GraphQLArgument( + description="id of the droid", type=GraphQLNonNull(GraphQLString) ) }, - resolver=lambda root, info, **args: getDroid(args['id']), + resolver=lambda root, info, **args: getDroid(args["id"]), ), - } + }, ) StarWarsSchema = GraphQLSchema(query=queryType, types=[humanType, droidType]) diff --git a/tests/starwars/test_introspection.py b/tests/starwars/test_introspection.py index 7cac8a20..f3e07298 100644 --- a/tests/starwars/test_introspection.py +++ b/tests/starwars/test_introspection.py @@ -6,7 +6,7 @@ def test_allows_querying_the_schema_for_types(): - query = ''' + query = """ query IntrospectionTypeQuery { __schema { types { @@ -14,55 +14,25 @@ def test_allows_querying_the_schema_for_types(): } } } - ''' + """ expected = { "__schema": { "types": [ - { - "name": 'Query' - }, - { - "name": 'Episode' - }, - { - "name": 'Character' - }, - { - "name": 'String' - }, - { - "name": 'Human' - }, - { - "name": 'Droid' - }, - { - "name": '__Schema' - }, - { - "name": '__Type' - }, - { - "name": '__TypeKind' - }, - { - "name": 'Boolean' - }, - { - "name": '__Field' - }, - { - "name": '__InputValue' - }, - { - "name": '__EnumValue' - }, - { - "name": '__Directive' - }, - { - "name": '__DirectiveLocation' - } + {"name": "Query"}, + {"name": "Episode"}, + {"name": "Character"}, + {"name": "String"}, + {"name": "Human"}, + {"name": "Droid"}, + {"name": "__Schema"}, + {"name": "__Type"}, + {"name": "__TypeKind"}, + {"name": "Boolean"}, + {"name": "__Field"}, + {"name": "__InputValue"}, + {"name": "__EnumValue"}, + {"name": "__Directive"}, + {"name": "__DirectiveLocation"}, ] } } @@ -73,7 +43,7 @@ def test_allows_querying_the_schema_for_types(): def test_allows_querying_the_schema_for_query_type(): - query = ''' + query = """ query IntrospectionQueryTypeQuery { __schema { queryType { @@ -81,82 +51,62 @@ def test_allows_querying_the_schema_for_query_type(): } } } - ''' + """ - expected = { - '__schema': { - 'queryType': { - 'name': 'Query' - }, - } - } + expected = {"__schema": {"queryType": {"name": "Query"}}} result = graphql(StarWarsSchema, query) assert not result.errors assert contain_subset(result.data, expected) def test_allows_querying_the_schema_for_a_specific_type(): - query = ''' + query = """ query IntrospectionDroidTypeQuery { __type(name: "Droid") { name } } - ''' + """ - expected = { - '__type': { - 'name': 'Droid' - } - } + expected = {"__type": {"name": "Droid"}} result = graphql(StarWarsSchema, query) assert not result.errors assert contain_subset(result.data, expected) def test_allows_querying_the_schema_for_an_object_kind(): - query = ''' + query = """ query IntrospectionDroidKindQuery { __type(name: "Droid") { name kind } } - ''' + """ - expected = { - '__type': { - 'name': 'Droid', - 'kind': 'OBJECT' - } - } + expected = {"__type": {"name": "Droid", "kind": "OBJECT"}} result = graphql(StarWarsSchema, query) assert not result.errors assert contain_subset(result.data, expected) def test_allows_querying_the_schema_for_an_interface_kind(): - query = ''' + query = """ query IntrospectionCharacterKindQuery { __type(name: "Character") { name kind } } - ''' - expected = { - '__type': { - 'name': 'Character', - 'kind': 'INTERFACE' - } - } + """ + expected = {"__type": {"name": "Character", "kind": "INTERFACE"}} result = graphql(StarWarsSchema, query) assert not result.errors assert contain_subset(result.data, expected) def test_allows_querying_the_schema_for_object_fields(): - query = ''' + query = """ query IntrospectionDroidFieldsQuery { __type(name: "Droid") { name @@ -169,48 +119,21 @@ def test_allows_querying_the_schema_for_object_fields(): } } } - ''' + """ expected = { - '__type': { - 'name': 'Droid', - 'fields': [ - { - 'name': 'id', - 'type': { - 'name': None, - 'kind': 'NON_NULL' - } - }, - { - 'name': 'name', - 'type': { - 'name': 'String', - 'kind': 'SCALAR' - } - }, - { - 'name': 'friends', - 'type': { - 'name': None, - 'kind': 'LIST' - } - }, + "__type": { + "name": "Droid", + "fields": [ + {"name": "id", "type": {"name": None, "kind": "NON_NULL"}}, + {"name": "name", "type": {"name": "String", "kind": "SCALAR"}}, + {"name": "friends", "type": {"name": None, "kind": "LIST"}}, + {"name": "appearsIn", "type": {"name": None, "kind": "LIST"}}, { - 'name': 'appearsIn', - 'type': { - 'name': None, - 'kind': 'LIST' - } + "name": "primaryFunction", + "type": {"name": "String", "kind": "SCALAR"}, }, - { - 'name': 'primaryFunction', - 'type': { - 'name': 'String', - 'kind': 'SCALAR' - } - } - ] + ], } } @@ -220,7 +143,7 @@ def test_allows_querying_the_schema_for_object_fields(): def test_allows_querying_the_schema_for_nested_object_fields(): - query = ''' + query = """ query IntrospectionDroidNestedFieldsQuery { __type(name: "Droid") { name @@ -237,62 +160,45 @@ def test_allows_querying_the_schema_for_nested_object_fields(): } } } - ''' + """ expected = { - '__type': { - 'name': 'Droid', - 'fields': [ + "__type": { + "name": "Droid", + "fields": [ { - 'name': 'id', - 'type': { - 'name': None, - 'kind': 'NON_NULL', - 'ofType': { - 'name': 'String', - 'kind': 'SCALAR' - } - } + "name": "id", + "type": { + "name": None, + "kind": "NON_NULL", + "ofType": {"name": "String", "kind": "SCALAR"}, + }, }, { - 'name': 'name', - 'type': { - 'name': 'String', - 'kind': 'SCALAR', - 'ofType': None - } + "name": "name", + "type": {"name": "String", "kind": "SCALAR", "ofType": None}, }, { - 'name': 'friends', - 'type': { - 'name': None, - 'kind': 'LIST', - 'ofType': { - 'name': 'Character', - 'kind': 'INTERFACE' - } - } + "name": "friends", + "type": { + "name": None, + "kind": "LIST", + "ofType": {"name": "Character", "kind": "INTERFACE"}, + }, }, { - 'name': 'appearsIn', - 'type': { - 'name': None, - 'kind': 'LIST', - 'ofType': { - 'name': 'Episode', - 'kind': 'ENUM' - } - } + "name": "appearsIn", + "type": { + "name": None, + "kind": "LIST", + "ofType": {"name": "Episode", "kind": "ENUM"}, + }, }, { - 'name': 'primaryFunction', - 'type': { - 'name': 'String', - 'kind': 'SCALAR', - 'ofType': None - } - } - ] + "name": "primaryFunction", + "type": {"name": "String", "kind": "SCALAR", "ofType": None}, + }, + ], } } result = graphql(StarWarsSchema, query) @@ -301,7 +207,7 @@ def test_allows_querying_the_schema_for_nested_object_fields(): def test_allows_querying_the_schema_for_field_args(): - query = ''' + query = """ query IntrospectionQueryTypeQuery { __schema { queryType { @@ -324,65 +230,59 @@ def test_allows_querying_the_schema_for_field_args(): } } } - ''' + """ expected = { - '__schema': { - 'queryType': { - 'fields': [ + "__schema": { + "queryType": { + "fields": [ { - 'name': 'hero', - 'args': [ + "name": "hero", + "args": [ { - 'defaultValue': None, - 'description': 'If omitted, returns the hero of the whole ' + - 'saga. If provided, returns the hero of ' + - 'that particular episode.', - 'name': 'episode', - 'type': { - 'kind': 'ENUM', - 'name': 'Episode', - 'ofType': None - } + "defaultValue": None, + "description": "If omitted, returns the hero of the whole " + + "saga. If provided, returns the hero of " + + "that particular episode.", + "name": "episode", + "type": { + "kind": "ENUM", + "name": "Episode", + "ofType": None, + }, } - ] + ], }, { - 'name': 'human', - 'args': [ + "name": "human", + "args": [ { - 'name': 'id', - 'description': 'id of the human', - 'type': { - 'kind': 'NON_NULL', - 'name': None, - 'ofType': { - 'kind': 'SCALAR', - 'name': 'String' - } + "name": "id", + "description": "id of the human", + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": {"kind": "SCALAR", "name": "String"}, }, - 'defaultValue': None + "defaultValue": None, } - ] + ], }, { - 'name': 'droid', - 'args': [ + "name": "droid", + "args": [ { - 'name': 'id', - 'description': 'id of the droid', - 'type': { - 'kind': 'NON_NULL', - 'name': None, - 'ofType': { - 'kind': 'SCALAR', - 'name': 'String' - } + "name": "id", + "description": "id of the droid", + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": {"kind": "SCALAR", "name": "String"}, }, - 'defaultValue': None + "defaultValue": None, } - ] - } + ], + }, ] } } @@ -394,19 +294,19 @@ def test_allows_querying_the_schema_for_field_args(): def test_allows_querying_the_schema_for_documentation(): - query = ''' + query = """ query IntrospectionDroidDescriptionQuery { __type(name: "Droid") { name description } } - ''' + """ expected = { - '__type': { - 'name': 'Droid', - 'description': 'A mechanical creature in the Star Wars universe.' + "__type": { + "name": "Droid", + "description": "A mechanical creature in the Star Wars universe.", } } result = graphql(StarWarsSchema, query) diff --git a/tests/starwars/test_query.py b/tests/starwars/test_query.py index 81a20c99..5e3c2cd0 100644 --- a/tests/starwars/test_query.py +++ b/tests/starwars/test_query.py @@ -5,25 +5,21 @@ def test_hero_name_query(): - query = ''' + query = """ query HeroNameQuery { hero { name } } - ''' - expected = { - 'hero': { - 'name': 'R2-D2' - } - } + """ + expected = {"hero": {"name": "R2-D2"}} result = graphql(StarWarsSchema, query) assert not result.errors assert result.data == expected def test_hero_name_and_friends_query(): - query = ''' + query = """ query HeroNameAndFriendsQuery { hero { id @@ -33,16 +29,16 @@ def test_hero_name_and_friends_query(): } } } - ''' + """ expected = { - 'hero': { - 'id': '2001', - 'name': 'R2-D2', - 'friends': [ - {'name': 'Luke Skywalker'}, - {'name': 'Han Solo'}, - {'name': 'Leia Organa'}, - ] + "hero": { + "id": "2001", + "name": "R2-D2", + "friends": [ + {"name": "Luke Skywalker"}, + {"name": "Han Solo"}, + {"name": "Leia Organa"}, + ], } } result = graphql(StarWarsSchema, query) @@ -51,7 +47,7 @@ def test_hero_name_and_friends_query(): def test_nested_query(): - query = ''' + query = """ query NestedQuery { hero { name @@ -64,63 +60,41 @@ def test_nested_query(): } } } - ''' + """ expected = { - 'hero': { - 'name': 'R2-D2', - 'friends': [ + "hero": { + "name": "R2-D2", + "friends": [ { - 'name': 'Luke Skywalker', - 'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI'], - 'friends': [ - { - 'name': 'Han Solo', - }, - { - 'name': 'Leia Organa', - }, - { - 'name': 'C-3PO', - }, - { - 'name': 'R2-D2', - }, - ] + "name": "Luke Skywalker", + "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], + "friends": [ + {"name": "Han Solo"}, + {"name": "Leia Organa"}, + {"name": "C-3PO"}, + {"name": "R2-D2"}, + ], }, { - 'name': 'Han Solo', - 'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI'], - 'friends': [ - { - 'name': 'Luke Skywalker', - }, - { - 'name': 'Leia Organa', - }, - { - 'name': 'R2-D2', - }, - ] + "name": "Han Solo", + "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], + "friends": [ + {"name": "Luke Skywalker"}, + {"name": "Leia Organa"}, + {"name": "R2-D2"}, + ], }, { - 'name': 'Leia Organa', - 'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI'], - 'friends': [ - { - 'name': 'Luke Skywalker', - }, - { - 'name': 'Han Solo', - }, - { - 'name': 'C-3PO', - }, - { - 'name': 'R2-D2', - }, - ] + "name": "Leia Organa", + "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], + "friends": [ + {"name": "Luke Skywalker"}, + {"name": "Han Solo"}, + {"name": "C-3PO"}, + {"name": "R2-D2"}, + ], }, - ] + ], } } result = graphql(StarWarsSchema, query) @@ -129,104 +103,80 @@ def test_nested_query(): def test_fetch_luke_query(): - query = ''' + query = """ query FetchLukeQuery { human(id: "1000") { name } } - ''' - expected = { - 'human': { - 'name': 'Luke Skywalker', - } - } + """ + expected = {"human": {"name": "Luke Skywalker"}} result = graphql(StarWarsSchema, query) assert not result.errors assert result.data == expected def test_fetch_some_id_query(): - query = ''' + query = """ query FetchSomeIDQuery($someId: String!) { human(id: $someId) { name } } - ''' - params = { - 'someId': '1000', - } - expected = { - 'human': { - 'name': 'Luke Skywalker', - } - } + """ + params = {"someId": "1000"} + expected = {"human": {"name": "Luke Skywalker"}} result = graphql(StarWarsSchema, query, variable_values=params) assert not result.errors assert result.data == expected def test_fetch_some_id_query2(): - query = ''' + query = """ query FetchSomeIDQuery($someId: String!) { human(id: $someId) { name } } - ''' - params = { - 'someId': '1002', - } - expected = { - 'human': { - 'name': 'Han Solo', - } - } + """ + params = {"someId": "1002"} + expected = {"human": {"name": "Han Solo"}} result = graphql(StarWarsSchema, query, variable_values=params) assert not result.errors assert result.data == expected def test_invalid_id_query(): - query = ''' + query = """ query humanQuery($id: String!) { human(id: $id) { name } } - ''' - params = { - 'id': 'not a valid id', - } - expected = { - 'human': None - } + """ + params = {"id": "not a valid id"} + expected = {"human": None} result = graphql(StarWarsSchema, query, variable_values=params) assert not result.errors assert result.data == expected def test_fetch_luke_aliased(): - query = ''' + query = """ query FetchLukeAliased { luke: human(id: "1000") { name } } - ''' - expected = { - 'luke': { - 'name': 'Luke Skywalker', - } - } + """ + expected = {"luke": {"name": "Luke Skywalker"}} result = graphql(StarWarsSchema, query) assert not result.errors assert result.data == expected def test_fetch_luke_and_leia_aliased(): - query = ''' + query = """ query FetchLukeAndLeiaAliased { luke: human(id: "1000") { name @@ -235,22 +185,15 @@ def test_fetch_luke_and_leia_aliased(): name } } - ''' - expected = { - 'luke': { - 'name': 'Luke Skywalker', - }, - 'leia': { - 'name': 'Leia Organa', - } - } + """ + expected = {"luke": {"name": "Luke Skywalker"}, "leia": {"name": "Leia Organa"}} result = graphql(StarWarsSchema, query) assert not result.errors assert result.data == expected def test_duplicate_fields(): - query = ''' + query = """ query DuplicateFields { luke: human(id: "1000") { name @@ -261,16 +204,10 @@ def test_duplicate_fields(): homePlanet } } - ''' + """ expected = { - 'luke': { - 'name': 'Luke Skywalker', - 'homePlanet': 'Tatooine', - }, - 'leia': { - 'name': 'Leia Organa', - 'homePlanet': 'Alderaan', - } + "luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"}, + "leia": {"name": "Leia Organa", "homePlanet": "Alderaan"}, } result = graphql(StarWarsSchema, query) assert not result.errors @@ -278,7 +215,7 @@ def test_duplicate_fields(): def test_use_fragment(): - query = ''' + query = """ query UseFragment { luke: human(id: "1000") { ...HumanFragment @@ -291,16 +228,10 @@ def test_use_fragment(): name homePlanet } - ''' + """ expected = { - 'luke': { - 'name': 'Luke Skywalker', - 'homePlanet': 'Tatooine', - }, - 'leia': { - 'name': 'Leia Organa', - 'homePlanet': 'Alderaan', - } + "luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"}, + "leia": {"name": "Leia Organa", "homePlanet": "Alderaan"}, } result = graphql(StarWarsSchema, query) assert not result.errors @@ -308,52 +239,45 @@ def test_use_fragment(): def test_check_type_of_r2(): - query = ''' + query = """ query CheckTypeOfR2 { hero { __typename name } } - ''' - expected = { - 'hero': { - '__typename': 'Droid', - 'name': 'R2-D2', - } - } + """ + expected = {"hero": {"__typename": "Droid", "name": "R2-D2"}} result = graphql(StarWarsSchema, query) assert not result.errors assert result.data == expected def test_check_type_of_luke(): - query = ''' + query = """ query CheckTypeOfLuke { hero(episode: EMPIRE) { __typename name } } - ''' - expected = { - 'hero': { - '__typename': 'Human', - 'name': 'Luke Skywalker', - } - } + """ + expected = {"hero": {"__typename": "Human", "name": "Luke Skywalker"}} result = graphql(StarWarsSchema, query) assert not result.errors assert result.data == expected def test_parse_error(): - query = ''' + query = """ qeury - ''' + """ result = graphql(StarWarsSchema, query) assert result.invalid formatted_error = format_error(result.errors[0]) - assert formatted_error['locations'] == [{'column': 9, 'line': 2}] - assert 'Syntax Error GraphQL (2:9) Unexpected Name "qeury"' in formatted_error['message'] + assert formatted_error["locations"] == [{"column": 9, "line": 2}] + assert ( + 'Syntax Error GraphQL (2:9) Unexpected Name "qeury"' + in formatted_error["message"] + ) assert result.data is None diff --git a/tests/starwars/test_validation.py b/tests/starwars/test_validation.py index 538297cd..3e389d53 100644 --- a/tests/starwars/test_validation.py +++ b/tests/starwars/test_validation.py @@ -6,13 +6,13 @@ def validation_errors(query): - source = Source(query, 'StarWars.graphql') + source = Source(query, "StarWars.graphql") ast = parse(source) return validate(StarWarsSchema, ast) def test_nested_query_with_fragment(): - query = ''' + query = """ query NestedQueryWithFragment { hero { ...NameAndAppearances @@ -28,32 +28,32 @@ def test_nested_query_with_fragment(): name appearsIn } - ''' + """ assert not validation_errors(query) def test_non_existent_fields(): - query = ''' + query = """ query HeroSpaceshipQuery { hero { favoriteSpaceship } } - ''' + """ assert validation_errors(query) def test_require_fields_on_object(): - query = ''' + query = """ query HeroNoFieldsQuery { hero } - ''' + """ assert validation_errors(query) def test_disallows_fields_on_scalars(): - query = ''' + query = """ query HeroFieldsOnScalarQuery { hero { name { @@ -61,24 +61,24 @@ def test_disallows_fields_on_scalars(): } } } - ''' + """ assert validation_errors(query) def test_disallows_object_fields_on_interfaces(): - query = ''' + query = """ query DroidFieldOnCharacter { hero { name primaryFunction } } - ''' + """ assert validation_errors(query) def test_allows_object_fields_in_fragments(): - query = ''' + query = """ query DroidFieldInFragment { hero { name @@ -88,12 +88,12 @@ def test_allows_object_fields_in_fragments(): fragment DroidFields on Droid { primaryFunction } - ''' + """ assert not validation_errors(query) def test_allows_object_fields_in_inline_fragments(): - query = ''' + query = """ query DroidFieldInFragment { hero { name @@ -104,5 +104,5 @@ def test_allows_object_fields_in_inline_fragments(): fragment DroidFields on Droid { primaryFunction } - ''' + """ assert not validation_errors(query) diff --git a/tests_py35/core_execution/__init__.py b/tests_py35/core_execution/__init__.py index 9db7df9a..8d60ccb1 100644 --- a/tests_py35/core_execution/__init__.py +++ b/tests_py35/core_execution/__init__.py @@ -1 +1 @@ -__author__ = 'jake' +__author__ = "jake" diff --git a/tests_py35/core_execution/test_asyncio_executor.py b/tests_py35/core_execution/test_asyncio_executor.py index b89d2f35..8d5334d5 100644 --- a/tests_py35/core_execution/test_asyncio_executor.py +++ b/tests_py35/core_execution/test_asyncio_executor.py @@ -6,90 +6,101 @@ from graphql.execution import execute from graphql.language.parser import parse from graphql.execution.executors.asyncio import AsyncioExecutor -from graphql.type import ( - GraphQLSchema, - GraphQLObjectType, - GraphQLField, - GraphQLString -) +from graphql.type import GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString def test_asyncio_py35_executor(): - ast = parse('query Example { a, b, c }') + ast = parse("query Example { a, b, c }") async def resolver(context, *_): await asyncio.sleep(0.001) - return 'hey' + return "hey" async def resolver_2(context, *_): await asyncio.sleep(0.003) - return 'hey2' + return "hey2" def resolver_3(context, *_): - return 'hey3' + return "hey3" - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2), - 'c': GraphQLField(GraphQLString, resolver=resolver_3) - }) + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + "c": GraphQLField(GraphQLString, resolver=resolver_3), + }, + ) result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor()) assert not result.errors - assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'} + assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"} def test_asyncio_py35_executor_return_promise(): - ast = parse('query Example { a, b, c }') + ast = parse("query Example { a, b, c }") async def resolver(context, *_): await asyncio.sleep(0.001) - return 'hey' + return "hey" async def resolver_2(context, *_): await asyncio.sleep(0.003) - return 'hey2' + return "hey2" def resolver_3(context, *_): - return 'hey3' + return "hey3" - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2), - 'c': GraphQLField(GraphQLString, resolver=resolver_3) - }) + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + "c": GraphQLField(GraphQLString, resolver=resolver_3), + }, + ) loop = asyncio.get_event_loop() async def do_exec(): - result = await execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor(loop), return_promise=True) + result = await execute( + GraphQLSchema(Type), + ast, + executor=AsyncioExecutor(loop), + return_promise=True, + ) assert not result.errors - assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'} + assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"} loop.run_until_complete(do_exec()) def test_asyncio_py35_executor_with_error(): - ast = parse('query Example { a, b }') + ast = parse("query Example { a, b }") async def resolver(context, *_): await asyncio.sleep(0.001) - return 'hey' + return "hey" async def resolver_2(context, *_): await asyncio.sleep(0.003) - raise Exception('resolver_2 failed!') + raise Exception("resolver_2 failed!") - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2) - }) + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + }, + ) result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor()) formatted_errors = list(map(format_error, result.errors)) - assert formatted_errors == [{ - 'locations': [{'line': 1, 'column': 20}], - 'path': ['b'], - 'message': 'resolver_2 failed!' - }] - assert result.data == {'a': 'hey', 'b': None} + assert formatted_errors == [ + { + "locations": [{"line": 1, "column": 20}], + "path": ["b"], + "message": "resolver_2 failed!", + } + ] + assert result.data == {"a": "hey", "b": None}