)]}'
{"keystoneclient/common/cms.py":[{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"7bbf88fc4231633d09f8e87b66d1b54f89042178","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        return None"},{"line_number":264,"context_line":"    if is_ans1_token(token_id):"},{"line_number":265,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":266,"context_line":"        hasher.update(token_id.encode())"},{"line_number":267,"context_line":"        return hasher.hexdigest()"},{"line_number":268,"context_line":"    else:"},{"line_number":269,"context_line":"        return token_id"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FFCU%3D","line":266,"updated":"2014-01-17 16:44:58.000000000","message":"Use an explicit encoding: \"ascii\" or \"utf-8\", because the implicit encoding is different in Python 2 and Python 3 (\"ascii\" or \"utf-8\").","commit_id":"4312c729936fa26500187f1a31b1cfce9c1fa3f2"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"b0ca79751a4472ffa38e6ddafe8605b81e76e2fa","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        return None"},{"line_number":264,"context_line":"    if is_ans1_token(token_id):"},{"line_number":265,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":266,"context_line":"        hasher.update(token_id.encode(\u0027utf-8\u0027))"},{"line_number":267,"context_line":"        return hasher.hexdigest()"},{"line_number":268,"context_line":"    else:"},{"line_number":269,"context_line":"        return token_id"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAUH%2F%2B%2BUo%3D","line":266,"updated":"2014-01-20 08:19:13.000000000","message":"What is the type of token_id in Python 2? If it\u0027s str (bytes), you may use:\n\nif isinstance(token_id, six.text_type):\n    token_id \u003d token_id.encode(\u0027utf-8\u0027)\n\nI guess that the type in Python 3 is str (unicode).","commit_id":"4bc075ec477135425bdcd0526348998aa5f9982a"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"7fbfd83c4e6eb6a5b938bab95e568763194ba498","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        return None"},{"line_number":264,"context_line":"    if is_ans1_token(token_id):"},{"line_number":265,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":266,"context_line":"        hasher.update(token_id.encode(\u0027utf-8\u0027))"},{"line_number":267,"context_line":"        return hasher.hexdigest()"},{"line_number":268,"context_line":"    else:"},{"line_number":269,"context_line":"        return token_id"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAUH%2F%2B7x4%3D","line":266,"in_reply_to":"AAAAUH%2F%2B%2BUo%3D","updated":"2014-01-20 16:26:34.000000000","message":"You\u0027re right, I\u0027ll resubmit.","commit_id":"4bc075ec477135425bdcd0526348998aa5f9982a"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"343798cb2720015ea5cbc2f4ba966f9844471a90","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2BuBw%3D","line":267,"updated":"2014-01-22 20:33:54.000000000","message":"why would token_id not be a string?","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"29bb1d4eb187c9f1a49f827cea316f5650a7de41","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2BO9g%3D","line":267,"in_reply_to":"AAAAUH%2F%2BoAU%3D","updated":"2014-01-28 20:48:04.000000000","message":"OK, I\u0027ll move the calls to encode() to callers.","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"d11b816932c7fa1343e1bd82b916bcd99199200b","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2BoAU%3D","line":267,"in_reply_to":"AAAAUH%2F%2Brog%3D","updated":"2014-01-23 19:23:31.000000000","message":"as far as I can tell this is only called from one place -- _validate_user_token in auth_token middleware. How about changing the caller to convert the token_id rather than converting it here?\n\nThe only other place it\u0027s called is in the tests... If the behavior of this function is changing then the test should also be changed to ensure it works correctly.","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"aefd5a909d516124b484d463f04dcef477e4e7f3","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2BsmQ%3D","line":267,"in_reply_to":"AAAAUH%2F%2Bspk%3D","updated":"2014-01-23 02:42:05.000000000","message":"i can clearly see what the confusion is. I\u0027ve been porting code to Python 3 for some time and still have trouble getting my head around it. In Python 2 \u0027foo\u0027 is bytes, and u\u0027foo\u0027 is a Unicode string.\n\nI\u0027m really not sure of what the API should be, since I\u0027m not familiar with keystoneclient. I think it\u0027s fine to pass \u0027foo\u0027 on Python 2. If we want to stick to bytes, we\u0027d have to move that isinstance(...) to the callers so that Python 3 works. I could try to do that.\n\n@Victor: can you confirm I\u0027m not saying anything stupid ?","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"e7a734d87f3a0ed7f2a2220612c40fb93b2dccd9","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2Bspk%3D","line":267,"in_reply_to":"AAAAUH%2F%2BsrQ%3D","updated":"2014-01-23 02:32:17.000000000","message":"so here\u0027s where I\u0027m confused... I thought token_id was always a text string and not bytes. But you\u0027re saying token_id is a text string on python3 but it\u0027s not a text string on python2?\n\nHow would you define the argument to this function to tell callers what they can use? \"token_id is either a string or bytes\"? (I\u0027m fine with this, but should update the docstring to say that.)\n\nSeems like it would be simpler to say that token_id is always a string and not bytes (or always bytes), and the caller should be handling making sure it\u0027s sending in the right type. (Although as I said I\u0027m fine either way, just document it.)","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"c8d0368d0e6bf75415aaa2444d81f127651a3172","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2BsrQ%3D","line":267,"in_reply_to":"AAAAUH%2F%2Bssw%3D","updated":"2014-01-23 02:22:33.000000000","message":"I could write a comment that explains that. In terms of actual code, I would rather test for functionality than for a given version of Python. It seems less likely to break in the future (should there be other backwards-incompatible changes in Python 4/5/6), and it is really what I mean: here, I\u0027m wondering whether I\u0027m working with a text string or bytes, not what interpreter the user is running.\n\nWDYT ? Of course, if you really think using \"if six.PY3: ... else: ...\" is better, I\u0027ll do that :)","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"c66a5f16f7ef1bff2a22d73dc526a91e7f9a58bc","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2Bssw%3D","line":267,"in_reply_to":"AAAAUH%2F%2Bstw%3D","updated":"2014-01-23 02:14:32.000000000","message":"If you want to make it obvious that you do \"this\" for python2 and \"that\" for python3, then use \"if six.PY3\" or whatever it is. I\u0027d prefer if the intended behavior was obfuscated in some technicality of the language.","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"eeca5a6f648b04802a66cbb79c0029c9e75a56bc","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2Brog%3D","line":267,"in_reply_to":"AAAAUH%2F%2BuBw%3D","updated":"2014-01-23 08:39:26.000000000","message":"According to keystoneclient/middleware/auth_token.py, the type of token_id is the native \"str\" type, so \"string\". The value comes from an HTTP header which are \"str\" strings. The problem is that \"str\" is a bytes string in Python 2, and a character (unicode) string in Python 3.\n\nhashlib expects the bytes type (well, \"str\" in Python 2, \"bytes\" in Python 3), not str.","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"05d8db2627ed77de2b96bd1e586a7f4684ba195f","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        return None"},{"line_number":265,"context_line":"    if is_ans1_token(token_id):"},{"line_number":266,"context_line":"        hasher \u003d hashlib.md5()"},{"line_number":267,"context_line":"        if isinstance(token_id, six.text_type):"},{"line_number":268,"context_line":"            token_id \u003d token_id.encode(\u0027utf-8\u0027)"},{"line_number":269,"context_line":"        hasher.update(token_id)"},{"line_number":270,"context_line":"        return hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2Bstw%3D","line":267,"in_reply_to":"AAAAUH%2F%2BuBw%3D","updated":"2014-01-23 02:11:28.000000000","message":"That is a good question. In Python 2, this function is always given bytes (\u003ctype \u0027str\u0027\u003e) as input. Now, this is a bit tricky, but in Python 2:\n\n    \u003e\u003e\u003e isinstance(\u0027foo\u0027, six.text_type)\n\n    False\n\n    \u003e\u003e\u003e isinstance(u\u0027foo\u0027, six.text_type)\n\n    True\n\nIn Python 3, if we call cms_hash_token(\u0027foo\u0027), then it will not be bytes and will therefore need to be encoded.\n\n@Victor: can you confirm ?","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"}],"keystoneclient/middleware/auth_token.py":[{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"e8954494e335db72f6c322b029d79b146dbe9a7e","unresolved":false,"context_lines":[{"line_number":829,"context_line":""},{"line_number":830,"context_line":"        try:"},{"line_number":831,"context_line":"            if isinstance(user_token, six.text_type):"},{"line_number":832,"context_line":"                user_token \u003d user_token.encode(\u0027utf-8\u0027)"},{"line_number":833,"context_line":"            token_id \u003d cms.cms_hash_token(user_token)"},{"line_number":834,"context_line":"            cached \u003d self._cache_get(token_id)"},{"line_number":835,"context_line":"            if cached:"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BO3g%3D","line":832,"updated":"2014-01-28 20:55:43.000000000","message":"does this work? now when we call cms.is_ans1_token, or self.verify_uuid_token it\u0027s going to be called with bytes rather than a string?\n\nI\u0027m thinking this was a bad idea to move this call up to the caller now. I\u0027d be fine if the conversion was down in cms_hash_token.","commit_id":"4f54bd5f5d8387a2bb84512db6340f102ed1edeb"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"d8e095b50d32b3b1ef46c356afecde5c0a537c69","unresolved":false,"context_lines":[{"line_number":829,"context_line":""},{"line_number":830,"context_line":"        try:"},{"line_number":831,"context_line":"            if isinstance(user_token, six.text_type):"},{"line_number":832,"context_line":"                user_token \u003d user_token.encode(\u0027utf-8\u0027)"},{"line_number":833,"context_line":"            token_id \u003d cms.cms_hash_token(user_token)"},{"line_number":834,"context_line":"            cached \u003d self._cache_get(token_id)"},{"line_number":835,"context_line":"            if cached:"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAUH%2F%2BOMo%3D","line":832,"in_reply_to":"AAAAUH%2F%2BO3g%3D","updated":"2014-01-28 23:04:44.000000000","message":"In Python 2, user_token is currently a string, right ? Well, it is also bytes, since in Python 2, \u0027strings\u0027 are bytes.So this just makes sure we also use bytes in Python 3.\n\nIf you still think it\u0027d be best to convert to bytes in cms_hash_token, I\u0027ll resend.","commit_id":"4f54bd5f5d8387a2bb84512db6340f102ed1edeb"}],"keystoneclient/utils.py":[{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"7bbf88fc4231633d09f8e87b66d1b54f89042178","unresolved":false,"context_lines":[{"line_number":146,"context_line":""},{"line_number":147,"context_line":"def hash_signed_token(signed_text):"},{"line_number":148,"context_line":"    hash_ \u003d hashlib.md5()"},{"line_number":149,"context_line":"    hash_.update(signed_text.encode())"},{"line_number":150,"context_line":"    return hash_.hexdigest()"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAUH%2F%2FFCI%3D","line":149,"updated":"2014-01-17 16:44:58.000000000","message":"ditto","commit_id":"4312c729936fa26500187f1a31b1cfce9c1fa3f2"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"343798cb2720015ea5cbc2f4ba966f9844471a90","unresolved":false,"context_lines":[{"line_number":146,"context_line":""},{"line_number":147,"context_line":"def hash_signed_token(signed_text):"},{"line_number":148,"context_line":"    hash_ \u003d hashlib.md5()"},{"line_number":149,"context_line":"    if isinstance(signed_text, six.text_type):"},{"line_number":150,"context_line":"        signed_text \u003d signed_text.encode(\u0027utf-8\u0027)"},{"line_number":151,"context_line":"    hash_.update(signed_text)"},{"line_number":152,"context_line":"    return hash_.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2BuBk%3D","line":149,"updated":"2014-01-22 20:33:54.000000000","message":"why would signed_text not be a text type?","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"},{"author":{"_account_id":8122,"name":"Cyril Roelandt","email":"cyril@redhat.com","username":"cyril.roelandt.enovance"},"change_message_id":"05d8db2627ed77de2b96bd1e586a7f4684ba195f","unresolved":false,"context_lines":[{"line_number":146,"context_line":""},{"line_number":147,"context_line":"def hash_signed_token(signed_text):"},{"line_number":148,"context_line":"    hash_ \u003d hashlib.md5()"},{"line_number":149,"context_line":"    if isinstance(signed_text, six.text_type):"},{"line_number":150,"context_line":"        signed_text \u003d signed_text.encode(\u0027utf-8\u0027)"},{"line_number":151,"context_line":"    hash_.update(signed_text)"},{"line_number":152,"context_line":"    return hash_.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAUH%2F%2Bsts%3D","line":149,"in_reply_to":"AAAAUH%2F%2BuBk%3D","updated":"2014-01-23 02:11:28.000000000","message":"ditto","commit_id":"8544c8a727083f0c9f90aa0f55fd0a741c7b49b6"}]}
