https://github.com/strollby/graphene-directives
Schema Directives implementation for graphene
https://github.com/strollby/graphene-directives
graphql graphql-python
Last synced: 2 months ago
JSON representation
Schema Directives implementation for graphene
- Host: GitHub
- URL: https://github.com/strollby/graphene-directives
- Owner: strollby
- License: mit
- Created: 2023-12-04T05:17:51.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-10-09T06:43:24.000Z (8 months ago)
- Last Synced: 2025-12-17T01:36:18.265Z (6 months ago)
- Topics: graphql, graphql-python
- Language: Python
- Homepage:
- Size: 178 KB
- Stars: 9
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# 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)