From 02083f6acffec12a835047389bb558baaa008e04 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Sat, 31 Dec 2022 17:17:22 +0800 Subject: [PATCH 01/10] feat: add support for jinja renderer --- graphql_server/render_graphiql.py | 32 ++++++++++++++----------------- tests/sanic/app.py | 10 ++-------- tests/test_query.py | 23 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/graphql_server/render_graphiql.py b/graphql_server/render_graphiql.py index 498f53b..13d0f48 100644 --- a/graphql_server/render_graphiql.py +++ b/graphql_server/render_graphiql.py @@ -1,5 +1,5 @@ """Based on (express-graphql)[https://github.com/graphql/express-graphql/blob/main/src/renderGraphiQL.ts] and -(subscriptions-transport-ws)[https://github.com/apollographql/subscriptions-transport-ws]""" +(graphql-ws)[https://github.com/enisdenjo/graphql-ws]""" import json import re from typing import Any, Dict, Optional, Tuple @@ -216,24 +216,12 @@ class GraphiQLOptions(TypedDict): should_persist_headers: Optional[bool] -def escape_js_value(value: Any) -> Any: - quotation = False - if value.startswith('"') and value.endswith('"'): - quotation = True - value = value[1 : len(value) - 1] - - value = value.replace("\\\\n", "\\\\\\n").replace("\\n", "\\\\n") - if quotation: - value = '"' + value.replace('\\\\"', '"').replace('"', '\\"') + '"' - - return value - - def process_var(template: str, name: str, value: Any, jsonify=False) -> str: - pattern = r"{{\s*" + name + r"(\s*|[^}]+)*\s*}}" + pattern = r"{{\s*" + name.replace("\\", r"\\") + r"(\s*|[^}]+)*\s*}}" if jsonify and value not in ["null", "undefined"]: value = json.dumps(value) - value = escape_js_value(value) + + value = value.replace("\\", r"\\") return re.sub(pattern, value, template) @@ -296,6 +284,9 @@ def _render_graphiql( or "false", } + if template_vars["result"] in ("null"): + template_vars["result"] = None + return graphiql_template, template_vars @@ -305,7 +296,7 @@ async def render_graphiql_async( options: Optional[GraphiQLOptions] = None, ) -> str: graphiql_template, template_vars = _render_graphiql(data, config, options) - jinja_env: Optional[Environment] = config.get("jinja_env") + jinja_env = config.get("jinja_env") if jinja_env: template = jinja_env.from_string(graphiql_template) @@ -324,6 +315,11 @@ def render_graphiql_sync( options: Optional[GraphiQLOptions] = None, ) -> str: graphiql_template, template_vars = _render_graphiql(data, config, options) + jinja_env = config.get("jinja_env") - source = simple_renderer(graphiql_template, **template_vars) + if jinja_env: + template = jinja_env.from_string(graphiql_template) + source = template.render(**template_vars) + else: + source = simple_renderer(graphiql_template, **template_vars) return source diff --git a/tests/sanic/app.py b/tests/sanic/app.py index f70dd8a..5387b97 100644 --- a/tests/sanic/app.py +++ b/tests/sanic/app.py @@ -8,20 +8,14 @@ from .schema import Schema -def create_app(path="/graphql", **kwargs): +def create_app(path="/graphql", schema=Schema, **kwargs): random_valid_app_name = f"App{uuid.uuid4().hex}" app = Sanic(random_valid_app_name) - schema = kwargs.pop("schema", None) or Schema app.add_route(GraphQLView.as_view(schema=schema, **kwargs), path) return app def url_string(uri="/graphql", **url_params): - string = "/graphql" - - if url_params: - string += "?" + urlencode(url_params) - - return string + return f"{uri}?{urlencode(url_params)}" if url_params else uri diff --git a/tests/test_query.py b/tests/test_query.py index a1352cc..1ae3526 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -15,6 +15,11 @@ load_json_body, run_http_query, ) +from graphql_server.render_graphiql import ( + GraphiQLConfig, + GraphiQLData, + render_graphiql_sync, +) from .schema import invalid_schema, schema from .utils import as_dicts @@ -653,3 +658,21 @@ def test_batch_allows_post_with_operation_name(): results, params = run_http_query(schema, "post", data, batch_enabled=True) assert results == [({"test": "Hello World", "shared": "Hello Everyone"}, None)] + + +def test_graphiql_render_umlaut(): + results, params = run_http_query( + schema, + "get", + data=dict(query="query helloWho($who: String){ test(who: $who) }"), + query_data=dict(variables='{"who": "Björn"}'), + catch=True, + ) + result, status_code = encode_execution_results(results) + + assert status_code == 200 + + graphiql_data = GraphiQLData(result=result, query=params[0].query) + source = render_graphiql_sync(data=graphiql_data, config=GraphiQLConfig()) + + assert "Hello Bj\\\\u00f6rn" in source From 881f8e27709fd6a8472c6e7727fc998065a1db05 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Sat, 31 Dec 2022 22:53:36 +0800 Subject: [PATCH 02/10] chore: update GraphiQL to 2.2.0 --- graphql_server/render_graphiql.py | 52 ++++++++++--------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/graphql_server/render_graphiql.py b/graphql_server/render_graphiql.py index 13d0f48..195603d 100644 --- a/graphql_server/render_graphiql.py +++ b/graphql_server/render_graphiql.py @@ -7,7 +7,7 @@ from jinja2 import Environment from typing_extensions import TypedDict -GRAPHIQL_VERSION = "1.4.7" +GRAPHIQL_VERSION = "2.2.0" GRAPHIQL_TEMPLATE = """