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
This commit is contained in:
Jonathan Kim 2020-06-29 23:26:08 +01:00 committed by GitHub
parent ecd11ccc1e
commit 5b2eb1109a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 6 deletions

View File

@ -38,7 +38,7 @@ class BaseType(SubclassWithMeta):
def __init_subclass_with_meta__( def __init_subclass_with_meta__(
cls, name=None, description=None, _meta=None, **_kwargs 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: if not _meta:
return return
_meta.name = name or cls.__name__ _meta.name = name or cls.__name__

View File

@ -21,14 +21,14 @@ class EnumOptions(BaseOptions):
class EnumMeta(SubclassWithMeta_Meta): 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) enum_members = dict(classdict, __eq__=eq_enum)
# We remove the Meta attribute from the class to not collide # We remove the Meta attribute from the class to not collide
# with the enum values. # with the enum values.
enum_members.pop("Meta", None) enum_members.pop("Meta", None)
enum = PyEnum(cls.__name__, enum_members) enum = PyEnum(cls.__name__, enum_members)
return SubclassWithMeta_Meta.__new__( return SubclassWithMeta_Meta.__new__(
cls, name, bases, dict(classdict, __enum__=enum), **options cls, name_, bases, dict(classdict, __enum__=enum), **options
) )
def get(cls, value): def get(cls, value):

View File

@ -20,12 +20,16 @@ class ObjectTypeOptions(BaseOptions):
class ObjectTypeMeta(BaseTypeMeta): 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 # We create this type, to then overload it with the dataclass attrs
class InterObjectType: class InterObjectType:
pass pass
base_cls = super().__new__(cls, name, (InterObjectType,) + bases, namespace) base_cls = super().__new__(
cls, name_, (InterObjectType,) + bases, namespace, **options,
)
if base_cls._meta: if base_cls._meta:
fields = [ fields = [
( (
@ -39,7 +43,7 @@ class ObjectTypeMeta(BaseTypeMeta):
) )
for key, field_value in base_cls._meta.fields.items() 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.__init__ = dataclass.__init__
InterObjectType.__eq__ = dataclass.__eq__ InterObjectType.__eq__ = dataclass.__eq__
InterObjectType.__repr__ = dataclass.__repr__ InterObjectType.__repr__ = dataclass.__repr__

View File

@ -295,3 +295,21 @@ def test_objecttype_meta_with_annotations():
schema = Schema(query=Query) schema = Schema(query=Query)
assert schema is not None 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"