Skip to content

Commit

Permalink
Merge 7ca5c22 into 557ec44
Browse files Browse the repository at this point in the history
  • Loading branch information
syrusakbary committed Jul 25, 2017
2 parents 557ec44 + 7ca5c22 commit abec4e5
Show file tree
Hide file tree
Showing 93 changed files with 2,220 additions and 859 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -2,8 +2,8 @@ language: python
sudo: false
python:
- 2.7
- 3.4
- 3.5
- 3.6
- pypy
before_install:
- |
Expand Down
10 changes: 5 additions & 5 deletions README.md
@@ -1,4 +1,4 @@
Please read [UPGRADE-v1.0.md](/UPGRADE-v1.0.md) to learn how to upgrade to Graphene `1.0`.
Please read [UPGRADE-v2.0.md](/UPGRADE-v2.0.md) to learn how to upgrade to Graphene `2.0`.

---

Expand Down Expand Up @@ -32,12 +32,12 @@ Also, Graphene is fully compatible with the GraphQL spec, working seamlessly wit
For instaling graphene, just run this command in your shell

```bash
pip install "graphene>=1.0"
pip install "graphene>=2.0.dev"
```

## 1.0 Upgrade Guide
## 2.0 Upgrade Guide

Please read [UPGRADE-v1.0.md](/UPGRADE-v1.0.md) to learn how to upgrade.
Please read [UPGRADE-v2.0.md](/UPGRADE-v2.0.md) to learn how to upgrade.


## Examples
Expand All @@ -48,7 +48,7 @@ Here is one example for you to get started:
class Query(graphene.ObjectType):
hello = graphene.String(description='A typical hello world')

def resolve_hello(self, args, context, info):
def resolve_hello(self):
return 'World'

schema = graphene.Schema(query=Query)
Expand Down
14 changes: 7 additions & 7 deletions README.rst
@@ -1,5 +1,5 @@
Please read `UPGRADE-v1.0.md </UPGRADE-v1.0.md>`__ to learn how to
upgrade to Graphene ``1.0``.
Please read `UPGRADE-v2.0.md </UPGRADE-v2.0.md>`__ to learn how to
upgrade to Graphene ``2.0``.

--------------

Expand All @@ -11,7 +11,7 @@ building GraphQL schemas/types fast and easily.

- **Easy to use:** Graphene helps you use GraphQL in Python without
effort.
- **Relay:** Graphene has builtin support for both Relay.
- **Relay:** Graphene has builtin support for Relay.
- **Data agnostic:** Graphene supports any kind of data source: SQL
(Django, SQLAlchemy), NoSQL, custom Python objects, etc. We believe
that by providing a complete API you could plug Graphene anywhere
Expand Down Expand Up @@ -47,12 +47,12 @@ For instaling graphene, just run this command in your shell

.. code:: bash
pip install "graphene>=1.0"
pip install "graphene>=2.0"
1.0 Upgrade Guide
2.0 Upgrade Guide
-----------------

Please read `UPGRADE-v1.0.md </UPGRADE-v1.0.md>`__ to learn how to
Please read `UPGRADE-v2.0.md </UPGRADE-v2.0.md>`__ to learn how to
upgrade.

Examples
Expand All @@ -65,7 +65,7 @@ Here is one example for you to get started:
class Query(graphene.ObjectType):
hello = graphene.String(description='A typical hello world')
def resolve_hello(self, args, context, info):
def resolve_hello(self):
return 'World'
schema = graphene.Schema(query=Query)
Expand Down
178 changes: 178 additions & 0 deletions UPGRADE-v2.0.md
@@ -0,0 +1,178 @@
# v2.0 Upgrade Guide

`ObjectType`, `Interface`, `InputObjectType`, `Scalar` and `Enum` implementations
have been quite simplified, without the need to define a explicit Metaclass for each subtype.

It also improves the function resolvers, [simplifying the code](#resolve_only_args) the
developer have to write to use them.

Deprecations:
* [`AbstractType`](#abstracttype-deprecated)
* [`resolve_only_args`](#resolve_only_args)

Breaking changes:
* [`Node Connections`](#node-connections)

New Features!
* [`InputObjectType`](#inputobjecttype)
* [`Meta as Class arguments`](#meta-ass-class-arguments) (_only available for Python 3_)


> The type metaclases are now deleted as are no longer necessary, if your code was depending
> on this strategy for creating custom attrs, see an [example on how to do it in 2.0](https://github.com/graphql-python/graphene/blob/2.0/graphene/tests/issues/test_425.py).
## Deprecations

### AbstractType deprecated

AbstractType is deprecated in graphene 2.0, you can now use normal inheritance instead.

Before:

```python
class CommonFields(AbstractType):
name = String()

class Pet(CommonFields, Interface):
pass
```

With 2.0:

```python
class CommonFields(object):
name = String()

class Pet(CommonFields, Interface):
pass
```

### resolve\_only\_args

`resolve_only_args` is now deprecated in favor of type annotations (using the polyfill `@graphene.annotate` in Python 2 in case is necessary for accessing `context` or `info`).

Before:

```python
class User(ObjectType):
name = String()

@resolve_only_args
def resolve_name(self):
return self.name
```

With 2.0:

```python
class User(ObjectType):
name = String()

def resolve_name(self):
return self.name
```


## Breaking Changes

### Node Connections

Node types no longer have a `Connection` by default.
In 2.0 and onwards `Connection`s should be defined explicitly.

Before:

```python
class User(ObjectType):
class Meta:
interfaces = [relay.Node]
name = String()

class Query(ObjectType):
user_connection = relay.ConnectionField(User)
```

With 2.0:

```python
class User(ObjectType):
class Meta:
interfaces = [relay.Node]
name = String()

class UserConnection(relay.Connection):
class Meta:
node = User

class Query(ObjectType):
user_connection = relay.ConnectionField(UserConnection)
```

## New Features

### InputObjectType

If you are using `InputObjectType`, you now can access
it's fields via `getattr` (`my_input.myattr`) when resolving, instead of
the classic way `my_input['myattr']`.

And also use custom defined properties on your input class.

Example. Before:

```python
class UserInput(InputObjectType):
id = ID()

def is_user_id(id):
return id.startswith('userid_')

class Query(ObjectType):
user = graphene.Field(User, input=UserInput())

@resolve_only_args
def resolve_user(self, input):
user_id = input.get('id')
if is_user_id(user_id):
return get_user(user_id)
```

With 2.0:

```python
class UserInput(InputObjectType):
id = ID()

@property
def is_user_id(self):
return self.id.startswith('userid_')

class Query(ObjectType):
user = graphene.Field(User, input=UserInput())

def resolve_user(self, input):
if input.is_user_id:
return get_user(input.id)

```


### Meta as Class arguments

Now you can use the meta options as class arguments (**ONLY PYTHON 3**).

Before:

```python
class Dog(ObjectType):
class Meta:
interfaces = [Pet]
name = String()
```

With 2.0:

```python
class Dog(ObjectType, interfaces=[Pet]):
name = String()
```
4 changes: 2 additions & 2 deletions docs/execution/dataloader.rst
Expand Up @@ -99,8 +99,8 @@ leaner code and at most 4 database requests, and possibly fewer if there are cac
best_friend = graphene.Field(lambda: User)
friends = graphene.List(lambda: User)
def resolve_best_friend(self, args, context, info):
def resolve_best_friend(self):
return user_loader.load(self.best_friend_id)
def resolve_friends(self, args, context, info):
def resolve_friends(self):
return user_loader.load_many(self.friend_ids)
3 changes: 2 additions & 1 deletion docs/execution/execute.rst
Expand Up @@ -24,7 +24,8 @@ You can pass context to a query via ``context_value``.
class Query(graphene.ObjectType):
name = graphene.String()
def resolve_name(self, args, context, info):
@graphene.annotate(context=graphene.Context)
def resolve_name(self, context):
return context.get('name')
schema = graphene.Schema(Query)
Expand Down
12 changes: 6 additions & 6 deletions docs/quickstart.rst
Expand Up @@ -12,15 +12,15 @@ Let’s build a basic GraphQL schema from scratch.
Requirements
------------

- Python (2.7, 3.2, 3.3, 3.4, 3.5, pypy)
- Graphene (1.0)
- Python (2.7, 3.4, 3.5, 3.6, pypy)
- Graphene (2.0)

Project setup
-------------

.. code:: bash
pip install "graphene>=1.0"
pip install "graphene>=2.0"
Creating a basic Schema
-----------------------
Expand All @@ -37,10 +37,10 @@ one field: ``hello`` and an input name. And when we query it, it should return `
import graphene
class Query(graphene.ObjectType):
hello = graphene.String(name=graphene.Argument(graphene.String, default_value="stranger"))
hello = graphene.String(name=graphene.String(default_value="stranger"))
def resolve_hello(self, args, context, info):
return 'Hello ' + args['name']
def resolve_hello(self, name):
return 'Hello ' + name
schema = graphene.Schema(query=Query)
Expand Down
2 changes: 1 addition & 1 deletion docs/relay/connection.rst
Expand Up @@ -41,5 +41,5 @@ that implements ``Node`` will have a default Connection.
name = graphene.String()
ships = relay.ConnectionField(ShipConnection)
def resolve_ships(self, args, context, info):
def resolve_ships(self):
return []
24 changes: 11 additions & 13 deletions docs/types/mutations.rst
Expand Up @@ -19,9 +19,8 @@ This example defines a Mutation:
ok = graphene.Boolean()
person = graphene.Field(lambda: Person)
@staticmethod
def mutate(root, args, context, info):
person = Person(name=args.get('name'))
def mutate(self, name):
person = Person(name=name)
ok = True
return CreatePerson(person=person, ok=ok)
Expand Down Expand Up @@ -90,30 +89,29 @@ InputFields are used in mutations to allow nested input data for mutations
To use an InputField you define an InputObjectType that specifies the structure of your input data




.. code:: python
import graphene
class PersonInput(graphene.InputObjectType):
name = graphene.String()
age = graphene.Int()
name = graphene.String(required=True)
age = graphene.Int(required=True)
class CreatePerson(graphene.Mutation):
class Input:
person_data = graphene.Argument(PersonInput)
person_data = PersonInput(required=True)
person = graphene.Field(lambda: Person)
person = graphene.Field(Person)
@staticmethod
def mutate(root, args, context, info):
p_data = args.get('person_data')
def mutate(root, person_data=None):
name = p_data.get('name')
age = p_data.get('age')
person = Person(name=name, age=age)
person = Person(
name=person_data.name,
age=person_data.age
)
return CreatePerson(person=person)
Expand Down

0 comments on commit abec4e5

Please sign in to comment.