mirror of
https://github.com/graphql-python/graphene.git
synced 2025-04-25 12:03:41 +03:00
104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
from collections import OrderedDict
|
|
|
|
import six
|
|
|
|
from ..utils.is_base_type import is_base_type
|
|
from .abstracttype import AbstractTypeMeta
|
|
from .interface import Interface
|
|
from .options import Options
|
|
from .utils import (get_fields_in_type, yank_fields_from_attrs,
|
|
get_base_fields, merge)
|
|
|
|
|
|
class ObjectTypeMeta(AbstractTypeMeta):
|
|
|
|
def __new__(cls, name, bases, attrs):
|
|
# Also ensure initialization is only performed for subclasses of
|
|
# ObjectType
|
|
if not is_base_type(bases, ObjectTypeMeta):
|
|
return type.__new__(cls, name, bases, attrs)
|
|
|
|
_meta = attrs.pop('_meta', None)
|
|
options = _meta or Options(
|
|
attrs.pop('Meta', None),
|
|
name=name,
|
|
description=attrs.get('__doc__'),
|
|
interfaces=(),
|
|
local_fields=OrderedDict(),
|
|
)
|
|
options.base_fields = get_base_fields(ObjectType, bases)
|
|
|
|
if not options.local_fields:
|
|
options.local_fields = get_fields_in_type(ObjectType, attrs)
|
|
yank_fields_from_attrs(attrs, options.local_fields)
|
|
|
|
options.interface_fields = OrderedDict()
|
|
for interface in options.interfaces:
|
|
assert issubclass(interface, Interface), (
|
|
'All interfaces of {} must be a subclass of Interface. Received "{}".'
|
|
).format(name, interface)
|
|
options.interface_fields.update(interface._meta.fields)
|
|
|
|
options.fields = merge(
|
|
options.interface_fields,
|
|
options.base_fields,
|
|
options.local_fields
|
|
)
|
|
|
|
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
|
|
|
|
for interface in options.interfaces:
|
|
interface.implements(cls)
|
|
|
|
return cls
|
|
|
|
def __str__(cls): # noqa: N802
|
|
return cls._meta.name
|
|
|
|
|
|
class ObjectType(six.with_metaclass(ObjectTypeMeta)):
|
|
|
|
@classmethod
|
|
def is_type_of(cls, root, context, info):
|
|
if isinstance(root, cls):
|
|
return True
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
# ObjectType acting as container
|
|
args_len = len(args)
|
|
fields = self._meta.fields.items()
|
|
if args_len > len(fields):
|
|
# Daft, but matches old exception sans the err msg.
|
|
raise IndexError("Number of args exceeds number of fields")
|
|
fields_iter = iter(fields)
|
|
|
|
if not kwargs:
|
|
for val, (name, field) in zip(args, fields_iter):
|
|
setattr(self, name, val)
|
|
else:
|
|
for val, (name, field) in zip(args, fields_iter):
|
|
setattr(self, name, val)
|
|
kwargs.pop(name, None)
|
|
|
|
for name, field in fields_iter:
|
|
try:
|
|
val = kwargs.pop(name)
|
|
setattr(self, name, val)
|
|
except KeyError:
|
|
pass
|
|
|
|
if kwargs:
|
|
for prop in list(kwargs):
|
|
try:
|
|
if isinstance(getattr(self.__class__, prop), property):
|
|
setattr(self, prop, kwargs.pop(prop))
|
|
except AttributeError:
|
|
pass
|
|
if kwargs:
|
|
raise TypeError(
|
|
"'{}' is an invalid keyword argument for {}".format(
|
|
list(kwargs)[0],
|
|
self.__class__.__name__
|
|
)
|
|
)
|