diff --git a/graphene/pyutils/version.py b/graphene/pyutils/version.py index f2005442..a0b0d2ba 100644 --- a/graphene/pyutils/version.py +++ b/graphene/pyutils/version.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import datetime import os import subprocess +from ..utils.comparison_helper import raise_assertion_if_not def get_version(version=None): @@ -44,8 +45,14 @@ def get_complete_version(version=None): if version is None: from graphene import VERSION as version else: - assert len(version) == 5 - assert version[3] in ("alpha", "beta", "rc", "final") + raise_assertion_if_not( + condition=len(version) is 5, + message="Wrong tuple provided" + ) + raise_assertion_if_not( + condition=version[3] in ("alpha", "beta", "rc", "final"), + message="Version not correct." + ) return version diff --git a/graphene/relay/connection.py b/graphene/relay/connection.py index 927dfcc4..968242ed 100644 --- a/graphene/relay/connection.py +++ b/graphene/relay/connection.py @@ -9,6 +9,7 @@ from ..types.field import Field from ..types.objecttype import ObjectType, ObjectTypeOptions from ..utils.thenables import maybe_thenable from .node import is_node +from ..utils.comparison_helper import raise_assertion_if_not class PageInfo(ObjectType): @@ -52,11 +53,17 @@ class Connection(ObjectType): @classmethod def __init_subclass_with_meta__(cls, node=None, name=None, **options): _meta = ConnectionOptions(cls) - assert node, "You have to provide a node in {}.Meta".format(cls.__name__) - assert issubclass( - node, (Scalar, Enum, ObjectType, Interface, Union, NonNull) - ), ('Received incompatible node "{}" for Connection {}.').format( - node, cls.__name__ + raise_assertion_if_not( + condition=node, + message="You have to provide a node in {}.Meta".format(cls.__name__) + ) + raise_assertion_if_not( + condition=issubclass( + node, (Scalar, Enum, ObjectType, Interface, Union, NonNull) + ), + message=('Received incompatible node "{}" for Connection {}.').format( + node, cls.__name__ + ) ) base_name = re.sub("Connection$", "", name or cls.__name__) or node._meta.name @@ -132,9 +139,12 @@ class IterableConnectionField(Field): "Read more: https://github.com/graphql-python/graphene/blob/v2.0.0/UPGRADE-v2.0.md#node-connections" ) - assert issubclass(connection_type, Connection), ( - '{} type have to be a subclass of Connection. Received "{}".' - ).format(self.__class__.__name__, connection_type) + raise_assertion_if_not( + condition=issubclass(connection_type, Connection), + message='{} type have to be a subclass of Connection. Received "{}".'.format( + self.__class__.__name__, connection_type + ) + ) return type @classmethod @@ -142,10 +152,16 @@ class IterableConnectionField(Field): if isinstance(resolved, connection_type): return resolved - assert isinstance(resolved, Iterable), ( - "Resolved value from the connection field have to be iterable or instance of {}. " - 'Received "{}"' - ).format(connection_type, resolved) + raise_assertion_if_not( + condition=isinstance(resolved, Iterable), + message=""" + Resolved value from the connection field have to be iterable or instance of {}. + Received "{}" + """.format( + connection_type, resolved + ) + ) + connection = connection_from_list( resolved, args, diff --git a/graphene/relay/mutation.py b/graphene/relay/mutation.py index ee758e78..23e0f655 100644 --- a/graphene/relay/mutation.py +++ b/graphene/relay/mutation.py @@ -17,8 +17,15 @@ class ClientIDMutation(Mutation): input_class = getattr(cls, "Input", None) base_name = re.sub("Payload$", "", name or cls.__name__) - assert not output, "Can't specify any output" - assert not arguments, "Can't specify any arguments" + raise_assertion_if_not( + condition=not output, + message="Can't specify any output" + ) + + raise_assertion_if_not( + condition=not arguments, + message="Can't specify any arguments" + ) bases = (InputObjectType,) if input_class: @@ -41,10 +48,13 @@ class ClientIDMutation(Mutation): ) mutate_and_get_payload = getattr(cls, "mutate_and_get_payload", None) if cls.mutate and cls.mutate.__func__ == ClientIDMutation.mutate.__func__: - assert mutate_and_get_payload, ( - "{name}.mutate_and_get_payload method is required" - " in a ClientIDMutation." - ).format(name=name or cls.__name__) + raise_assertion_if_not( + condition=mutate_and_get_payload, + message="{name}.mutate_and_get_payload method is required" \ + " in a ClientIDMutation.".format( + name=name or cls.__name__ + ) + ) if not name: name = "{}Payload".format(base_name) diff --git a/graphene/relay/node.py b/graphene/relay/node.py index d9c4c0f6..50c1fccb 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -7,6 +7,7 @@ from graphql_relay import from_global_id, to_global_id from ..types import ID, Field, Interface, ObjectType from ..types.interface import InterfaceOptions from ..types.utils import get_type +from ..utils.comparison_helper import raise_assertion_if_not def is_node(objecttype): diff --git a/graphene/types/argument.py b/graphene/types/argument.py index 9c75bcee..e34133bb 100644 --- a/graphene/types/argument.py +++ b/graphene/types/argument.py @@ -5,6 +5,7 @@ from .dynamic import Dynamic from .mountedtype import MountedType from .structures import NonNull from .utils import get_type +from ..utils.comparison_helper import raise_assertion_if_not class Argument(MountedType): @@ -73,10 +74,11 @@ def to_arguments(args, extra_args=None): raise ValueError('Unknown argument "{}".'.format(default_name)) arg_name = default_name or arg.name - assert ( - arg_name not in arguments - ), 'More than one Argument have same name "{}".'.format( - arg_name + raise_assertion_if_not( + condition=arg_name not in arguments, + message='More than one Argument have same name "{}".'.format( + arg_name + ) ) arguments[arg_name] = arg diff --git a/graphene/types/base.py b/graphene/types/base.py index aa97ed22..a2d74509 100644 --- a/graphene/types/base.py +++ b/graphene/types/base.py @@ -1,5 +1,6 @@ from ..utils.subclass_with_meta import SubclassWithMeta from ..utils.trim_docstring import trim_docstring +from ..utils.comparison_helper import raise_assertion_if_not class BaseOptions(object): @@ -31,7 +32,10 @@ class BaseType(SubclassWithMeta): @classmethod def __init_subclass_with_meta__(cls, name=None, description=None, _meta=None): - assert "_meta" not in cls.__dict__, "Can't assign directly meta" + raise_assertion_if_not( + condition="_meta" not in cls.__dict__, + message="Can't assign directly meta" + ) if not _meta: return _meta.name = name or cls.__name__ diff --git a/graphene/types/datetime.py b/graphene/types/datetime.py index 739032b0..f7f60519 100644 --- a/graphene/types/datetime.py +++ b/graphene/types/datetime.py @@ -6,6 +6,7 @@ from aniso8601 import parse_date, parse_datetime, parse_time from graphql.language import ast from .scalars import Scalar +from ..utils.comparison_helper import raise_assertion_if_not class Date(Scalar): @@ -19,9 +20,10 @@ class Date(Scalar): def serialize(date): if isinstance(date, datetime.datetime): date = date.date() - assert isinstance( - date, datetime.date - ), 'Received not compatible date "{}"'.format(repr(date)) + raise_assertion_if_not( + condition=isinstance(date, datetime.date), + message='Received not compatible date "{}"'.format(repr(date)) + ) return date.isoformat() @classmethod @@ -46,9 +48,10 @@ class DateTime(Scalar): @staticmethod def serialize(dt): - assert isinstance( - dt, (datetime.datetime, datetime.date) - ), 'Received not compatible datetime "{}"'.format(repr(dt)) + raise_assertion_if_not( + condition=isinstance(dt, (datetime.datetime, datetime.date)), + message='Received not compatible datetime "{}"'.format(repr(dt)) + ) return dt.isoformat() @classmethod @@ -73,9 +76,10 @@ class Time(Scalar): @staticmethod def serialize(time): - assert isinstance( - time, datetime.time - ), 'Received not compatible time "{}"'.format(repr(time)) + raise_assertion_if_not( + condition=isinstance(time, datetime.time), + message='Received not compatible time "{}"'.format(repr(time)) + ) return time.isoformat() @classmethod diff --git a/graphene/types/field.py b/graphene/types/field.py index a1428632..3582a242 100644 --- a/graphene/types/field.py +++ b/graphene/types/field.py @@ -7,6 +7,7 @@ from .mountedtype import MountedType from .structures import NonNull from .unmountedtype import UnmountedType from .utils import get_type +from ..utils.comparison_helper import raise_assertion_if_not base_type = type @@ -34,15 +35,24 @@ class Field(MountedType): **extra_args ): super(Field, self).__init__(_creation_counter=_creation_counter) - assert not args or isinstance(args, Mapping), ( - 'Arguments in a field have to be a mapping, received "{}".' - ).format(args) - assert not ( - source and resolver - ), "A Field cannot have a source and a resolver in at the same time." - assert not callable(default_value), ( - 'The default value can not be a function but received "{}".' - ).format(base_type(default_value)) + raise_assertion_if_not( + condition=not args or isinstance(args, Mapping), + message='Arguments in a field have to be a mapping, received "{}".'.format( + args + ) + ) + + raise_assertion_if_not( + condition=not(source and resolver), + message="A Field cannot have a source and a resolver in at the same time." + ) + + raise_assertion_if_not( + condition=not callable(default_value), + message='The default value can not be a function but received "{}".'.format( + base_type(default_value) + ) + ) if required: type = NonNull(type) diff --git a/graphene/types/mountedtype.py b/graphene/types/mountedtype.py index 6d0c8cf8..e5eaa35c 100644 --- a/graphene/types/mountedtype.py +++ b/graphene/types/mountedtype.py @@ -1,5 +1,6 @@ from ..utils.orderedtype import OrderedType from .unmountedtype import UnmountedType +from ..utils.comparison_helper import raise_assertion_if_not class MountedType(OrderedType): @@ -8,8 +9,9 @@ class MountedType(OrderedType): """ Mount the UnmountedType instance """ - assert isinstance(unmounted, UnmountedType), ("{} can't mount {}").format( - cls.__name__, repr(unmounted) + raise_assertion_if_not( + condition=isinstance(unmounted, UnmountedType), + message="{} can't mount {}".format(cls.__name__, repr(unmounted)) ) return cls( diff --git a/graphene/types/mutation.py b/graphene/types/mutation.py index aa8f86bb..f71d3d08 100644 --- a/graphene/types/mutation.py +++ b/graphene/types/mutation.py @@ -6,6 +6,7 @@ from ..utils.props import props from .field import Field from .objecttype import ObjectType, ObjectTypeOptions from .utils import yank_fields_from_attrs +from ..utils.comparison_helper import raise_assertion_if_not # For static type checking with Mypy MYPY = False @@ -62,7 +63,10 @@ class Mutation(ObjectType): if not resolver: mutate = getattr(cls, "mutate", None) - assert mutate, "All mutations must define a mutate method in it" + raise_assertion_if_not( + condition=mutate, + message="All mutations must define a mutate method in it" + ) resolver = get_unbound_function(mutate) if _meta.fields: diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index be4addb2..140dd076 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -4,6 +4,7 @@ from .base import BaseOptions, BaseType from .field import Field from .interface import Interface from .utils import yank_fields_from_attrs +from ..utils.comparison_helper import raise_assertion_if_not # For static type checking with Mypy MYPY = False @@ -39,18 +40,25 @@ class ObjectType(BaseType): fields = OrderedDict() for interface in interfaces: - assert issubclass(interface, Interface), ( - 'All interfaces of {} must be a subclass of Interface. Received "{}".' - ).format(cls.__name__, interface) + raise_assertion_if_not( + condition=issubclass(interface, Interface), + message='All interfaces of {} must be a subclass of Interface. Received "{}".'.format( + cls.__name__, interface + ) + ) fields.update(interface._meta.fields) for base in reversed(cls.__mro__): fields.update(yank_fields_from_attrs(base.__dict__, _as=Field)) - assert not (possible_types and cls.is_type_of), ( - "{name}.Meta.possible_types will cause type collision with {name}.is_type_of. " - "Please use one or other." - ).format(name=cls.__name__) + raise_assertion_if_not( + condition=not (possible_types and cls.is_type_of), + message=("{name}.Meta.possible_types will cause type collision with {name}.is_type_of. " \ + "Please use one or other.".format( + name=cls.__name__ + ) + ) + ) if _meta.fields: _meta.fields.update(fields) diff --git a/graphene/types/schema.py b/graphene/types/schema.py index a885c88a..39fee633 100644 --- a/graphene/types/schema.py +++ b/graphene/types/schema.py @@ -13,6 +13,7 @@ from graphql.utils.schema_printer import print_schema from .definitions import GrapheneGraphQLType from .objecttype import ObjectType from .typemap import TypeMap, is_graphene_type +from ..utils.comparison_helper import raise_assertion_if_not def assert_valid_root_type(_type): @@ -20,9 +21,10 @@ def assert_valid_root_type(_type): return is_graphene_objecttype = inspect.isclass(_type) and issubclass(_type, ObjectType) is_graphql_objecttype = isinstance(_type, GraphQLObjectType) - assert is_graphene_objecttype or is_graphql_objecttype, ( - "Type {} is not a valid ObjectType." - ).format(_type) + raise_assertion_if_not( + condition=is_graphene_objecttype or is_graphql_objecttype, + message="Type {} is not a valid ObjectType.".format(_type) + ) class Schema(GraphQLSchema): @@ -53,10 +55,11 @@ class Schema(GraphQLSchema): if directives is None: directives = [GraphQLIncludeDirective, GraphQLSkipDirective] - assert all( - isinstance(d, GraphQLDirective) for d in directives - ), "Schema directives must be List[GraphQLDirective] if provided but got: {}.".format( - directives + raise_assertion_if_not( + condition=all(isinstance(d, GraphQLDirective) for d in directives), + message="Schema directives must be List[GraphQLDirective] if provided but got: {}.".format( + directives + ) ) self._directives = directives self.build_typemap() diff --git a/graphene/types/structures.py b/graphene/types/structures.py index dde68f0f..f383e6cc 100644 --- a/graphene/types/structures.py +++ b/graphene/types/structures.py @@ -1,5 +1,6 @@ from .unmountedtype import UnmountedType from .utils import get_type +from ..utils.comparison_helper import raise_assertion_if_not class Structure(UnmountedType): @@ -67,9 +68,12 @@ class NonNull(Structure): def __init__(self, *args, **kwargs): super(NonNull, self).__init__(*args, **kwargs) - assert not isinstance(self._of_type, NonNull), ( - "Can only create NonNull of a Nullable GraphQLType but got: {}." - ).format(self._of_type) + raise_assertion_if_not( + condition=not isinstance(self._of_type, NonNull), + message="Can only create NonNull of a Nullable GraphQLType but got: {}.".format( + self._of_type + ) + ) def __str__(self): return "{}!".format(self.of_type) diff --git a/graphene/types/typemap.py b/graphene/types/typemap.py index 9edb8518..25735613 100644 --- a/graphene/types/typemap.py +++ b/graphene/types/typemap.py @@ -40,6 +40,7 @@ from .scalars import ID, Boolean, Float, Int, Scalar, String from .structures import List, NonNull from .union import Union from .utils import get_field_as +from ..utils.comparison_helper import raise_assertion_if_not def is_graphene_type(_type): @@ -60,10 +61,16 @@ def resolve_type(resolve_type_func, map, type_name, root, info): if inspect.isclass(_type) and issubclass(_type, ObjectType): graphql_type = map.get(_type._meta.name) - assert graphql_type, "Can't find type {} in schema".format(_type._meta.name) - assert graphql_type.graphene_type == _type, ( - "The type {} does not match with the associated graphene type {}." - ).format(_type, graphql_type.graphene_type) + raise_assertion_if_not( + condition=graphql_type, + message="Can't find type {} in schema".format(_type._meta.name) + ) + raise_assertion_if_not( + condition=graphql_type.graphene_type is _type, + message="The type {} does not match with the associated graphene type {}.".format( + _type, graphql_type.graphene_type + ) + ) return graphql_type return _type @@ -94,9 +101,12 @@ class TypeMap(GraphQLTypeMap): if type._meta.name in map: _type = map[type._meta.name] if isinstance(_type, GrapheneGraphQLType): - assert _type.graphene_type == type, ( - "Found different types with the same name in the schema: {}, {}." - ).format(_type.graphene_type, type) + raise_assertion_if_not( + condition=_type.graphene_type is type, + message="Found different types with the same name in the schema: {}, {}.".format( + _type.graphene_type, type + ) + ) return map if issubclass(type, ObjectType): @@ -173,9 +183,12 @@ class TypeMap(GraphQLTypeMap): if type._meta.name in map: _type = map[type._meta.name] if isinstance(_type, GrapheneGraphQLType): - assert _type.graphene_type == type, ( - "Found different types with the same name in the schema: {}, {}." - ).format(_type.graphene_type, type) + raise_assertion_if_not( + condition=_type.graphene_type is type, + message="Found different types with the same name in the schema: {}, {}.".format( + _type.graphene_type, type + ) + ) return _type def interfaces(): @@ -183,7 +196,9 @@ class TypeMap(GraphQLTypeMap): for interface in type._meta.interfaces: self.graphene_reducer(map, interface) internal_type = map[interface._meta.name] - assert internal_type.graphene_type == interface + raise_assertion_if_not( + condition=internal_type.graphene_type is interface + ) interfaces.append(internal_type) return interfaces @@ -207,9 +222,12 @@ class TypeMap(GraphQLTypeMap): if type._meta.name in map: _type = map[type._meta.name] if isinstance(_type, GrapheneInterfaceType): - assert _type.graphene_type == type, ( - "Found different types with the same name in the schema: {}, {}." - ).format(_type.graphene_type, type) + raise_assertion_if_not( + condition=_type.graphene_type is type, + message="Found different types with the same name in the schema: {}, {}.".format( + _type.graphene_type, type + ) + ) return _type _resolve_type = None @@ -248,7 +266,9 @@ class TypeMap(GraphQLTypeMap): for objecttype in type._meta.types: self.graphene_reducer(map, objecttype) internal_type = map[objecttype._meta.name] - assert internal_type.graphene_type == objecttype + raise_assertion_if_not( + condition=internal_type.graphene_type is objecttype + ) union_types.append(internal_type) return union_types diff --git a/graphene/types/union.py b/graphene/types/union.py index dc207e8e..5b3bfd96 100644 --- a/graphene/types/union.py +++ b/graphene/types/union.py @@ -1,5 +1,6 @@ from .base import BaseOptions, BaseType from .unmountedtype import UnmountedType +from ..utils.comparison_helper import raise_assertion_if_not # For static type checking with Mypy MYPY = False @@ -23,10 +24,10 @@ class Union(UnmountedType, BaseType): @classmethod def __init_subclass_with_meta__(cls, types=None, **options): - assert ( - isinstance(types, (list, tuple)) and len(types) > 0 - ), "Must provide types for Union {name}.".format(name=cls.__name__) - + raise_assertion_if_not( + condition=isinstance(types, (list, tuple)) and len(types) > 0, + message="Must provide types for Union {name}.".format(name=cls.__name__) + ) _meta = UnionOptions(cls) _meta.types = types super(Union, cls).__init_subclass_with_meta__(_meta=_meta, **options) diff --git a/graphene/types/uuid.py b/graphene/types/uuid.py index abb8f110..d1f42683 100644 --- a/graphene/types/uuid.py +++ b/graphene/types/uuid.py @@ -5,6 +5,7 @@ from uuid import UUID as _UUID from graphql.language import ast from .scalars import Scalar +from ..utils.comparison_helper import raise_assertion_if_not class UUID(Scalar): @@ -14,8 +15,9 @@ class UUID(Scalar): def serialize(uuid): if isinstance(uuid, str): uuid = _UUID(uuid) - assert isinstance(uuid, _UUID), "Expected UUID instance, received {}".format( - uuid + raise_assertion_if_not( + condition=isinstance(uuid, _UUID), + message="Expected UUID instance, received {}".format(uuid) ) return str(uuid) diff --git a/graphene/utils/annotate.py b/graphene/utils/annotate.py index 43a26ef6..9b8cb15c 100644 --- a/graphene/utils/annotate.py +++ b/graphene/utils/annotate.py @@ -2,6 +2,7 @@ import six from ..pyutils.compat import func_name, signature from .deprecated import warn_deprecation +from .comparison_helper import raise_assertion_if_not def annotate(_func=None, _trigger_warning=True, **annotations): @@ -22,9 +23,12 @@ def annotate(_func=None, _trigger_warning=True, **annotations): # We make sure the annotations are valid for key, value in annotations.items(): - assert key in func_signature.parameters, ( - 'The key {key} is not a function parameter in the function "{func_name}".' - ).format(key=key, func_name=func_name(_func)) + raise_assertion_if_not( + condition= key in func_signature.parameters, + message='The key {key} is not a function parameter in the function "{func_name}".'.format( + key=key, func_name=func_name(_func) + ) + ) func_annotations = getattr(_func, "__annotations__", None) if func_annotations is None: diff --git a/graphene/utils/comparison_helper.py b/graphene/utils/comparison_helper.py new file mode 100644 index 00000000..477382e6 --- /dev/null +++ b/graphene/utils/comparison_helper.py @@ -0,0 +1,3 @@ +def raise_assertion_if_not(condition=None, message=None): + if not condition: + raise AssertionError(message) diff --git a/graphene/utils/subclass_with_meta.py b/graphene/utils/subclass_with_meta.py index 01fc5375..5b4ff134 100644 --- a/graphene/utils/subclass_with_meta.py +++ b/graphene/utils/subclass_with_meta.py @@ -4,6 +4,8 @@ import six from ..pyutils.init_subclass import InitSubclassMeta from .props import props +from .comparison_helper import raise_assertion_if_not + class SubclassWithMeta_Meta(InitSubclassMeta): @@ -42,10 +44,13 @@ class SubclassWithMeta(six.with_metaclass(SubclassWithMeta_Meta)): abstract = options.pop("abstract", False) if abstract: - assert not options, ( - "Abstract types can only contain the abstract attribute. " - "Received: abstract, {option_keys}" - ).format(option_keys=", ".join(options.keys())) + raise_assertion_if_not( + condition=not options, + message="Abstract types can only contain the abstract attribute. " \ + "Received: abstract, {option_keys}".format( + option_keys=", ".join(options.keys()) + ) + ) else: super_class = super(cls, cls) if hasattr(super_class, "__init_subclass_with_meta__"):