mirror of
https://github.com/graphql-python/graphene.git
synced 2025-07-18 03:52:24 +03:00
Allow fast ObjectType creation based on dataclasses
This commit is contained in:
parent
1cf303a27b
commit
9b28a7f182
1181
graphene/pyutils/dataclasses.py
Normal file
1181
graphene/pyutils/dataclasses.py
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
from typing import Type
|
||||
|
||||
from ..utils.subclass_with_meta import SubclassWithMeta
|
||||
from ..utils.subclass_with_meta import SubclassWithMeta, SubclassWithMeta_Meta
|
||||
from ..utils.trim_docstring import trim_docstring
|
||||
|
||||
|
||||
|
@ -26,6 +26,8 @@ class BaseOptions:
|
|||
return "<{} name={}>".format(self.__class__.__name__, repr(self.name))
|
||||
|
||||
|
||||
BaseTypeMeta = SubclassWithMeta_Meta
|
||||
|
||||
class BaseType(SubclassWithMeta):
|
||||
@classmethod
|
||||
def create_type(cls, class_name, **options):
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from .base import BaseOptions, BaseType
|
||||
from .base import BaseOptions, BaseType, BaseTypeMeta
|
||||
from .field import Field
|
||||
from .interface import Interface
|
||||
from .utils import yank_fields_from_attrs
|
||||
|
||||
from ..pyutils.dataclasses import make_dataclass, field
|
||||
|
||||
# For static type checking with Mypy
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
|
@ -14,7 +16,24 @@ class ObjectTypeOptions(BaseOptions):
|
|||
interfaces = () # type: Iterable[Type[Interface]]
|
||||
|
||||
|
||||
class ObjectType(BaseType):
|
||||
class ObjectTypeMeta(BaseTypeMeta):
|
||||
def __new__(cls, name, bases, namespace):
|
||||
# We create this type, to then overload it with the dataclass attrs
|
||||
class InterObjectType:
|
||||
pass
|
||||
|
||||
base_cls = super().__new__(cls, name, (InterObjectType, ) + bases, namespace)
|
||||
if base_cls._meta:
|
||||
fields = [
|
||||
(key, 'typing.Any', field(default=field_value.default_value if isinstance(field_value, Field) else None))
|
||||
for key, field_value in base_cls._meta.fields.items()
|
||||
]
|
||||
dataclass = make_dataclass(name, fields, bases=())
|
||||
InterObjectType.__init__ = dataclass.__init__
|
||||
return base_cls
|
||||
|
||||
|
||||
class ObjectType(BaseType, metaclass=ObjectTypeMeta):
|
||||
"""
|
||||
Object Type Definition
|
||||
|
||||
|
|
|
@ -83,6 +83,10 @@ def test_generate_objecttype_with_fields():
|
|||
|
||||
def test_generate_objecttype_with_private_attributes():
|
||||
class MyObjectType(ObjectType):
|
||||
def __init__(self, _private_state=None, **kwargs):
|
||||
self._private_state = _private_state
|
||||
super().__init__(**kwargs)
|
||||
|
||||
_private_state = None
|
||||
|
||||
assert "_private_state" not in MyObjectType._meta.fields
|
||||
|
@ -173,17 +177,17 @@ def test_objecttype_as_container_all_kwargs():
|
|||
|
||||
|
||||
def test_objecttype_as_container_extra_args():
|
||||
with raises(IndexError) as excinfo:
|
||||
with raises(TypeError) as excinfo:
|
||||
Container("1", "2", "3")
|
||||
|
||||
assert "Number of args exceeds number of fields" == str(excinfo.value)
|
||||
assert "__init__() takes from 1 to 3 positional arguments but 4 were given" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_objecttype_as_container_invalid_kwargs():
|
||||
with raises(TypeError) as excinfo:
|
||||
Container(unexisting_field="3")
|
||||
|
||||
assert "'unexisting_field' is an invalid keyword argument for Container" == str(
|
||||
assert "__init__() got an unexpected keyword argument 'unexisting_field'" == str(
|
||||
excinfo.value
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user