From 5b2eb1109a58dfddfbf9ee40f35f28435bf14ac6 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Mon, 29 Jun 2020 23:26:08 +0100 Subject: [PATCH] ObjectType meta arguments (#1219) * Pass extra kwargs down the meta chain * Rename name argument to allow custom name * Reword error message * Explicitly define kwargs * Revert change to explicit kwargs * name -> name_ for Enum __new__ function --- graphene/types/base.py | 2 +- graphene/types/enum.py | 4 ++-- graphene/types/objecttype.py | 10 +++++++--- graphene/types/tests/test_objecttype.py | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/graphene/types/base.py b/graphene/types/base.py index 129834b0..84cb377a 100644 --- a/graphene/types/base.py +++ b/graphene/types/base.py @@ -38,7 +38,7 @@ class BaseType(SubclassWithMeta): def __init_subclass_with_meta__( cls, name=None, description=None, _meta=None, **_kwargs ): - assert "_meta" not in cls.__dict__, "Can't assign directly meta" + assert "_meta" not in cls.__dict__, "Can't assign meta directly" if not _meta: return _meta.name = name or cls.__name__ diff --git a/graphene/types/enum.py b/graphene/types/enum.py index 1d290a20..70e8ee8e 100644 --- a/graphene/types/enum.py +++ b/graphene/types/enum.py @@ -21,14 +21,14 @@ class EnumOptions(BaseOptions): class EnumMeta(SubclassWithMeta_Meta): - def __new__(cls, name, bases, classdict, **options): + def __new__(cls, name_, bases, classdict, **options): enum_members = dict(classdict, __eq__=eq_enum) # We remove the Meta attribute from the class to not collide # with the enum values. enum_members.pop("Meta", None) enum = PyEnum(cls.__name__, enum_members) return SubclassWithMeta_Meta.__new__( - cls, name, bases, dict(classdict, __enum__=enum), **options + cls, name_, bases, dict(classdict, __enum__=enum), **options ) def get(cls, value): diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index c16f50b8..f4a0f5a0 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -20,12 +20,16 @@ class ObjectTypeOptions(BaseOptions): class ObjectTypeMeta(BaseTypeMeta): - def __new__(cls, name, bases, namespace): + def __new__(cls, name_, bases, namespace, **options): + # Note: it's safe to pass options as keyword arguments as they are still type-checked by ObjectTypeOptions. + # We create this type, to then overload it with the dataclass attrs class InterObjectType: pass - base_cls = super().__new__(cls, name, (InterObjectType,) + bases, namespace) + base_cls = super().__new__( + cls, name_, (InterObjectType,) + bases, namespace, **options, + ) if base_cls._meta: fields = [ ( @@ -39,7 +43,7 @@ class ObjectTypeMeta(BaseTypeMeta): ) for key, field_value in base_cls._meta.fields.items() ] - dataclass = make_dataclass(name, fields, bases=()) + dataclass = make_dataclass(name_, fields, bases=()) InterObjectType.__init__ = dataclass.__init__ InterObjectType.__eq__ = dataclass.__eq__ InterObjectType.__repr__ = dataclass.__repr__ diff --git a/graphene/types/tests/test_objecttype.py b/graphene/types/tests/test_objecttype.py index 85a46867..1ff8fc8f 100644 --- a/graphene/types/tests/test_objecttype.py +++ b/graphene/types/tests/test_objecttype.py @@ -295,3 +295,21 @@ def test_objecttype_meta_with_annotations(): schema = Schema(query=Query) assert schema is not None + + +def test_objecttype_meta_arguments(): + class MyInterface(Interface): + foo = String() + + class MyType(ObjectType, interfaces=[MyInterface]): + bar = String() + + assert MyType._meta.interfaces == [MyInterface] + assert list(MyType._meta.fields.keys()) == ["foo", "bar"] + + +def test_objecttype_type_name(): + class MyObjectType(ObjectType, name="FooType"): + pass + + assert MyObjectType._meta.name == "FooType"