GraphQL-core is a Python port of GraphQL.js, the JavaScript reference implementation for GraphQL.
—
Validate GraphQL documents against schemas using specification-defined validation rules and custom validation logic. Ensures queries are well-formed, use valid fields and types, and follow GraphQL specification requirements before execution.
Validate complete GraphQL documents against a schema using all specification-defined rules.
def validate(
schema: GraphQLSchema,
document_ast: DocumentNode,
rules: Optional[Collection[Type[ASTValidationRule]]] = None,
max_errors: Optional[int] = None,
type_info: Optional[TypeInfo] = None,
) -> List[GraphQLError]Parameters:
schema: GraphQL schema to validate againstdocument_ast: Parsed GraphQL document AST to validaterules: Optional custom validation rules (defaults to specified_rules)max_errors: Maximum number of errors to collect before stoppingtype_info: Optional type information contextReturns: List of validation errors found in the document
from graphql import validate, parse, build_schema
schema = build_schema('''
type Query {
user(id: ID!): User
users: [User]
}
type User {
id: ID!
name: String
email: String
}
''')
# Valid query
valid_query_ast = parse('{ user(id: "123") { name email } }')
errors = validate(schema, valid_query_ast)
print(len(errors)) # 0
# Invalid query - unknown field
invalid_query_ast = parse('{ user(id: "123") { name invalidField } }')
errors = validate(schema, invalid_query_ast)
print(len(errors)) # 1
print(errors[0].message) # Cannot query field "invalidField" on type "User"Access validation state and type information during rule execution.
class ValidationContext:
def __init__(
self,
schema: GraphQLSchema,
document: DocumentNode,
type_info: TypeInfo,
on_error: Callable[[GraphQLError], None]
)
def report_error(self, error: GraphQLError) -> None
def get_errors(self) -> List[GraphQLError]
def get_schema(self) -> GraphQLSchema
def get_document(self) -> DocumentNode
def get_fragment(self, name: str) -> Optional[FragmentDefinitionNode]
def get_fragment_spreads(self, node: SelectionSetNode) -> List[FragmentSpreadNode]
def get_recursively_referenced_fragments(self, operation: OperationDefinitionNode) -> List[FragmentDefinitionNode]
class ASTValidationContext(ValidationContext):
"""Validation context for executable documents"""
pass
class SDLValidationContext(ValidationContext):
"""Validation context for schema definition language documents"""
passAll validation rules implement the ValidationRule interface and can be used individually or in combination.
class ValidationRule:
def __init__(self, context: ValidationContext)
def enter(self, node: Node, key: Optional[str], parent: Optional[Node], path: List[Union[int, str]], ancestors: List[Node]) -> Optional[VisitorAction]
def leave(self, node: Node, key: Optional[str], parent: Optional[Node], path: List[Union[int, str]], ancestors: List[Node]) -> Optional[VisitorAction]
class ASTValidationRule(ValidationRule):
"""Base class for executable document validation rules"""
pass
class SDLValidationRule(ValidationRule):
"""Base class for schema definition language validation rules"""
pass
# All specification-defined validation rules
specified_rules: List[Type[ValidationRule]]Specification-defined validation rules that can be used individually or customized.
# Executable definition rules
class ExecutableDefinitionsRule(ASTValidationRule):
"""Ensures only executable definitions (operations and fragments) are present"""
class LoneAnonymousOperationRule(ASTValidationRule):
"""Ensures anonymous operations are alone in the document"""
class UniqueOperationNamesRule(ASTValidationRule):
"""Ensures operation names are unique within a document"""
# Field and fragment rules
class FieldsOnCorrectTypeRule(ASTValidationRule):
"""Ensures fields are queried on types that define them"""
class FragmentsOnCompositeTypesRule(ASTValidationRule):
"""Ensures fragments are on composite types"""
class KnownFragmentNamesRule(ASTValidationRule):
"""Ensures fragment spreads refer to defined fragments"""
class NoFragmentCyclesRule(ASTValidationRule):
"""Prevents circular fragment references"""
class UniqueFragmentNamesRule(ASTValidationRule):
"""Ensures fragment names are unique"""
class NoUnusedFragmentsRule(ASTValidationRule):
"""Ensures all fragments are used"""
class PossibleFragmentSpreadsRule(ASTValidationRule):
"""Ensures fragment spreads are possible"""
class OverlappingFieldsCanBeMergedRule(ASTValidationRule):
"""Complex rule ensuring field selection merging is valid"""
# Argument rules
class KnownArgumentNamesRule(ASTValidationRule):
"""Ensures arguments are defined on fields and directives"""
class UniqueArgumentNamesRule(ASTValidationRule):
"""Ensures argument names are unique per field/directive"""
class ProvidedRequiredArgumentsRule(ASTValidationRule):
"""Ensures required arguments are provided"""
# Variable rules
class UniqueVariableNamesRule(ASTValidationRule):
"""Ensures variable names are unique per operation"""
class NoUndefinedVariablesRule(ASTValidationRule):
"""Ensures all used variables are defined"""
class NoUnusedVariablesRule(ASTValidationRule):
"""Ensures all defined variables are used"""
class VariablesAreInputTypesRule(ASTValidationRule):
"""Ensures variables are input types"""
class VariablesInAllowedPositionRule(ASTValidationRule):
"""Ensures variable usage matches definitions"""
# Value and type rules
class ValuesOfCorrectTypeRule(ASTValidationRule):
"""Ensures values match their expected types"""
class ScalarLeafsRule(ASTValidationRule):
"""Ensures scalar fields don't have selections"""
# Directive rules
class KnownDirectivesRule(ASTValidationRule):
"""Ensures directives are defined and in valid locations"""
class UniqueDirectivesPerLocationRule(ASTValidationRule):
"""Ensures non-repeatable directives appear once per location"""
# Subscription rules
class SingleFieldSubscriptionsRule(ASTValidationRule):
"""Ensures subscriptions select only one root field"""
# Miscellaneous rules
class KnownTypeNamesRule(ASTValidationRule):
"""Ensures type names exist in the schema"""
class UniqueInputFieldNamesRule(ASTValidationRule):
"""Ensures input object field names are unique"""Rules specific to validating schema definition language documents.
class LoneSchemaDefinitionRule(SDLValidationRule):
"""Ensures only one schema definition exists"""
class UniqueOperationTypesRule(SDLValidationRule):
"""Ensures operation types are unique in schema"""
class UniqueTypeNamesRule(SDLValidationRule):
"""Ensures type names are unique in schema"""
class UniqueEnumValueNamesRule(SDLValidationRule):
"""Ensures enum value names are unique per enum"""
class UniqueFieldDefinitionNamesRule(SDLValidationRule):
"""Ensures field names are unique per type"""
class UniqueArgumentDefinitionNamesRule(SDLValidationRule):
"""Ensures argument names are unique per field"""
class UniqueDirectiveNamesRule(SDLValidationRule):
"""Ensures directive names are unique in schema"""
class PossibleTypeExtensionsRule(SDLValidationRule):
"""Ensures type extensions are valid"""Optional rules not defined by the GraphQL specification but useful for specific use cases.
class NoDeprecatedCustomRule(ASTValidationRule):
"""Prevents usage of deprecated fields and enum values"""
class NoSchemaIntrospectionCustomRule(ASTValidationRule):
"""Prevents introspection queries for security"""from graphql import ValidationRule, GraphQLError
class NoIntrospectionRule(ValidationRule):
def enter_field(self, node, key, parent, path, ancestors):
if node.name.value.startswith('__'):
self.context.report_error(
GraphQLError(
'Introspection is disabled',
nodes=[node]
)
)
# Use custom rule
from graphql import validate, specified_rules
custom_rules = list(specified_rules) + [NoIntrospectionRule]
errors = validate(schema, document_ast, rules=custom_rules)Use TypeInfo to provide enhanced validation with type context.
from graphql.utilities import TypeInfo
# Create type info for enhanced validation
type_info = TypeInfo(schema)
errors = validate(schema, document_ast, type_info=type_info)from graphql import (
validate, parse, build_schema, specified_rules,
NoDeprecatedCustomRule, ValidationContext
)
schema = build_schema('''
type Query {
user(id: ID!): User
deprecated_field: String @deprecated(reason: "Use user instead")
}
type User {
id: ID!
name: String
old_name: String @deprecated
}
''')
query = parse('''
{
user(id: "123") {
name
old_name
}
deprecated_field
}
''')
# Validate with custom rules
all_rules = list(specified_rules) + [NoDeprecatedCustomRule]
errors = validate(schema, query_ast, rules=all_rules)
for error in errors:
print(f"Error: {error.message}")
if error.locations:
for location in error.locations:
print(f" at line {location.line}, column {location.column}")# Import required types
from typing import List, Optional, Sequence, Callable, Type, Union
from graphql.type import GraphQLSchema
from graphql.language import DocumentNode, Node, FragmentDefinitionNode, OperationDefinitionNode, SelectionSetNode, FragmentSpreadNode
from graphql.error import GraphQLError
from graphql.utilities import TypeInfo
from graphql.language.visitor import VisitorAction
# Core validation types
ValidationRule = Type[ValidationRule]
ASTValidationRule = Type[ASTValidationRule]
SDLValidationRule = Type[SDLValidationRule]
# Validation context types
ValidationContext = class ValidationContext
ASTValidationContext = class ASTValidationContext
SDLValidationContext = class SDLValidationContext
# Rule collections
specified_rules: List[Type[ValidationRule]]Install with Tessl CLI
npx tessl i tessl/pypi-graphql-core