mirror of
https://github.com/graphql-python/graphene.git
synced 2025-07-22 13:59:51 +03:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
2e44cb0586
|
@ -153,7 +153,7 @@ class Query(ObjectType):
|
|||
```
|
||||
|
||||
Also, if you wanted to create an `ObjectType` that implements `Node`, you have to do it
|
||||
explicity.
|
||||
explicitly.
|
||||
|
||||
## Django
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ def resolve_my_field(root, info, my_arg):
|
|||
return ...
|
||||
```
|
||||
|
||||
**PS.: Take care with receiving args like `my_arg` as above. This doesn't work for optional (non-required) arguments as stantard `Connection`'s arguments (first, last, after, before).**
|
||||
**PS.: Take care with receiving args like `my_arg` as above. This doesn't work for optional (non-required) arguments as standard `Connection`'s arguments (first, last, after, before).**
|
||||
You may need something like this:
|
||||
|
||||
```python
|
||||
|
|
|
@ -4,5 +4,5 @@ File uploading
|
|||
File uploading is not part of the official GraphQL spec yet and is not natively
|
||||
implemented in Graphene.
|
||||
|
||||
If your server needs to support file uploading then you can use the libary: `graphene-file-upload <https://github.com/lmcgartland/graphene-file-upload>`_ which enhances Graphene to add file
|
||||
If your server needs to support file uploading then you can use the library: `graphene-file-upload <https://github.com/lmcgartland/graphene-file-upload>`_ which enhances Graphene to add file
|
||||
uploads and conforms to the unoffical GraphQL `multipart request spec <https://github.com/jaydenseric/graphql-multipart-request-spec>`_.
|
||||
|
|
|
@ -86,7 +86,7 @@ In the Python ``Enum`` implementation you can access a member by initing the Enu
|
|||
assert Color(1) == Color.RED
|
||||
|
||||
|
||||
However, in Graphene ``Enum`` you need to call get to have the same effect:
|
||||
However, in Graphene ``Enum`` you need to call `.get` to have the same effect:
|
||||
|
||||
.. code:: python
|
||||
|
||||
|
|
|
@ -52,7 +52,10 @@ class EnumMeta(SubclassWithMeta_Meta):
|
|||
return super(EnumMeta, cls).__call__(*args, **kwargs)
|
||||
# return cls._meta.enum(*args, **kwargs)
|
||||
|
||||
def from_enum(cls, enum, description=None, deprecation_reason=None): # noqa: N805
|
||||
def from_enum(
|
||||
cls, enum, name=None, description=None, deprecation_reason=None
|
||||
): # noqa: N805
|
||||
name = name or enum.__name__
|
||||
description = description or enum.__doc__
|
||||
meta_dict = {
|
||||
"enum": enum,
|
||||
|
@ -60,7 +63,7 @@ class EnumMeta(SubclassWithMeta_Meta):
|
|||
"deprecation_reason": deprecation_reason,
|
||||
}
|
||||
meta_class = type("Meta", (object,), meta_dict)
|
||||
return type(meta_class.enum.__name__, (Enum,), {"Meta": meta_class})
|
||||
return type(name, (Enum,), {"Meta": meta_class})
|
||||
|
||||
|
||||
class Enum(UnmountedType, BaseType, metaclass=EnumMeta):
|
||||
|
|
|
@ -5,11 +5,12 @@ from .utils import yank_fields_from_attrs
|
|||
# For static type checking with Mypy
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
from typing import Dict # NOQA
|
||||
from typing import Dict, Iterable, Type # NOQA
|
||||
|
||||
|
||||
class InterfaceOptions(BaseOptions):
|
||||
fields = None # type: Dict[str, Field]
|
||||
interfaces = () # type: Iterable[Type[Interface]]
|
||||
|
||||
|
||||
class Interface(BaseType):
|
||||
|
@ -45,7 +46,7 @@ class Interface(BaseType):
|
|||
"""
|
||||
|
||||
@classmethod
|
||||
def __init_subclass_with_meta__(cls, _meta=None, **options):
|
||||
def __init_subclass_with_meta__(cls, _meta=None, interfaces=(), **options):
|
||||
if not _meta:
|
||||
_meta = InterfaceOptions(cls)
|
||||
|
||||
|
@ -58,6 +59,9 @@ class Interface(BaseType):
|
|||
else:
|
||||
_meta.fields = fields
|
||||
|
||||
if not _meta.interfaces:
|
||||
_meta.interfaces = interfaces
|
||||
|
||||
super(Interface, cls).__init_subclass_with_meta__(_meta=_meta, **options)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -233,11 +233,20 @@ class TypeMap(dict):
|
|||
else None
|
||||
)
|
||||
|
||||
def interfaces():
|
||||
interfaces = []
|
||||
for graphene_interface in graphene_type._meta.interfaces:
|
||||
interface = self.add_type(graphene_interface)
|
||||
assert interface.graphene_type == graphene_interface
|
||||
interfaces.append(interface)
|
||||
return interfaces
|
||||
|
||||
return GrapheneInterfaceType(
|
||||
graphene_type=graphene_type,
|
||||
name=graphene_type._meta.name,
|
||||
description=graphene_type._meta.description,
|
||||
fields=partial(self.create_fields_for_type, graphene_type),
|
||||
interfaces=interfaces,
|
||||
resolve_type=resolve_type,
|
||||
)
|
||||
|
||||
|
|
|
@ -328,6 +328,52 @@ def test_enum_resolver_compat():
|
|||
assert results.data["colorByName"] == Color.RED.name
|
||||
|
||||
|
||||
def test_enum_with_name():
|
||||
from enum import Enum as PyEnum
|
||||
|
||||
class Color(PyEnum):
|
||||
RED = 1
|
||||
YELLOW = 2
|
||||
BLUE = 3
|
||||
|
||||
GColor = Enum.from_enum(Color, description="original colors")
|
||||
UniqueGColor = Enum.from_enum(
|
||||
Color, name="UniqueColor", description="unique colors"
|
||||
)
|
||||
|
||||
class Query(ObjectType):
|
||||
color = GColor(required=True)
|
||||
unique_color = UniqueGColor(required=True)
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
||||
assert (
|
||||
str(schema).strip()
|
||||
== dedent(
|
||||
'''
|
||||
type Query {
|
||||
color: Color!
|
||||
uniqueColor: UniqueColor!
|
||||
}
|
||||
|
||||
"""original colors"""
|
||||
enum Color {
|
||||
RED
|
||||
YELLOW
|
||||
BLUE
|
||||
}
|
||||
|
||||
"""unique colors"""
|
||||
enum UniqueColor {
|
||||
RED
|
||||
YELLOW
|
||||
BLUE
|
||||
}
|
||||
'''
|
||||
).strip()
|
||||
)
|
||||
|
||||
|
||||
def test_enum_resolver_invalid():
|
||||
from enum import Enum as PyEnum
|
||||
|
||||
|
|
|
@ -25,13 +25,18 @@ def test_generate_interface():
|
|||
|
||||
|
||||
def test_generate_interface_with_meta():
|
||||
class MyFirstInterface(Interface):
|
||||
pass
|
||||
|
||||
class MyInterface(Interface):
|
||||
class Meta:
|
||||
name = "MyOtherInterface"
|
||||
description = "Documentation"
|
||||
interfaces = [MyFirstInterface]
|
||||
|
||||
assert MyInterface._meta.name == "MyOtherInterface"
|
||||
assert MyInterface._meta.description == "Documentation"
|
||||
assert MyInterface._meta.interfaces == [MyFirstInterface]
|
||||
|
||||
|
||||
def test_generate_interface_with_fields():
|
||||
|
|
|
@ -289,3 +289,33 @@ def test_objecttype_with_possible_types():
|
|||
assert graphql_type.is_type_of
|
||||
assert graphql_type.is_type_of({}, None) is True
|
||||
assert graphql_type.is_type_of(MyObjectType(), None) is False
|
||||
|
||||
|
||||
def test_interface_with_interfaces():
|
||||
class FooInterface(Interface):
|
||||
foo = String()
|
||||
|
||||
class BarInterface(Interface):
|
||||
class Meta:
|
||||
interfaces = [FooInterface]
|
||||
|
||||
foo = String()
|
||||
bar = String()
|
||||
|
||||
type_map = create_type_map([FooInterface, BarInterface])
|
||||
assert "FooInterface" in type_map
|
||||
foo_graphql_type = type_map["FooInterface"]
|
||||
assert isinstance(foo_graphql_type, GraphQLInterfaceType)
|
||||
assert foo_graphql_type.name == "FooInterface"
|
||||
|
||||
assert "BarInterface" in type_map
|
||||
bar_graphql_type = type_map["BarInterface"]
|
||||
assert isinstance(bar_graphql_type, GraphQLInterfaceType)
|
||||
assert bar_graphql_type.name == "BarInterface"
|
||||
|
||||
fields = bar_graphql_type.fields
|
||||
assert list(fields) == ["foo", "bar"]
|
||||
assert isinstance(fields["foo"], GraphQLField)
|
||||
assert isinstance(fields["bar"], GraphQLField)
|
||||
|
||||
assert bar_graphql_type.interfaces == [foo_graphql_type]
|
||||
|
|
Loading…
Reference in New Issue
Block a user