# graphene-federation3
Federation support for graphene
Federation specs implementation on top of Python graphene lib
https://www.apollographql.com/docs/apollo-server/federation/federation-spec/
Based on discussion: https://github.com/graphql-python/graphene/issues/953#issuecomment-508481652
Supports now:
* sdl (_service fields) # make possible to add schema in federation (as is)
* `@key` decorator (entity support) # to perform Queries across service boundaries
* You can use multiple `@key` per each ObjectType
```python
@key('id')
@key('email')
class User(ObjectType):
id = Int(required=True)
email = String()
def __resolve_reference(self, info, **kwargs):
if self.id is not None:
return User(id=self.id, email=f'name_{self.id}@gmail.com')
return User(id=123, email=self.email)
```
* extend # extend remote types
* external # mark field as external
* requires # mark that field resolver requires other fields to be pre-fetched
* provides # to annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway.
* **Base class should be decorated with `@provides`** as well as field on a base type that provides. Check example bellow:
```python
import graphene
from graphene_federation3 import provides
@provides
class ArticleThatProvideAuthorAge(graphene.ObjectType):
id = Int(required=True)
text = String(required=True)
author = provides(Field(User), fields='age')
```
```python
import graphene
from graphene_federation3 import build_schema, key
@key(
fields='id') # mark File as Entity and add in EntityUnion https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#key
class File(graphene.ObjectType):
id = graphene.Int(required=True)
name = graphene.String()
def resolve_id(self, info, **kwargs):
return 1
def resolve_name(self, info, **kwargs):
return self.name
def __resolve_reference(self, info,
**kwargs): # https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference
return get_file_by_id(self.id)
```
```python
import graphene
from graphene_federation3 import build_schema
class Query(graphene.ObjectType):
...
pass
schema = build_schema(Query) # add _service{sdl} field in Query
```
```python
import graphene
from graphene_federation3 import external, extend
@extend(fields='id')
class Message(graphene.ObjectType):
id = external(graphene.Int(required=True))
def resolve_id(self, **kwargs):
return 1
```
### __resolve_reference
* Each type which is decorated with `@key` or `@extend` is added to `_Entity` union
* `__resolve_reference` method can be defined for each type that is an entity. This method is called whenever an entity is requested as part of the fulfilling a query plan.
If not explicitly defined, default resolver is used. Default resolver just creates instance of type with passed fieldset as kwargs, see [`entity.get_entity_query`](graphene_federation3/entity.py) for more details
* You should define `__resolve_reference`, if you need to extract object before passing it to fields resolvers (example: [FileNode](integration_tests/service_b/schema.py))
* You should not define `__resolve_reference`, if fileds resolvers need only data passed in fieldset (example: [FunnyText](integration_tests/service_a/schema.py))
* read more in [official documentation](https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference)
------------------------
### Known issues:
1. decorators will not work properly
* on fields with capitalised letters with `auto_camelcase=True`, for example: `my_ABC_field = String()`
* on fields with custom names for example `some_field = String(name='another_name')`
---------------------------
For more details see [examples](examples/)
Or better check [integration_tests](integration_tests/)
Also cool [example](https://github.com/preply/graphene-federation/issues/1) of integration with Mongoengine
### For contribution:
#### Run tests:
* `make test`
* if you've changed Dockerfile or requirements run `make build` before `make test`
---------------------------
Also, you can read about how we've come to federation at Preply [here](https://medium.com/preply-engineering/apollo-federation-support-in-graphene-761a0512456d)
Raw data
{
"_id": null,
"home_page": "https://gitlab.com/live-art-project/graphene-federation3",
"name": "graphene-federation3",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "graphene,gql,federation",
"author": "Yorsh Siarhei",
"author_email": "myrik260138@gmail.com",
"download_url": "",
"platform": null,
"description": "# graphene-federation3\nFederation support for graphene\n\n\nFederation specs implementation on top of Python graphene lib \nhttps://www.apollographql.com/docs/apollo-server/federation/federation-spec/\n\nBased on discussion: https://github.com/graphql-python/graphene/issues/953#issuecomment-508481652\n\nSupports now:\n* sdl (_service fields) # make possible to add schema in federation (as is)\n* `@key` decorator (entity support) # to perform Queries across service boundaries\n * You can use multiple `@key` per each ObjectType\n ```python\n @key('id')\n @key('email')\n class User(ObjectType):\n id = Int(required=True)\n email = String()\n \n def __resolve_reference(self, info, **kwargs):\n if self.id is not None:\n return User(id=self.id, email=f'name_{self.id}@gmail.com')\n return User(id=123, email=self.email) \n ```\n* extend # extend remote types\n* external # mark field as external \n* requires # mark that field resolver requires other fields to be pre-fetched\n* provides # to annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. \n * **Base class should be decorated with `@provides`** as well as field on a base type that provides. Check example bellow:\n ```python\n import graphene\n from graphene_federation3 import provides\n \n @provides\n class ArticleThatProvideAuthorAge(graphene.ObjectType):\n id = Int(required=True)\n text = String(required=True)\n author = provides(Field(User), fields='age')\n ```\n\n```python\nimport graphene\nfrom graphene_federation3 import build_schema, key\n\n\n@key(\n fields='id') # mark File as Entity and add in EntityUnion https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#key\nclass File(graphene.ObjectType):\n id = graphene.Int(required=True)\n name = graphene.String()\n\n def resolve_id(self, info, **kwargs):\n return 1\n\n def resolve_name(self, info, **kwargs):\n return self.name\n\n def __resolve_reference(self, info,\n **kwargs): # https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference\n return get_file_by_id(self.id)\n```\n\n```python\nimport graphene\nfrom graphene_federation3 import build_schema\n\n\nclass Query(graphene.ObjectType):\n ...\n pass\n\n\nschema = build_schema(Query) # add _service{sdl} field in Query\n```\n\n```python\nimport graphene\nfrom graphene_federation3 import external, extend\n\n\n@extend(fields='id')\nclass Message(graphene.ObjectType):\n id = external(graphene.Int(required=True))\n\n def resolve_id(self, **kwargs):\n return 1\n\n```\n\n### __resolve_reference\n* Each type which is decorated with `@key` or `@extend` is added to `_Entity` union\n* `__resolve_reference` method can be defined for each type that is an entity. This method is called whenever an entity is requested as part of the fulfilling a query plan.\nIf not explicitly defined, default resolver is used. Default resolver just creates instance of type with passed fieldset as kwargs, see [`entity.get_entity_query`](graphene_federation3/entity.py) for more details\n* You should define `__resolve_reference`, if you need to extract object before passing it to fields resolvers (example: [FileNode](integration_tests/service_b/schema.py))\n* You should not define `__resolve_reference`, if fileds resolvers need only data passed in fieldset (example: [FunnyText](integration_tests/service_a/schema.py))\n* read more in [official documentation](https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference)\n------------------------\n\n\n### Known issues:\n1. decorators will not work properly\n* on fields with capitalised letters with `auto_camelcase=True`, for example: `my_ABC_field = String()`\n* on fields with custom names for example `some_field = String(name='another_name')`\n\n---------------------------\n\nFor more details see [examples](examples/)\n\nOr better check [integration_tests](integration_tests/)\n\nAlso cool [example](https://github.com/preply/graphene-federation/issues/1) of integration with Mongoengine\n\n\n### For contribution:\n#### Run tests:\n* `make test`\n* if you've changed Dockerfile or requirements run `make build` before `make test`\n\n---------------------------\n\nAlso, you can read about how we've come to federation at Preply [here](https://medium.com/preply-engineering/apollo-federation-support-in-graphene-761a0512456d) \n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Federation implementation for graphene3",
"version": "0.3.3.1687272414",
"project_urls": {
"Homepage": "https://gitlab.com/live-art-project/graphene-federation3"
},
"split_keywords": [
"graphene",
"gql",
"federation"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "7cc9116744ed7f47944701252838f748b3589c897907b424733fd1ac48336a48",
"md5": "e3931566f55e4fc3c23777c51179c314",
"sha256": "125dd6a3405123a6c84fcf77949eb3b98d3abb6bf9e897e6a0c109ef89941671"
},
"downloads": -1,
"filename": "graphene_federation3-0.3.3.1687272414-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e3931566f55e4fc3c23777c51179c314",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 13842,
"upload_time": "2023-06-20T14:46:56",
"upload_time_iso_8601": "2023-06-20T14:46:56.674712Z",
"url": "https://files.pythonhosted.org/packages/7c/c9/116744ed7f47944701252838f748b3589c897907b424733fd1ac48336a48/graphene_federation3-0.3.3.1687272414-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-20 14:46:56",
"github": false,
"gitlab": true,
"bitbucket": false,
"codeberg": false,
"gitlab_user": "live-art-project",
"gitlab_project": "graphene-federation3",
"lcname": "graphene-federation3"
}