Repository: mirumee/ariadne

Issue:
Provide gql() utility function for wrapping/validating SDL on spot
Currently, syntax errors in SDL are raised by `graphql()`, which itself is called deep in GraphQL server initialization logic. This makes it trickier to trace back to invalid type definitions - especially in complex projects.

Ariadne could provide `gql()` utility function that would allow developers to mark pieces of code as SDL, and validate those SDL strings on scripts execution, raising execetions with traceback pointing to point of definition, making those easier to find and debug:

```python
from ariadne import gql

type_defs = gql("""
    type User {
        username: String!
        posts: [Post!]
        threads: [Thread!]
        follows [User!]
        likes: [Post!]
    }
""")
```

Above code would raise `GraphQLSyntaxError` pointing to `type_defs`, instead of somewhere in GraphQL server initialization logic.

This approach adds one more advantage: If we know that strings wrapped with `gql()` are SDL, we can develop a pattern for GraphQL syntax highlighters for IDEs to use to color GraphQL syntax in Python projects.

Lastly, `gql()` should pass through the strings, because our current modularization implementation is very simple: internally it does string joining using `\n` as glue. We'll rather avoid reimplementing it to create custom mechanism operating on `ast`'s.


Discussion:

Resolving patch:
diff --git a/ariadne/__init__.py b/ariadne/__init__.py
--- a/ariadne/__init__.py
+++ b/ariadne/__init__.py
@@ -1,5 +1,6 @@
 from .executable_schema import make_executable_schema
 from .resolvers import add_resolve_functions_to_schema, default_resolver, resolve_to
+from .utils import gql
 from .wsgi_middleware import GraphQLMiddleware
 
 __all__ = [
@@ -8,4 +9,5 @@
     "default_resolver",
     "make_executable_schema",
     "resolve_to",
+    "gql",
 ]
diff --git a/ariadne/utils.py b/ariadne/utils.py
new file mode 100644
--- /dev/null
+++ b/ariadne/utils.py
@@ -0,0 +1,6 @@
+from graphql import parse
+
+
+def gql(value: str) -> str:
+    parse(value)
+    return value


Test patch:
diff --git a/tests/test_gql_util.py b/tests/test_gql_util.py
new file mode 100644
--- /dev/null
+++ b/tests/test_gql_util.py
@@ -0,0 +1,54 @@
+import pytest
+from graphql.error import GraphQLSyntaxError
+
+from ariadne import gql
+
+
+def test_valid_graphql_schema_string_is_returned_unchanged():
+    sdl = """
+        type User {
+            username: String!
+        }
+    """
+    result = gql(sdl)
+    assert sdl == result
+
+
+def test_invalid_graphql_schema_string_causes_syntax_error():
+    with pytest.raises(GraphQLSyntaxError):
+        gql(
+            """
+                type User {
+                    username String!
+                }
+            """
+        )
+
+
+def test_valid_graphql_query_string_is_returned_unchanged():
+    query = """
+        query TestQuery {
+            auth
+            users {
+                id
+                username
+            }
+        }
+    """
+    result = gql(query)
+    assert query == result
+
+
+def test_invalid_graphql_query_string_causes_syntax_error():
+    with pytest.raises(GraphQLSyntaxError):
+        gql(
+            """
+                query TestQuery {
+                    auth
+                    users
+                        id
+                        username
+                    }
+                }
+            """
+        )