-
Notifications
You must be signed in to change notification settings - Fork 49
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
Fix bytes concatination error in Client.search() #94
Conversation
cfcd059
to
a63ebcb
Compare
a63ebcb
to
9098126
Compare
Decide "join method" according to the type of "query".
A version of test_search, passing a bytes string to Client.search().
if anything else than tuple is passed.
Since *args is passed we'll always get a tuple which needs to be looked into for bytes first.
So I did some testing and came up with this if query:
items = []
for item in query:
if type(item) == bytes:
items.append(item.decode())
else:
items.append(item)
fields['q'] = ' '.join(items)
... Edit: More pythonic way if query:
items = [item.decode() if type(item) == bytes else item for item in query]
fields['q'] = ' '.join(items) This allows for mixed types in client.search("trash", b"80")
client.search("trash", "80")
client.search("trash" "80")
client.search(b"trash80")
client.search("trash80") All are valid. Also to pass the tests with multiple queries I'm sure you can come up with better variable names etc. 😄 This also needs to be tested with the real API but i'm sure it works fine |
if necessary.
unicode and mixed combinations are accepted. Add a new fixture in tests/res/database responding to the multivalue search.
Add tests and corresponding fixtures to proof that passing keyword arguments (**fields) is working.
Hi @AnssiAhola, sorry for not getting back to this earlier...other stuff.... Thanks a lot, that's a great solution!
Exactly what we should aim for here. Nice! I slightly reformatted the list comprehension for readability/linelength, have a look. What do you think?
Funnily enough: Not this time! No better ideas than "item" and "items" ;-) And it fits within 79 chars, which I like (even though we don't currently enforce that style in the project). Maybe I do have an idea: "part" and "parts"? Better?
I'll see if I can do some real tests and also ask users having the problem with Discogs searches in beets if they want to try it. I also added some tests to check if passing keyword arguments is actually working. We didn't have that yet, right? It's quite a pile of new tests now, please tell me which you think are not necessary or could be combined! Am I correct that we now support mixed types when passing *query but not when passing **fields. Should we support that too? |
discogs_client/client.py
Outdated
raise TypeError("{} method is expecting tuple, got {}.".format( | ||
__name__, type(query) | ||
)) | ||
|
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.
Do you agree this check is redundant and should be kicked out? As far as I understand *args always passes tuple.
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.
Yeah, I think this can be left out.
Looks good to me!
Yeah. I like part/parts better. I think those fit better in this context.
Didn't see any at least. And can't have too many tests imo! 😄
It seems that **fields are passed straight to discogs_client/discogs_client/utils.py Lines 16 to 21 in 65e8e95
|
if query: | ||
fields['q'] = ' '.join(query) | ||
items = [ | ||
item.decode() if type(item) == bytes else item for item in query |
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.
maybe this can be simplified with str()
?
items = [str(item) for item in query]
Haven't tested if that would work but given the docs say bytes can be passed into it, i don't see why not
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 tried that when I initially started to work on this issue. str() doesn't change the string type, bytes stay bytes and unicode stays unicode, thus it doesn't avoid different types concat errors. Not 100% sure anymore but I'll doublecheck later today or tomorrow.
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.
Hmmm I did not recall entirely correct: It seems the join does work but its not usable on another end:
items = [
str(item) for item in query
]
for item in items:
print(item)
fields['q'] = ' '.join(items)
print(fields)
$ python -m unittest discogs_client.tests.test_models.ModelsTestCase.test_multiterm_mixed_search
trash
b'80'
{'q': "trash b'80'"}
E
======================================================================
ERROR: test_multiterm_mixed_search (discogs_client.tests.test_models.ModelsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jojo/git/discogs_client/discogs_client/tests/test_models.py", line 64, in test_multiterm_mixed_search
self.assertEqual(len(results), 13)
File "/home/jojo/git/discogs_client/discogs_client/models.py", line 363, in __len__
return self.count
File "/home/jojo/git/discogs_client/discogs_client/models.py", line 334, in count
self._load_pagination_info()
File "/home/jojo/git/discogs_client/discogs_client/models.py", line 289, in _load_pagination_info
data = self.client._get(self._url_for_page(1))
File "/home/jojo/git/discogs_client/discogs_client/client.py", line 113, in _get
return self._request('GET', url)
File "/home/jojo/git/discogs_client/discogs_client/client.py", line 110, in _request
raise HTTPError(body['message'], status_code)
discogs_client.exceptions.HTTPError: 404: Resource not found.
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
But with the decode solution:
items = [
item.decode() if type(item) == bytes else item for item in query
]
for item in items:
print(item)
fields['q'] = ' '.join(items)
print(fields)
$ python -m unittest discogs_client.tests.test_models.ModelsTestCase.test_multiterm_mixed_search
trash
80
{'q': 'trash 80'}
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
:-)
Wow! Now that's one hell of an ugly unreadable function! ;-) Played around a little with the test of this method but I think what I did is a very unlikely case (different types for key and value)
the bytes_keyval test:
the mixed_keyval test:
Not sure if this is likely to ever happen, just playing around:
I'll leave all this for now and let's move on with this PR's actual issue :-) |
This reverts commit 6f68311. Not required at all since *args ensures a tuple.
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.
LGTM! 👍
Thanks for all the help and review @AnssiAhola 💯 ❤️ |
Todo: