├── .gitignore ├── .travis.yml ├── AUTHORS ├── LICENSE ├── MANIFEST.in ├── README.rst ├── graphql ├── __init__.py ├── ast.py ├── exceptions.py ├── lexer.py ├── parser.py └── parsetab.py ├── requirements.txt ├── setup.py └── tests ├── __init__.py ├── test_ast.py ├── test_lexer.py └── test_parser.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # Packages 4 | *.egg 5 | *.egg-info 6 | dist 7 | build 8 | 9 | # Installer logs 10 | pip-log.txt 11 | 12 | # Unit test / coverage reports 13 | .coverage 14 | .tox 15 | nosetests.xml 16 | 17 | # PyCharm 18 | .idea 19 | 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.7 4 | - 3.4 5 | - 3.5 6 | - 3.6 7 | - 3.7 8 | - 3.8 9 | - 3.9 10 | - "pypy" 11 | install: 12 | - pip install ply==3.11 13 | script: nosetests 14 | notifications: 15 | slack: ivelum:m5sGlwz1uEy5sQ32n0kg9lNh 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Created by Denis Stebunov 2 | 3 | Bug reports, suggestions and patches: 4 | - R. Rigdon 5 | - Josh Miller 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 ivelum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst LICENSE -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | graphql-py 2 | ========== 3 | 4 | .. image:: https://travis-ci.org/ivelum/graphql-py.svg?branch=master 5 | :target: https://travis-ci.org/ivelum/graphql-py 6 | 7 | GraphQL lexer and parser written in pure Python, produces AST. Features: 8 | 9 | * Complies with latest `working draft of GraphQL specification`_; 10 | * Fast enough, built on `PLY`_; 11 | * Tested vs. Python 2.7, 3.4 - 3.9, and PyPy 12 | 13 | .. _working draft of GraphQL specification: https://facebook.github.io/graphql/ 14 | .. _PLY: http://www.dabeaz.com/ply/ 15 | 16 | Installation 17 | ------------ 18 | 19 | .. code:: shell 20 | 21 | $ pip install graphql-py 22 | 23 | Usage 24 | ----- 25 | 26 | .. code:: shell 27 | 28 | from graphql.parser import GraphQLParser 29 | 30 | parser = GraphQLParser() 31 | ast = parser.parse(""" 32 | query UserQuery { 33 | user(id: 4) { 34 | id 35 | name 36 | profilePic 37 | avatar: profilePic(width: 30, height: 30) 38 | } 39 | } 40 | """) 41 | print(ast) 42 | 43 | License 44 | ------- 45 | 46 | MIT 47 | -------------------------------------------------------------------------------- /graphql/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.8.1' 2 | -------------------------------------------------------------------------------- /graphql/ast.py: -------------------------------------------------------------------------------- 1 | class Node(object): 2 | def __str__(self): 3 | children = [] 4 | for k, v in self.__dict__.items(): 5 | if v: 6 | if isinstance(v, (list, tuple)): 7 | v = '[%s]' % ', '.join([str(v) for v in v if v]) 8 | children.append('%s=%s' % (k, v)) 9 | return u'<%s%s%s>' % ( 10 | self.__class__.__name__, 11 | ': ' if children else '', 12 | ', '.join(children), 13 | ) 14 | 15 | __repr__ = __str__ 16 | 17 | def __eq__(self, other): 18 | if not isinstance(other, self.__class__): 19 | return False 20 | for k, v in self.__dict__.items(): 21 | if getattr(other, k) != v: 22 | return False 23 | return True 24 | 25 | def __ne__(self, other): 26 | return not self.__eq__(other) 27 | 28 | 29 | class Document(Node): 30 | def __init__(self, definitions=None): 31 | self.definitions = definitions or [] 32 | 33 | 34 | class Definition(Node): 35 | pass 36 | 37 | 38 | class FragmentDefinition(Definition): 39 | def __init__(self, name, type_condition, selections, directives=None): 40 | self.name = name 41 | self.type_condition = type_condition 42 | self.selections = selections 43 | self.directives = directives or [] 44 | 45 | 46 | class OperationDefinition(Definition): 47 | def __init__(self, selections, name=None, variable_definitions=None, 48 | directives=None): 49 | self.selections = selections 50 | self.name = name 51 | self.variable_definitions = variable_definitions or [] 52 | self.directives = directives or [] 53 | 54 | 55 | class Query(OperationDefinition): 56 | pass 57 | 58 | 59 | class Mutation(OperationDefinition): 60 | pass 61 | 62 | 63 | class Subscription(OperationDefinition): 64 | pass 65 | 66 | 67 | class Selection(Node): 68 | pass 69 | 70 | 71 | class Field(Selection): 72 | def __init__(self, name, alias=None, arguments=None, directives=None, 73 | selections=None): 74 | self.name = name 75 | self.alias = alias 76 | self.arguments = arguments or [] 77 | self.directives = directives or [] 78 | self.selections = selections or [] 79 | 80 | 81 | class FragmentSpread(Selection): 82 | def __init__(self, name, directives=None): 83 | self.name = name 84 | self.directives = directives or [] 85 | 86 | 87 | class InlineFragment(Selection): 88 | def __init__(self, type_condition, selections, directives=None): 89 | self.type_condition = type_condition 90 | self.selections = selections 91 | self.directives = directives or [] 92 | 93 | 94 | class Argument(Node): 95 | def __init__(self, name, value): 96 | self.name = name 97 | self.value = value 98 | 99 | 100 | class Value(Node): 101 | def __init__(self, value): 102 | self.value = value 103 | 104 | 105 | class VariableDefinition(Value): 106 | def __init__(self, name, type, default_value=None): 107 | self.name = name 108 | self.type = type 109 | self.default_value = default_value 110 | 111 | 112 | class Variable(Value): 113 | def __init__(self, name): 114 | self.name = name 115 | 116 | 117 | class Directive(Node): 118 | def __init__(self, name, arguments=None): 119 | self.name = name 120 | self.arguments = arguments or [] 121 | 122 | 123 | class Type(Node): 124 | pass 125 | 126 | 127 | class NamedType(Type): 128 | def __init__(self, name): 129 | self.name = name 130 | 131 | 132 | class ListType(Type): 133 | def __init__(self, type): 134 | self.type = type 135 | 136 | 137 | class NonNullType(Type): 138 | def __init__(self, type): 139 | self.type = type 140 | 141 | 142 | class TypeCondition(NamedType): 143 | pass 144 | -------------------------------------------------------------------------------- /graphql/exceptions.py: -------------------------------------------------------------------------------- 1 | class ParseError(Exception): 2 | def __init__(self, message=None, value=None, line=None, column=None): 3 | self.value = value 4 | self.line = line 5 | self.column = column 6 | super(ParseError, self).__init__(message) 7 | 8 | def __str__(self): 9 | message = super(ParseError, self).__str__() 10 | if self.line: 11 | position_info = 'Line %s' % self.line 12 | if self.column: 13 | position_info += ', col %s' % self.column 14 | return '%s: %s' % (position_info, message) 15 | else: 16 | return message 17 | 18 | 19 | class LexerError(ParseError): 20 | pass 21 | 22 | 23 | class SyntaxError(ParseError): 24 | pass 25 | -------------------------------------------------------------------------------- /graphql/lexer.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | from decimal import Decimal 3 | 4 | import ply.lex as lex 5 | from ply.lex import TOKEN 6 | 7 | from .exceptions import LexerError 8 | 9 | 10 | class GraphQLLexer(object): 11 | """ 12 | GraphQL lexer with PLY-compatible interface for usage with PLY-yacc. 13 | 14 | Usage example: 15 | 16 | lexer = GraphQLLexer() 17 | lexer.input(some_text) 18 | for token in lexer: 19 | print token.type, token.value 20 | 21 | To use it with yacc, pass instance of GraphQLLexer to yacc.parse() method: 22 | 23 | lexer = GraphQLLexer() 24 | yacc.parse(input=some_text, lexer=lexer) 25 | 26 | """ 27 | def __init__(self, **kwargs): 28 | self._lexer = lex.lex(module=self, **kwargs) 29 | self.reset() 30 | 31 | def reset(self): 32 | self.text = '' 33 | self._lexer.lineno = 1 34 | return self 35 | 36 | def input(self, s): 37 | self.reset() 38 | self.text = s 39 | self._lexer.input(s) 40 | return self 41 | 42 | def token(self): 43 | return self._lexer.token() 44 | 45 | # Iterator interface 46 | def __iter__(self): 47 | return self 48 | 49 | def next(self): 50 | t = self.token() 51 | if t is None: 52 | raise StopIteration 53 | return t 54 | 55 | __next__ = next 56 | 57 | def find_column(self, t): 58 | """ 59 | Returns token position in current text, starting from 1 60 | """ 61 | cr = max(self.text.rfind(l, 0, t.lexpos) for l in self.line_terminators) 62 | if cr == -1: 63 | return t.lexpos + 1 64 | return t.lexpos - cr 65 | 66 | whitespace = ' \t\v\f\u00A0' 67 | line_terminators = '\n\r\u2028\u2029' 68 | comma = ',' 69 | 70 | re_line_terminators = r'\n\r\u2028\u2029' 71 | 72 | re_escaped_char = r'\\[\"\\/bfnrt]' 73 | re_escaped_unicode = r'\\u[0-9A-Fa-f]{4}' 74 | re_string_char = r'[^\"\\' + re_line_terminators + u']' 75 | 76 | re_int_value = r'(-?0|-?[1-9][0-9]*)' 77 | re_fraction_part = r'\.[0-9]+' 78 | re_exponent_part = r'[eE][\+-]?[0-9]+' 79 | 80 | tokens = [ 81 | 'NAME', 82 | 'FRAGMENT', 83 | 'QUERY', 84 | 'MUTATION', 85 | 'SUBSCRIPTION', 86 | 'ON', 87 | 'TRUE', 88 | 'FALSE', 89 | 'NULL', 90 | 'STRING_VALUE', 91 | 'FLOAT_VALUE', 92 | 'INT_VALUE', 93 | 'BANG', 94 | 'DOLLAR', 95 | 'PAREN_L', 96 | 'PAREN_R', 97 | 'COLON', 98 | 'EQUALS', 99 | 'AT', 100 | 'BRACKET_L', 101 | 'BRACKET_R', 102 | 'BRACE_L', 103 | 'BRACE_R', 104 | 'SPREAD', 105 | ] 106 | 107 | t_BANG = '!' 108 | t_DOLLAR = r'\$' 109 | t_PAREN_L = r'\(' 110 | t_PAREN_R = r'\)' 111 | t_COLON = ':' 112 | t_EQUALS = '=' 113 | t_AT = '@' 114 | t_BRACKET_L = r'\[' 115 | t_BRACKET_R = r'\]' 116 | t_BRACE_L = r'\{' 117 | t_BRACE_R = r'\}' 118 | t_SPREAD = r'\.\.\.' 119 | 120 | t_NAME = r'[_A-Za-z][_0-9A-Za-z]*' 121 | 122 | t_ignore = whitespace + comma 123 | 124 | @TOKEN(r'\#[^' + re_line_terminators + ']*') 125 | def t_COMMENT(self, t): 126 | return # return nothing, ignore comments 127 | 128 | @TOKEN(r'\"(' + re_escaped_char + 129 | '|' + re_escaped_unicode + 130 | '|' + re_string_char + r')*\"') 131 | def t_STRING_VALUE(self, t): 132 | t.value = t.value[1:-1] # cut leading and trailing quotes "" 133 | return t 134 | 135 | @TOKEN(re_int_value + re_fraction_part + re_exponent_part + '|' + 136 | re_int_value + re_fraction_part + '|' + 137 | re_int_value + re_exponent_part) 138 | def t_FLOAT_VALUE(self, t): 139 | t.value = Decimal(t.value) 140 | return t 141 | 142 | @TOKEN(re_int_value) 143 | def t_INT_VALUE(self, t): 144 | t.value = int(t.value) 145 | return t 146 | 147 | not_followed_by_name = '(?![_0-9A-Za-z])' 148 | 149 | @TOKEN('fragment' + not_followed_by_name) 150 | def t_FRAGMENT(self, t): 151 | return t 152 | 153 | @TOKEN('query' + not_followed_by_name) 154 | def t_QUERY(self, t): 155 | return t 156 | 157 | @TOKEN('mutation' + not_followed_by_name) 158 | def t_MUTATION(self, t): 159 | return t 160 | 161 | @TOKEN('subscription' + not_followed_by_name) 162 | def t_SUBSCRIPTION(self, t): 163 | return t 164 | 165 | @TOKEN('on' + not_followed_by_name) 166 | def t_ON(self, t): 167 | return t 168 | 169 | @TOKEN('true' + not_followed_by_name) 170 | def t_TRUE(self, t): 171 | t.value = True 172 | return t 173 | 174 | @TOKEN('false' + not_followed_by_name) 175 | def t_FALSE(self, t): 176 | t.value = False 177 | return t 178 | 179 | @TOKEN('null' + not_followed_by_name) 180 | def t_NULL(self, t): 181 | t.value = None 182 | return t 183 | 184 | def t_error(self, t): 185 | raise LexerError( 186 | message='Illegal character %s' % repr(t.value[0]), 187 | value=t.value, 188 | line=t.lineno, 189 | column=self.find_column(t), 190 | ) 191 | 192 | @TOKEN('[' + re_line_terminators + ']+') 193 | def t_newline(self, t): 194 | t.lexer.lineno += len(t.value) 195 | return 196 | -------------------------------------------------------------------------------- /graphql/parser.py: -------------------------------------------------------------------------------- 1 | import ply.yacc as yacc 2 | 3 | from .ast import * # noqa 4 | from .exceptions import SyntaxError 5 | from .lexer import GraphQLLexer 6 | 7 | 8 | class GraphQLParser(object): 9 | """ 10 | GraphQL parser, builds AST. 11 | 12 | Can be used with any PLY-compatible lexer, by default uses GraphQLLexer. 13 | 14 | Usage example: 15 | 16 | parser = GraphQLParser() 17 | document = parser.parse(some_text) 18 | 19 | Use with custom lexer: 20 | 21 | parser = GraphQLParser() 22 | document = parser.parse(some_text, lexer=my_lexer) 23 | 24 | Note that custom lexer must provide the same set of tokens as defined in 25 | GraphQLLexer.tokens. 26 | 27 | """ 28 | def __init__(self, debug=False, **kwargs): 29 | self.default_lexer = GraphQLLexer() 30 | self.tokens = self.default_lexer.tokens 31 | kwargs['debug'] = debug 32 | self.yacc = yacc.yacc(module=self, **kwargs) 33 | 34 | def parse(self, input=None, lexer=None, **kwargs): 35 | lexer = lexer or self.default_lexer 36 | return self.yacc.parse(input=input, lexer=lexer, **kwargs) 37 | 38 | start = 'document' 39 | 40 | def p_document(self, p): 41 | """ 42 | document : definition_list 43 | """ 44 | p[0] = Document(definitions=p[1]) 45 | 46 | def p_document_shorthand(self, p): 47 | """ 48 | document : selection_set 49 | """ 50 | p[0] = Document(definitions=[Query(selections=p[1])]) 51 | 52 | def p_document_shorthand_with_fragments(self, p): 53 | """ 54 | document : selection_set fragment_list 55 | """ 56 | p[0] = Document(definitions=[Query(selections=p[1])] + p[2]) 57 | 58 | def p_fragment_list(self, p): 59 | """ 60 | fragment_list : fragment_list fragment_definition 61 | """ 62 | p[0] = p[1] + [p[2]] 63 | 64 | def p_fragment_list_single(self, p): 65 | """ 66 | fragment_list : fragment_definition 67 | """ 68 | p[0] = [p[1]] 69 | 70 | def p_definition_list(self, p): 71 | """ 72 | definition_list : definition_list definition 73 | """ 74 | p[0] = p[1] + [p[2]] 75 | 76 | def p_definition_list_single(self, p): 77 | """ 78 | definition_list : definition 79 | """ 80 | p[0] = [p[1]] 81 | 82 | def p_definition(self, p): 83 | """ 84 | definition : operation_definition 85 | | fragment_definition 86 | """ 87 | p[0] = p[1] 88 | 89 | def operation_cls(self, operation_type): 90 | if operation_type == 'query': 91 | return Query 92 | elif operation_type == 'mutation': 93 | return Mutation 94 | elif operation_type == 'subscription': 95 | return Subscription 96 | 97 | def p_operation_definition1(self, p): 98 | """ 99 | operation_definition : operation_type name variable_definitions directives selection_set 100 | """ 101 | p[0] = self.operation_cls(p[1])( 102 | selections=p[5], 103 | name=p[2], 104 | variable_definitions=p[3], 105 | directives=p[4], 106 | ) 107 | 108 | def p_operation_definition2(self, p): 109 | """ 110 | operation_definition : operation_type name variable_definitions selection_set 111 | """ 112 | p[0] = self.operation_cls(p[1])( 113 | selections=p[4], 114 | name=p[2], 115 | variable_definitions=p[3], 116 | ) 117 | 118 | def p_operation_definition3(self, p): 119 | """ 120 | operation_definition : operation_type name directives selection_set 121 | """ 122 | p[0] = self.operation_cls(p[1])( 123 | selections=p[4], 124 | name=p[2], 125 | directives=p[3], 126 | ) 127 | 128 | def p_operation_definition4(self, p): 129 | """ 130 | operation_definition : operation_type name selection_set 131 | """ 132 | p[0] = self.operation_cls(p[1])(selections=p[3], name=p[2]) 133 | 134 | def p_operation_definition5(self, p): 135 | """ 136 | operation_definition : operation_type variable_definitions directives selection_set 137 | """ 138 | p[0] = self.operation_cls(p[1])( 139 | selections=p[4], 140 | variable_definitions=p[2], 141 | directives=p[3], 142 | ) 143 | 144 | def p_operation_definition6(self, p): 145 | """ 146 | operation_definition : operation_type variable_definitions selection_set 147 | """ 148 | p[0] = self.operation_cls(p[1])( 149 | selections=p[3], 150 | variable_definitions=p[2], 151 | ) 152 | 153 | def p_operation_definition7(self, p): 154 | """ 155 | operation_definition : operation_type directives selection_set 156 | """ 157 | p[0] = self.operation_cls(p[1])( 158 | selections=p[3], 159 | directives=p[2], 160 | ) 161 | 162 | def p_operation_definition8(self, p): 163 | """ 164 | operation_definition : operation_type selection_set 165 | """ 166 | p[0] = self.operation_cls(p[1])(selections=p[2]) 167 | 168 | def p_operation_type(self, p): 169 | """ 170 | operation_type : QUERY 171 | | MUTATION 172 | | SUBSCRIPTION 173 | """ 174 | p[0] = p[1] 175 | 176 | def p_selection_set(self, p): 177 | """ 178 | selection_set : BRACE_L selection_list BRACE_R 179 | """ 180 | p[0] = p[2] 181 | 182 | def p_selection_list(self, p): 183 | """ 184 | selection_list : selection_list selection 185 | """ 186 | p[0] = p[1] + [p[2]] 187 | 188 | def p_selection_list_single(self, p): 189 | """ 190 | selection_list : selection 191 | """ 192 | p[0] = [p[1]] 193 | 194 | def p_selection(self, p): 195 | """ 196 | selection : field 197 | | fragment_spread 198 | | inline_fragment 199 | """ 200 | p[0] = p[1] 201 | 202 | def p_field_all(self, p): 203 | """ 204 | field : alias name arguments directives selection_set 205 | """ 206 | p[0] = Field(name=p[2], alias=p[1], arguments=p[3], directives=p[4], 207 | selections=p[5]) 208 | 209 | def p_field_optional1_1(self, p): 210 | """ 211 | field : name arguments directives selection_set 212 | """ 213 | p[0] = Field(name=p[1], arguments=p[2], directives=p[3], 214 | selections=p[5]) 215 | 216 | def p_field_optional1_2(self, p): 217 | """ 218 | field : alias name directives selection_set 219 | """ 220 | p[0] = Field(name=p[2], alias=p[1], directives=p[3], selections=p[5]) 221 | 222 | def p_field_optional1_3(self, p): 223 | """ 224 | field : alias name arguments selection_set 225 | """ 226 | p[0] = Field(name=p[2], alias=p[1], arguments=p[3], selections=p[4]) 227 | 228 | def p_field_optional1_4(self, p): 229 | """ 230 | field : alias name arguments directives 231 | """ 232 | p[0] = Field(name=p[2], alias=p[1], arguments=p[3], directives=p[4]) 233 | 234 | def p_field_optional2_1(self, p): 235 | """ 236 | field : name directives selection_set 237 | """ 238 | p[0] = Field(name=p[1], directives=p[2], selections=p[3]) 239 | 240 | def p_field_optional2_2(self, p): 241 | """ 242 | field : name arguments selection_set 243 | """ 244 | p[0] = Field(name=p[1], arguments=p[2], selections=p[3]) 245 | 246 | def p_field_optional2_3(self, p): 247 | """ 248 | field : name arguments directives 249 | """ 250 | p[0] = Field(name=p[1], arguments=p[2], directives=p[3]) 251 | 252 | def p_field_optional2_4(self, p): 253 | """ 254 | field : alias name selection_set 255 | """ 256 | p[0] = Field(name=p[2], alias=p[1], selections=p[3]) 257 | 258 | def p_field_optional2_5(self, p): 259 | """ 260 | field : alias name directives 261 | """ 262 | p[0] = Field(name=p[2], alias=p[1], directives=p[3]) 263 | 264 | def p_field_optional2_6(self, p): 265 | """ 266 | field : alias name arguments 267 | """ 268 | p[0] = Field(name=p[2], alias=p[1], arguments=p[3]) 269 | 270 | def p_field_optional3_1(self, p): 271 | """ 272 | field : alias name 273 | """ 274 | p[0] = Field(name=p[2], alias=p[1]) 275 | 276 | def p_field_optional3_2(self, p): 277 | """ 278 | field : name arguments 279 | """ 280 | p[0] = Field(name=p[1], arguments=p[2]) 281 | 282 | def p_field_optional3_3(self, p): 283 | """ 284 | field : name directives 285 | """ 286 | p[0] = Field(name=p[1], directives=p[2]) 287 | 288 | def p_field_optional3_4(self, p): 289 | """ 290 | field : name selection_set 291 | """ 292 | p[0] = Field(name=p[1], selections=p[2]) 293 | 294 | def p_field_optional4(self, p): 295 | """ 296 | field : name 297 | """ 298 | p[0] = Field(name=p[1]) 299 | 300 | def p_fragment_spread1(self, p): 301 | """ 302 | fragment_spread : SPREAD fragment_name directives 303 | """ 304 | p[0] = FragmentSpread(name=p[2], directives=p[3]) 305 | 306 | def p_fragment_spread2(self, p): 307 | """ 308 | fragment_spread : SPREAD fragment_name 309 | """ 310 | p[0] = FragmentSpread(name=p[2]) 311 | 312 | def p_fragment_definition1(self, p): 313 | """ 314 | fragment_definition : FRAGMENT fragment_name ON type_condition directives selection_set 315 | """ 316 | p[0] = FragmentDefinition(name=p[2], type_condition=p[4], 317 | selections=p[6], directives=p[5]) 318 | 319 | def p_fragment_definition2(self, p): 320 | """ 321 | fragment_definition : FRAGMENT fragment_name ON type_condition selection_set 322 | """ 323 | p[0] = FragmentDefinition(name=p[2], type_condition=p[4], 324 | selections=p[5]) 325 | 326 | def p_inline_fragment1(self, p): 327 | """ 328 | inline_fragment : SPREAD ON type_condition directives selection_set 329 | """ 330 | p[0] = InlineFragment(type_condition=p[3], selections=p[5], 331 | directives=p[4]) 332 | 333 | def p_inline_fragment2(self, p): 334 | """ 335 | inline_fragment : SPREAD ON type_condition selection_set 336 | """ 337 | p[0] = InlineFragment(type_condition=p[3], selections=p[4]) 338 | 339 | def p_fragment_name(self, p): 340 | """ 341 | fragment_name : NAME 342 | | FRAGMENT 343 | | QUERY 344 | | MUTATION 345 | | SUBSCRIPTION 346 | | TRUE 347 | | FALSE 348 | | NULL 349 | """ 350 | p[0] = p[1] 351 | 352 | def p_type_condition(self, p): 353 | """ 354 | type_condition : named_type 355 | """ 356 | p[0] = p[1] 357 | 358 | def p_directives(self, p): 359 | """ 360 | directives : directive_list 361 | """ 362 | p[0] = p[1] 363 | 364 | def p_directive_list(self, p): 365 | """ 366 | directive_list : directive_list directive 367 | """ 368 | p[0] = p[1] + [p[2]] 369 | 370 | def p_directive_list_single(self, p): 371 | """ 372 | directive_list : directive 373 | """ 374 | p[0] = [p[1]] 375 | 376 | def p_directive(self, p): 377 | """ 378 | directive : AT name arguments 379 | | AT name 380 | """ 381 | arguments = p[3] if len(p) == 4 else None 382 | p[0] = Directive(name=p[2], arguments=arguments) 383 | 384 | def p_arguments(self, p): 385 | """ 386 | arguments : PAREN_L argument_list PAREN_R 387 | """ 388 | p[0] = p[2] 389 | 390 | def p_argument_list(self, p): 391 | """ 392 | argument_list : argument_list argument 393 | """ 394 | p[0] = p[1] + [p[2]] 395 | 396 | def p_argument_list_single(self, p): 397 | """ 398 | argument_list : argument 399 | """ 400 | p[0] = [p[1]] 401 | 402 | def p_argument(self, p): 403 | """ 404 | argument : name COLON value 405 | """ 406 | p[0] = Argument(name=p[1], value=p[3]) 407 | 408 | def p_variable_definitions(self, p): 409 | """ 410 | variable_definitions : PAREN_L variable_definition_list PAREN_R 411 | """ 412 | p[0] = p[2] 413 | 414 | def p_variable_definition_list(self, p): 415 | """ 416 | variable_definition_list : variable_definition_list variable_definition 417 | """ 418 | p[0] = p[1] + [p[2]] 419 | 420 | def p_variable_definition_list_single(self, p): 421 | """ 422 | variable_definition_list : variable_definition 423 | """ 424 | p[0] = [p[1]] 425 | 426 | def p_variable_definition1(self, p): 427 | """ 428 | variable_definition : DOLLAR name COLON type default_value 429 | """ 430 | p[0] = VariableDefinition(name=p[2], type=p[4], default_value=p[5]) 431 | 432 | def p_variable_definition2(self, p): 433 | """ 434 | variable_definition : DOLLAR name COLON type 435 | """ 436 | p[0] = VariableDefinition(name=p[2], type=p[4]) 437 | 438 | def p_variable(self, p): 439 | """ 440 | variable : DOLLAR name 441 | """ 442 | p[0] = Variable(name=p[2]) 443 | 444 | def p_default_value(self, p): 445 | """ 446 | default_value : EQUALS const_value 447 | """ 448 | p[0] = p[2] 449 | 450 | def p_name(self, p): 451 | """ 452 | name : NAME 453 | | FRAGMENT 454 | | QUERY 455 | | MUTATION 456 | | SUBSCRIPTION 457 | | ON 458 | | TRUE 459 | | FALSE 460 | | NULL 461 | """ 462 | p[0] = p[1] 463 | 464 | def p_alias(self, p): 465 | """ 466 | alias : name COLON 467 | """ 468 | p[0] = p[1] 469 | 470 | def p_value(self, p): 471 | """ 472 | value : variable 473 | | INT_VALUE 474 | | FLOAT_VALUE 475 | | STRING_VALUE 476 | | null_value 477 | | boolean_value 478 | | enum_value 479 | | list_value 480 | | object_value 481 | """ 482 | p[0] = p[1] 483 | 484 | def p_const_value(self, p): 485 | """ 486 | const_value : INT_VALUE 487 | | FLOAT_VALUE 488 | | STRING_VALUE 489 | | null_value 490 | | boolean_value 491 | | enum_value 492 | | const_list_value 493 | | const_object_value 494 | """ 495 | p[0] = p[1] 496 | 497 | def p_boolean_value(self, p): 498 | """ 499 | boolean_value : TRUE 500 | | FALSE 501 | """ 502 | p[0] = p[1] 503 | 504 | def p_null_value(self, p): 505 | """ 506 | null_value : NULL 507 | """ 508 | p[0] = p[1] 509 | 510 | def p_enum_value(self, p): 511 | """ 512 | enum_value : NAME 513 | | FRAGMENT 514 | | QUERY 515 | | MUTATION 516 | | SUBSCRIPTION 517 | | ON 518 | """ 519 | p[0] = p[1] 520 | 521 | def p_list_value(self, p): 522 | """ 523 | list_value : BRACKET_L value_list BRACKET_R 524 | | BRACKET_L BRACKET_R 525 | """ 526 | p[0] = p[2] if len(p) == 4 else [] 527 | 528 | def p_value_list(self, p): 529 | """ 530 | value_list : value_list value 531 | """ 532 | p[0] = p[1] + [p[2]] 533 | 534 | def p_value_list_single(self, p): 535 | """ 536 | value_list : value 537 | """ 538 | p[0] = [p[1]] 539 | 540 | def p_const_list_value(self, p): 541 | """ 542 | const_list_value : BRACKET_L const_value_list BRACKET_R 543 | | BRACKET_L BRACKET_R 544 | """ 545 | p[0] = p[2] if len(p) == 4 else [] 546 | 547 | def p_const_value_list(self, p): 548 | """ 549 | const_value_list : const_value_list const_value 550 | """ 551 | p[0] = p[1] + [p[2]] 552 | 553 | def p_const_value_list_single(self, p): 554 | """ 555 | const_value_list : const_value 556 | """ 557 | p[0] = [p[1]] 558 | 559 | def p_object_value(self, p): 560 | """ 561 | object_value : BRACE_L object_field_list BRACE_R 562 | | BRACE_L BRACE_R 563 | """ 564 | p[0] = p[2] if len(p) == 4 else {} 565 | 566 | def p_object_field_list(self, p): 567 | """ 568 | object_field_list : object_field_list object_field 569 | """ 570 | obj = p[1].copy() 571 | obj.update(p[2]) 572 | p[0] = obj 573 | 574 | def p_object_field_list_single(self, p): 575 | """ 576 | object_field_list : object_field 577 | """ 578 | p[0] = p[1] 579 | 580 | def p_object_field(self, p): 581 | """ 582 | object_field : name COLON value 583 | """ 584 | p[0] = {p[1]: p[3]} 585 | 586 | def p_const_object_value(self, p): 587 | """ 588 | const_object_value : BRACE_L const_object_field_list BRACE_R 589 | | BRACE_L BRACE_R 590 | """ 591 | p[0] = p[2] if len(p) == 4 else {} 592 | 593 | def p_const_object_field_list(self, p): 594 | """ 595 | const_object_field_list : const_object_field_list const_object_field 596 | """ 597 | obj = p[1].copy() 598 | obj.update(p[2]) 599 | p[0] = obj 600 | 601 | def p_const_object_field_list_single(self, p): 602 | """ 603 | const_object_field_list : const_object_field 604 | """ 605 | p[0] = p[1] 606 | 607 | def p_const_object_field(self, p): 608 | """ 609 | const_object_field : name COLON const_value 610 | """ 611 | p[0] = {p[1]: p[3]} 612 | 613 | def p_type(self, p): 614 | """ 615 | type : named_type 616 | | list_type 617 | | non_null_type 618 | """ 619 | p[0] = p[1] 620 | 621 | def p_named_type(self, p): 622 | """ 623 | named_type : name 624 | """ 625 | p[0] = NamedType(name=p[1]) 626 | 627 | def p_list_type(self, p): 628 | """ 629 | list_type : BRACKET_L type BRACKET_R 630 | """ 631 | p[0] = ListType(type=p[2]) 632 | 633 | def p_non_null_type(self, p): 634 | """ 635 | non_null_type : named_type BANG 636 | | list_type BANG 637 | """ 638 | p[0] = NonNullType(type=p[1]) 639 | 640 | def p_error(self, token): 641 | if token is None: 642 | self.raise_syntax_error('Unexpected end of input') 643 | else: 644 | fragment = token.value 645 | if len(fragment) > 20: 646 | fragment = fragment[:17] + '...' 647 | self.raise_syntax_error( 648 | 'Syntax error at %s' % repr(fragment), 649 | token=token, 650 | ) 651 | 652 | def raise_syntax_error(self, message, token=None): 653 | if token is None: 654 | raise SyntaxError(message) 655 | lexer = token.lexer 656 | if callable(getattr(lexer, 'find_column', None)): 657 | column = lexer.find_column(token) 658 | else: 659 | column = None 660 | raise SyntaxError( 661 | message=message, 662 | value=token.value, 663 | line=token.lineno, 664 | column=column, 665 | ) 666 | -------------------------------------------------------------------------------- /graphql/parsetab.py: -------------------------------------------------------------------------------- 1 | 2 | # /Users/dvs/Dropbox/Code/graphql-py/graphql/parsetab.py 3 | # This file is automatically generated. Do not edit. 4 | _tabversion = '3.5' 5 | 6 | _lr_method = 'LALR' 7 | 8 | _lr_signature = 'E6D6D5E915094EAB3A68E387CED054AB' 9 | 10 | _lr_action_items = {'BRACE_L':([0,8,10,11,12,22,24,25,26,27,28,29,30,31,32,33,34,35,38,39,53,54,55,61,62,64,70,71,73,74,76,83,84,85,86,90,93,94,95,99,101,102,106,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,138,139,140,141,143,147,151,152,153,155,157,158,159,160,161,162,163,164,165,169,170,171,173,176,177,178,180,],[5,5,-18,-19,-20,5,-79,-74,-75,-76,-77,-78,-80,-81,-82,5,5,5,-58,-60,5,5,5,5,5,5,-59,-62,5,5,5,5,-57,-131,5,-67,-61,5,5,-63,130,5,5,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,130,-72,130,-111,-113,-119,166,-110,-112,-118,130,-93,-94,-95,-96,-97,-98,-99,-100,166,166,-115,-117,-124,-114,-116,-123,166,]),'FRAGMENT':([0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,36,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,63,65,66,69,70,71,72,73,74,75,76,77,78,79,80,82,87,88,89,93,95,96,97,98,99,100,101,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,137,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[9,9,9,-7,26,-8,-9,26,41,-18,-19,-20,-6,9,-5,26,-23,-24,-25,-26,26,-42,41,-79,-74,-75,-76,-77,-78,-80,-81,-82,-17,-58,-60,26,-50,-49,-51,-52,-53,-54,-55,-56,-4,-21,-22,-38,-39,-40,-41,-83,26,-44,26,-13,-15,-16,26,-59,-62,26,-37,-36,-35,-34,-33,-32,26,-65,-43,-11,-12,-14,-61,-31,-30,-29,-28,-63,-64,124,-48,-10,26,-46,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,26,-103,-101,-102,-104,-105,-106,-107,-108,-109,124,26,-47,26,-45,-72,124,-111,-113,26,-119,-121,124,-110,-112,-118,-120,124,-93,-94,-95,-96,-97,-98,-99,-100,124,26,-122,124,-115,-117,26,-124,-126,-114,-116,-123,-125,124,-127,]),'QUERY':([0,2,4,5,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,36,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,63,65,66,69,70,71,72,73,74,75,76,77,78,79,80,82,87,88,89,93,95,96,97,98,99,100,101,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,137,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[10,10,-7,27,-8,-9,27,44,-18,-19,-20,-6,27,-23,-24,-25,-26,27,-42,44,-79,-74,-75,-76,-77,-78,-80,-81,-82,-17,-58,-60,27,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,27,-44,27,-13,-15,-16,27,-59,-62,27,-37,-36,-35,-34,-33,-32,27,-65,-43,-11,-12,-14,-61,-31,-30,-29,-28,-63,-64,125,-48,-10,27,-46,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,27,-103,-101,-102,-104,-105,-106,-107,-108,-109,125,27,-47,27,-45,-72,125,-111,-113,27,-119,-121,125,-110,-112,-118,-120,125,-93,-94,-95,-96,-97,-98,-99,-100,125,27,-122,125,-115,-117,27,-124,-126,-114,-116,-123,-125,125,-127,]),'MUTATION':([0,2,4,5,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,36,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,63,65,66,69,70,71,72,73,74,75,76,77,78,79,80,82,87,88,89,93,95,96,97,98,99,100,101,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,137,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[11,11,-7,28,-8,-9,28,45,-18,-19,-20,-6,28,-23,-24,-25,-26,28,-42,45,-79,-74,-75,-76,-77,-78,-80,-81,-82,-17,-58,-60,28,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,28,-44,28,-13,-15,-16,28,-59,-62,28,-37,-36,-35,-34,-33,-32,28,-65,-43,-11,-12,-14,-61,-31,-30,-29,-28,-63,-64,126,-48,-10,28,-46,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,28,-103,-101,-102,-104,-105,-106,-107,-108,-109,126,28,-47,28,-45,-72,126,-111,-113,28,-119,-121,126,-110,-112,-118,-120,126,-93,-94,-95,-96,-97,-98,-99,-100,126,28,-122,126,-115,-117,28,-124,-126,-114,-116,-123,-125,126,-127,]),'SUBSCRIPTION':([0,2,4,5,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,36,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,63,65,66,69,70,71,72,73,74,75,76,77,78,79,80,82,87,88,89,93,95,96,97,98,99,100,101,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,137,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[12,12,-7,29,-8,-9,29,46,-18,-19,-20,-6,29,-23,-24,-25,-26,29,-42,46,-79,-74,-75,-76,-77,-78,-80,-81,-82,-17,-58,-60,29,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,29,-44,29,-13,-15,-16,29,-59,-62,29,-37,-36,-35,-34,-33,-32,29,-65,-43,-11,-12,-14,-61,-31,-30,-29,-28,-63,-64,127,-48,-10,29,-46,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,29,-103,-101,-102,-104,-105,-106,-107,-108,-109,127,29,-47,29,-45,-72,127,-111,-113,29,-119,-121,127,-110,-112,-118,-120,127,-93,-94,-95,-96,-97,-98,-99,-100,127,29,-122,127,-115,-117,29,-124,-126,-114,-116,-123,-125,127,-127,]),'$end':([1,2,3,4,6,7,13,14,15,36,50,51,63,65,66,87,88,89,104,107,137,],[0,-1,-2,-7,-8,-9,-6,-3,-5,-17,-4,-21,-13,-15,-16,-11,-12,-14,-10,-46,-45,]),'SPREAD':([5,16,17,18,19,20,22,24,25,26,27,28,29,30,31,32,38,39,41,43,44,45,46,47,48,49,51,52,53,54,55,56,59,70,71,73,74,75,76,77,78,82,93,95,96,97,98,99,103,108,131,],[23,23,-23,-24,-25,-26,-42,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-44,-59,-62,-37,-36,-35,-34,-33,-32,-43,-61,-31,-30,-29,-28,-63,-48,-27,-47,]),'NAME':([5,8,9,10,11,12,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,69,70,71,72,73,74,75,76,77,78,79,80,82,93,95,96,97,98,99,100,101,103,105,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[25,25,43,-18,-19,-20,25,-23,-24,-25,-26,25,-42,43,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,25,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,25,-44,25,25,-59,-62,25,-37,-36,-35,-34,-33,-32,25,-65,-43,-61,-31,-30,-29,-28,-63,-64,123,-48,25,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,25,-103,-101,-102,-104,-105,-106,-107,-108,-109,123,25,-47,25,-72,123,-111,-113,25,-119,-121,123,-110,-112,-118,-120,123,-93,-94,-95,-96,-97,-98,-99,-100,123,25,-122,123,-115,-117,25,-124,-126,-114,-116,-123,-125,123,-127,]),'ON':([5,8,10,11,12,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,69,70,71,72,73,74,75,76,77,78,79,80,82,93,95,96,97,98,99,100,101,103,105,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[24,24,-18,-19,-20,24,-23,-24,-25,-26,24,-42,60,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,24,-50,72,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,24,-44,24,24,-59,-62,24,-37,-36,-35,-34,-33,-32,24,-65,-43,-61,-31,-30,-29,-28,-63,-64,128,-48,24,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,24,-103,-101,-102,-104,-105,-106,-107,-108,-109,128,24,-47,24,-72,128,-111,-113,24,-119,-121,128,-110,-112,-118,-120,128,-93,-94,-95,-96,-97,-98,-99,-100,128,24,-122,128,-115,-117,24,-124,-126,-114,-116,-123,-125,128,-127,]),'TRUE':([5,8,9,10,11,12,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,69,70,71,72,73,74,75,76,77,78,79,80,82,93,95,96,97,98,99,100,101,103,105,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[30,30,47,-18,-19,-20,30,-23,-24,-25,-26,30,-42,47,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,30,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,30,-44,30,30,-59,-62,30,-37,-36,-35,-34,-33,-32,30,-65,-43,-61,-31,-30,-29,-28,-63,-64,121,-48,30,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,30,-103,-101,-102,-104,-105,-106,-107,-108,-109,121,30,-47,30,-72,121,-111,-113,30,-119,-121,121,-110,-112,-118,-120,121,-93,-94,-95,-96,-97,-98,-99,-100,121,30,-122,121,-115,-117,30,-124,-126,-114,-116,-123,-125,121,-127,]),'FALSE':([5,8,9,10,11,12,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,69,70,71,72,73,74,75,76,77,78,79,80,82,93,95,96,97,98,99,100,101,103,105,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[31,31,48,-18,-19,-20,31,-23,-24,-25,-26,31,-42,48,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,31,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,31,-44,31,31,-59,-62,31,-37,-36,-35,-34,-33,-32,31,-65,-43,-61,-31,-30,-29,-28,-63,-64,122,-48,31,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,31,-103,-101,-102,-104,-105,-106,-107,-108,-109,122,31,-47,31,-72,122,-111,-113,31,-119,-121,122,-110,-112,-118,-120,122,-93,-94,-95,-96,-97,-98,-99,-100,122,31,-122,122,-115,-117,31,-124,-126,-114,-116,-123,-125,122,-127,]),'NULL':([5,8,9,10,11,12,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,38,39,40,41,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,69,70,71,72,73,74,75,76,77,78,79,80,82,93,95,96,97,98,99,100,101,103,105,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,136,138,139,140,141,142,143,144,147,151,152,153,154,155,157,158,159,160,161,162,163,164,165,166,168,169,170,171,172,173,174,176,177,178,179,180,181,],[32,32,49,-18,-19,-20,32,-23,-24,-25,-26,32,-42,49,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,32,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-83,32,-44,32,32,-59,-62,32,-37,-36,-35,-34,-33,-32,32,-65,-43,-61,-31,-30,-29,-28,-63,-64,120,-48,32,-27,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,32,-103,-101,-102,-104,-105,-106,-107,-108,-109,120,32,-47,32,-72,120,-111,-113,32,-119,-121,120,-110,-112,-118,-120,120,-93,-94,-95,-96,-97,-98,-99,-100,120,32,-122,120,-115,-117,32,-124,-126,-114,-116,-123,-125,120,-127,]),'PAREN_L':([8,10,11,12,22,24,25,26,27,28,29,30,31,32,33,53,71,],[37,-18,-19,-20,58,-79,-74,-75,-76,-77,-78,-80,-81,-82,37,58,58,]),'AT':([8,10,11,12,22,24,25,26,27,28,29,30,31,32,33,34,38,39,41,43,44,45,46,47,48,49,53,54,59,61,70,71,73,83,84,85,90,93,94,99,],[40,-18,-19,-20,40,-79,-74,-75,-76,-77,-78,-80,-81,-82,40,40,40,-60,-50,-49,-51,-52,-53,-54,-55,-56,40,40,40,40,-59,-62,40,40,-57,-131,-67,-61,40,-63,]),'BRACE_R':([16,17,18,19,20,22,24,25,26,27,28,29,30,31,32,38,39,41,43,44,45,46,47,48,49,51,52,53,54,55,56,59,70,71,73,74,75,76,77,78,82,93,95,96,97,98,99,103,108,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,130,131,138,140,142,143,144,151,153,154,157,158,159,160,161,162,163,164,166,168,170,172,173,174,176,178,179,181,],[51,-23,-24,-25,-26,-42,-79,-74,-75,-76,-77,-78,-80,-81,-82,-58,-60,-50,-49,-51,-52,-53,-54,-55,-56,-21,-22,-38,-39,-40,-41,-44,-59,-62,-37,-36,-35,-34,-33,-32,-43,-61,-31,-30,-29,-28,-63,-48,-27,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,143,-47,-72,-111,153,-119,-121,-110,-118,-120,-93,-94,-95,-96,-97,-98,-99,-100,173,-122,-115,178,-124,-126,-114,-123,-125,-127,]),'COLON':([22,24,25,26,27,28,29,30,31,32,81,92,145,175,],[57,-79,-74,-75,-76,-77,-78,-80,-81,-82,101,105,155,180,]),'BANG':([24,25,26,27,28,29,30,31,32,85,133,134,167,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,-131,148,149,-132,]),'EQUALS':([24,25,26,27,28,29,30,31,32,85,132,133,134,135,148,149,167,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,-131,147,-128,-129,-130,-133,-134,-132,]),'PAREN_R':([24,25,26,27,28,29,30,31,32,67,68,79,80,85,91,100,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,132,133,134,135,138,140,143,146,148,149,151,153,156,157,158,159,160,161,162,163,164,167,170,173,176,178,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,90,-69,99,-65,-131,-68,-64,-66,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,-71,-128,-129,-130,-72,-111,-119,-70,-133,-134,-110,-118,-73,-93,-94,-95,-96,-97,-98,-99,-100,-132,-115,-124,-114,-123,]),'DOLLAR':([24,25,26,27,28,29,30,31,32,37,67,68,85,91,101,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,132,133,134,135,138,139,140,141,143,146,148,149,151,152,153,155,156,157,158,159,160,161,162,163,164,167,170,173,176,178,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,69,69,-69,-131,-68,119,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,119,-71,-128,-129,-130,-72,119,-111,-113,-119,-70,-133,-134,-110,-112,-118,119,-73,-93,-94,-95,-96,-97,-98,-99,-100,-132,-115,-124,-114,-123,]),'BRACKET_R':([24,25,26,27,28,29,30,31,32,85,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,133,134,135,138,139,140,141,143,148,149,150,151,152,153,157,158,159,160,161,162,163,164,165,167,169,170,171,173,176,177,178,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,-131,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,140,-128,-129,-130,-72,151,-111,-113,-119,-133,-134,167,-110,-112,-118,-93,-94,-95,-96,-97,-98,-99,-100,170,-132,176,-115,-117,-124,-114,-116,-123,]),'INT_VALUE':([24,25,26,27,28,29,30,31,32,101,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,138,139,140,141,143,147,151,152,153,155,157,158,159,160,161,162,163,164,165,169,170,171,173,176,177,178,180,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,111,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,111,-72,111,-111,-113,-119,157,-110,-112,-118,111,-93,-94,-95,-96,-97,-98,-99,-100,157,157,-115,-117,-124,-114,-116,-123,157,]),'FLOAT_VALUE':([24,25,26,27,28,29,30,31,32,101,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,138,139,140,141,143,147,151,152,153,155,157,158,159,160,161,162,163,164,165,169,170,171,173,176,177,178,180,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,112,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,112,-72,112,-111,-113,-119,158,-110,-112,-118,112,-93,-94,-95,-96,-97,-98,-99,-100,158,158,-115,-117,-124,-114,-116,-123,158,]),'STRING_VALUE':([24,25,26,27,28,29,30,31,32,101,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,138,139,140,141,143,147,151,152,153,155,157,158,159,160,161,162,163,164,165,169,170,171,173,176,177,178,180,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,113,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,113,-72,113,-111,-113,-119,159,-110,-112,-118,113,-93,-94,-95,-96,-97,-98,-99,-100,159,159,-115,-117,-124,-114,-116,-123,159,]),'BRACKET_L':([24,25,26,27,28,29,30,31,32,101,105,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,136,138,139,140,141,143,147,151,152,153,155,157,158,159,160,161,162,163,164,165,169,170,171,173,176,177,178,180,],[-79,-74,-75,-76,-77,-78,-80,-81,-82,129,136,-84,-85,-86,-87,-88,-89,-90,-91,-92,-103,-101,-102,-104,-105,-106,-107,-108,-109,129,136,-72,129,-111,-113,-119,165,-110,-112,-118,129,-93,-94,-95,-96,-97,-98,-99,-100,165,165,-115,-117,-124,-114,-116,-123,165,]),} 11 | 12 | _lr_action = {} 13 | for _k, _v in _lr_action_items.items(): 14 | for _x,_y in zip(_v[0],_v[1]): 15 | if not _x in _lr_action: _lr_action[_x] = {} 16 | _lr_action[_x][_k] = _y 17 | del _lr_action_items 18 | 19 | _lr_goto_items = {'document':([0,],[1,]),'definition_list':([0,],[2,]),'selection_set':([0,8,22,33,34,35,53,54,55,61,62,64,73,74,76,83,86,94,95,102,106,],[3,36,56,63,65,66,75,77,78,87,88,89,96,97,98,103,104,107,108,131,137,]),'definition':([0,2,],[4,13,]),'operation_definition':([0,2,],[6,6,]),'fragment_definition':([0,2,3,14,],[7,7,15,50,]),'operation_type':([0,2,],[8,8,]),'fragment_list':([3,],[14,]),'selection_list':([5,],[16,]),'selection':([5,16,],[17,52,]),'field':([5,16,],[18,18,]),'fragment_spread':([5,16,],[19,19,]),'inline_fragment':([5,16,],[20,20,]),'alias':([5,16,],[21,21,]),'name':([5,8,16,21,40,58,60,69,72,79,105,119,130,136,142,166,172,],[22,33,22,53,71,81,85,92,85,81,85,138,145,85,145,175,175,]),'variable_definitions':([8,33,],[34,61,]),'directives':([8,22,33,34,53,54,59,61,73,83,94,],[35,55,62,64,74,76,82,86,95,102,106,]),'directive_list':([8,22,33,34,53,54,59,61,73,83,94,],[38,38,38,38,38,38,38,38,38,38,38,]),'directive':([8,22,33,34,38,53,54,59,61,73,83,94,],[39,39,39,39,70,39,39,39,39,39,39,39,]),'fragment_name':([9,23,],[42,59,]),'arguments':([22,53,71,],[54,73,93,]),'variable_definition_list':([37,],[67,]),'variable_definition':([37,67,],[68,91,]),'argument_list':([58,],[79,]),'argument':([58,79,],[80,100,]),'type_condition':([60,72,],[83,94,]),'named_type':([60,72,105,136,],[84,84,133,133,]),'value':([101,129,139,155,],[109,141,152,168,]),'variable':([101,129,139,155,],[110,110,110,110,]),'null_value':([101,129,139,147,155,165,169,180,],[114,114,114,160,114,160,160,160,]),'boolean_value':([101,129,139,147,155,165,169,180,],[115,115,115,161,115,161,161,161,]),'enum_value':([101,129,139,147,155,165,169,180,],[116,116,116,162,116,162,162,162,]),'list_value':([101,129,139,155,],[117,117,117,117,]),'object_value':([101,129,139,155,],[118,118,118,118,]),'type':([105,136,],[132,150,]),'list_type':([105,136,],[134,134,]),'non_null_type':([105,136,],[135,135,]),'value_list':([129,],[139,]),'object_field_list':([130,],[142,]),'object_field':([130,142,],[144,154,]),'default_value':([132,],[146,]),'const_value':([147,165,169,180,],[156,171,177,181,]),'const_list_value':([147,165,169,180,],[163,163,163,163,]),'const_object_value':([147,165,169,180,],[164,164,164,164,]),'const_value_list':([165,],[169,]),'const_object_field_list':([166,],[172,]),'const_object_field':([166,172,],[174,179,]),} 20 | 21 | _lr_goto = {} 22 | for _k, _v in _lr_goto_items.items(): 23 | for _x, _y in zip(_v[0], _v[1]): 24 | if not _x in _lr_goto: _lr_goto[_x] = {} 25 | _lr_goto[_x][_k] = _y 26 | del _lr_goto_items 27 | _lr_productions = [ 28 | ("S' -> document","S'",1,None,None,None), 29 | ('document -> definition_list','document',1,'p_document','parser.py',42), 30 | ('document -> selection_set','document',1,'p_document_shorthand','parser.py',48), 31 | ('document -> selection_set fragment_list','document',2,'p_document_shorthand_with_fragments','parser.py',54), 32 | ('fragment_list -> fragment_list fragment_definition','fragment_list',2,'p_fragment_list','parser.py',60), 33 | ('fragment_list -> fragment_definition','fragment_list',1,'p_fragment_list_single','parser.py',66), 34 | ('definition_list -> definition_list definition','definition_list',2,'p_definition_list','parser.py',72), 35 | ('definition_list -> definition','definition_list',1,'p_definition_list_single','parser.py',78), 36 | ('definition -> operation_definition','definition',1,'p_definition','parser.py',84), 37 | ('definition -> fragment_definition','definition',1,'p_definition','parser.py',85), 38 | ('operation_definition -> operation_type name variable_definitions directives selection_set','operation_definition',5,'p_operation_definition1','parser.py',99), 39 | ('operation_definition -> operation_type name variable_definitions selection_set','operation_definition',4,'p_operation_definition2','parser.py',110), 40 | ('operation_definition -> operation_type name directives selection_set','operation_definition',4,'p_operation_definition3','parser.py',120), 41 | ('operation_definition -> operation_type name selection_set','operation_definition',3,'p_operation_definition4','parser.py',130), 42 | ('operation_definition -> operation_type variable_definitions directives selection_set','operation_definition',4,'p_operation_definition5','parser.py',136), 43 | ('operation_definition -> operation_type variable_definitions selection_set','operation_definition',3,'p_operation_definition6','parser.py',146), 44 | ('operation_definition -> operation_type directives selection_set','operation_definition',3,'p_operation_definition7','parser.py',155), 45 | ('operation_definition -> operation_type selection_set','operation_definition',2,'p_operation_definition8','parser.py',164), 46 | ('operation_type -> QUERY','operation_type',1,'p_operation_type','parser.py',170), 47 | ('operation_type -> MUTATION','operation_type',1,'p_operation_type','parser.py',171), 48 | ('operation_type -> SUBSCRIPTION','operation_type',1,'p_operation_type','parser.py',172), 49 | ('selection_set -> BRACE_L selection_list BRACE_R','selection_set',3,'p_selection_set','parser.py',178), 50 | ('selection_list -> selection_list selection','selection_list',2,'p_selection_list','parser.py',184), 51 | ('selection_list -> selection','selection_list',1,'p_selection_list_single','parser.py',190), 52 | ('selection -> field','selection',1,'p_selection','parser.py',196), 53 | ('selection -> fragment_spread','selection',1,'p_selection','parser.py',197), 54 | ('selection -> inline_fragment','selection',1,'p_selection','parser.py',198), 55 | ('field -> alias name arguments directives selection_set','field',5,'p_field_all','parser.py',204), 56 | ('field -> name arguments directives selection_set','field',4,'p_field_optional1_1','parser.py',211), 57 | ('field -> alias name directives selection_set','field',4,'p_field_optional1_2','parser.py',218), 58 | ('field -> alias name arguments selection_set','field',4,'p_field_optional1_3','parser.py',224), 59 | ('field -> alias name arguments directives','field',4,'p_field_optional1_4','parser.py',230), 60 | ('field -> name directives selection_set','field',3,'p_field_optional2_1','parser.py',236), 61 | ('field -> name arguments selection_set','field',3,'p_field_optional2_2','parser.py',242), 62 | ('field -> name arguments directives','field',3,'p_field_optional2_3','parser.py',248), 63 | ('field -> alias name selection_set','field',3,'p_field_optional2_4','parser.py',254), 64 | ('field -> alias name directives','field',3,'p_field_optional2_5','parser.py',260), 65 | ('field -> alias name arguments','field',3,'p_field_optional2_6','parser.py',266), 66 | ('field -> alias name','field',2,'p_field_optional3_1','parser.py',272), 67 | ('field -> name arguments','field',2,'p_field_optional3_2','parser.py',278), 68 | ('field -> name directives','field',2,'p_field_optional3_3','parser.py',284), 69 | ('field -> name selection_set','field',2,'p_field_optional3_4','parser.py',290), 70 | ('field -> name','field',1,'p_field_optional4','parser.py',296), 71 | ('fragment_spread -> SPREAD fragment_name directives','fragment_spread',3,'p_fragment_spread1','parser.py',302), 72 | ('fragment_spread -> SPREAD fragment_name','fragment_spread',2,'p_fragment_spread2','parser.py',308), 73 | ('fragment_definition -> FRAGMENT fragment_name ON type_condition directives selection_set','fragment_definition',6,'p_fragment_definition1','parser.py',314), 74 | ('fragment_definition -> FRAGMENT fragment_name ON type_condition selection_set','fragment_definition',5,'p_fragment_definition2','parser.py',321), 75 | ('inline_fragment -> SPREAD ON type_condition directives selection_set','inline_fragment',5,'p_inline_fragment1','parser.py',328), 76 | ('inline_fragment -> SPREAD ON type_condition selection_set','inline_fragment',4,'p_inline_fragment2','parser.py',335), 77 | ('fragment_name -> NAME','fragment_name',1,'p_fragment_name','parser.py',341), 78 | ('fragment_name -> FRAGMENT','fragment_name',1,'p_fragment_name','parser.py',342), 79 | ('fragment_name -> QUERY','fragment_name',1,'p_fragment_name','parser.py',343), 80 | ('fragment_name -> MUTATION','fragment_name',1,'p_fragment_name','parser.py',344), 81 | ('fragment_name -> SUBSCRIPTION','fragment_name',1,'p_fragment_name','parser.py',345), 82 | ('fragment_name -> TRUE','fragment_name',1,'p_fragment_name','parser.py',346), 83 | ('fragment_name -> FALSE','fragment_name',1,'p_fragment_name','parser.py',347), 84 | ('fragment_name -> NULL','fragment_name',1,'p_fragment_name','parser.py',348), 85 | ('type_condition -> named_type','type_condition',1,'p_type_condition','parser.py',354), 86 | ('directives -> directive_list','directives',1,'p_directives','parser.py',360), 87 | ('directive_list -> directive_list directive','directive_list',2,'p_directive_list','parser.py',366), 88 | ('directive_list -> directive','directive_list',1,'p_directive_list_single','parser.py',372), 89 | ('directive -> AT name arguments','directive',3,'p_directive','parser.py',378), 90 | ('directive -> AT name','directive',2,'p_directive','parser.py',379), 91 | ('arguments -> PAREN_L argument_list PAREN_R','arguments',3,'p_arguments','parser.py',386), 92 | ('argument_list -> argument_list argument','argument_list',2,'p_argument_list','parser.py',392), 93 | ('argument_list -> argument','argument_list',1,'p_argument_list_single','parser.py',398), 94 | ('argument -> name COLON value','argument',3,'p_argument','parser.py',404), 95 | ('variable_definitions -> PAREN_L variable_definition_list PAREN_R','variable_definitions',3,'p_variable_definitions','parser.py',410), 96 | ('variable_definition_list -> variable_definition_list variable_definition','variable_definition_list',2,'p_variable_definition_list','parser.py',416), 97 | ('variable_definition_list -> variable_definition','variable_definition_list',1,'p_variable_definition_list_single','parser.py',422), 98 | ('variable_definition -> DOLLAR name COLON type default_value','variable_definition',5,'p_variable_definition1','parser.py',428), 99 | ('variable_definition -> DOLLAR name COLON type','variable_definition',4,'p_variable_definition2','parser.py',434), 100 | ('variable -> DOLLAR name','variable',2,'p_variable','parser.py',440), 101 | ('default_value -> EQUALS const_value','default_value',2,'p_default_value','parser.py',446), 102 | ('name -> NAME','name',1,'p_name','parser.py',452), 103 | ('name -> FRAGMENT','name',1,'p_name','parser.py',453), 104 | ('name -> QUERY','name',1,'p_name','parser.py',454), 105 | ('name -> MUTATION','name',1,'p_name','parser.py',455), 106 | ('name -> SUBSCRIPTION','name',1,'p_name','parser.py',456), 107 | ('name -> ON','name',1,'p_name','parser.py',457), 108 | ('name -> TRUE','name',1,'p_name','parser.py',458), 109 | ('name -> FALSE','name',1,'p_name','parser.py',459), 110 | ('name -> NULL','name',1,'p_name','parser.py',460), 111 | ('alias -> name COLON','alias',2,'p_alias','parser.py',466), 112 | ('value -> variable','value',1,'p_value','parser.py',472), 113 | ('value -> INT_VALUE','value',1,'p_value','parser.py',473), 114 | ('value -> FLOAT_VALUE','value',1,'p_value','parser.py',474), 115 | ('value -> STRING_VALUE','value',1,'p_value','parser.py',475), 116 | ('value -> null_value','value',1,'p_value','parser.py',476), 117 | ('value -> boolean_value','value',1,'p_value','parser.py',477), 118 | ('value -> enum_value','value',1,'p_value','parser.py',478), 119 | ('value -> list_value','value',1,'p_value','parser.py',479), 120 | ('value -> object_value','value',1,'p_value','parser.py',480), 121 | ('const_value -> INT_VALUE','const_value',1,'p_const_value','parser.py',486), 122 | ('const_value -> FLOAT_VALUE','const_value',1,'p_const_value','parser.py',487), 123 | ('const_value -> STRING_VALUE','const_value',1,'p_const_value','parser.py',488), 124 | ('const_value -> null_value','const_value',1,'p_const_value','parser.py',489), 125 | ('const_value -> boolean_value','const_value',1,'p_const_value','parser.py',490), 126 | ('const_value -> enum_value','const_value',1,'p_const_value','parser.py',491), 127 | ('const_value -> const_list_value','const_value',1,'p_const_value','parser.py',492), 128 | ('const_value -> const_object_value','const_value',1,'p_const_value','parser.py',493), 129 | ('boolean_value -> TRUE','boolean_value',1,'p_boolean_value','parser.py',499), 130 | ('boolean_value -> FALSE','boolean_value',1,'p_boolean_value','parser.py',500), 131 | ('null_value -> NULL','null_value',1,'p_null_value','parser.py',506), 132 | ('enum_value -> NAME','enum_value',1,'p_enum_value','parser.py',512), 133 | ('enum_value -> FRAGMENT','enum_value',1,'p_enum_value','parser.py',513), 134 | ('enum_value -> QUERY','enum_value',1,'p_enum_value','parser.py',514), 135 | ('enum_value -> MUTATION','enum_value',1,'p_enum_value','parser.py',515), 136 | ('enum_value -> SUBSCRIPTION','enum_value',1,'p_enum_value','parser.py',516), 137 | ('enum_value -> ON','enum_value',1,'p_enum_value','parser.py',517), 138 | ('list_value -> BRACKET_L value_list BRACKET_R','list_value',3,'p_list_value','parser.py',523), 139 | ('list_value -> BRACKET_L BRACKET_R','list_value',2,'p_list_value','parser.py',524), 140 | ('value_list -> value_list value','value_list',2,'p_value_list','parser.py',530), 141 | ('value_list -> value','value_list',1,'p_value_list_single','parser.py',536), 142 | ('const_list_value -> BRACKET_L const_value_list BRACKET_R','const_list_value',3,'p_const_list_value','parser.py',542), 143 | ('const_list_value -> BRACKET_L BRACKET_R','const_list_value',2,'p_const_list_value','parser.py',543), 144 | ('const_value_list -> const_value_list const_value','const_value_list',2,'p_const_value_list','parser.py',549), 145 | ('const_value_list -> const_value','const_value_list',1,'p_const_value_list_single','parser.py',555), 146 | ('object_value -> BRACE_L object_field_list BRACE_R','object_value',3,'p_object_value','parser.py',561), 147 | ('object_value -> BRACE_L BRACE_R','object_value',2,'p_object_value','parser.py',562), 148 | ('object_field_list -> object_field_list object_field','object_field_list',2,'p_object_field_list','parser.py',568), 149 | ('object_field_list -> object_field','object_field_list',1,'p_object_field_list_single','parser.py',576), 150 | ('object_field -> name COLON value','object_field',3,'p_object_field','parser.py',582), 151 | ('const_object_value -> BRACE_L const_object_field_list BRACE_R','const_object_value',3,'p_const_object_value','parser.py',588), 152 | ('const_object_value -> BRACE_L BRACE_R','const_object_value',2,'p_const_object_value','parser.py',589), 153 | ('const_object_field_list -> const_object_field_list const_object_field','const_object_field_list',2,'p_const_object_field_list','parser.py',595), 154 | ('const_object_field_list -> const_object_field','const_object_field_list',1,'p_const_object_field_list_single','parser.py',603), 155 | ('const_object_field -> name COLON const_value','const_object_field',3,'p_const_object_field','parser.py',609), 156 | ('type -> named_type','type',1,'p_type','parser.py',615), 157 | ('type -> list_type','type',1,'p_type','parser.py',616), 158 | ('type -> non_null_type','type',1,'p_type','parser.py',617), 159 | ('named_type -> name','named_type',1,'p_named_type','parser.py',623), 160 | ('list_type -> BRACKET_L type BRACKET_R','list_type',3,'p_list_type','parser.py',629), 161 | ('non_null_type -> named_type BANG','non_null_type',2,'p_non_null_type','parser.py',635), 162 | ('non_null_type -> list_type BANG','non_null_type',2,'p_non_null_type','parser.py',636), 163 | ] 164 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ply==3.6 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import graphql 5 | 6 | try: 7 | from setuptools import setup 8 | except ImportError: 9 | from distutils.core import setup 10 | 11 | os.environ['PYTHONDONTWRITEBYTECODE'] = '1' 12 | 13 | packages = ['graphql'] 14 | requires = ['ply>=3.6'] 15 | 16 | setup( 17 | name='graphql-py', 18 | version=graphql.__version__, 19 | description='graphql-py: Parser for latest GraphQL specification', 20 | long_description=open('README.rst').read(), 21 | author='Denis Stebunov', 22 | author_email='support@ivelum.com', 23 | url='https://github.com/ivelum/graphql-py/', 24 | packages=packages, 25 | install_requires=requires, 26 | license=open('LICENSE').read(), 27 | zip_safe=False, 28 | classifiers=[ 29 | 'Development Status :: 3 - Alpha', 30 | 'Intended Audience :: Developers', 31 | 'Natural Language :: English', 32 | 'License :: OSI Approved :: MIT License', 33 | 'Programming Language :: Python', 34 | 'Programming Language :: Python :: 2.7', 35 | 'Programming Language :: Python :: 3.4', 36 | 'Programming Language :: Python :: 3.5', 37 | 'Programming Language :: Python :: 3.6', 38 | 'Programming Language :: Python :: 3.7', 39 | 'Programming Language :: Python :: 3.8', 40 | 'Programming Language :: Python :: 3.9', 41 | ], 42 | ) 43 | 44 | del os.environ['PYTHONDONTWRITEBYTECODE'] 45 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivelum/graphql-py/9859dff2d1adb1a738c5bcfa31ff8cef5b6caad1/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_ast.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | from graphql.ast import Document, Query, Mutation, Field 4 | 5 | 6 | class GraphQLASTTest(TestCase): 7 | def test_equality(self): 8 | self.assertEqual(Document(), Document()) 9 | doc1 = Document(definitions=[ 10 | Query(selections=[Field(name='me')], name='q'), 11 | ]) 12 | self.assertEqual( 13 | doc1, 14 | Document(definitions=[ 15 | Query(selections=[Field(name='me')], name='q') 16 | ]), 17 | ) 18 | self.assertNotEqual( 19 | doc1, 20 | Document(definitions=[ 21 | Query(selections=[Field(name='not_me')], name='q') 22 | ]), 23 | ) 24 | self.assertNotEqual( 25 | doc1, 26 | Document(definitions=[ 27 | Mutation(selections=[Field(name='me')], name='q') 28 | ]), 29 | ) 30 | -------------------------------------------------------------------------------- /tests/test_lexer.py: -------------------------------------------------------------------------------- 1 | from decimal import Decimal 2 | from unittest import TestCase 3 | 4 | from graphql.lexer import GraphQLLexer 5 | from graphql.exceptions import LexerError 6 | 7 | 8 | class GraphQLLexerTest(TestCase): 9 | lexer = GraphQLLexer() 10 | 11 | def assert_output(self, lexer, expected): 12 | actual = list(lexer) 13 | len_actual = len(actual) 14 | len_expected = len(expected) 15 | self.assertEqual( 16 | len_actual, 17 | len_expected, 18 | 'Actual output length %s does not match expected length %s\n' 19 | 'Actual: %s\n' 20 | 'Expected: %s' % (len_actual, len_expected, actual, expected) 21 | ) 22 | for i, token in enumerate(actual): 23 | self.assertEqual(token.type, expected[i][0]) 24 | self.assertEqual(token.value, expected[i][1]) 25 | 26 | def test_punctuator(self): 27 | self.assert_output(self.lexer.input('!'), [('BANG', '!')]) 28 | self.assert_output(self.lexer.input('$'), [('DOLLAR', '$')]) 29 | self.assert_output(self.lexer.input('('), [('PAREN_L', '(')]) 30 | self.assert_output(self.lexer.input(')'), [('PAREN_R', ')')]) 31 | self.assert_output(self.lexer.input(':'), [('COLON', ':')]) 32 | self.assert_output(self.lexer.input('='), [('EQUALS', '=')]) 33 | self.assert_output(self.lexer.input('@'), [('AT', '@')]) 34 | self.assert_output(self.lexer.input('['), [('BRACKET_L', '[')]) 35 | self.assert_output(self.lexer.input(']'), [('BRACKET_R', ']')]) 36 | self.assert_output(self.lexer.input('{'), [('BRACE_L', '{')]) 37 | self.assert_output(self.lexer.input('}'), [('BRACE_R', '}')]) 38 | self.assert_output(self.lexer.input('...'), [('SPREAD', '...')]) 39 | 40 | def test_name(self): 41 | for name in ('a', 'myVar_42', '__LOL__', '_', '_0'): 42 | self.assert_output(self.lexer.input(name), [('NAME', name)]) 43 | 44 | def test_reserved_words(self): 45 | reserved = ('fragment', 'query', 'mutation', 'on') 46 | for word in reserved: 47 | self.assert_output(self.lexer.input(word), [(word.upper(), word)]) 48 | # A word made of reserved words should be treated as a name 49 | for word in ('queryType', 'mutation42', 'on_fragment'): 50 | self.assert_output(self.lexer.input(word), [('NAME', word)]) 51 | 52 | def test_true(self): 53 | self.assert_output(self.lexer.input('true'), [('TRUE', True)]) 54 | self.assert_output(self.lexer.input('True'), [('NAME', 'True')]) 55 | 56 | def test_false(self): 57 | self.assert_output(self.lexer.input('false'), [('FALSE', False)]) 58 | self.assert_output(self.lexer.input('False'), [('NAME', 'False')]) 59 | 60 | def test_null(self): 61 | self.assert_output(self.lexer.input('null'), [('NULL', None)]) 62 | self.assert_output(self.lexer.input('Null'), [('NAME', 'Null')]) 63 | 64 | def test_int(self): 65 | for val in ('0', '-0', '42', '-42'): 66 | self.assert_output( 67 | self.lexer.input(val), 68 | [('INT_VALUE', int(val))], 69 | ) 70 | 71 | def test_float(self): 72 | for val in ('-0.5e+42', '42.0', '2E64', '2.71e-0002'): 73 | self.assert_output( 74 | self.lexer.input(val), 75 | [('FLOAT_VALUE', Decimal(val))], 76 | ) 77 | 78 | def test_string(self): 79 | for s in ('""', u'""', '"42"', r'"\t\n\u0042 ^"'): 80 | self.assert_output( 81 | self.lexer.input(s), 82 | [('STRING_VALUE', s.strip('"'))] 83 | ) 84 | 85 | def test_comment(self): 86 | lexer = self.lexer.input(""" 87 | 42 # lol this is a number. But this -> 9000 is not. 88 | "" # lol this is a string. But this -> "gav" is not. 89 | # lol the whole line commented 90 | # 91 | """) 92 | self.assert_output(lexer, [('INT_VALUE', 42), ('STRING_VALUE', '')]) 93 | 94 | def test_illegal_chars(self): 95 | for s in ('"', '^'): 96 | try: 97 | list(self.lexer.input(s)) 98 | self.fail('Illegal char exception not raised for %s' % repr(s)) 99 | except LexerError as e: 100 | self.assertEqual(1, e.line) 101 | self.assertEqual(1, e.column) 102 | self.assertTrue( 103 | str(e).startswith('Line 1, col 1: Illegal character') 104 | ) 105 | self.assertEqual(s, e.value) 106 | 107 | def test_positional_info(self): 108 | for i, t in enumerate(self.lexer.input('1\n 3\n 5\n')): 109 | self.assertEqual(i + 1, t.lineno) 110 | self.assertEqual(i * 2 + 1, self.lexer.find_column(t)) 111 | 112 | -------------------------------------------------------------------------------- /tests/test_parser.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | from graphql.ast import Argument, Document, Field, FragmentDefinition, \ 4 | FragmentSpread, Mutation, NamedType, NonNullType, Query, Subscription, \ 5 | Variable, VariableDefinition 6 | from graphql.parser import GraphQLParser 7 | 8 | 9 | class GraphQLParseTest(TestCase): 10 | parser = GraphQLParser() 11 | 12 | def test_shorthand(self): 13 | self.assertEqual( 14 | self.parser.parse('{ me { name } }'), 15 | Document(definitions=[ 16 | Query(selections=[ 17 | Field(selections=[Field(name='name')], name='me') 18 | ]) 19 | ]) 20 | ) 21 | self.assertEqual( 22 | self.parser.parse(""" 23 | { 24 | user(id: 4) { 25 | id 26 | name 27 | profilePic 28 | avatar: profilePic(width: 30, height: 30) 29 | } 30 | } 31 | """), 32 | Document(definitions=[ 33 | Query(selections=[ 34 | Field( 35 | selections=[ 36 | Field(name='id'), 37 | Field(name='name'), 38 | Field(name='profilePic'), 39 | Field(alias='avatar', name='profilePic', arguments=[ 40 | Argument(name='width', value=30), 41 | Argument(name='height', value=30) 42 | ]) 43 | ], 44 | name='user', 45 | arguments=[Argument(name='id', value=4)] 46 | ) 47 | ]) 48 | ]) 49 | ) 50 | 51 | def test_mutation_shorthand(self): 52 | self.assertEqual( 53 | self.parser.parse(""" 54 | mutation { 55 | likeStory(storyID: 12345) { 56 | story { 57 | likeCount 58 | } 59 | } 60 | } 61 | """), 62 | Document(definitions=[ 63 | Mutation(selections=[ 64 | Field( 65 | selections=[ 66 | Field(name='story', selections=[ 67 | Field(name='likeCount') 68 | ]), 69 | ], 70 | name='likeStory', 71 | arguments=[Argument(name='storyID', value=12345)] 72 | ) 73 | ]) 74 | ]) 75 | ) 76 | 77 | def test_with_fragments(self): 78 | self.assertEqual( 79 | self.parser.parse(""" 80 | query withNestedFragments { 81 | user(id: 4) { 82 | friends(first: 10) { 83 | ...friendFields 84 | } 85 | mutualFriends(first: 10) { 86 | ...friendFields 87 | } 88 | } 89 | } 90 | 91 | fragment friendFields on User { 92 | id 93 | name 94 | ...standardProfilePic 95 | } 96 | 97 | fragment standardProfilePic on User { 98 | profilePic(size: "small") 99 | } 100 | """), 101 | Document(definitions=[ 102 | Query(name='withNestedFragments', 103 | selections=[ 104 | Field(selections=[ 105 | Field(selections=[ 106 | FragmentSpread(name='friendFields') 107 | ], 108 | name='friends', 109 | arguments=[ 110 | Argument(name='first', value=10) 111 | ]), 112 | Field(selections=[ 113 | FragmentSpread(name='friendFields') 114 | ], 115 | name='mutualFriends', 116 | arguments=[ 117 | Argument(name='first', value=10) 118 | ]) 119 | ], 120 | name='user', 121 | arguments=[Argument(name='id', value=4)]) 122 | ] 123 | ), 124 | FragmentDefinition(type_condition=NamedType(name='User'), 125 | name='friendFields', 126 | selections=[ 127 | Field(name='id'), 128 | Field(name='name'), 129 | FragmentSpread(name='standardProfilePic') 130 | ] 131 | ), 132 | FragmentDefinition(type_condition=NamedType(name='User'), 133 | name='standardProfilePic', 134 | selections=[ 135 | Field(name='profilePic', 136 | arguments=[Argument(name='size', value='small')] 137 | ) 138 | ]) 139 | ]) 140 | ) 141 | 142 | def test_shorthand_query_with_fragments(self): 143 | self.assertEqual( 144 | self.parser.parse(""" 145 | { 146 | hero { 147 | name 148 | ...DroidFields 149 | } 150 | } 151 | 152 | fragment DroidFields on Droid { 153 | primaryFunction 154 | } 155 | """), 156 | Document(definitions=[ 157 | Query(selections=[ 158 | Field( 159 | name='hero', 160 | selections=[ 161 | Field(name='name'), 162 | FragmentSpread(name='DroidFields'), 163 | ] 164 | ), 165 | ]), 166 | FragmentDefinition(type_condition=NamedType(name='Droid'), 167 | name='DroidFields', 168 | selections=[Field(name='primaryFunction')] 169 | ), 170 | ]) 171 | ) 172 | 173 | def test_shorthand_vs_query(self): 174 | self.assertEqual( 175 | self.parser.parse(""" 176 | query { 177 | hero { 178 | name 179 | } 180 | } 181 | """), 182 | self.parser.parse(""" 183 | { 184 | hero { 185 | name 186 | } 187 | } 188 | """), 189 | ) 190 | 191 | def test_variables(self): 192 | self.assertEqual( 193 | self.parser.parse(""" 194 | query withVariable($userId: Int = 0, $userName: String) { 195 | user(id: $userId, name: $userName) { 196 | nick 197 | } 198 | } 199 | """), 200 | Document(definitions=[Query( 201 | name='withVariable', 202 | variable_definitions=[VariableDefinition( 203 | name='userId', 204 | type=NamedType(name='Int'), 205 | default_value=0 206 | ), VariableDefinition( 207 | name='userName', 208 | type=NamedType(name='String') 209 | )], 210 | selections=[Field( 211 | selections=[Field(name='nick')], 212 | name='user', 213 | arguments=[Argument( 214 | name='id', 215 | value=Variable(name='userId'), 216 | ), Argument( 217 | name='name', 218 | value=Variable(name='userName') 219 | )] 220 | )]) 221 | ]) 222 | ) 223 | 224 | def test_arguments(self): 225 | self.assertEqual( 226 | self.parser.parse(""" 227 | { 228 | episodes (number: null, isPrequel: false) { 229 | id 230 | } 231 | } 232 | """), 233 | Document(definitions=[Query( 234 | selections=[Field( 235 | selections=[Field(name='id')], 236 | name='episodes', 237 | arguments=[Argument( 238 | name='number', 239 | value=None 240 | ), Argument( 241 | name='isPrequel', 242 | value=False 243 | )] 244 | )]) 245 | ]) 246 | ) 247 | 248 | def test_with_subscription(self): 249 | self.assertEqual( 250 | self.parser.parse(""" 251 | subscription onSomething($deviceId: ID!) { 252 | onSomething(deviceId: $deviceId,) { 253 | deviceId 254 | deviceType 255 | datapoints { 256 | id 257 | } 258 | } 259 | } 260 | """), 261 | Document(definitions=[ 262 | Subscription( 263 | name="onSomething", 264 | selections=[ 265 | Field( 266 | name="onSomething", 267 | arguments=[Argument( 268 | name="deviceId", 269 | value=Variable( 270 | name="deviceId" 271 | ) 272 | )], 273 | selections=[ 274 | Field( 275 | name="deviceId" 276 | ), 277 | Field( 278 | name="deviceType" 279 | ), 280 | Field( 281 | name="datapoints", 282 | selections=[ 283 | Field(name="id") 284 | ] 285 | ) 286 | ] 287 | ) 288 | ], 289 | variable_definitions=[ 290 | VariableDefinition( 291 | name="deviceId", 292 | type=NonNullType( 293 | type=NamedType( 294 | name="ID" 295 | ) 296 | ) 297 | ) 298 | ] 299 | ) 300 | ]) 301 | ) 302 | --------------------------------------------------------------------------------