808 lines
20 KiB
Python
808 lines
20 KiB
Python
from copy import copy, deepcopy
|
|
from enum import Enum
|
|
from typing import Any, Dict, List, Tuple, Optional, Union
|
|
|
|
from .source import Source
|
|
from .token_kind import TokenKind
|
|
from ..pyutils import camel_to_snake
|
|
|
|
__all__ = [
|
|
"Location",
|
|
"Token",
|
|
"Node",
|
|
"NameNode",
|
|
"DocumentNode",
|
|
"DefinitionNode",
|
|
"ExecutableDefinitionNode",
|
|
"OperationDefinitionNode",
|
|
"VariableDefinitionNode",
|
|
"SelectionSetNode",
|
|
"SelectionNode",
|
|
"FieldNode",
|
|
"ArgumentNode",
|
|
"ConstArgumentNode",
|
|
"FragmentSpreadNode",
|
|
"InlineFragmentNode",
|
|
"FragmentDefinitionNode",
|
|
"ValueNode",
|
|
"ConstValueNode",
|
|
"VariableNode",
|
|
"IntValueNode",
|
|
"FloatValueNode",
|
|
"StringValueNode",
|
|
"BooleanValueNode",
|
|
"NullValueNode",
|
|
"EnumValueNode",
|
|
"ListValueNode",
|
|
"ConstListValueNode",
|
|
"ObjectValueNode",
|
|
"ConstObjectValueNode",
|
|
"ObjectFieldNode",
|
|
"ConstObjectFieldNode",
|
|
"DirectiveNode",
|
|
"ConstDirectiveNode",
|
|
"TypeNode",
|
|
"NamedTypeNode",
|
|
"ListTypeNode",
|
|
"NonNullTypeNode",
|
|
"TypeSystemDefinitionNode",
|
|
"SchemaDefinitionNode",
|
|
"OperationType",
|
|
"OperationTypeDefinitionNode",
|
|
"TypeDefinitionNode",
|
|
"ScalarTypeDefinitionNode",
|
|
"ObjectTypeDefinitionNode",
|
|
"FieldDefinitionNode",
|
|
"InputValueDefinitionNode",
|
|
"InterfaceTypeDefinitionNode",
|
|
"UnionTypeDefinitionNode",
|
|
"EnumTypeDefinitionNode",
|
|
"EnumValueDefinitionNode",
|
|
"InputObjectTypeDefinitionNode",
|
|
"DirectiveDefinitionNode",
|
|
"SchemaExtensionNode",
|
|
"TypeExtensionNode",
|
|
"TypeSystemExtensionNode",
|
|
"ScalarTypeExtensionNode",
|
|
"ObjectTypeExtensionNode",
|
|
"InterfaceTypeExtensionNode",
|
|
"UnionTypeExtensionNode",
|
|
"EnumTypeExtensionNode",
|
|
"InputObjectTypeExtensionNode",
|
|
"QUERY_DOCUMENT_KEYS",
|
|
]
|
|
|
|
|
|
class Token:
|
|
"""AST Token
|
|
|
|
Represents a range of characters represented by a lexical token within a Source.
|
|
"""
|
|
|
|
__slots__ = "kind", "start", "end", "line", "column", "prev", "next", "value"
|
|
|
|
kind: TokenKind # the kind of token
|
|
start: int # the character offset at which this Node begins
|
|
end: int # the character offset at which this Node ends
|
|
line: int # the 1-indexed line number on which this Token appears
|
|
column: int # the 1-indexed column number at which this Token begins
|
|
# for non-punctuation tokens, represents the interpreted value of the token:
|
|
value: Optional[str]
|
|
# Tokens exist as nodes in a double-linked-list amongst all tokens including
|
|
# ignored tokens. <SOF> is always the first node and <EOF> the last.
|
|
prev: Optional["Token"]
|
|
next: Optional["Token"]
|
|
|
|
def __init__(
|
|
self,
|
|
kind: TokenKind,
|
|
start: int,
|
|
end: int,
|
|
line: int,
|
|
column: int,
|
|
value: Optional[str] = None,
|
|
) -> None:
|
|
self.kind = kind
|
|
self.start, self.end = start, end
|
|
self.line, self.column = line, column
|
|
self.value = value
|
|
self.prev = self.next = None
|
|
|
|
def __str__(self) -> str:
|
|
return self.desc
|
|
|
|
def __repr__(self) -> str:
|
|
"""Print a simplified form when appearing in repr() or inspect()."""
|
|
return f"<Token {self.desc} {self.line}:{self.column}>"
|
|
|
|
def __inspect__(self) -> str:
|
|
return repr(self)
|
|
|
|
def __eq__(self, other: Any) -> bool:
|
|
if isinstance(other, Token):
|
|
return (
|
|
self.kind == other.kind
|
|
and self.start == other.start
|
|
and self.end == other.end
|
|
and self.line == other.line
|
|
and self.column == other.column
|
|
and self.value == other.value
|
|
)
|
|
elif isinstance(other, str):
|
|
return other == self.desc
|
|
return False
|
|
|
|
def __hash__(self) -> int:
|
|
return hash(
|
|
(self.kind, self.start, self.end, self.line, self.column, self.value)
|
|
)
|
|
|
|
def __copy__(self) -> "Token":
|
|
"""Create a shallow copy of the token"""
|
|
token = self.__class__(
|
|
self.kind,
|
|
self.start,
|
|
self.end,
|
|
self.line,
|
|
self.column,
|
|
self.value,
|
|
)
|
|
token.prev = self.prev
|
|
return token
|
|
|
|
def __deepcopy__(self, memo: Dict) -> "Token":
|
|
"""Allow only shallow copies to avoid recursion."""
|
|
return copy(self)
|
|
|
|
def __getstate__(self) -> Dict[str, Any]:
|
|
"""Remove the links when pickling.
|
|
|
|
Keeping the links would make pickling a schema too expensive.
|
|
"""
|
|
return {
|
|
key: getattr(self, key)
|
|
for key in self.__slots__
|
|
if key not in {"prev", "next"}
|
|
}
|
|
|
|
def __setstate__(self, state: Dict[str, Any]) -> None:
|
|
"""Reset the links when un-pickling."""
|
|
for key, value in state.items():
|
|
setattr(self, key, value)
|
|
self.prev = self.next = None
|
|
|
|
@property
|
|
def desc(self) -> str:
|
|
"""A helper property to describe a token as a string for debugging"""
|
|
kind, value = self.kind.value, self.value
|
|
return f"{kind} {value!r}" if value else kind
|
|
|
|
|
|
class Location:
|
|
"""AST Location
|
|
|
|
Contains a range of UTF-8 character offsets and token references that identify the
|
|
region of the source from which the AST derived.
|
|
"""
|
|
|
|
__slots__ = (
|
|
"start",
|
|
"end",
|
|
"start_token",
|
|
"end_token",
|
|
"source",
|
|
)
|
|
|
|
start: int # character offset at which this Node begins
|
|
end: int # character offset at which this Node ends
|
|
start_token: Token # Token at which this Node begins
|
|
end_token: Token # Token at which this Node ends.
|
|
source: Source # Source document the AST represents
|
|
|
|
def __init__(self, start_token: Token, end_token: Token, source: Source) -> None:
|
|
self.start = start_token.start
|
|
self.end = end_token.end
|
|
self.start_token = start_token
|
|
self.end_token = end_token
|
|
self.source = source
|
|
|
|
def __str__(self) -> str:
|
|
return f"{self.start}:{self.end}"
|
|
|
|
def __repr__(self) -> str:
|
|
"""Print a simplified form when appearing in repr() or inspect()."""
|
|
return f"<Location {self.start}:{self.end}>"
|
|
|
|
def __inspect__(self) -> str:
|
|
return repr(self)
|
|
|
|
def __eq__(self, other: Any) -> bool:
|
|
if isinstance(other, Location):
|
|
return self.start == other.start and self.end == other.end
|
|
elif isinstance(other, (list, tuple)) and len(other) == 2:
|
|
return self.start == other[0] and self.end == other[1]
|
|
return False
|
|
|
|
def __ne__(self, other: Any) -> bool:
|
|
return not self == other
|
|
|
|
def __hash__(self) -> int:
|
|
return hash((self.start, self.end))
|
|
|
|
|
|
class OperationType(Enum):
|
|
|
|
QUERY = "query"
|
|
MUTATION = "mutation"
|
|
SUBSCRIPTION = "subscription"
|
|
|
|
|
|
# Default map from node kinds to their node attributes (internal)
|
|
QUERY_DOCUMENT_KEYS: Dict[str, Tuple[str, ...]] = {
|
|
"name": (),
|
|
"document": ("definitions",),
|
|
"operation_definition": (
|
|
"name",
|
|
"variable_definitions",
|
|
"directives",
|
|
"selection_set",
|
|
),
|
|
"variable_definition": ("variable", "type", "default_value", "directives"),
|
|
"variable": ("name",),
|
|
"selection_set": ("selections",),
|
|
"field": ("alias", "name", "arguments", "directives", "selection_set"),
|
|
"argument": ("name", "value"),
|
|
"fragment_spread": ("name", "directives"),
|
|
"inline_fragment": ("type_condition", "directives", "selection_set"),
|
|
"fragment_definition": (
|
|
# Note: fragment variable definitions are deprecated and will be removed in v3.3
|
|
"name",
|
|
"variable_definitions",
|
|
"type_condition",
|
|
"directives",
|
|
"selection_set",
|
|
),
|
|
"list_value": ("values",),
|
|
"object_value": ("fields",),
|
|
"object_field": ("name", "value"),
|
|
"directive": ("name", "arguments"),
|
|
"named_type": ("name",),
|
|
"list_type": ("type",),
|
|
"non_null_type": ("type",),
|
|
"schema_definition": ("description", "directives", "operation_types"),
|
|
"operation_type_definition": ("type",),
|
|
"scalar_type_definition": ("description", "name", "directives"),
|
|
"object_type_definition": (
|
|
"description",
|
|
"name",
|
|
"interfaces",
|
|
"directives",
|
|
"fields",
|
|
),
|
|
"field_definition": ("description", "name", "arguments", "type", "directives"),
|
|
"input_value_definition": (
|
|
"description",
|
|
"name",
|
|
"type",
|
|
"default_value",
|
|
"directives",
|
|
),
|
|
"interface_type_definition": (
|
|
"description",
|
|
"name",
|
|
"interfaces",
|
|
"directives",
|
|
"fields",
|
|
),
|
|
"union_type_definition": ("description", "name", "directives", "types"),
|
|
"enum_type_definition": ("description", "name", "directives", "values"),
|
|
"enum_value_definition": ("description", "name", "directives"),
|
|
"input_object_type_definition": ("description", "name", "directives", "fields"),
|
|
"directive_definition": ("description", "name", "arguments", "locations"),
|
|
"schema_extension": ("directives", "operation_types"),
|
|
"scalar_type_extension": ("name", "directives"),
|
|
"object_type_extension": ("name", "interfaces", "directives", "fields"),
|
|
"interface_type_extension": ("name", "interfaces", "directives", "fields"),
|
|
"union_type_extension": ("name", "directives", "types"),
|
|
"enum_type_extension": ("name", "directives", "values"),
|
|
"input_object_type_extension": ("name", "directives", "fields"),
|
|
}
|
|
|
|
|
|
# Base AST Node
|
|
|
|
|
|
class Node:
|
|
"""AST nodes"""
|
|
|
|
# allow custom attributes and weak references (not used internally)
|
|
__slots__ = "__dict__", "__weakref__", "loc", "_hash"
|
|
|
|
loc: Optional[Location]
|
|
|
|
kind: str = "ast" # the kind of the node as a snake_case string
|
|
keys: Tuple[str, ...] = ("loc",) # the names of the attributes of this node
|
|
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
"""Initialize the node with the given keyword arguments."""
|
|
for key in self.keys:
|
|
value = kwargs.get(key)
|
|
if isinstance(value, list):
|
|
value = tuple(value)
|
|
setattr(self, key, value)
|
|
|
|
def __repr__(self) -> str:
|
|
"""Get a simple representation of the node."""
|
|
name, loc = self.__class__.__name__, getattr(self, "loc", None)
|
|
return f"{name} at {loc}" if loc else name
|
|
|
|
def __eq__(self, other: Any) -> bool:
|
|
"""Test whether two nodes are equal (recursively)."""
|
|
return (
|
|
isinstance(other, Node)
|
|
and self.__class__ == other.__class__
|
|
and all(getattr(self, key) == getattr(other, key) for key in self.keys)
|
|
)
|
|
|
|
def __hash__(self) -> int:
|
|
"""Get a cached hash value for the node."""
|
|
# Caching the hash values improves the performance of AST validators
|
|
hashed = getattr(self, "_hash", None)
|
|
if hashed is None:
|
|
self._hash = id(self) # avoid recursion
|
|
hashed = hash(tuple(getattr(self, key) for key in self.keys))
|
|
self._hash = hashed
|
|
return hashed
|
|
|
|
def __setattr__(self, key: str, value: Any) -> None:
|
|
# reset cashed hash value if attributes are changed
|
|
if hasattr(self, "_hash") and key in self.keys:
|
|
del self._hash
|
|
super().__setattr__(key, value)
|
|
|
|
def __copy__(self) -> "Node":
|
|
"""Create a shallow copy of the node."""
|
|
return self.__class__(**{key: getattr(self, key) for key in self.keys})
|
|
|
|
def __deepcopy__(self, memo: Dict) -> "Node":
|
|
"""Create a deep copy of the node"""
|
|
# noinspection PyArgumentList
|
|
return self.__class__(
|
|
**{key: deepcopy(getattr(self, key), memo) for key in self.keys}
|
|
)
|
|
|
|
def __init_subclass__(cls) -> None:
|
|
super().__init_subclass__()
|
|
name = cls.__name__
|
|
try:
|
|
name = name.removeprefix("Const").removesuffix("Node")
|
|
except AttributeError: # pragma: no cover (Python < 3.9)
|
|
if name.startswith("Const"):
|
|
name = name[5:]
|
|
if name.endswith("Node"):
|
|
name = name[:-4]
|
|
cls.kind = camel_to_snake(name)
|
|
keys: List[str] = []
|
|
for base in cls.__bases__:
|
|
# noinspection PyUnresolvedReferences
|
|
keys.extend(base.keys) # type: ignore
|
|
keys.extend(cls.__slots__)
|
|
cls.keys = tuple(keys)
|
|
|
|
def to_dict(self, locations: bool = False) -> Dict:
|
|
from ..utilities import ast_to_dict
|
|
|
|
return ast_to_dict(self, locations)
|
|
|
|
|
|
# Name
|
|
|
|
|
|
class NameNode(Node):
|
|
__slots__ = ("value",)
|
|
|
|
value: str
|
|
|
|
|
|
# Document
|
|
|
|
|
|
class DocumentNode(Node):
|
|
__slots__ = ("definitions",)
|
|
|
|
definitions: Tuple["DefinitionNode", ...]
|
|
|
|
|
|
class DefinitionNode(Node):
|
|
__slots__ = ()
|
|
|
|
|
|
class ExecutableDefinitionNode(DefinitionNode):
|
|
__slots__ = "name", "directives", "variable_definitions", "selection_set"
|
|
|
|
name: Optional[NameNode]
|
|
directives: Tuple["DirectiveNode", ...]
|
|
variable_definitions: Tuple["VariableDefinitionNode", ...]
|
|
selection_set: "SelectionSetNode"
|
|
|
|
|
|
class OperationDefinitionNode(ExecutableDefinitionNode):
|
|
__slots__ = ("operation",)
|
|
|
|
operation: OperationType
|
|
|
|
|
|
class VariableDefinitionNode(Node):
|
|
__slots__ = "variable", "type", "default_value", "directives"
|
|
|
|
variable: "VariableNode"
|
|
type: "TypeNode"
|
|
default_value: Optional["ConstValueNode"]
|
|
directives: Tuple["ConstDirectiveNode", ...]
|
|
|
|
|
|
class SelectionSetNode(Node):
|
|
__slots__ = ("selections",)
|
|
|
|
selections: Tuple["SelectionNode", ...]
|
|
|
|
|
|
class SelectionNode(Node):
|
|
__slots__ = ("directives",)
|
|
|
|
directives: Tuple["DirectiveNode", ...]
|
|
|
|
|
|
class FieldNode(SelectionNode):
|
|
__slots__ = "alias", "name", "arguments", "selection_set"
|
|
|
|
alias: Optional[NameNode]
|
|
name: NameNode
|
|
arguments: Tuple["ArgumentNode", ...]
|
|
selection_set: Optional[SelectionSetNode]
|
|
|
|
|
|
class ArgumentNode(Node):
|
|
__slots__ = "name", "value"
|
|
|
|
name: NameNode
|
|
value: "ValueNode"
|
|
|
|
|
|
class ConstArgumentNode(ArgumentNode):
|
|
|
|
value: "ConstValueNode"
|
|
|
|
|
|
# Fragments
|
|
|
|
|
|
class FragmentSpreadNode(SelectionNode):
|
|
__slots__ = ("name",)
|
|
|
|
name: NameNode
|
|
|
|
|
|
class InlineFragmentNode(SelectionNode):
|
|
__slots__ = "type_condition", "selection_set"
|
|
|
|
type_condition: "NamedTypeNode"
|
|
selection_set: SelectionSetNode
|
|
|
|
|
|
class FragmentDefinitionNode(ExecutableDefinitionNode):
|
|
__slots__ = ("type_condition",)
|
|
|
|
name: NameNode
|
|
type_condition: "NamedTypeNode"
|
|
|
|
|
|
# Values
|
|
|
|
|
|
class ValueNode(Node):
|
|
__slots__ = ()
|
|
|
|
|
|
class VariableNode(ValueNode):
|
|
__slots__ = ("name",)
|
|
|
|
name: NameNode
|
|
|
|
|
|
class IntValueNode(ValueNode):
|
|
__slots__ = ("value",)
|
|
|
|
value: str
|
|
|
|
|
|
class FloatValueNode(ValueNode):
|
|
__slots__ = ("value",)
|
|
|
|
value: str
|
|
|
|
|
|
class StringValueNode(ValueNode):
|
|
__slots__ = "value", "block"
|
|
|
|
value: str
|
|
block: Optional[bool]
|
|
|
|
|
|
class BooleanValueNode(ValueNode):
|
|
__slots__ = ("value",)
|
|
|
|
value: bool
|
|
|
|
|
|
class NullValueNode(ValueNode):
|
|
__slots__ = ()
|
|
|
|
|
|
class EnumValueNode(ValueNode):
|
|
__slots__ = ("value",)
|
|
|
|
value: str
|
|
|
|
|
|
class ListValueNode(ValueNode):
|
|
__slots__ = ("values",)
|
|
|
|
values: Tuple[ValueNode, ...]
|
|
|
|
|
|
class ConstListValueNode(ListValueNode):
|
|
|
|
values: Tuple["ConstValueNode", ...]
|
|
|
|
|
|
class ObjectValueNode(ValueNode):
|
|
__slots__ = ("fields",)
|
|
|
|
fields: Tuple["ObjectFieldNode", ...]
|
|
|
|
|
|
class ConstObjectValueNode(ObjectValueNode):
|
|
|
|
fields: Tuple["ConstObjectFieldNode", ...]
|
|
|
|
|
|
class ObjectFieldNode(Node):
|
|
__slots__ = "name", "value"
|
|
|
|
name: NameNode
|
|
value: ValueNode
|
|
|
|
|
|
class ConstObjectFieldNode(ObjectFieldNode):
|
|
|
|
value: "ConstValueNode"
|
|
|
|
|
|
ConstValueNode = Union[
|
|
IntValueNode,
|
|
FloatValueNode,
|
|
StringValueNode,
|
|
BooleanValueNode,
|
|
NullValueNode,
|
|
EnumValueNode,
|
|
ConstListValueNode,
|
|
ConstObjectValueNode,
|
|
]
|
|
|
|
|
|
# Directives
|
|
|
|
|
|
class DirectiveNode(Node):
|
|
__slots__ = "name", "arguments"
|
|
|
|
name: NameNode
|
|
arguments: Tuple[ArgumentNode, ...]
|
|
|
|
|
|
class ConstDirectiveNode(DirectiveNode):
|
|
|
|
arguments: Tuple[ConstArgumentNode, ...]
|
|
|
|
|
|
# Type Reference
|
|
|
|
|
|
class TypeNode(Node):
|
|
__slots__ = ()
|
|
|
|
|
|
class NamedTypeNode(TypeNode):
|
|
__slots__ = ("name",)
|
|
|
|
name: NameNode
|
|
|
|
|
|
class ListTypeNode(TypeNode):
|
|
__slots__ = ("type",)
|
|
|
|
type: TypeNode
|
|
|
|
|
|
class NonNullTypeNode(TypeNode):
|
|
__slots__ = ("type",)
|
|
|
|
type: Union[NamedTypeNode, ListTypeNode]
|
|
|
|
|
|
# Type System Definition
|
|
|
|
|
|
class TypeSystemDefinitionNode(DefinitionNode):
|
|
__slots__ = ()
|
|
|
|
|
|
class SchemaDefinitionNode(TypeSystemDefinitionNode):
|
|
__slots__ = "description", "directives", "operation_types"
|
|
|
|
description: Optional[StringValueNode]
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
operation_types: Tuple["OperationTypeDefinitionNode", ...]
|
|
|
|
|
|
class OperationTypeDefinitionNode(Node):
|
|
__slots__ = "operation", "type"
|
|
|
|
operation: OperationType
|
|
type: NamedTypeNode
|
|
|
|
|
|
# Type Definition
|
|
|
|
|
|
class TypeDefinitionNode(TypeSystemDefinitionNode):
|
|
__slots__ = "description", "name", "directives"
|
|
|
|
description: Optional[StringValueNode]
|
|
name: NameNode
|
|
directives: Tuple[DirectiveNode, ...]
|
|
|
|
|
|
class ScalarTypeDefinitionNode(TypeDefinitionNode):
|
|
__slots__ = ()
|
|
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
|
|
|
|
class ObjectTypeDefinitionNode(TypeDefinitionNode):
|
|
__slots__ = "interfaces", "fields"
|
|
|
|
interfaces: Tuple[NamedTypeNode, ...]
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
fields: Tuple["FieldDefinitionNode", ...]
|
|
|
|
|
|
class FieldDefinitionNode(DefinitionNode):
|
|
__slots__ = "description", "name", "directives", "arguments", "type"
|
|
|
|
description: Optional[StringValueNode]
|
|
name: NameNode
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
arguments: Tuple["InputValueDefinitionNode", ...]
|
|
type: TypeNode
|
|
|
|
|
|
class InputValueDefinitionNode(DefinitionNode):
|
|
__slots__ = "description", "name", "directives", "type", "default_value"
|
|
|
|
description: Optional[StringValueNode]
|
|
name: NameNode
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
type: TypeNode
|
|
default_value: Optional[ConstValueNode]
|
|
|
|
|
|
class InterfaceTypeDefinitionNode(TypeDefinitionNode):
|
|
__slots__ = "fields", "interfaces"
|
|
|
|
fields: Tuple["FieldDefinitionNode", ...]
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
interfaces: Tuple[NamedTypeNode, ...]
|
|
|
|
|
|
class UnionTypeDefinitionNode(TypeDefinitionNode):
|
|
__slots__ = ("types",)
|
|
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
types: Tuple[NamedTypeNode, ...]
|
|
|
|
|
|
class EnumTypeDefinitionNode(TypeDefinitionNode):
|
|
__slots__ = ("values",)
|
|
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
values: Tuple["EnumValueDefinitionNode", ...]
|
|
|
|
|
|
class EnumValueDefinitionNode(DefinitionNode):
|
|
__slots__ = "description", "name", "directives"
|
|
|
|
description: Optional[StringValueNode]
|
|
name: NameNode
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
|
|
|
|
class InputObjectTypeDefinitionNode(TypeDefinitionNode):
|
|
__slots__ = ("fields",)
|
|
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
fields: Tuple[InputValueDefinitionNode, ...]
|
|
|
|
|
|
# Directive Definitions
|
|
|
|
|
|
class DirectiveDefinitionNode(TypeSystemDefinitionNode):
|
|
__slots__ = "description", "name", "arguments", "repeatable", "locations"
|
|
|
|
description: Optional[StringValueNode]
|
|
name: NameNode
|
|
arguments: Tuple[InputValueDefinitionNode, ...]
|
|
repeatable: bool
|
|
locations: Tuple[NameNode, ...]
|
|
|
|
|
|
# Type System Extensions
|
|
|
|
|
|
class SchemaExtensionNode(Node):
|
|
__slots__ = "directives", "operation_types"
|
|
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
operation_types: Tuple[OperationTypeDefinitionNode, ...]
|
|
|
|
|
|
# Type Extensions
|
|
|
|
|
|
class TypeExtensionNode(TypeSystemDefinitionNode):
|
|
__slots__ = "name", "directives"
|
|
|
|
name: NameNode
|
|
directives: Tuple[ConstDirectiveNode, ...]
|
|
|
|
|
|
TypeSystemExtensionNode = Union[SchemaExtensionNode, TypeExtensionNode]
|
|
|
|
|
|
class ScalarTypeExtensionNode(TypeExtensionNode):
|
|
__slots__ = ()
|
|
|
|
|
|
class ObjectTypeExtensionNode(TypeExtensionNode):
|
|
__slots__ = "interfaces", "fields"
|
|
|
|
interfaces: Tuple[NamedTypeNode, ...]
|
|
fields: Tuple[FieldDefinitionNode, ...]
|
|
|
|
|
|
class InterfaceTypeExtensionNode(TypeExtensionNode):
|
|
__slots__ = "interfaces", "fields"
|
|
|
|
interfaces: Tuple[NamedTypeNode, ...]
|
|
fields: Tuple[FieldDefinitionNode, ...]
|
|
|
|
|
|
class UnionTypeExtensionNode(TypeExtensionNode):
|
|
__slots__ = ("types",)
|
|
|
|
types: Tuple[NamedTypeNode, ...]
|
|
|
|
|
|
class EnumTypeExtensionNode(TypeExtensionNode):
|
|
__slots__ = ("values",)
|
|
|
|
values: Tuple[EnumValueDefinitionNode, ...]
|
|
|
|
|
|
class InputObjectTypeExtensionNode(TypeExtensionNode):
|
|
__slots__ = ("fields",)
|
|
|
|
fields: Tuple[InputValueDefinitionNode, ...]
|