Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create v2 that is compatible with Core v2 #21

Merged
merged 5 commits into from
Jul 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
ignore = E203,W503,E704
exclude = .git,.mypy_cache,.pytest_cache,.tox,.venv,__pycache__,build,dist,docs
max-line-length = 88
39 changes: 20 additions & 19 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
# Created by https://www.gitignore.io

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
Expand All @@ -22,40 +13,50 @@ lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
*.cover
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/

.python-version

.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

.mypy_cache/

.idea/
16 changes: 8 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ language: python
dist: xenial

python:
- 2.7
- 3.5
- 3.6
- 3.7
- pypy3
- "2.7"
- "3.5"
- "3.6"
- "3.7"
- "pypy3"
install:
- pip install pytest pytest-cov flake8
- pip install .
- pip install "flake8>=3.7,<4"
script:
- py.test --cov=graphql_relay
# - flake8
- python setup.py test -a "--cov=graphql_relay"
- flake8 setup.py src tests
after_success:
- pip install coveralls
- coveralls
54 changes: 25 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ that documentation and the corresponding tests in this library together.
Install Relay Library for GraphQL Python

```sh
pip install graphql-core --pre # Last version of graphql-core
pip install "graphql-core>=2,<3" # use version 2.x of graphql-core
pip install graphql-relay
```

Expand All @@ -54,13 +54,13 @@ returning those types.
they return a connection type.
- `connection_definitions` returns a `connection_type` and its associated
`edgeType`, given a name and a node type.
- `connection_from_list` is a helper method that takes an array and the
- `connection_from_list` is a helper method that takes a list and the
arguments from `connection_args`, does pagination and filtering, and returns
an object in the shape expected by a `connection_type`'s `resolver` function.
- `connection_from_promised_list` is similar to `connection_from_list`, but
it takes a promise that resolves to an array, and returns a promise that
resolves to the expected shape by `connection_type`.
- `cursor_for_object_in_connection` is a helper method that takes an array and a
- `cursor_for_object_in_connection` is a helper method that takes a list and a
member object, and returns a cursor for use in the mutation payload.

An example usage of these methods from the [test schema](tests/starwars/schema.py):
Expand All @@ -69,32 +69,31 @@ An example usage of these methods from the [test schema](tests/starwars/schema.p
ship_edge, ship_connection = connection_definitions('Ship', shipType)

factionType = GraphQLObjectType(
name= 'Faction',
description= 'A faction in the Star Wars saga',
name='Faction',
description='A faction in the Star Wars saga',
fields= lambda: {
'id': global_id_field('Faction'),
'name': GraphQLField(
GraphQLString,
description='The name of the faction.',
),
'ships': GraphQLField(
shipConnection,
description= 'The ships used by the faction.',
args= connection_args,
resolver= lambda faction, args, *_: connection_from_list(
map(getShip, faction.ships),
args
ship_connection,
description='The ships used by the faction.',
args=connection_args,
resolver=lambda faction, _info, **args: connection_from_list(
[getShip(ship) for ship in faction.ships], args
),
)
},
interfaces= [node_interface]
interfaces=[node_interface]
)
```

This shows adding a `ships` field to the `Faction` object that is a connection.
It uses `connection_definitions({name: 'Ship', nodeType: shipType})` to create
the connection type, adds `connection_args` as arguments on this function, and
then implements the resolver function by passing the array of ships and the
then implements the resolver function by passing the list of ships and the
arguments to `connection_from_list`.

### Object Identification
Expand All @@ -108,7 +107,7 @@ this, it takes a function to resolve an ID to an object, and to determine
the type of a given object.
- `to_global_id` takes a type name and an ID specific to that type name,
and returns a "global ID" that is unique among all types.
- `from_global_id` takes the "global ID" created by `toGlobalID`, and retuns
- `from_global_id` takes the "global ID" created by `to_global_id`, and returns
the type name and ID used to create it.
- `global_id_field` creates the configuration for an `id` field on a node.
- `plural_identifying_root_field` creates a field that accepts a list of
Expand All @@ -118,17 +117,16 @@ objects.
An example usage of these methods from the [test schema](tests/starwars/schema.py):

```python
def get_node(global_id, context, info):
resolvedGlobalId = from_global_id(global_id)
_type, _id = resolvedGlobalId.type, resolvedGlobalId.id
if _type == 'Faction':
return getFaction(_id)
elif _type == 'Ship':
return getShip(_id)
def get_node(global_id, _info):
type_, id_ = from_global_id(global_id)
if type_ == 'Faction':
return getFaction(id_)
elif type_ == 'Ship':
return getShip(id_)
else:
return None

def get_node_type(obj, context, info):
def get_node_type(obj, _info):
if isinstance(obj, Faction):
return factionType
else:
Expand Down Expand Up @@ -177,11 +175,9 @@ class IntroduceShipMutation(object):
def __init__(self, shipId, factionId, clientMutationId=None):
self.shipId = shipId
self.factionId = factionId
self.clientMutationId = None
self.clientMutationId = clientMutationId

def mutate_and_get_payload(data, *_):
shipName = data.get('shipName')
factionId = data.get('factionId')
def mutate_and_get_payload(_info, shipName, factionId, **_input):
newShip = createShip(shipName, factionId)
return IntroduceShipMutation(
shipId=newShip.id,
Expand All @@ -201,19 +197,19 @@ shipMutation = mutation_with_client_mutation_id(
output_fields= {
'ship': GraphQLField(
shipType,
resolver= lambda payload, *_: getShip(payload.shipId)
resolver=lambda payload, _info: getShip(payload.shipId)
),
'faction': GraphQLField(
factionType,
resolver= lambda payload, *_: getFaction(payload.factionId)
resolver=lambda payload, _info: getFaction(payload.factionId)
)
},
mutate_and_get_payload=mutate_and_get_payload
)

mutationType = GraphQLObjectType(
'Mutation',
fields= lambda: {
fields=lambda: {
'introduceShip': shipMutation
}
)
Expand Down
Loading