-
Notifications
You must be signed in to change notification settings - Fork 2
Metadata query params #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
# do not add duplicate keys to query_params list | ||
existing_keys = [] | ||
for param in query_params: | ||
existing_keys.append(param[0]) | ||
|
||
for key in kwargs: | ||
if key not in existing_keys: | ||
query_params.append([key, kwargs.get(key)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the place in which this new logic is most relevant. Previously, a named query param would appear twice because all args were added to the params list even if they already matched one of the conditionals above
patch_api/rest.py
Outdated
def recursive_urlencode(self, d): | ||
"""URL-encode a multidimensional dictionary. | ||
|
||
>>> data = {'a': 'b&c', 'd': {'e': {'f&g': 'h*i'}}, 'j': 'k'} | ||
>>> recursive_urlencode(data) | ||
u'a=b%26c&j=k&d[e][f%26g]=h%2Ai' | ||
""" | ||
|
||
def recursion(d, base=[]): | ||
pairs = [] | ||
|
||
for key, value in d.items(): | ||
new_base = base + [key] | ||
if hasattr(value, "values"): | ||
pairs += recursion(value, new_base) | ||
else: | ||
new_pair = None | ||
if len(new_base) > 1: | ||
first = urllib.parse.quote(new_base.pop(0)) | ||
rest = map(lambda x: urllib.parse.quote(x), new_base) | ||
new_pair = "%s[%s]=%s" % ( | ||
first, | ||
"][".join(rest), | ||
urllib.parse.quote(str(value)), | ||
) | ||
else: | ||
new_pair = "%s=%s" % ( | ||
urllib.parse.quote(str(key)), | ||
urllib.parse.quote(str(value)), | ||
) | ||
pairs.append(new_pair) | ||
return pairs | ||
|
||
return "&".join(recursion(d)) | ||
|
||
def encoded_query_params(self, query_params): | ||
if not query_params: | ||
return "" | ||
|
||
final_query_params = "" | ||
for key, value in query_params: | ||
if isinstance(value, dict): | ||
nested_param = {} | ||
nested_param[key] = value | ||
final_query_params += self.recursive_urlencode(nested_param) | ||
query_params.remove((key, value)) | ||
|
||
if query_params: | ||
final_query_params += "&" + urlencode(query_params) | ||
|
||
return "?" + final_query_params |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is all custom code. I took recursive_urlencode
from a stackoverflow answer and modified it to work with python3.
encoded_query_params
is a method I wrote
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a chance we could unit test those two methods? I trust the global test but this might save some pain later.
self.assertEqual(estimate.data.order.mass_g, 1000622) | ||
self.assertEqual(estimate.data.mass_g, 1000622) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I confirmed this change is correct with Brendan
@@ -75,7 +75,7 @@ def test_create_and_retrieve_shipping_estimate(self): | |||
) | |||
self.assertEqual(estimate.data.order, None) | |||
self.assertEqual(estimate.data.type, "shipping") | |||
self.assertEqual(estimate.data.mass_g, 373) | |||
self.assertEqual(estimate.data.mass_g, 249) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I confirmed this change is correct with Brendan
|
||
### Added | ||
|
||
- Fixed ability to create Orders with `metadata` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. This library does like repeating itself though.
Open question about unit-testing the query params method.
### Added | ||
|
||
- Fixed ability to create Orders with `metadata` | ||
- Add support for querying Orders by `metadata` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the new ETH parameter here as well?
|
||
# do not add duplicate keys to query_params list | ||
existing_keys = [] | ||
for param in query_params: | ||
existing_keys.append(param[0]) | ||
|
||
for key in kwargs: | ||
query_params.append([key, kwargs.get(key)]) | ||
if key not in existing_keys: | ||
query_params.append([key, kwargs.get(key)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll probably want to address the fact that this is duplicated several times over?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose but this logic does seem useful to have in each case so there aren't duplicate params in the list
patch_api/rest.py
Outdated
def recursive_urlencode(self, d): | ||
"""URL-encode a multidimensional dictionary. | ||
|
||
>>> data = {'a': 'b&c', 'd': {'e': {'f&g': 'h*i'}}, 'j': 'k'} | ||
>>> recursive_urlencode(data) | ||
u'a=b%26c&j=k&d[e][f%26g]=h%2Ai' | ||
""" | ||
|
||
def recursion(d, base=[]): | ||
pairs = [] | ||
|
||
for key, value in d.items(): | ||
new_base = base + [key] | ||
if hasattr(value, "values"): | ||
pairs += recursion(value, new_base) | ||
else: | ||
new_pair = None | ||
if len(new_base) > 1: | ||
first = urllib.parse.quote(new_base.pop(0)) | ||
rest = map(lambda x: urllib.parse.quote(x), new_base) | ||
new_pair = "%s[%s]=%s" % ( | ||
first, | ||
"][".join(rest), | ||
urllib.parse.quote(str(value)), | ||
) | ||
else: | ||
new_pair = "%s=%s" % ( | ||
urllib.parse.quote(str(key)), | ||
urllib.parse.quote(str(value)), | ||
) | ||
pairs.append(new_pair) | ||
return pairs | ||
|
||
return "&".join(recursion(d)) | ||
|
||
def encoded_query_params(self, query_params): | ||
if not query_params: | ||
return "" | ||
|
||
final_query_params = "" | ||
for key, value in query_params: | ||
if isinstance(value, dict): | ||
nested_param = {} | ||
nested_param[key] = value | ||
final_query_params += self.recursive_urlencode(nested_param) | ||
query_params.remove((key, value)) | ||
|
||
if query_params: | ||
final_query_params += "&" + urlencode(query_params) | ||
|
||
return "?" + final_query_params |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a chance we could unit test those two methods? I trust the global test but this might save some pain later.
test/test_rest.py
Outdated
encoded_params = client.encoded_query_params([('mass_g', 100)]) | ||
self.assertEqual(encoded_params, "?mass_g=100") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pcothenet unit tests added 🥳 and they caught a small issue of adding an extra &
to the url
What
Why
Clients want the ability to query orders via metadata.
SDK Release Checklist