Directive
Tartiflette bases most of its extensibility on Directives. A directive will allow you to execute a behavior at 6 different stages.
on_build: To wrap your directive around the build process of the SDLon_field_execution: Allows you to wrap the field execution. (e.g. Access Rights on a specific field, apply a specific rate limit on a field.)on_argument_execution: Allows you to wrap the argument execution. (e.g Check the format of an input.).on_pre_output_coercion: Allows you to hook the execution flow right before a field result value is being coerced (Appears in version0.10.0)on_post_input_coercion: Allows you to hook the execution flow right after an argument value has beed coerced (Appears in version0.10.0)on_introspection: During an introspection query, allows you to wrap the schema fields to add metadata (e.g. add deprecated information) to fields or even to remove objects (e.g. dynamic introspection based on access rights).
How to declare a new directive?
directive @myDirective(
    name: String = "Chuck"
) on FIELD_DEFINITION
type Query {
    hello: String @myDirective(name: "Norris")
}
from typing import Any, Callable, Dict, Optional
from tartiflette import Directive
@Directive("myDirective")
class MyDirective:
    async def on_field_execution(
        self,
        directive_args: Dict[str, Any],
        next_resolver: Callable,
        parent_result: Optional[Any],
        args: Dict[str, Any],
        ctx: Optional[Dict[str, Any]],
        info: "Info",
    ) -> Any:
        ######################
        # Add your code here #
        ######################
        return await next_resolver(parent_result, args, ctx, info)
    async def on_argument_execution(
        self,
        directive_args: Dict[str, Any],
        next_directive: Callable,
        argument_definition: "GraphQLArgument",
        args: Dict[str, Any],
        ctx: Optional[Dict[str, Any]],
        info: "Info",
    ) -> Any:
        ######################
        # Add your code here #
        ######################
        return await next_directive(argument_definition, args, ctx, info)
    async def on_post_input_coercion(
        self,
        directive_args: Dict[str, Any],
        next_directive: Callable,
        value: Any,
        argument_definition: "GraphQLArgument",
        ctx: Optional[Dict[str, Any]],
        info: "Info",
    ) -> Any:
        ######################
        # Add your code here #
        ######################
        return await next_directive(value, argument_definition, ctx, info)
    async def on_pre_output_coercion(
        self,
        directive_args: Dict[str, Any],
        next_directive: Callable,
        value: Any,
        field_definition: "GraphQLField",
        ctx: Optional[Dict[str, Any]],
        info: "Info",
    ) -> Any:
        ######################
        # Add your code here #
        ######################
        return await next_directive(value, field_definition, ctx, info)
    async def on_introspection(
        self,
        directive_args: Dict[str, Any],
        next_directive: Callable,
        introspected_element: Any,
        ctx: Optional[Dict[str, Any]],
        info: "Info",
    ) -> Any:
        ######################
        # Add your code here #
        ######################
        return await next_directive(introspected_element, ctx, info)
Execution Flow
Warning: This is valid since 0.10.0
Directive Hook Execution flow is like:

Example
directive @directiveField on FIELD
directive @directiveScalar on SCALAR
directive @directiveEnum on ENUM
directive @directiveEnumValue on ENUM_VALUE
directive @directiveObject on OBJECT
directive @directiveInputObject on INPUT_OBJECT
directive @directiveArgument on ARGUMENT
scalar aScalar @directiveScalar
enum anEnum @directiveEnum {
    ONE @directiveEnumValue
    TWO
}
input anInputObject @directiveInputObject {
    anInputField: aScalar
}
type aType @directiveObject {
    aField: aScalar @directiveField
    anEnumField: anEnum @directiveField
}
type Query {
    field1: aType
    field2(anArgument: anInputObject @directiveArgument): aType
    field3: anEnum
}
with Resolvers as:
@Resolver("Query.field1")
async def query_field1_resolver(pr, args, ctx, info):
    return {"aField": "aValue", "anEnumField":"ONE"}
@Resolver("Query.field2")
async def query_field2_resolver(pr, args, ctx, info):
    return {"aField": "aValue", "anEnumField":"TWO"}
@Resolver("Query.field3")
async def query_field3_resolver(pr, args, ctx, info):
    return "TWO"
Query 1
query aQuery {
    field1 {
        aField
        anEnumField
    }
}
The resolution of Query.field1 will ran:
Query.field1Resolveron_pre_output_coercionof directivedirectiveObjectof typeaTypeoutput_coercerfor ObjectType
Then the resolution of aType.aField will ran: (Parrallely ran with aType.anEnumField)
on_field_executionof directivedirectiveFieldonaType.aFieldaType.aFieldResolveron_pre_output_coercionof directivedirectiveScalaronaScalaroutput_coercerof the scalaraScalar.
The resolution of aType.anEnumField will ran: (Parrallely ran with aType.aField)
on_field_executionof directivedirectiveFieldonaType.anEnumFieldaType.anEnumFieldResolveron_pre_output_coercionof directivedirectiveEnumValuecauseONEhas a directiveon_pre_output_coercionof directivedirectiveEnumof enumanEnumoutput_coercerfor enum.
Query 2
query aQuery {
    field2(anArgument: {anInputField: 3}) {
        aField
        anEnumField
    }
}
The resolution of Query.field2 will ran:
input_coercerfor InputObjectTypeinput_coercerfor argumentanInputFieldof typeaScalaron_post_input_coercionof directivedirectiveScalarof scalaraScalaron_post_input_coercionof directivedirectiveInputObjectof typeanInputTypeon_argument_executionof directivedirectiveArgumentfor argumentanArgumentQuery.field2Resolveron_pre_output_coercionof directivedirectiveObjectof typeaTypeoutput_coercerfor ObjectType
Then the resolution of aType.aField will ran: (Parrallely ran with aType.anEnumField)
on_field_executionof directivedirectiveFieldonaType.aFieldaType.aFieldResolveron_pre_output_coercionof directivedirectiveScalaronaScalaroutput_coercerof the scalaraScalar.
The resolution of aType.anEnumField will ran: (Parrallely ran with aType.aField)
on_field_executionof directivedirectiveFieldonaType.anEnumFieldaType.anEnumFieldResolver (methodatype_anenumfield_resolverreturned "ONE")on_pre_output_coercionof directivedirectiveEnumValuecauseONEhas a directiveon_pre_output_coercionof directivedirectiveEnumof enumanEnumoutput_coercerfor enum.
Query 3
query aQuery {
    field3
}
The resolution of Query.field3 will ran:
Query.field3Resolveron_pre_output_coercionof directivedirectiveEnumof enumanEnumoutput_coercerfor EnumType