# Graphene Directives
Schema Directives implementation for graphene
[![PyPI version][pypi-image]][pypi-url]
[![PyPI pyversions][pypi-version-image]][pypi-version-url]
[![Downloads][pypi-downloads-image]][pypi-downloads-url]
[![Test Status][tests-image]][tests-url]
[![Coverage Status][coveralls-image]][coveralls-url]
[pypi-image]: https://badge.fury.io/py/graphene-directives.svg
[pypi-url]: https://pypi.org/project/graphene-directives/
[pypi-version-image]: https://img.shields.io/pypi/pyversions/graphene-directives.svg
[pypi-version-url]: https://pypi.python.org/pypi/graphene-directives/
[pypi-downloads-image]: https://pepy.tech/badge/graphene-directives
[pypi-downloads-url]: https://pepy.tech/project/graphene-directives
[tests-image]: https://github.com/strollby/graphene-directives/actions/workflows/test.yml/badge.svg?branch=main
[tests-url]: https://github.com/strollby/graphene-directives/actions/workflows/test.yml
[coveralls-image]: https://coveralls.io/repos/github/strollby/graphene-directives/badge.svg?branch=main
[coveralls-url]: https://coveralls.io/github/strollby/graphene-directives?branch=main
------------------------
## Directive Locations Supported
- [x] DirectiveLocation.SCHEMA
- [x] DirectiveLocation.OBJECT
- [x] DirectiveLocation.ENUM
- [x] DirectiveLocation.INTERFACE
- [x] DirectiveLocation.UNION
- [x] DirectiveLocation.SCALAR
- [x] DirectiveLocation.FIELD_DEFINITION
- [x] DirectiveLocation.INPUT_FIELD_DEFINITION
- [x] DirectiveLocation.INPUT_OBJECT
- [x] DirectiveLocation.ENUM_VALUE
- [x] DirectiveLocation.ARGUMENT_DEFINITION,
------------------------
## Example
### Using `@directive`
```python
import graphene
from graphql import (
GraphQLArgument,
GraphQLInt,
GraphQLNonNull,
GraphQLString,
)
from graphene_directives import CustomDirective, DirectiveLocation, build_schema, directive
CacheDirective = CustomDirective(
name="cache",
locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],
args={
"max_age": GraphQLArgument(
GraphQLNonNull(GraphQLInt),
description="Specifies the maximum age for cache in seconds.",
),
"swr": GraphQLArgument(
GraphQLInt, description="Stale-while-revalidate value in seconds. Optional."
),
"scope": GraphQLArgument(
GraphQLString, description="Scope of the cache. Optional."
),
},
description="Caching directive to control cache behavior of fields or fragments.",
)
@directive(CacheDirective, max_age=200)
class SomeType(graphene.ObjectType):
field_1 = directive(CacheDirective, field=graphene.String(), max_age=300)
field_2 = directive(CacheDirective, field=graphene.String(), max_age=300, swr=2)
field_3 = graphene.String()
class Query(graphene.ObjectType):
some_query = graphene.Field(SomeType)
schema = build_schema(
query=Query, directives=[CacheDirective]
)
```
### Using `directive_decorator`
```python
import graphene
from graphql import (
GraphQLArgument,
GraphQLInt,
GraphQLNonNull,
GraphQLString,
)
from graphene_directives import CustomDirective, DirectiveLocation, build_schema, directive_decorator
CacheDirective = CustomDirective(
name="cache",
locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],
args={
"max_age": GraphQLArgument(
GraphQLNonNull(GraphQLInt),
description="Specifies the maximum age for cache in seconds.",
),
"swr": GraphQLArgument(
GraphQLInt, description="Stale-while-revalidate value in seconds. Optional."
),
"scope": GraphQLArgument(
GraphQLString, description="Scope of the cache. Optional."
),
},
description="Caching directive to control cache behavior of fields or fragments.",
)
# This returns a partial of directive function
cache = directive_decorator(target_directive=CacheDirective)
@cache(max_age=200)
class SomeType(graphene.ObjectType):
field_1 = cache(field=graphene.String(), max_age=300)
field_2 = cache(field=graphene.String(), max_age=300, swr=2)
field_3 = graphene.String()
class Query(graphene.ObjectType):
some_query = graphene.Field(SomeType)
schema = build_schema(
query=Query, directives=[CacheDirective]
)
```
### Custom Input Validation
```python
from typing import Any
import graphene
from graphql import (
GraphQLArgument,
GraphQLInt,
GraphQLNonNull,
GraphQLString,
)
from graphene_directives import CustomDirective, DirectiveLocation, Schema, build_schema, directive_decorator
def input_transform(inputs: dict, _schema: Schema) -> dict:
"""
def input_transform (inputs: Any, schema: Schema) -> dict,
"""
if inputs.get("max_age") > 200:
inputs["swr"] = 30
return inputs
def validate_non_field_input(_type: Any, inputs: dict, _schema: Schema) -> bool:
"""
def validator (type_: graphene type, inputs: Any, schema: Schema) -> bool,
if validator returns False, library raises DirectiveCustomValidationError
"""
if inputs.get("max_age") > 2500:
return False
return True
def validate_field_input(
_parent_type: Any, _field_type: Any, inputs: dict, _schema: Schema
) -> bool:
"""
def validator (parent_type_: graphene_type, field_type_: graphene type, inputs: Any, schema: Schema) -> bool,
if validator returns False, library raises DirectiveCustomValidationError
"""
if inputs.get("max_age") > 2500:
return False
return True
CacheDirective = CustomDirective(
name="cache",
locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],
args={
"max_age": GraphQLArgument(
GraphQLNonNull(GraphQLInt),
description="Specifies the maximum age for cache in seconds.",
),
"swr": GraphQLArgument(
GraphQLInt, description="Stale-while-revalidate value in seconds. Optional."
),
"scope": GraphQLArgument(
GraphQLString, description="Scope of the cache. Optional."
),
},
description="Caching directive to control cache behavior of fields or fragments.",
non_field_validator=validate_non_field_input,
field_validator=validate_field_input,
input_transform=input_transform,
)
# This returns a partial of directive function
cache = directive_decorator(target_directive=CacheDirective)
@cache(max_age=200)
class SomeType(graphene.ObjectType):
field_1 = cache(field=graphene.String(), max_age=300)
field_2 = cache(field=graphene.String(), max_age=300, swr=2)
field_3 = graphene.String()
class Query(graphene.ObjectType):
some_query = graphene.Field(SomeType)
schema = build_schema(
query=Query, directives=[CacheDirective]
)
```
### Complex Use Cases
Refer [`Code`](./example/complex_uses.py) and [`Graphql Output`](./example/complex_uses.graphql)
Raw data
{
"_id": null,
"home_page": "https://github.com/strollby/graphene-directives",
"name": "graphene-directives",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.9,<4",
"maintainer_email": "",
"keywords": "graphene-directives,graphene,graphql,graphql-directives,graphql-custom-directives",
"author": "Strollby",
"author_email": "developers@strollby.com",
"download_url": "https://files.pythonhosted.org/packages/c7/9e/b15c37455a2746865e9c9e7c8046a01051ccd12e7df3e4cf224411b6eeef/graphene_directives-0.4.6.tar.gz",
"platform": null,
"description": "# Graphene Directives\nSchema Directives implementation for graphene\n\n[![PyPI version][pypi-image]][pypi-url]\n[![PyPI pyversions][pypi-version-image]][pypi-version-url]\n[![Downloads][pypi-downloads-image]][pypi-downloads-url]\n[![Test Status][tests-image]][tests-url]\n[![Coverage Status][coveralls-image]][coveralls-url]\n\n[pypi-image]: https://badge.fury.io/py/graphene-directives.svg\n[pypi-url]: https://pypi.org/project/graphene-directives/\n[pypi-version-image]: https://img.shields.io/pypi/pyversions/graphene-directives.svg\n[pypi-version-url]: https://pypi.python.org/pypi/graphene-directives/\n[pypi-downloads-image]: https://pepy.tech/badge/graphene-directives\n[pypi-downloads-url]: https://pepy.tech/project/graphene-directives\n[tests-image]: https://github.com/strollby/graphene-directives/actions/workflows/test.yml/badge.svg?branch=main\n[tests-url]: https://github.com/strollby/graphene-directives/actions/workflows/test.yml\n[coveralls-image]: https://coveralls.io/repos/github/strollby/graphene-directives/badge.svg?branch=main\n[coveralls-url]: https://coveralls.io/github/strollby/graphene-directives?branch=main\n\n------------------------\n\n## Directive Locations Supported\n\n- [x] DirectiveLocation.SCHEMA\n- [x] DirectiveLocation.OBJECT\n- [x] DirectiveLocation.ENUM\n- [x] DirectiveLocation.INTERFACE\n- [x] DirectiveLocation.UNION\n- [x] DirectiveLocation.SCALAR\n- [x] DirectiveLocation.FIELD_DEFINITION\n- [x] DirectiveLocation.INPUT_FIELD_DEFINITION\n- [x] DirectiveLocation.INPUT_OBJECT\n- [x] DirectiveLocation.ENUM_VALUE\n- [x] DirectiveLocation.ARGUMENT_DEFINITION,\n\n------------------------\n\n## Example\n\n### Using `@directive`\n\n```python\nimport graphene\nfrom graphql import (\n GraphQLArgument,\n GraphQLInt,\n GraphQLNonNull,\n GraphQLString,\n)\n\nfrom graphene_directives import CustomDirective, DirectiveLocation, build_schema, directive\n\nCacheDirective = CustomDirective(\n name=\"cache\",\n locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],\n args={\n \"max_age\": GraphQLArgument(\n GraphQLNonNull(GraphQLInt),\n description=\"Specifies the maximum age for cache in seconds.\",\n ),\n \"swr\": GraphQLArgument(\n GraphQLInt, description=\"Stale-while-revalidate value in seconds. Optional.\"\n ),\n \"scope\": GraphQLArgument(\n GraphQLString, description=\"Scope of the cache. Optional.\"\n ),\n },\n description=\"Caching directive to control cache behavior of fields or fragments.\",\n)\n\n\n@directive(CacheDirective, max_age=200)\nclass SomeType(graphene.ObjectType):\n field_1 = directive(CacheDirective, field=graphene.String(), max_age=300)\n field_2 = directive(CacheDirective, field=graphene.String(), max_age=300, swr=2)\n field_3 = graphene.String()\n\n\nclass Query(graphene.ObjectType):\n some_query = graphene.Field(SomeType)\n\n\nschema = build_schema(\n query=Query, directives=[CacheDirective]\n) \n```\n\n\n### Using `directive_decorator`\n\n```python\nimport graphene\nfrom graphql import (\n GraphQLArgument,\n GraphQLInt,\n GraphQLNonNull,\n GraphQLString,\n)\n\nfrom graphene_directives import CustomDirective, DirectiveLocation, build_schema, directive_decorator\n\nCacheDirective = CustomDirective(\n name=\"cache\",\n locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],\n args={\n \"max_age\": GraphQLArgument(\n GraphQLNonNull(GraphQLInt),\n description=\"Specifies the maximum age for cache in seconds.\",\n ),\n \"swr\": GraphQLArgument(\n GraphQLInt, description=\"Stale-while-revalidate value in seconds. Optional.\"\n ),\n \"scope\": GraphQLArgument(\n GraphQLString, description=\"Scope of the cache. Optional.\"\n ),\n },\n description=\"Caching directive to control cache behavior of fields or fragments.\",\n)\n\n# This returns a partial of directive function\ncache = directive_decorator(target_directive=CacheDirective)\n\n\n@cache(max_age=200)\nclass SomeType(graphene.ObjectType):\n field_1 = cache(field=graphene.String(), max_age=300)\n field_2 = cache(field=graphene.String(), max_age=300, swr=2)\n field_3 = graphene.String()\n\n\nclass Query(graphene.ObjectType):\n some_query = graphene.Field(SomeType)\n\n\nschema = build_schema(\n query=Query, directives=[CacheDirective]\n)\n```\n\n### Custom Input Validation\n\n```python\nfrom typing import Any\n\nimport graphene\nfrom graphql import (\n GraphQLArgument,\n GraphQLInt,\n GraphQLNonNull,\n GraphQLString,\n)\n\nfrom graphene_directives import CustomDirective, DirectiveLocation, Schema, build_schema, directive_decorator\n\n\ndef input_transform(inputs: dict, _schema: Schema) -> dict:\n \"\"\"\n def input_transform (inputs: Any, schema: Schema) -> dict,\n \"\"\"\n if inputs.get(\"max_age\") > 200:\n inputs[\"swr\"] = 30\n return inputs\n\n\ndef validate_non_field_input(_type: Any, inputs: dict, _schema: Schema) -> bool:\n \"\"\"\n def validator (type_: graphene type, inputs: Any, schema: Schema) -> bool,\n if validator returns False, library raises DirectiveCustomValidationError\n \"\"\"\n if inputs.get(\"max_age\") > 2500:\n return False\n return True\n\n\ndef validate_field_input(\n _parent_type: Any, _field_type: Any, inputs: dict, _schema: Schema\n) -> bool:\n \"\"\"\n def validator (parent_type_: graphene_type, field_type_: graphene type, inputs: Any, schema: Schema) -> bool,\n if validator returns False, library raises DirectiveCustomValidationError\n \"\"\"\n if inputs.get(\"max_age\") > 2500:\n return False\n return True\n\n\nCacheDirective = CustomDirective(\n name=\"cache\",\n locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT],\n args={\n \"max_age\": GraphQLArgument(\n GraphQLNonNull(GraphQLInt),\n description=\"Specifies the maximum age for cache in seconds.\",\n ),\n \"swr\": GraphQLArgument(\n GraphQLInt, description=\"Stale-while-revalidate value in seconds. Optional.\"\n ),\n \"scope\": GraphQLArgument(\n GraphQLString, description=\"Scope of the cache. Optional.\"\n ),\n },\n description=\"Caching directive to control cache behavior of fields or fragments.\",\n non_field_validator=validate_non_field_input,\n field_validator=validate_field_input,\n input_transform=input_transform,\n)\n\n# This returns a partial of directive function\ncache = directive_decorator(target_directive=CacheDirective)\n\n\n@cache(max_age=200)\nclass SomeType(graphene.ObjectType):\n field_1 = cache(field=graphene.String(), max_age=300)\n field_2 = cache(field=graphene.String(), max_age=300, swr=2)\n field_3 = graphene.String()\n\n\nclass Query(graphene.ObjectType):\n some_query = graphene.Field(SomeType)\n\n\nschema = build_schema(\n query=Query, directives=[CacheDirective]\n)\n```\n\n\n### Complex Use Cases\n\nRefer [`Code`](./example/complex_uses.py) and [`Graphql Output`](./example/complex_uses.graphql)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Schema Directives implementation for graphene",
"version": "0.4.6",
"project_urls": {
"Documentation": "https://github.com/strollby/graphene-directives",
"Homepage": "https://github.com/strollby/graphene-directives",
"Repository": "https://github.com/strollby/graphene-directives"
},
"split_keywords": [
"graphene-directives",
"graphene",
"graphql",
"graphql-directives",
"graphql-custom-directives"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "73946953ac8965ffeb78ef2ade787310150c689a2fbc44cbbb4fd941f0c17c0a",
"md5": "ce31b501a0ae42cc11c10437934c01c3",
"sha256": "6caae14e675bfafe90ed54e6c2aa571b502b854f56b41fb6dedd3c9e98e3c08d"
},
"downloads": -1,
"filename": "graphene_directives-0.4.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ce31b501a0ae42cc11c10437934c01c3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9,<4",
"size": 16742,
"upload_time": "2024-01-15T18:07:53",
"upload_time_iso_8601": "2024-01-15T18:07:53.244892Z",
"url": "https://files.pythonhosted.org/packages/73/94/6953ac8965ffeb78ef2ade787310150c689a2fbc44cbbb4fd941f0c17c0a/graphene_directives-0.4.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c79eb15c37455a2746865e9c9e7c8046a01051ccd12e7df3e4cf224411b6eeef",
"md5": "7a626f76ab8b498900017c8ba0def49d",
"sha256": "c37bd3223817433f3442794748721b7a72ad821110018975607652d4d9d33a16"
},
"downloads": -1,
"filename": "graphene_directives-0.4.6.tar.gz",
"has_sig": false,
"md5_digest": "7a626f76ab8b498900017c8ba0def49d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9,<4",
"size": 13888,
"upload_time": "2024-01-15T18:07:55",
"upload_time_iso_8601": "2024-01-15T18:07:55.124015Z",
"url": "https://files.pythonhosted.org/packages/c7/9e/b15c37455a2746865e9c9e7c8046a01051ccd12e7df3e4cf224411b6eeef/graphene_directives-0.4.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-15 18:07:55",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "strollby",
"github_project": "graphene-directives",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "graphene-directives"
}