Engine
The way to generate an engine is pretty simple, most of the time, you will use the create_engine
method, expose in tartiflette
package. This method performs all the necessary task needed to build your engine.
create_engine
prepares and cooks your engine
create_engine
is the easiest and quickiest method to instanciate and build an Engine(). Behind the scene, this factory will implement the regular cooking process.
Using the SDL (Schema Definition Language) parameter with different types
sdl
parameter contains the raw schema
When the from tartiflette import create_engine
engine = await create_engine(
"""
type Query {
hello: String
}
"""
)
sdl
parameter targets a file
When the The file path specified has to contain the full schema definition language.
from tartiflette import create_engine
engine = await create_engine(
"/User/chuck/workspace/mytartiflette/schema.graphql"
)
sdl
parameter targets a file list
When the Every file will be concatenated, in the order of the provided list.
from tartiflette import create_engine
engine = await create_engine(
[
"/User/chuck/workspace/mytartiflette/schema_query.graphql",
"/User/chuck/workspace/mytartiflette/schema_mutation.graphql"
]
)
sdl
parameter targets a folder
When the Every file which ends by .graphql
(or .sdl
) will be concatenated in lexicographical order.
from tartiflette import create_engine
engine = await create_engine(
"/User/chuck/workspace/mytartiflette"
)
Advanced constructor
The create_engine
method provides an advanced interface for initialization. It accepts optional and named parameters.
from tartiflette import create_engine
engine = await create_engine(
sdl,
schema_name="default",
)
- sdl: Schema Definition Language, detailed above.
- schema_name: Schema used from the Schema Registry. (default: "default")
- error_coercer: Coercer used when an error is raised.
- custom_default_resolver: Use another default resolver. (Useful if you want to override the behavior for resolving a property, e.g. from snake_case to camelCase and vice versa).
- modules: list of modules containing your decorated code such as
@Resolver
,@Subscription
,@Scalar
and@Directive
.
error_coercer
Parameter: The main objective of the error_coercer
is to provide you a way to extend the behavior when an exception is raised into tartiflette.
For instance:
- Add a log entry when a third-party exceptions is raised (e.g pymsql, redis).
- Hide technical message's exception for production environment (don't expose your internal stack from outside)
error_coercer
SHOULDN'T be used for custom functional exception, for this common use-case, please take a look of the TartifletteError
and its documentation's page.
import logging
from tartiflette import create_engine
class CustomException(Exception):
def __init__(self, type_name, message):
self.type = type_name
self.message = message
def my_error_coercer(exception, error) -> dict:
if isinstance(exception, CustomException):
logging.error("Unable to reach the Storage host.")
error["extensions"]["type"] = exception.type
return error
e = await create_engine(
"my_sdl.graphql",
error_coercer=my_error_coercer
)
custom_default_resolver
Parameter: Use another default resolver. It can be useful to override the behavior for resolving a property, from snake_case
to camelCase
and vice versa.
from tartiflette import create_engine
async def my_default_resolver(parent_result, arguments, context, info):
do_ing_some_thin_gs = 42
return a_value
e = await create_engine(
"my_sdl.graphql",
custom_default_resolver=my_default_resolver
)
modules
Parameter: Prior creating the Engine()
, all your code must be decoratored by these following ones to be taken into account.
@Resolver
@Subscription
@Scalar
@Directive
Doing it by yourself could be verbose and generate a lot of imports.
Both for your internal code and the plugins management, tartiflette provides a parameters called modules
which give you the ability to specify all the internal and external code you want to import. In addition to the module, you will be able to specify a configuration, which will be mostly used by the tartiflette plugin approach.
from tartiflette import create_engine
engine = await create_engine(
os.path.dirname(os.path.abspath(__file__)) + "/sdl",
modules=[
"recipes_manager.query_resolvers",
"recipes_manager.mutation_resolvers",
"recipes_manager.subscription_resolvers",
"recipes_manager.directives.auth",
"recipes_manager.directives.rate_limiting",
]
)
instead of
import recipes_manager.query_resolvers
import recipes_manager.mutation_resolvers
import recipes_manager.subscription_resolvers
import recipes_manager.directives.auth
import recipes_manager.directives.rate_limiting
engine = await create_engine(
os.path.dirname(os.path.abspath(__file__)) + "/sdl"
)
Giving configuration to a module
from tartiflette import create_engine
engine = create_engine(
os.path.dirname(os.path.abspath(__file__)) + "/sdl",
modules=[
"recipes_manager.query_resolvers",
"recipes_manager.mutation_resolvers",
{ "name": "a.module.that.needs.config", "config": {"key": "value"} },
{ "name": "another.module.that.needs.config", "config": {"key": "value"} }
]
)
Advanced instanciation
For those who want to integrate tartiflette in advanced use-cases. You could be interested by owning the process of building an Engine()
.
Why owning the cooking (building) process of tartiflette?
The cooking process of tartiflette is equals to a build
process on another librairies, it will prepare your engine to be executed. Thus, it's useless to say that an engine instance can't be executed without beeing cooked. Like the meal, you can't eat a tartiflette without cooking it first. That's it.
Customise the cooking process is interesting to integrate tartiflette into another librairies, like aiohttp
, starlette
, django
and so one.
For your information: tartiflette-aiohttp
has its own flow to manage the cooking process of the Engine.
cook()
your tartiflette
As specified above, the Engine() needs to be cook() before being executed. Here are the sequence to execute a query on an Engine()
instance.
from tartiflette import Engine
# 1. Create an instance of the Engine
engine = Engine()
# 2. Cook (build) the engine to prepare it to be executed
await engine.cook(
"""
type Query {
hello: String
}
"""
)
# 3. Execute a GraphQL Query
engine.execute(
query="query { hello )"
)
cook()
interface
The cook()
method is asynchronous, this strong choice will allow us to execute asynchronous tasks during the building process, like:
- Fetching SDL from another API.
- Fetch third-parties services (Database structure, Cloud provider objects ...)
- Fetch Schema from a Schema Manager.
async def cook(
self,
sdl: Union[str, List[str]],
error_coercer: Callable[[Exception], dict] = None,
custom_default_resolver: Optional[Callable] = None,
modules: Optional[Union[str, List[Union[str, Dict[str, Union[str, Dict[str, str]]]]]]] = None,
schema_name: str = "default",
):
pass
- sdl: Schema Definition Language, detailed above.
- error_coercer: Coercer used when an error is raised.
- custom_default_resolver: Use another default resolver. (Useful if you want to override the behavior for resolving a property, e.g. from snake_case to camelCase and vice versa).
- modules: list of modules containing your decorated code such as
@Resolver
,@Subscription
,@Scalar
and@Directive
. - schema_name: Schema used from the Schema Registry. (default: "default")