From a540a504b7601621a89d56c5681b7060e8045db6 Mon Sep 17 00:00:00 2001 From: sv-developer <20506046+Eggwise@users.noreply.github.com> Date: Wed, 4 May 2022 22:02:43 +0700 Subject: [PATCH 1/5] add support for boolean --- nested_query_string/nested_query_string.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nested_query_string/nested_query_string.py b/nested_query_string/nested_query_string.py index 5b50a2f..e97e8a2 100644 --- a/nested_query_string/nested_query_string.py +++ b/nested_query_string/nested_query_string.py @@ -41,6 +41,8 @@ def encode(cls, value, key = None): return key + "=" + cls.__escape(value) elif class_name == int: return key + "=" + str(value) + elif class_name == bool: + return value elif class_name == None: return '' else: From 1fd5a5faf3d4d105f89926e0e3ab43e41f287a71 Mon Sep 17 00:00:00 2001 From: sv-developer <20506046+Eggwise@users.noreply.github.com> Date: Wed, 4 May 2022 22:08:57 +0700 Subject: [PATCH 2/5] Fix None ? --- nested_query_string/nested_query_string.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nested_query_string/nested_query_string.py b/nested_query_string/nested_query_string.py index e97e8a2..802c420 100644 --- a/nested_query_string/nested_query_string.py +++ b/nested_query_string/nested_query_string.py @@ -43,6 +43,8 @@ def encode(cls, value, key = None): return key + "=" + str(value) elif class_name == bool: return value + elif value is None: + return None elif class_name == None: return '' else: From b766a186f7f528a3080c48049ce98cbafdd7f9e0 Mon Sep 17 00:00:00 2001 From: sv-developer <20506046+Eggwise@users.noreply.github.com> Date: Wed, 4 May 2022 22:11:34 +0700 Subject: [PATCH 3/5] Update nested_query_string.py --- nested_query_string/nested_query_string.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nested_query_string/nested_query_string.py b/nested_query_string/nested_query_string.py index 802c420..c6b7fb1 100644 --- a/nested_query_string/nested_query_string.py +++ b/nested_query_string/nested_query_string.py @@ -42,9 +42,9 @@ def encode(cls, value, key = None): elif class_name == int: return key + "=" + str(value) elif class_name == bool: - return value + return 'false' if value is False else 'true' elif value is None: - return None + return '' elif class_name == None: return '' else: From 64edb00a76675e09af27ee017536a3fa06910f2b Mon Sep 17 00:00:00 2001 From: sv-developer <20506046+Eggwise@users.noreply.github.com> Date: Sun, 22 May 2022 17:46:47 +0700 Subject: [PATCH 4/5] Format and add support for booleans and none --- .gitignore | 1 + nested_query_string/nested_query_string.py | 102 ++++++++++++--------- setup.py | 37 ++++---- test/nested_query_string_test.py | 76 +++++++++------ 4 files changed, 125 insertions(+), 91 deletions(-) diff --git a/.gitignore b/.gitignore index fda7fdd..d06015f 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ coverage.xml # Sphinx documentation docs/_build/ +.idea \ No newline at end of file diff --git a/nested_query_string/nested_query_string.py b/nested_query_string/nested_query_string.py index c6b7fb1..a4aeefc 100644 --- a/nested_query_string/nested_query_string.py +++ b/nested_query_string/nested_query_string.py @@ -8,55 +8,67 @@ is_py3 = (_ver[0] == 3) if is_py2: - from urllib import quote + from urllib import quote elif is_py3: - from urllib.parse import quote + from urllib.parse import quote + class UnsupportedParameterClassException(Exception): - def __init__(self, value, obj): - self.value = value - self.obj = obj - def __str__(self): - return repr(self.value) + " <" + repr(self.obj.__class__.__name__) +":" + repr(self.obj) +">" + def __init__(self, value, obj): + self.value = value + self.obj = obj + + def __str__(self): + return repr(self.value) + " <" + repr(self.obj.__class__.__name__) + ":" + repr(self.obj) + ">" + class NestedQueryString: - @classmethod - def encode(cls, value, key = None): - class_name = value.__class__ - if class_name == dict: - result = [] - for k, v in value.items(): - result.append(cls.encode(v, cls.__append_key(key, k))) - result = '&'.join(result) - return result - elif class_name == list: - result = [] - for v in value: - result.append(cls.encode(v, key+'[]')) - result = '&'.join(result) - return result - elif class_name == str: - return key + "=" + cls.__escape(value) - elif class_name == int: - return key + "=" + str(value) - elif class_name == bool: - return 'false' if value is False else 'true' - elif value is None: - return '' - elif class_name == None: - return '' - else: - raise UnsupportedParameterClassException('Unknown value class', value) - - @classmethod - def __escape(cls, value): - return quote(value) - - @classmethod - def __append_key(cls, root_key, key): - if root_key is None: - return key - else: - return root_key + "["+key+"]" + @classmethod + def encode(cls, value, key=None): + class_name = value.__class__ + + if class_name == dict: + result = [] + for k, v in value.items(): + result.append(cls.encode(v, cls.__append_key(key, k))) + result = '&'.join(result) + return result + + if class_name == list: + result = [] + for v in value: + result.append(cls.encode(v, key + '[]')) + result = '&'.join(result) + return result + + if class_name == str: + return key + "=" + cls.__escape(value) + + if class_name == int: + return key + "=" + str(value) + + if class_name == bool: + if value is True: + return key + "=" + 'true' + return key + "=" + 'false' + + if value is None: + return key + "=" + '' + + if class_name is None: + return '' + + raise UnsupportedParameterClassException('Unknown value class', value) + + @classmethod + def __escape(cls, value): + return quote(value) + + @classmethod + def __append_key(cls, root_key, key): + if root_key is None: + return key + else: + return root_key + "[" + key + "]" diff --git a/setup.py b/setup.py index ade84a6..84c315d 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ if not __version__: raise RuntimeError('Cannot find version information') + def data_for(filename): with open(filename) as fd: content = fd.read() @@ -27,22 +28,22 @@ def data_for(filename): setup( - name="nested_query_string", - version=__version__, - description='Generate nested query strings similar to rack and node qs', - license='MIT', - author='Cine.io Engineering', - author_email='engineering@cine.io', - url='https://github.com/cine-io/nested-query-string', - packages=packages, - package_data={'': ['LICENSE']}, - include_package_data=True, - install_requires=requires, - classifiers=[ - "License :: OSI Approved :: MIT License", - "Programming Language :: Python", - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Topic :: Internet", - ], + name="nested_query_string", + version=__version__, + description='Generate nested query strings similar to rack and node qs', + license='MIT', + author='Cine.io Engineering', + author_email='engineering@cine.io', + url='https://github.com/cine-io/nested-query-string', + packages=packages, + package_data={'': ['LICENSE']}, + include_package_data=True, + install_requires=requires, + classifiers=[ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Topic :: Internet", + ], ) diff --git a/test/nested_query_string_test.py b/test/nested_query_string_test.py index 6cc9367..dec6c57 100644 --- a/test/nested_query_string_test.py +++ b/test/nested_query_string_test.py @@ -1,48 +1,68 @@ import sys, os, time -testdir = os.path.dirname(__file__) -srcdir = '../nested_query_string' -sys.path.insert(0, os.path.abspath(os.path.join(testdir, srcdir))) + +test_dir = os.path.dirname(__file__) +src_dir = '../nested_query_string' +sys.path.insert(0, os.path.abspath(os.path.join(test_dir, src_dir))) import unittest from nested_query_string import NestedQueryString, UnsupportedParameterClassException + class NestedQueryStringTestCase(unittest.TestCase): - def assertEqualQueryStrings(self, expected, actual): - expectedValues = expected.split("&") - actualValues = actual.split("&") - self.assertEqual(sorted(expected), sorted(actual)) + def assertEqualQueryStrings(self, expected, actual): + self.assertEqual(sorted(expected), sorted(actual)) + class EncodeTest(NestedQueryStringTestCase): - def runTest(self): - qs = NestedQueryString.encode({'abc': 'def'}) - self.assertEqualQueryStrings(qs, 'abc=def') + def runTest(self): + qs = NestedQueryString.encode({'abc': 'def'}) + self.assertEqualQueryStrings(qs, 'abc=def') + class EncodeNumericTest(NestedQueryStringTestCase): - def runTest(self): - qs = NestedQueryString.encode({'abc': 1}) - self.assertEqualQueryStrings(qs, 'abc=1') + def runTest(self): + qs = NestedQueryString.encode({'abc': 1}) + self.assertEqualQueryStrings(qs, 'abc=1') + class EncodeNumericAndStringTest(NestedQueryStringTestCase): - def runTest(self): - qs = NestedQueryString.encode({'abc': 'def', 'ghi': 1}) - self.assertEqualQueryStrings(qs, "abc=def&ghi=1") + def runTest(self): + qs = NestedQueryString.encode({'abc': 'def', 'ghi': 1}) + self.assertEqualQueryStrings(qs, "abc=def&ghi=1") + class EncodeDictTest(NestedQueryStringTestCase): - def runTest(self): - qs = NestedQueryString.encode({'abc': {'def': 'ghi', 'jkl': 'mno'}, 'pqr': 'stu'}) - self.assertEqualQueryStrings(qs, "abc[def]=ghi&abc[jkl]=mno&pqr=stu") + def runTest(self): + qs = NestedQueryString.encode({'abc': {'def': 'ghi', 'jkl': 'mno'}, 'pqr': 'stu'}) + self.assertEqualQueryStrings(qs, "abc[def]=ghi&abc[jkl]=mno&pqr=stu") + class EncodeListTest(NestedQueryStringTestCase): - def runTest(self): - qs = NestedQueryString.encode({'abc': ['def', 'ghi']}) - self.assertEqualQueryStrings(qs, 'abc[]=def&abc[]=ghi') + def runTest(self): + qs = NestedQueryString.encode({'abc': ['def', 'ghi']}) + self.assertEqualQueryStrings(qs, 'abc[]=def&abc[]=ghi') + + +class EncodeBooleanTest(NestedQueryStringTestCase): + def runTest(self): + encode_params = { + 'name': True, + 'deep': { + 'deep_name': False + } + } + expected = 'name=true&deep[deep_name]=false' + qs = NestedQueryString.encode(encode_params) + self.assertEqual(expected, qs) + class EncodeMixedTest(NestedQueryStringTestCase): - def runTest(self): - qs = NestedQueryString.encode({'abc': ['def', {'ghi': 'jkl'}]}) - self.assertEqualQueryStrings(qs, 'abc[]=def&abc[][ghi]=jkl') + def runTest(self): + qs = NestedQueryString.encode({'abc': ['def', {'ghi': 'jkl'}]}) + self.assertEqualQueryStrings(qs, 'abc[]=def&abc[][ghi]=jkl') + class EncodeExceptionTest(NestedQueryStringTestCase): - def runTest(self): - with self.assertRaises(UnsupportedParameterClassException): - NestedQueryString.encode({'abc': EncodeExceptionTest}) + def runTest(self): + with self.assertRaises(UnsupportedParameterClassException): + NestedQueryString.encode({'abc': EncodeExceptionTest}) From 91102cb4cfef2f708c183d627d4e0c517eea296b Mon Sep 17 00:00:00 2001 From: sher9sv Date: Mon, 22 Aug 2022 18:27:05 +0200 Subject: [PATCH 5/5] float support --- nested_query_string/nested_query_string.py | 3 +++ test/nested_query_string_test.py | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/nested_query_string/nested_query_string.py b/nested_query_string/nested_query_string.py index a4aeefc..b1bb724 100644 --- a/nested_query_string/nested_query_string.py +++ b/nested_query_string/nested_query_string.py @@ -49,6 +49,9 @@ def encode(cls, value, key=None): if class_name == int: return key + "=" + str(value) + if class_name == float: + return key + "=" + str(value) + if class_name == bool: if value is True: return key + "=" + 'true' diff --git a/test/nested_query_string_test.py b/test/nested_query_string_test.py index dec6c57..773b6f5 100644 --- a/test/nested_query_string_test.py +++ b/test/nested_query_string_test.py @@ -25,6 +25,12 @@ def runTest(self): self.assertEqualQueryStrings(qs, 'abc=1') +class EncodeFloatTest(NestedQueryStringTestCase): + def runTest(self): + qs = NestedQueryString.encode({'abc': 12345.12345}) + self.assertEqualQueryStrings(qs, 'abc=12345.12345') + + class EncodeNumericAndStringTest(NestedQueryStringTestCase): def runTest(self): qs = NestedQueryString.encode({'abc': 'def', 'ghi': 1})