Skip to content

Commit

Permalink
Add support for declaring and using interfaces (#55)
Browse files Browse the repository at this point in the history
Add support for declaring and using interfaces
  • Loading branch information
patrick91 authored May 9, 2019
2 parents 6da4d23 + b89a1aa commit 1949938
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 6 deletions.
11 changes: 11 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Release Type: minor

Added support for declaring interface by using `@strawberry.interface`

Example:

```python
@strawberry.interface
class Node:
id: strawberry.ID
```
2 changes: 1 addition & 1 deletion strawberry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
from .mutation import mutation, subscription # noqa
from .scalars import ID # noqa
from .schema import Schema # noqa
from .type import input, type # noqa
from .type import input, type, interface # noqa
1 change: 1 addition & 0 deletions strawberry/constants.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
IS_STRAWBERRY_FIELD = "_is_strawberry_field"
IS_STRAWBERRY_INPUT = "_is_strawberry_input"
IS_STRAWBERRY_INTERFACE = "_is_strawberry_interface"
28 changes: 23 additions & 5 deletions strawberry/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
GraphQLField,
GraphQLInputField,
GraphQLInputObjectType,
GraphQLInterfaceType,
GraphQLObjectType,
)
from graphql.utilities.schema_printer import print_type

from .constants import IS_STRAWBERRY_FIELD, IS_STRAWBERRY_INPUT
from .constants import IS_STRAWBERRY_FIELD, IS_STRAWBERRY_INPUT, IS_STRAWBERRY_INTERFACE
from .type_converter import REGISTRY, get_graphql_type_for_annotation
from .utils.str_converters import to_camel_case

Expand Down Expand Up @@ -51,7 +52,7 @@ def _convert_annotations_fields(cls, *, is_input=False):
return fields


def _process_type(cls, *, is_input=False, description=None):
def _process_type(cls, *, is_input=False, is_interface=False, description=None):
name = cls.__name__
REGISTRY[name] = cls

Expand All @@ -75,16 +76,30 @@ def _get_fields():

if is_input:
setattr(cls, IS_STRAWBERRY_INPUT, True)
elif is_interface:
setattr(cls, IS_STRAWBERRY_INTERFACE, True)

extra_kwargs = {"description": description or cls.__doc__}

TypeClass = GraphQLInputObjectType if is_input else GraphQLObjectType
if is_input:
TypeClass = GraphQLInputObjectType
elif is_interface:
TypeClass = GraphQLInterfaceType
else:
TypeClass = GraphQLObjectType

extra_kwargs["interfaces"] = [
klass.field
for klass in cls.__bases__
if hasattr(klass, IS_STRAWBERRY_INTERFACE)
]

cls.field = TypeClass(name, lambda: _get_fields(), **extra_kwargs)

return dataclass(cls, repr=False)


def type(cls=None, *, is_input=False, description=None):
def type(cls=None, *, is_input=False, is_interface=False, description=None):
"""Annotates a class as a GraphQL type.
Example usage:
Expand All @@ -95,7 +110,9 @@ def type(cls=None, *, is_input=False, description=None):
"""

def wrap(cls):
return _process_type(cls, is_input=is_input, description=description)
return _process_type(
cls, is_input=is_input, is_interface=is_interface, description=description
)

if cls is None:
return wrap
Expand All @@ -104,3 +121,4 @@ def wrap(cls):


input = partial(type, is_input=True)
interface = partial(type, is_interface=True)
36 changes: 36 additions & 0 deletions tests/test_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import textwrap

import strawberry


def test_interface():
@strawberry.interface
class Node:
id: strawberry.ID

expected_representation = """
interface Node {
id: ID!
}
"""

assert repr(Node("a")) == textwrap.dedent(expected_representation).strip()


def test_implementing_interface():
@strawberry.interface
class Node:
id: strawberry.ID

@strawberry.type
class Post(Node):
title: str

expected_representation = """
type Post implements Node {
id: ID!
title: String!
}
"""

assert repr(Post("a", "abc")) == textwrap.dedent(expected_representation).strip()

0 comments on commit 1949938

Please sign in to comment.