Repository: tartiflette/tartiflette
Pull request #244 (2019-06-28 13:44:33)

Return to a more flexible engine interface.
- [x] Code
- [x] Changelog
- [x] Tests.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 522c555..12eb52f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 ## [Released]
 
 - [0.11.x] Brand new **plugin approach** _(featured at the [GraphQL Conf 2019](https://graphqlconf.org))_
+  - [0.11.2](./changelogs/0.11.2.md) - 2019-06-28
   - [0.11.1](./changelogs/0.11.1.md) - 2019-06-18
   - [0.11.0](./changelogs/0.11.0.md) - 2019-06-17
 - [0.10.x]
diff --git a/changelogs/0.11.2.md b/changelogs/0.11.2.md
new file mode 100644
index 0000000..5d65f6d
--- /dev/null
+++ b/changelogs/0.11.2.md
@@ -0,0 +1,5 @@
+# [0.11.2] - 2019-06-28
+
+## Fixed
+
+  - Engine: Old Engine API is back, cook will override engine saved parameters by it own if any are given
diff --git a/setup.py b/setup.py
index e676695..87ee637 100644
--- a/setup.py
+++ b/setup.py
@@ -60,7 +60,7 @@ _TEST_REQUIRE = [
 
 _BENCHMARK_REQUIRE = ["pytest-benchmark==3.2.2"]
 
-_VERSION = "0.11.1"
+_VERSION = "0.11.2"
 
 _PACKAGES = find_packages(exclude=["tests*"])
 
diff --git a/tartiflette/engine.py b/tartiflette/engine.py
index f038fb4..702bdcb 100644
--- a/tartiflette/engine.py
+++ b/tartiflette/engine.py
@@ -1,7 +1,7 @@
 import logging
 
 from importlib import import_module, invalidate_caches
-from inspect import isawaitable
+from inspect import isawaitable, iscoroutinefunction
 from typing import Any, AsyncIterable, Callable, Dict, List, Optional, Union
 
 from tartiflette.executors.basic import (
@@ -96,78 +96,68 @@ class Engine:
         modules=None,
     ) -> None:
         """
-        Create an Engine instance
+        Create an uncooked Engine instance
         """
-        self._error_coercer = None
-        self._modules = None
         self._parser = TartifletteRequestParser()
         self._schema = None
-
-        if (
-            sdl
-            or schema_name
-            or error_coercer
-            or custom_default_resolver
-            or modules
-        ):
-            logger.warning(
-                """
-                the tartiflette Engine() API evolved started the 0.11 version.
-
-                The engine creation is now asynchronous, to give the ability for the community to
-                create plugins. From now, please use the `create_engine` method to create an instance
-                of `Engine()`.
-
-                ```python
-                from tartiflette import create_engine
-
-                engine = await create_engine(
-                    sdl,
-                    schema_name = "default",
-                    error_coercer = None,
-                    custom_default_resolver = None,
-                    modules = None,
-                )
-                ```
-
-                More details on the website: https://tartiflette.io/docs/api/engine#create_engine-prepares-and-cooks-your-engine
-                """
-            )
+        self._schema_name = schema_name
+        self._error_coercer = error_coercer
+        self._custom_default_resolver = custom_default_resolver
+        self._modules = modules
+        self._sdl = sdl
 
     async def cook(
         self,
-        sdl: Union[str, List[str]],
+        sdl: Union[str, List[str]] = None,
         error_coercer: Callable[[Exception], dict] = None,
         custom_default_resolver: Optional[Callable] = None,
         modules: Optional[Union[str, List[str]]] = None,
-        schema_name: str = "default",
+        schema_name: str = None,
     ):
         """
         Cook the tartiflette, basicly prepare the engine by binding it to given modules using the schema_name as a key.
         You wont be able to execute a request if the engine wasn't cooked.
 
-        Arguments:
-            sdl {Union[str, List[str]]} -- The SDL to work with.
-
         Keyword Arguments:
+            sdl {Union[str, List[str]]} -- The SDL to work with.
             schema_name {str} -- The name of the SDL (default: {"default"})
             error_coercer {Callable[[Exception, dict], dict]} -- An optional callable in charge of transforming a couple Exception/error into an error dict (default: {default_error_coercer})
             custom_default_resolver {Optional[Callable]} -- An optional callable that will replace the tartiflette default_resolver (Will be called like a resolver for each UNDECORATED field) (default: {None})
             modules {Optional[Union[str, List[str]]]} -- An optional list of string containing the name of the modules you want the engine to import, usually this modules contains your Resolvers, Directives, Scalar or Subscription code (default: {None})
         """
 
-        if not modules:
-            modules = []
+        if modules is None:
+            modules = self._modules or []
 
         if isinstance(modules, str):
             modules = [modules]
 
+        sdl = sdl or self._sdl
+        if not sdl:
+            raise Exception("Please provide a SDL")
+
+        schema_name = schema_name or self._schema_name or "default"
+
+        custom_default_resolver = (
+            custom_default_resolver or self._custom_default_resolver
+        )
+        if custom_default_resolver and not iscoroutinefunction(
+            custom_default_resolver
+        ):
+            raise Exception(
+                f"Given custom_default_resolver "
+                f"{custom_default_resolver} "
+                f"is not a coroutine function"
+            )
+
         self._error_coercer = error_coercer_factory(
-            error_coercer or default_error_coercer
+            error_coercer or self._error_coercer or default_error_coercer
         )
+
         self._modules, modules_sdl = await _import_modules(
             modules, schema_name
         )
+
         SchemaRegistry.register_sdl(schema_name, sdl, modules_sdl)
         self._schema = SchemaBakery.bake(schema_name, custom_default_resolver)
 


Test patch:
diff --git a/tests/unit/test_engine.py b/tests/unit/test_engine.py
index b5a2ba3..5f242e8 100644
--- a/tests/unit/test_engine.py
+++ b/tests/unit/test_engine.py
@@ -267,3 +267,76 @@ async def test_engine_subscribe_with_default_resolver_alias(clean_registry):
         "subscription { aliasCounter: counter(startAt: 4) }"
     ):
         assert result == {"data": {"aliasCounter": expected_values.pop()}}
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+    "sdl,expected,pass_to",
+    [
+        ("type Query { lol: Int }", "ok", "engine"),
+        ("type Query { lol: Int }", "ok", "cook"),
+        (None, Exception(), "None"),
+    ],
+)
+async def test_engine_api_sdl(sdl, expected, pass_to, clean_registry):
+    from tartiflette import Engine
+
+    if pass_to == "engine":
+        e = Engine(sdl)
+    else:
+        e = Engine()
+
+    if isinstance(expected, Exception):
+        with pytest.raises(Exception):
+            if pass_to == "cook":
+                await e.cook(sdl)
+            else:
+                await e.cook()
+    else:
+        if pass_to == "cook":
+            await e.cook(sdl)
+        else:
+            await e.cook()
+        assert e._schema is not None
+
+
+async def bob():
+    pass
+
+
+def boby():
+    pass
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+    "cdr,expected,pass_to",
+    [
+        (bob, "ok", "engine"),
+        (bob, "ok", "cook"),
+        (boby, Exception(), "engine"),
+        (boby, Exception(), "cook"),
+    ],
+)
+async def test_engine_api_cdr(cdr, expected, pass_to, clean_registry):
+    from tartiflette import Engine
+
+    sdl = "type Query { lol: Int }"
+
+    if pass_to == "engine":
+        e = Engine(sdl, custom_default_resolver=cdr)
+    else:
+        e = Engine()
+
+    if isinstance(expected, Exception):
+        with pytest.raises(Exception):
+            if pass_to == "cook":
+                await e.cook(sdl, custom_default_resolver=cdr)
+            else:
+                await e.cook()
+    else:
+        if pass_to == "cook":
+            await e.cook(sdl, custom_default_resolver=cdr)
+        else:
+            await e.cook()
+        assert e._schema is not None