graphene-federation


Namegraphene-federation JSON
Version 3.1.4 PyPI version JSON
download
home_pagehttps://github.com/graphql-python/graphene-federation
SummaryFederation implementation for graphene
upload_time2023-05-24 01:38:54
maintainer
docs_urlNone
authorIgor Kasianov
requires_python
licenseMIT
keywords graphene graphql gql federation
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # graphene-federation

Federation support for ![Graphene Logo](http://graphene-python.org/favicon.png) [Graphene](http://graphene-python.org) following the [Apollo Federation specifications](https://www.apollographql.com/docs/federation/subgraph-spec).

[![PyPI version][pypi-image]][pypi-url]
[![Unit Tests Status][unit-tests-image]][unit-tests-url]
[![Coverage Status][coveralls-image]][coveralls-url]
[![Integration Tests Status][integration-tests-image]][integration-tests-url]

[pypi-image]: https://badge.fury.io/py/graphene-federation.svg
[pypi-url]: https://pypi.org/project/graphene-federation/
[unit-tests-image]: https://github.com/graphql-python/graphene-federation/workflows/Unit%20Tests/badge.svg?branch=main
[unit-tests-url]: https://github.com/graphql-python/graphene-federation/actions?query=workflow%3A"Unit+Tests"
[coveralls-image]: https://coveralls.io/repos/github/graphql-python/graphene-federation/badge.svg?branch=main
[coveralls-url]: https://coveralls.io/github/graphql-python/graphene-federation?branch=main
[integration-tests-image]: https://github.com/graphql-python/graphene-federation/workflows/Integration%20Tests/badge.svg?branch=main
[integration-tests-url]: https://github.com/graphql-python/graphene-federation/actions?query=workflow%3A"Integration+Tests"


This repository is heavily based on the repo it was forked from... Huge thanks to [Preply for setting up the foundations](https://medium.com/preply-engineering/apollo-federation-support-in-graphene-761a0512456d).

WARNING: This version is not compatible with `graphene` version below v3.
If you need to use a version compatible with `graphene` v2 I recommend using the version 1.0.0 of `graphene_federation`.

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

## Supported Features

At the moment it supports:

* `sdl` (`_service` on field): enable to add schema in federation (as is)
* `@key` decorator (entity support): enable to perform queries across service boundaries (you can have more than one key per type)
* `@extend`: extend remote types
* `external()`: mark a field as external
* `requires()`: mark that field resolver requires other fields to be pre-fetched
* `provides()`/`@provides`: annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway.

Each type which is decorated with `@key` or `@extend` is added to the `_Entity` union.
The [`__resolve_reference` method](https://www.apollographql.com/docs/federation/api/apollo-federation/#__resolvereference) can be defined for each type that is an entity.
Note that since the notation with double underscores can be problematic in Python for model inheritance this resolver method can also be named `_resolve_reference` (the `__resolve_reference` method will take precedence if both are declared).

This method is called whenever an entity is requested as part of the fulfilling a query plan.
If not explicitly defined, the default resolver is used.
The default resolver just creates instance of type with passed fieldset as kwargs, see [`entity.get_entity_query`](graphene_federation/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/src/schema.py))
* You should not define `__resolve_reference`, if fields resolvers need only data passed in fieldset (example: [FunnyText](integration_tests/service_a/src/schema.py))
Read more in [official documentation](https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference).

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

## Example

Here is an example of implementation based on the [Apollo Federation introduction example](https://www.apollographql.com/docs/federation/).
It implements a federation schema for a basic e-commerce application over three services: accounts, products, reviews.

### Accounts
First add an account service that expose a `User` type that can then be referenced in other services by its `id` field:

```python
from graphene import Field, ID, ObjectType, String
from graphene_federation import build_schema, key

@key("id")
class User(ObjectType):
    id = Int(required=True)
    username = String(required=True)

    def __resolve_reference(self, info, **kwargs):
        """
        Here we resolve the reference of the user entity referenced by its `id` field.
        """
        return User(id=self.id, email=f"user_{self.id}@mail.com")

class Query(ObjectType):
    me = Field(User)

schema = build_schema(query=Query)
```

### Product
The product service exposes a `Product` type that can be used by other services via the `upc` field:

```python
from graphene import Argument, ID, Int, List, ObjectType, String
from graphene_federation import build_schema, key

@key("upc")
class Product(ObjectType):
    upc = String(required=True)
    name = String(required=True)
    price = Int()

    def __resolve_reference(self, info, **kwargs):
        """
        Here we resolve the reference of the product entity referenced by its `upc` field.
        """
        return Product(upc=self.upc, name=f"product {self.upc}")

class Query(ObjectType):
    topProducts = List(Product, first=Argument(Int, default_value=5))

schema = build_schema(query=Query)
```

### Reviews
The reviews service exposes a `Review` type which has a link to both the `User` and `Product` types.
It also has the ability to provide the username of the `User`.
On top of that it adds to the `User`/`Product` types (that are both defined in other services) the ability to get their reviews.

```python
from graphene import Field, ID, Int, List, ObjectType, String
from graphene_federation import build_schema, extend, external, provides

@extend("id")
class User(ObjectType):
    id = external(Int(required=True))
    reviews = List(lambda: Review)

    def resolve_reviews(self, info, *args, **kwargs):
        """
        Get all the reviews of a given user. (not implemented here)
        """
        return []

@extend("upc")
class Product(ObjectType):
    upc = external(String(required=True))
    reviews = List(lambda: Review)

# Note that both the base type and the field need to be decorated with `provides` (on the field itself you need to specify which fields get provided).
@provides
class Review(ObjectType):
    body = String()
    author = provides(Field(User), fields="username")
    product = Field(Product)

class Query(ObjectType):
    review = Field(Review)

schema = build_schema(query=Query)
```

### Federation

Note that each schema declaration for the services is a valid graphql schema (it only adds the `_Entity` and `_Service` types).
The best way to check that the decorator are set correctly is to request the service sdl:

```python
from graphql import graphql

query = """
query {
    _service {
        sdl
    }
}
"""

result = graphql(schema, query)
print(result.data["_service"]["sdl"])
```

Those can then be used in a federated schema.

You can find more examples in the unit / integration tests and [examples folder](examples/).

There is also a cool [example](https://github.com/preply/graphene-federation/issues/1) of integration with Mongoengine.

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

## Known issues

1. decorators will not work properly on fields with custom names for example `some_field = String(name='another_name')`

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

## Contributing

* You can run the unit tests by doing: `make tests`.
* You can run the integration tests by doing `make integration-build && make integration-test`.
* You can get a development environment (on a Docker container) with `make dev-setup`.
* You should use `black` to format your code.

The tests are automatically run on Travis CI on push to GitHub.

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

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/graphql-python/graphene-federation",
    "name": "graphene-federation",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "graphene,graphql,gql,federation",
    "author": "Igor Kasianov",
    "author_email": "super.hang.glider@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/c4/e0/3bb1d0a48775535d716b81d6259489471ddbb77779d1447b18a0ed66c40f/graphene-federation-3.1.4.tar.gz",
    "platform": null,
    "description": "# graphene-federation\n\nFederation support for ![Graphene Logo](http://graphene-python.org/favicon.png) [Graphene](http://graphene-python.org) following the [Apollo Federation specifications](https://www.apollographql.com/docs/federation/subgraph-spec).\n\n[![PyPI version][pypi-image]][pypi-url]\n[![Unit Tests Status][unit-tests-image]][unit-tests-url]\n[![Coverage Status][coveralls-image]][coveralls-url]\n[![Integration Tests Status][integration-tests-image]][integration-tests-url]\n\n[pypi-image]: https://badge.fury.io/py/graphene-federation.svg\n[pypi-url]: https://pypi.org/project/graphene-federation/\n[unit-tests-image]: https://github.com/graphql-python/graphene-federation/workflows/Unit%20Tests/badge.svg?branch=main\n[unit-tests-url]: https://github.com/graphql-python/graphene-federation/actions?query=workflow%3A\"Unit+Tests\"\n[coveralls-image]: https://coveralls.io/repos/github/graphql-python/graphene-federation/badge.svg?branch=main\n[coveralls-url]: https://coveralls.io/github/graphql-python/graphene-federation?branch=main\n[integration-tests-image]: https://github.com/graphql-python/graphene-federation/workflows/Integration%20Tests/badge.svg?branch=main\n[integration-tests-url]: https://github.com/graphql-python/graphene-federation/actions?query=workflow%3A\"Integration+Tests\"\n\n\nThis repository is heavily based on the repo it was forked from... Huge thanks to [Preply for setting up the foundations](https://medium.com/preply-engineering/apollo-federation-support-in-graphene-761a0512456d).\n\nWARNING: This version is not compatible with `graphene` version below v3.\nIf you need to use a version compatible with `graphene` v2 I recommend using the version 1.0.0 of `graphene_federation`.\n\n------------------------\n\n## Supported Features\n\nAt the moment it supports:\n\n* `sdl` (`_service` on field): enable to add schema in federation (as is)\n* `@key` decorator (entity support): enable to perform queries across service boundaries (you can have more than one key per type)\n* `@extend`: extend remote types\n* `external()`: mark a field as external\n* `requires()`: mark that field resolver requires other fields to be pre-fetched\n* `provides()`/`@provides`: annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway.\n\nEach type which is decorated with `@key` or `@extend` is added to the `_Entity` union.\nThe [`__resolve_reference` method](https://www.apollographql.com/docs/federation/api/apollo-federation/#__resolvereference) can be defined for each type that is an entity.\nNote that since the notation with double underscores can be problematic in Python for model inheritance this resolver method can also be named `_resolve_reference` (the `__resolve_reference` method will take precedence if both are declared).\n\nThis method is called whenever an entity is requested as part of the fulfilling a query plan.\nIf not explicitly defined, the default resolver is used.\nThe default resolver just creates instance of type with passed fieldset as kwargs, see [`entity.get_entity_query`](graphene_federation/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/src/schema.py))\n* You should not define `__resolve_reference`, if fields resolvers need only data passed in fieldset (example: [FunnyText](integration_tests/service_a/src/schema.py))\nRead more in [official documentation](https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference).\n\n------------------------\n\n## Example\n\nHere is an example of implementation based on the [Apollo Federation introduction example](https://www.apollographql.com/docs/federation/).\nIt implements a federation schema for a basic e-commerce application over three services: accounts, products, reviews.\n\n### Accounts\nFirst add an account service that expose a `User` type that can then be referenced in other services by its `id` field:\n\n```python\nfrom graphene import Field, ID, ObjectType, String\nfrom graphene_federation import build_schema, key\n\n@key(\"id\")\nclass User(ObjectType):\n    id = Int(required=True)\n    username = String(required=True)\n\n    def __resolve_reference(self, info, **kwargs):\n        \"\"\"\n        Here we resolve the reference of the user entity referenced by its `id` field.\n        \"\"\"\n        return User(id=self.id, email=f\"user_{self.id}@mail.com\")\n\nclass Query(ObjectType):\n    me = Field(User)\n\nschema = build_schema(query=Query)\n```\n\n### Product\nThe product service exposes a `Product` type that can be used by other services via the `upc` field:\n\n```python\nfrom graphene import Argument, ID, Int, List, ObjectType, String\nfrom graphene_federation import build_schema, key\n\n@key(\"upc\")\nclass Product(ObjectType):\n    upc = String(required=True)\n    name = String(required=True)\n    price = Int()\n\n    def __resolve_reference(self, info, **kwargs):\n        \"\"\"\n        Here we resolve the reference of the product entity referenced by its `upc` field.\n        \"\"\"\n        return Product(upc=self.upc, name=f\"product {self.upc}\")\n\nclass Query(ObjectType):\n    topProducts = List(Product, first=Argument(Int, default_value=5))\n\nschema = build_schema(query=Query)\n```\n\n### Reviews\nThe reviews service exposes a `Review` type which has a link to both the `User` and `Product` types.\nIt also has the ability to provide the username of the `User`.\nOn top of that it adds to the `User`/`Product` types (that are both defined in other services) the ability to get their reviews.\n\n```python\nfrom graphene import Field, ID, Int, List, ObjectType, String\nfrom graphene_federation import build_schema, extend, external, provides\n\n@extend(\"id\")\nclass User(ObjectType):\n    id = external(Int(required=True))\n    reviews = List(lambda: Review)\n\n    def resolve_reviews(self, info, *args, **kwargs):\n        \"\"\"\n        Get all the reviews of a given user. (not implemented here)\n        \"\"\"\n        return []\n\n@extend(\"upc\")\nclass Product(ObjectType):\n    upc = external(String(required=True))\n    reviews = List(lambda: Review)\n\n# Note that both the base type and the field need to be decorated with `provides` (on the field itself you need to specify which fields get provided).\n@provides\nclass Review(ObjectType):\n    body = String()\n    author = provides(Field(User), fields=\"username\")\n    product = Field(Product)\n\nclass Query(ObjectType):\n    review = Field(Review)\n\nschema = build_schema(query=Query)\n```\n\n### Federation\n\nNote that each schema declaration for the services is a valid graphql schema (it only adds the `_Entity` and `_Service` types).\nThe best way to check that the decorator are set correctly is to request the service sdl:\n\n```python\nfrom graphql import graphql\n\nquery = \"\"\"\nquery {\n    _service {\n        sdl\n    }\n}\n\"\"\"\n\nresult = graphql(schema, query)\nprint(result.data[\"_service\"][\"sdl\"])\n```\n\nThose can then be used in a federated schema.\n\nYou can find more examples in the unit / integration tests and [examples folder](examples/).\n\nThere is also a cool [example](https://github.com/preply/graphene-federation/issues/1) of integration with Mongoengine.\n\n------------------------\n\n## Known issues\n\n1. decorators will not work properly on fields with custom names for example `some_field = String(name='another_name')`\n\n------------------------\n\n## Contributing\n\n* You can run the unit tests by doing: `make tests`.\n* You can run the integration tests by doing `make integration-build && make integration-test`.\n* You can get a development environment (on a Docker container) with `make dev-setup`.\n* You should use `black` to format your code.\n\nThe tests are automatically run on Travis CI on push to GitHub.\n\n---------------------------\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Federation implementation for graphene",
    "version": "3.1.4",
    "project_urls": {
        "Download": "https://github.com/graphql-python/graphene-federation/archive/3.1.4.tar.gz",
        "Homepage": "https://github.com/graphql-python/graphene-federation"
    },
    "split_keywords": [
        "graphene",
        "graphql",
        "gql",
        "federation"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9e7dfac382d07e833c36ddebf1149ee71f83cb87358f97b97e07f7729aa51cfd",
                "md5": "f04b745ed0ebc282df7f99bd95811edf",
                "sha256": "3edc91315a4bf8e36842ca406adc0dc65b3b9853ee85fa9394aee2ef2fb6c5ba"
            },
            "downloads": -1,
            "filename": "graphene_federation-3.1.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f04b745ed0ebc282df7f99bd95811edf",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 36677,
            "upload_time": "2023-05-24T01:38:53",
            "upload_time_iso_8601": "2023-05-24T01:38:53.140051Z",
            "url": "https://files.pythonhosted.org/packages/9e/7d/fac382d07e833c36ddebf1149ee71f83cb87358f97b97e07f7729aa51cfd/graphene_federation-3.1.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c4e03bb1d0a48775535d716b81d6259489471ddbb77779d1447b18a0ed66c40f",
                "md5": "627a5030ae49215c66718c44b5aa3863",
                "sha256": "c652af850fd7a7f0ef220ae405d584b4214e6cc8662418142a7da23358bf7262"
            },
            "downloads": -1,
            "filename": "graphene-federation-3.1.4.tar.gz",
            "has_sig": false,
            "md5_digest": "627a5030ae49215c66718c44b5aa3863",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 22210,
            "upload_time": "2023-05-24T01:38:54",
            "upload_time_iso_8601": "2023-05-24T01:38:54.462543Z",
            "url": "https://files.pythonhosted.org/packages/c4/e0/3bb1d0a48775535d716b81d6259489471ddbb77779d1447b18a0ed66c40f/graphene-federation-3.1.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-24 01:38:54",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "graphql-python",
    "github_project": "graphene-federation",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "graphene-federation"
}
        
Elapsed time: 0.10405s