Skip to content

Commit

Permalink
Add support for renaming fields (#57)
Browse files Browse the repository at this point in the history
Add support for renaming fields
  • Loading branch information
patrick91 authored May 9, 2019
2 parents db791f9 + ca4f5a9 commit 3914261
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 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 renaming fields. Example usage:


```python
@strawberry.type
class Query:
example: str = strawberry.field(name='test')
```

12 changes: 8 additions & 4 deletions strawberry/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ class LazyFieldWrapper:
>>> return TypeB()
"""

def __init__(self, obj, is_subscription, **kwargs):
def __init__(self, obj, is_subscription, name=None, **kwargs):
self._wrapped_obj = obj
self.is_subscription = is_subscription
self.name = name
self.kwargs = kwargs

if callable(self._wrapped_obj):
Expand Down Expand Up @@ -106,14 +107,15 @@ def __init__(self, *, is_subscription=False, **kwargs):
self.field = dataclasses.field()
self.is_subscription = is_subscription
self.description = kwargs.get("description", None)
self.name = kwargs.pop("name", None)
self.kwargs = kwargs

def __call__(self, wrap):
setattr(wrap, IS_STRAWBERRY_FIELD, True)

self.kwargs["description"] = self.description or wrap.__doc__

return LazyFieldWrapper(wrap, self.is_subscription, **self.kwargs)
return LazyFieldWrapper(wrap, self.is_subscription, self.name, **self.kwargs)


def convert_args(args, annotations):
Expand Down Expand Up @@ -186,7 +188,7 @@ def _resolve(event, info):
return GraphQLField(field_type, args=arguments, **kwargs)


def field(wrap=None, *, is_subscription=False, description=None):
def field(wrap=None, *, is_subscription=False, name=None, description=None):
"""Annotates a method or property as a GraphQL field.
This is normally used inside a type declaration:
Expand All @@ -202,7 +204,9 @@ def field(wrap=None, *, is_subscription=False, description=None):
it can be used both as decorator and as a normal function.
"""

field = strawberry_field(description=description, is_subscription=is_subscription)
field = strawberry_field(
name=name, description=description, is_subscription=is_subscription
)

# when calling this with parens we are going to return a strawberry_field
# instance, so it can be used as both decorator and function.
Expand Down
26 changes: 18 additions & 8 deletions strawberry/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from graphql.utilities.schema_printer import print_type

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

Expand All @@ -26,6 +27,10 @@ def _resolver(obj, info):
if getattr(field_resolver, IS_STRAWBERRY_FIELD, False):
return field_resolver(obj, info)

elif field_resolver.__class__ is strawberry_field:
# TODO: support default values
return None

return field_resolver

return _resolver
Expand All @@ -38,10 +43,12 @@ def _convert_annotations_fields(cls, *, is_input=False):
fields = {}

for key, annotation in annotations.items():
field_name = to_camel_case(key)
class_field = getattr(cls, key, None)

description = getattr(class_field, "description", None)
name = getattr(class_field, "name", None)

field_name = name or to_camel_case(key)

fields[field_name] = FieldClass(
get_graphql_type_for_annotation(annotation, key),
Expand All @@ -64,13 +71,16 @@ def repr_(self):
def _get_fields():
fields = _convert_annotations_fields(cls, is_input=is_input)

fields.update(
{
to_camel_case(key): value.field
for key, value in cls.__dict__.items()
if getattr(value, IS_STRAWBERRY_FIELD, False)
}
)
strawberry_fields = {
key: value
for key, value in cls.__dict__.items()
if getattr(value, IS_STRAWBERRY_FIELD, False)
}

for key, value in strawberry_fields.items():
name = getattr(value, "name", None) or to_camel_case(key)

fields[name] = value.field

return fields

Expand Down
24 changes: 24 additions & 0 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import typing
from enum import Enum

import strawberry
Expand Down Expand Up @@ -132,6 +133,29 @@ def example(self, info, query_param: str) -> str:
assert result.data["example"] == "hi"


def test_can_rename_fields():
@strawberry.type
class Query:
hello_world: typing.Optional[str] = strawberry.field(name="hello")

@strawberry.field(name="example1")
def example(self, info, query_param: str) -> str:
return query_param

schema = strawberry.Schema(query=Query)

query = """{
hello
example1(queryParam: "hi")
}"""

result = graphql_sync(schema, query)

assert not result.errors
assert result.data["hello"] is None
assert result.data["example1"] == "hi"


def test_type_description():
@strawberry.type(description="Decorator argument description")
class TypeA:
Expand Down

0 comments on commit 3914261

Please sign in to comment.