Ejemplo n.º 1
0
    def validate(self) -> bool:
        """
        Check that the given schema is valid.

        :return: bool
        """
        # TODO: Optimization: most validation functions iterate over
        # the schema types: it could be done in one loop.
        validators = [
            self._validate_schema_named_types,
            self._validate_object_follow_interfaces,
            self._validate_schema_root_types_exist,
            self._validate_non_empty_object,
            self._validate_union_is_acceptable,
            self._validate_all_scalars_have_implementations,
            self._validate_enum_values_are_unique,
            self._validate_arguments_have_valid_type,
            self._validate_input_type_composed_of_input_type,
            self._validate_directive_implementation
            # TODO: Validate Field: default value must be of given type
            # TODO: Check all objects have resolvers (at least in parent)
        ]
        errors = []
        for validator in validators:
            errors.extend(validator())

        if errors:
            raise GraphQLSchemaError(
                message=_format_schema_error_message(errors))
        return True
Ejemplo n.º 2
0
 def _validate_schema_root_types_exist(self) -> bool:
     # Check "query" which is the only mandatory root type
     if self.query_type not in self._gql_types:
         raise GraphQLSchemaError(
             "schema could not find the root `query` type `{}`.".format(
                 self.query_type))
     if (self.mutation_type != "Mutation"
             and self.mutation_type not in self._gql_types):
         raise GraphQLSchemaError(
             "schema could not find the root `mutation` type `{}`.".format(
                 self.mutation_type))
     if (self.subscription_type != "Subscription"
             and self.subscription_type not in self._gql_types):
         raise GraphQLSchemaError(
             "schema could not find the root `subscription` type `{}`.".
             format(self.subscription_type))
     return True
Ejemplo n.º 3
0
 def _validate_non_empty_object(self):
     for type_name, gql_type in self._gql_types.items():
         if isinstance(gql_type, GraphQLObjectType) and not gql_type.fields:
             raise GraphQLSchemaError(
                 "object type `{}` has no fields.".format(
                     type_name
                 )
             )
     return True
Ejemplo n.º 4
0
 def _validate_all_scalars_have_implementations(self) -> bool:
     for type_name, gql_type in self._gql_types.items():
         if isinstance(gql_type, GraphQLScalarType):
             if (gql_type.coerce_output is None
                     or gql_type.coerce_input is None):
                 raise GraphQLSchemaError(
                     "scalar type `{}` must have a coercion "
                     "function for inputs and outputs.".format(type_name))
     return True
Ejemplo n.º 5
0
 def _validate_enum_values_are_unique(self) -> bool:
     for type_name, gql_type in self._gql_types.items():
         if isinstance(gql_type, GraphQLEnumType):
             for value in gql_type.values:
                 if str(value.value) in self._gql_types:
                     raise GraphQLSchemaError(
                         "enum type `{}` has a value of `{}` which "
                         "is not unique in the GraphQL schema.".format(
                             type_name, str(value.value)))
     return True
Ejemplo n.º 6
0
 def _validate_object_follow_interfaces(self):
     for type_name, gql_type in self._gql_types.items():
         try:
             for iface_name in gql_type.interfaces:
                 try:
                     iface_type = self._gql_types[iface_name]
                 except KeyError:
                     raise GraphQLSchemaError(
                         "GraphQL type `{}` implements the `{}` interface "
                         "which does not exist!".format(
                             gql_type.name, iface_name
                         )
                     )
                 if not isinstance(iface_type, GraphQLInterfaceType):
                     raise GraphQLSchemaError(
                         "GraphQL type `{}` implements the `{}` interface "
                         "which is not an interface!".format(
                             gql_type.name, iface_name,
                         )
                     )
                 for iface_field_name, iface_field in iface_type.fields.items():
                     try:
                         gql_type_field = gql_type.fields[iface_field_name]
                     except KeyError:
                         raise GraphQLSchemaError(
                             "field `{}` is missing in GraphQL type `{}` "
                             "that implements the `{}` interface.".format(
                                 iface_field_name, gql_type.name, iface_name,
                             )
                         )
                     if gql_type_field.gql_type != iface_field.gql_type:
                         raise GraphQLSchemaError(
                             "field `{}` in GraphQL type `{}` that "
                             "implements the `{}` interface does not follow "
                             "the interface field type `{}`.".format(
                                 iface_field_name, gql_type.name, iface_name,
                                 iface_field.gql_type
                             )
                         )
         except (AttributeError, TypeError):
             pass
     return True
Ejemplo n.º 7
0
 def _validate_union_is_acceptable(self) -> bool:
     for type_name, gql_type in self._gql_types.items():
         if isinstance(gql_type, GraphQLUnionType):
             for contained_type_name in gql_type.gql_types:
                 if contained_type_name == type_name:
                     raise GraphQLSchemaError(
                         "union type `{}` contains itself.".format(
                             type_name))
                     # TODO: Are there other restrictions for `Union`s ?
                     # can they contain interfaces ?
                     # can they mix types: interface | object | scalar
     return True
Ejemplo n.º 8
0
 def _validate_schema_named_types(self) -> bool:
     for type_name, gql_type in self._gql_types.items():
         try:
             for field in gql_type.fields:
                 reduced_type = reduce_type(field.gql_type)
                 if str(reduced_type) not in self._gql_types:
                     raise GraphQLSchemaError(
                         "field `{}` in GraphQL type `{}` is invalid, "
                         "the given type `{}` does not exist!".format(
                             field.name, type_name, reduced_type))
         except AttributeError:
             pass
     return True
Ejemplo n.º 9
0
    def _validate_extensions(self) -> None:
        validators = [
            self._validate_enum_extensions,
            self._validate_input_object_extensions,
            self._validate_object_extensions,
            self._validate_interface_extensions,
            self._validate_scalar_extensions,
            self._validate_union_extensions,
            self._validate_schema_extensions,
        ]
        errors = []
        for validator in validators:
            errors.extend(validator())

        if errors:
            raise GraphQLSchemaError(
                message=_format_schema_error_message(errors))