From d2795f49a9dcd19d5a7e5b640714f7241bcd19dd Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 11:52:12 -0400 Subject: [PATCH 1/7] refs #2: Super simple test to create a query string. --- .../tests/test_query_string_builder.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/graphql_query_string_builder/tests/test_query_string_builder.py b/graphql_query_string_builder/tests/test_query_string_builder.py index 77ea872..871fda5 100644 --- a/graphql_query_string_builder/tests/test_query_string_builder.py +++ b/graphql_query_string_builder/tests/test_query_string_builder.py @@ -1,6 +1,9 @@ from unittest import TestCase +from graphql_query_string_builder import Query + class QueryStringBuilderTestCase(TestCase): - def test(self): - pass + def test_query_string_is_built(self): + query = Query(foo=['id', 'bar']) + self.assertEqual(str(query), 'query { foo { id bar }}') From fe8a1da2016320894e52d79a8d24a2a2351bcb4e Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 11:52:46 -0400 Subject: [PATCH 2/7] refs #2: Created a simple Query class. --- graphql_query_string_builder/__init__.py | 6 ++++++ graphql_query_string_builder/query.py | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100644 graphql_query_string_builder/query.py diff --git a/graphql_query_string_builder/__init__.py b/graphql_query_string_builder/__init__.py index e69de29..eb0432b 100644 --- a/graphql_query_string_builder/__init__.py +++ b/graphql_query_string_builder/__init__.py @@ -0,0 +1,6 @@ +from graphql_query_string_builder.query import Query + + +__all__ = [ + 'Query', +] diff --git a/graphql_query_string_builder/query.py b/graphql_query_string_builder/query.py new file mode 100644 index 0000000..d67fa86 --- /dev/null +++ b/graphql_query_string_builder/query.py @@ -0,0 +1,9 @@ +class Query(object): + def __init__(self, *args, **kwargs): + self.kwargs = kwargs + + def __str__(self): + return 'query {{ {key} {{ {values} }}}}'.format( + key=list(self.kwargs.keys())[0], + values=' '.join(list(self.kwargs.values())[0]), + ) From 961b96a4249cf2216c7fab3e7f0c4fb5691681c5 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 12:21:41 -0400 Subject: [PATCH 3/7] refs #2: Added simple tests showing customization of the resulting query can be done. --- .../tests/test_query_string_builder.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/graphql_query_string_builder/tests/test_query_string_builder.py b/graphql_query_string_builder/tests/test_query_string_builder.py index 871fda5..786f3e3 100644 --- a/graphql_query_string_builder/tests/test_query_string_builder.py +++ b/graphql_query_string_builder/tests/test_query_string_builder.py @@ -5,5 +5,22 @@ class QueryStringBuilderTestCase(TestCase): def test_query_string_is_built(self): - query = Query(foo=['id', 'bar']) - self.assertEqual(str(query), 'query { foo { id bar }}') + query = Query() + self.assertEqual( + query.render_query_string(foo=['id', 'bar']), + 'query { foo { id bar }}', + ) + + def test_camel_case_happens_by_default(self): + query = Query() + self.assertEqual( + query.render_query_string(foo_bar_baz=['id', 'bar']), + 'query { fooBarBaz { id bar }}', + ) + + def test_disabling_camel_case_removes_camel_case(self): + query = Query(auto_camel_case=False) + self.assertEqual( + query.render_query_string(foo_bar_baz=['id', 'bar']), + 'query { foo_bar_baz { id bar }}', + ) From 41fd115084308f91171d88d7f14a3ceb2d67379a Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 12:22:05 -0400 Subject: [PATCH 4/7] refs #2: Small refactor to allow configuring the resulting query. --- graphql_query_string_builder/query.py | 33 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/graphql_query_string_builder/query.py b/graphql_query_string_builder/query.py index d67fa86..a740ed7 100644 --- a/graphql_query_string_builder/query.py +++ b/graphql_query_string_builder/query.py @@ -1,9 +1,34 @@ class Query(object): - def __init__(self, *args, **kwargs): - self.kwargs = kwargs + def __init__(self, auto_camel_case=True, **kwargs): + self.auto_camel_case = auto_camel_case + + def _camel_case_string(self, s): + parts = s.split('_') + if len(parts) == 1: + return s + first_part = parts[0] + rest = parts[1:] + camel = [r.title() for r in rest] + return ''.join([first_part] + camel) + + def render_query_string(self, **kwargs): + query_parameters = dict(kwargs) + assert len(query_parameters) == 1 # TODO Switch this to a better exception + key = list(kwargs.keys())[0] + value = list(kwargs.values())[0] + if self.auto_camel_case: + # TODO Camel case values too + key = self._camel_case_string(key) + return str(QueryStringBuilder(key=key, value=value)) + + +class QueryStringBuilder(object): + def __init__(self, key, value): + self.key = key + self.value = value def __str__(self): return 'query {{ {key} {{ {values} }}}}'.format( - key=list(self.kwargs.keys())[0], - values=' '.join(list(self.kwargs.values())[0]), + key=self.key, + values=' '.join(self.value), ) From cd320f4ab6a1ed78c4e2d64578c2b513b1718fde Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 12:39:53 -0400 Subject: [PATCH 5/7] refs #2: Tell coverage to show missing lines --- .coveragerc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..013dd20 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,2 @@ +[report] +show_missing = True From e9ddff3495da57db7ccb30df1bc4ae092e28fa69 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 12:40:08 -0400 Subject: [PATCH 6/7] refs #2: Updated tox command for coverage. --- tox.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index 5944fe5..efd65a3 100644 --- a/tox.ini +++ b/tox.ini @@ -23,13 +23,13 @@ skipsdist = True # Coverage for python 2.7 and and 3.6 only [testenv:py27-coverage] commands = - nosetests --with-doctest --with-coverage --cover-package graphql_query_string_builder [] + nosetests --with-doctest --with-coverage --cover-erase --cover-branches --cover-package graphql_query_string_builder [] [testenv:py34-coverage] commands = - nosetests --with-doctest --with-coverage --cover-package graphql_query_string_builder [] + nosetests --with-doctest --with-coverage --cover-erase --cover-branches --cover-package graphql_query_string_builder [] [testenv:py36-coverage] commands = - nosetests --with-doctest --with-coverage --cover-package graphql_query_string_builder [] + nosetests --with-doctest --with-coverage --cover-erase --cover-branches --cover-package graphql_query_string_builder [] [testenv:py27pep8] basepython = python2.7 From 89207a9ee0f1156503e25550bc80db207853acad Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Sat, 16 Sep 2017 12:40:27 -0400 Subject: [PATCH 7/7] refs #2: Added an exception if multiple kwargs passed in. Plus a test. --- graphql_query_string_builder/exceptions.py | 6 ++++++ graphql_query_string_builder/query.py | 7 +++++++ .../tests/test_query_string_builder.py | 6 ++++++ 3 files changed, 19 insertions(+) create mode 100644 graphql_query_string_builder/exceptions.py diff --git a/graphql_query_string_builder/exceptions.py b/graphql_query_string_builder/exceptions.py new file mode 100644 index 0000000..ca18c3f --- /dev/null +++ b/graphql_query_string_builder/exceptions.py @@ -0,0 +1,6 @@ +class GraphqlQueryStringBuilderException(Exception): + pass + + +class ImproperlyConfiguredException(GraphqlQueryStringBuilderException): + pass diff --git a/graphql_query_string_builder/query.py b/graphql_query_string_builder/query.py index a740ed7..b497c57 100644 --- a/graphql_query_string_builder/query.py +++ b/graphql_query_string_builder/query.py @@ -1,3 +1,6 @@ +from graphql_query_string_builder.exceptions import ImproperlyConfiguredException + + class Query(object): def __init__(self, auto_camel_case=True, **kwargs): self.auto_camel_case = auto_camel_case @@ -13,6 +16,10 @@ def _camel_case_string(self, s): def render_query_string(self, **kwargs): query_parameters = dict(kwargs) + if len(query_parameters) != 1: + raise ImproperlyConfiguredException( + 'You can only pass in a single kwarg to `render_query_string` at this time', + ) assert len(query_parameters) == 1 # TODO Switch this to a better exception key = list(kwargs.keys())[0] value = list(kwargs.values())[0] diff --git a/graphql_query_string_builder/tests/test_query_string_builder.py b/graphql_query_string_builder/tests/test_query_string_builder.py index 786f3e3..2b73486 100644 --- a/graphql_query_string_builder/tests/test_query_string_builder.py +++ b/graphql_query_string_builder/tests/test_query_string_builder.py @@ -1,6 +1,7 @@ from unittest import TestCase from graphql_query_string_builder import Query +from graphql_query_string_builder.exceptions import ImproperlyConfiguredException class QueryStringBuilderTestCase(TestCase): @@ -24,3 +25,8 @@ def test_disabling_camel_case_removes_camel_case(self): query.render_query_string(foo_bar_baz=['id', 'bar']), 'query { foo_bar_baz { id bar }}', ) + + def test_only_one_kwarg_can_be_passed_to_render_query_string(self): + query = Query() + with self.assertRaises(ImproperlyConfiguredException): + query.render_query_string(foo=1, bar=2)