)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"61f033bb815208b2410814a15c1f84638d74fbbf","unresolved":false,"context_lines":[{"line_number":22,"context_line":"functionalty."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"Change-Id: I3546674dcd9eddec2c378929dd3f759f667cfd5d"},{"line_number":25,"context_line":"Fixes-Bug: #1233838"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"AAAAS3%2F%2FFzY%3D","line":25,"updated":"2013-10-04 15:32:41.000000000","message":"I would tag this as Partial-Bug instead of Fixes-Bug since there will be another commit with the final fix.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":22,"context_line":"functionalty."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"Change-Id: I3546674dcd9eddec2c378929dd3f759f667cfd5d"},{"line_number":25,"context_line":"Fixes-Bug: #1233838"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"AAAATH%2F%2FIYw%3D","line":25,"in_reply_to":"AAAAS3%2F%2FFzY%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":17,"context_line":"  - keystone.tests.test_pemutils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Functionality in these utilities will be utilized to fix bug #1233838"},{"line_number":20,"context_line":"in a subsequent commit. It is hoped these modules will moved to Oslo"},{"line_number":21,"context_line":"common code. Each module has a doc string describing their purpose and"},{"line_number":22,"context_line":"functionalty."},{"line_number":23,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"AAAATn%2F%2FdnE%3D","line":20,"updated":"2013-11-05 14:52:32.000000000","message":"If the target for this code is oslo, why not just propose it there then sync it into keystone when it\u0027s merged?  That is the normal workflow IME","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"f93e2727c4a7904bd668e3c2e7cd8920a37d4626","unresolved":false,"context_lines":[{"line_number":17,"context_line":"  - keystone.tests.test_pemutils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Functionality in these utilities will be utilized to fix bug #1233838"},{"line_number":20,"context_line":"in a subsequent commit. It is hoped these modules will moved to Oslo"},{"line_number":21,"context_line":"common code. Each module has a doc string describing their purpose and"},{"line_number":22,"context_line":"functionalty."},{"line_number":23,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"AAAATn%2F%2FYds%3D","line":20,"in_reply_to":"AAAATn%2F%2FYo4%3D","updated":"2013-11-07 16:54:23.000000000","message":"+1, once code is in Oslo, syncs to the projects tend to go rather smooth since the code has already been blessed. Chances are this might not be a clean copy paste from Keystone to Oslo, there will probably be revisions to get this patch into Oslo. So committing this once to Oslo before Keystone will more than likely result in less work cleaning up the initial implementation in Keystone if it were merged here first, less technical debt.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"dfa12fd26bed6ca4e786fa2d13cced623f69cd0e","unresolved":false,"context_lines":[{"line_number":17,"context_line":"  - keystone.tests.test_pemutils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Functionality in these utilities will be utilized to fix bug #1233838"},{"line_number":20,"context_line":"in a subsequent commit. It is hoped these modules will moved to Oslo"},{"line_number":21,"context_line":"common code. Each module has a doc string describing their purpose and"},{"line_number":22,"context_line":"functionalty."},{"line_number":23,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"AAAATn%2F%2FYo4%3D","line":20,"in_reply_to":"AAAATn%2F%2FdZs%3D","updated":"2013-11-07 16:05:22.000000000","message":"Well FWIW, that is not the way the openstack process works in my experience - getting the patch reviewed and into keystone involves pretty much the exact same amount of effort as getting it into oslo, so it may as well just go into oslo, if that\u0027s where you hope it will end up, IMHO.  \n\nThis also has the advantage of ensuring the interfaces are acceptable to the oslo folks now, rather than having churn on the keystone side if you end up needing to change them as a result of the oslo review process.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":17,"context_line":"  - keystone.tests.test_pemutils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Functionality in these utilities will be utilized to fix bug #1233838"},{"line_number":20,"context_line":"in a subsequent commit. It is hoped these modules will moved to Oslo"},{"line_number":21,"context_line":"common code. Each module has a doc string describing their purpose and"},{"line_number":22,"context_line":"functionalty."},{"line_number":23,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"AAAATn%2F%2FdZs%3D","line":20,"in_reply_to":"AAAATn%2F%2FdnE%3D","updated":"2013-11-07 00:28:17.000000000","message":"Because we need it in keystone now. Further delays due to procedural hurdles is not helping the project.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"}],"keystone/common/base64_utils.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":47,"context_line":"#------------------------------------------------------------------------------"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"class InvalidBase64Error(ValueError):"},{"line_number":51,"context_line":"    pass"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"#------------------------------------------------------------------------------"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIOc%3D","line":50,"updated":"2013-10-03 20:59:45.000000000","message":"In the interest of future planning and possibly moving this to Oslo, it might be helpful to have this whole change contained within a directory specific to base64 operations. This will be helpful because then in Oslo it can be treated as a module as well (e.g. see the openstack/common/rpc/* or openstack/common/notifier/* modules for examples). Then when that times comes it would be easier to just move a directory instead of moving several modules underneath /keystone/common/. \n\nThis might also be helpful if we want to move InvalidBase64Error to its own module (/keystone/common/base64utils/exceptions.py for instance, making it easier to add new exceptions if/when this all develops. This makes things easier to find and reference when they are all in one place, and also follow structure similar to other openstack projects. \n\nJust a couple thoughts.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":47,"context_line":"#------------------------------------------------------------------------------"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"class InvalidBase64Error(ValueError):"},{"line_number":51,"context_line":"    pass"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"#------------------------------------------------------------------------------"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FINI%3D","line":50,"in_reply_to":"AAAAS3%2F%2FIOc%3D","updated":"2013-10-25 16:17:19.000000000","message":"I don\u0027t see the value in moving these to a subdirectory with the intent of moving to oslo, most of the simple oslo common utilities are currently contained in single files, e.g.\n\nauthutils.py\ncliutils.py\nexcutils.py\nfileutils.py\nfuncutils.py\ngettextutils.py\nimportutils.py\njsonutils.py\nlockutils.py\nnetwork_utils.py\nprocessutils.py\nsslutils.py\nstrutils.py\ntimeutils.py\nuuidutils.py\nxmlutils.py\n\nI do notice I have an underscore in my filenames which is not consistent with the olso common naming, I\u0027ll fix that.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"#------------------------------------------------------------------------------"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"whitespace_strip_re \u003d re.compile(r\u0027\\s+\u0027)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"base64_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9+/\u003d]+$\u0027)"},{"line_number":58,"context_line":"base64url_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9---_\u003d]+$\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdO0%3D","line":55,"updated":"2013-10-15 23:08:45.000000000","message":"does this also need to strip out newlines?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"#------------------------------------------------------------------------------"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"whitespace_strip_re \u003d re.compile(r\u0027\\s+\u0027)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"base64_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9+/\u003d]+$\u0027)"},{"line_number":58,"context_line":"base64url_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9---_\u003d]+$\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FUd4%3D","line":55,"in_reply_to":"AAAATH%2F%2FdO0%3D","updated":"2013-10-25 16:17:19.000000000","message":"It does. From the Python re module doc: When the UNICODE flag is not specified, it (\\s)  matches any whitespace character, this is equivalent to the set [ \\t\\n\\r\\f\\v]. Note, it is not necessary to use the re.MULTILINE flag here either since there are no ^ or $ anchors in the regexp.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":61,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"base64_to_base64url_trans \u003d string.maketrans(\u0027+/\u0027, \u0027-_\u0027)"},{"line_number":64,"context_line":"base64url_to_base64_trans \u003d string.maketrans(\u0027-_\u0027, \u0027+/\u0027)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"#------------------------------------------------------------------------------"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdNc%3D","line":64,"updated":"2013-10-15 23:08:45.000000000","message":"(NIT) I personally think constants should be all caps (easy to identity they are a constant in the code that way when used)","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91957d3159b932d2d9fc6841f13fcf4799b15726","unresolved":false,"context_lines":[{"line_number":61,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"base64_to_base64url_trans \u003d string.maketrans(\u0027+/\u0027, \u0027-_\u0027)"},{"line_number":64,"context_line":"base64url_to_base64_trans \u003d string.maketrans(\u0027-_\u0027, \u0027+/\u0027)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"#------------------------------------------------------------------------------"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2F43U%3D","line":64,"in_reply_to":"AAAATH%2F%2FUXo%3D","updated":"2013-10-25 17:02:25.000000000","message":"No need.  This just a NIT and personal style.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":61,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"base64_to_base64url_trans \u003d string.maketrans(\u0027+/\u0027, \u0027-_\u0027)"},{"line_number":64,"context_line":"base64url_to_base64_trans \u003d string.maketrans(\u0027-_\u0027, \u0027+/\u0027)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"#------------------------------------------------------------------------------"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FUXo%3D","line":64,"in_reply_to":"AAAATH%2F%2FdNc%3D","updated":"2013-10-25 16:17:19.000000000","message":"(NIT) I guess that depends on your definition of a constant. Are module scoped objects created at run time constants? I generally don\u0027t think of these as constants because they\u0027re actually variables that can be assigned to and whose value is the result of executing code (function call). Maybe too many years of C coding has coloured my definition of a constant. Technically Python doesn\u0027t have any constants. If you mean a constant is any variable which you\u0027re not supposed to modify then yes, they\u0027re constants. If these were simple values (e.g. a string or an integer value) as opposed to the result of a function call I\u0027d be much more comfortable calling them a constant, but these are actually function call results.\n\nIf you still feel strongly these identifiers should be all caps I\u0027ll change it.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"def is_valid_base64(text, alphabet\u003d\u0027base64\u0027):"},{"line_number":70,"context_line":"    \u0027\u0027\u0027test if input text can be base64 decoded"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    :param text: input base64 text"},{"line_number":73,"context_line":"    :returns: True if text can be decoded as base64, False otherwise"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIOI%3D","line":70,"updated":"2013-10-03 20:59:45.000000000","message":"Follow docstring convention specified in keystone/HACKING.rst\n\n\nhttps://github.com/openstack/keystone/blob/master/HACKING.rst#docstrings\n\n\nmainly \"\"\" instead of \u0027\u0027\u0027\n\nThis applies for all instances in this module.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"def is_valid_base64(text, alphabet\u003d\u0027base64\u0027):"},{"line_number":70,"context_line":"    \u0027\u0027\u0027test if input text can be base64 decoded"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    :param text: input base64 text"},{"line_number":73,"context_line":"    :returns: True if text can be decoded as base64, False otherwise"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdSc%3D","line":70,"in_reply_to":"AAAAS3%2F%2FIOI%3D","updated":"2013-10-15 23:08:45.000000000","message":"(NIT): You should also include a period at the end of the first line of the docstring. (other docstrings should be updated similarly)","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"def is_valid_base64(text, alphabet\u003d\u0027base64\u0027):"},{"line_number":70,"context_line":"    \u0027\u0027\u0027test if input text can be base64 decoded"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    :param text: input base64 text"},{"line_number":73,"context_line":"    :returns: True if text can be decoded as base64, False otherwise"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FUU8%3D","line":70,"in_reply_to":"AAAAS3%2F%2FIOI%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"def is_valid_base64(text, alphabet\u003d\u0027base64\u0027):"},{"line_number":70,"context_line":"    \u0027\u0027\u0027test if input text can be base64 decoded"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    :param text: input base64 text"},{"line_number":73,"context_line":"    :returns: True if text can be decoded as base64, False otherwise"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FUU4%3D","line":70,"in_reply_to":"AAAATH%2F%2FdSc%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":69,"context_line":"def is_valid_base64(text, alphabet\u003d\u0027base64\u0027):"},{"line_number":70,"context_line":"    \u0027\u0027\u0027test if input text can be base64 decoded"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    :param text: input base64 text"},{"line_number":73,"context_line":"    :returns: True if text can be decoded as base64, False otherwise"},{"line_number":74,"context_line":"    \u0027\u0027\u0027"},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FINs%3D","line":72,"updated":"2013-10-03 20:59:45.000000000","message":"Document param alphabet with it default value.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":69,"context_line":"def is_valid_base64(text, alphabet\u003d\u0027base64\u0027):"},{"line_number":70,"context_line":"    \u0027\u0027\u0027test if input text can be base64 decoded"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    :param text: input base64 text"},{"line_number":73,"context_line":"    :returns: True if text can be decoded as base64, False otherwise"},{"line_number":74,"context_line":"    \u0027\u0027\u0027"},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLhI%3D","line":72,"in_reply_to":"AAAAS3%2F%2FINs%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    if alphabet \u003d\u003d \u0027base64\u0027:"},{"line_number":77,"context_line":"        decoder \u003d base64.b64decode"},{"line_number":78,"context_line":"    elif alphabet \u003d\u003d \u0027base64url\u0027:"},{"line_number":79,"context_line":"        decoder \u003d base64.urlsafe_b64decode"},{"line_number":80,"context_line":"    else:"},{"line_number":81,"context_line":"        raise ValueError(\"unknown alphabet \u0027%s\u0027\" % (alphabet))"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdQo%3D","line":78,"updated":"2013-10-15 23:08:45.000000000","message":"This seems suboptimal.  Are we planning on eventually supporting a bunch of random base64 alphabets?  Going with a boolean here instead of a string makes more sense in the context of 2 possibilities.  It also eliminates the need to raise the ValueError","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91957d3159b932d2d9fc6841f13fcf4799b15726","unresolved":false,"context_lines":[{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    if alphabet \u003d\u003d \u0027base64\u0027:"},{"line_number":77,"context_line":"        decoder \u003d base64.b64decode"},{"line_number":78,"context_line":"    elif alphabet \u003d\u003d \u0027base64url\u0027:"},{"line_number":79,"context_line":"        decoder \u003d base64.urlsafe_b64decode"},{"line_number":80,"context_line":"    else:"},{"line_number":81,"context_line":"        raise ValueError(\"unknown alphabet \u0027%s\u0027\" % (alphabet))"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2F42E%3D","line":78,"in_reply_to":"AAAATH%2F%2FLew%3D","updated":"2013-10-25 17:02:25.000000000","message":"That is fair enough, then I would recommend making \"decoder\" the variable name and let the developer pass in a method reference that will be used to validate the base64.  You could provide a convenience attribute for base64 and urlsafe_b64decode (e.g. is_valid_base64(text, decoder\u003dbase64utils.urlsafe_decoder).  \n\nUsing an arbitrary string here feels like the wrong approach overall, since it requires logic changes for each new \"alphabet\" we want to support.\n\nThis would make the first if-block here a simple \"if iscallable\" check and raise a value error if the decoder isn\u0027t \"callable\".","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    if alphabet \u003d\u003d \u0027base64\u0027:"},{"line_number":77,"context_line":"        decoder \u003d base64.b64decode"},{"line_number":78,"context_line":"    elif alphabet \u003d\u003d \u0027base64url\u0027:"},{"line_number":79,"context_line":"        decoder \u003d base64.urlsafe_b64decode"},{"line_number":80,"context_line":"    else:"},{"line_number":81,"context_line":"        raise ValueError(\"unknown alphabet \u0027%s\u0027\" % (alphabet))"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLew%3D","line":78,"in_reply_to":"AAAATH%2F%2FdQo%3D","updated":"2013-10-25 16:17:19.000000000","message":"There are 8 different alphabets, we\u0027re currently only interested in 2. But if the parameter was a boolean allowing only a selection of 2 of the possible 8 then the API is not extensible. API\u0027s which are not designed to be extensible create problems later because they demand an API change to accommodate future needs. It\u0027s better to permit future needs without changing the API.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"85e44a2764d8f8c5181ae966ffec275670d93487","unresolved":false,"context_lines":[{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    if alphabet \u003d\u003d \u0027base64\u0027:"},{"line_number":77,"context_line":"        decoder \u003d base64.b64decode"},{"line_number":78,"context_line":"    elif alphabet \u003d\u003d \u0027base64url\u0027:"},{"line_number":79,"context_line":"        decoder \u003d base64.urlsafe_b64decode"},{"line_number":80,"context_line":"    else:"},{"line_number":81,"context_line":"        raise ValueError(\"unknown alphabet \u0027%s\u0027\" % (alphabet))"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2FuZ4%3D","line":78,"in_reply_to":"AAAATn%2F%2F42E%3D","updated":"2013-10-29 21:13:42.000000000","message":"I don\u0027t want to pass the decoder into the function for several reasons\n\n1) using the decoder to check for validity is an internal implementation detail\n\n2) there is no way to know if an externally provided decoder behaves as the validator expects.\n\n3) if the only thing is_valid_base64() does is attempt to decode the input and check for exceptions there isn\u0027t much point in having a validator function, the same thing can be trivially done by the caller.\n\nFWIW I did discover a condition where the Python base64 decoders do not raise an exception on invalid input, instead you get back a zero length result, is_valid_base64() did not check that condition.\n\nTo address your concerns about the alphabet parameter, I split is_valid_base64() into 2 independent functions, is_valid_base64() and is_valid_base64url(). This is consistent with the rest of the module which handles the url variants independently, in hind-sight for consistency it should have been done this way previously.\n\nI also rewrote the is_valid_base64() function so as not to attempt decoding as the validity test. Instead it now strips whitespace, checks for the presence of any non-alphabet characters and validates the correct padding, all without invoking any base64 module functions, this should be more robust because we\u0027re not depending on decoder behaviour and it more closely follows the RFC. The unit test was updated to reflect this change.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":78,"context_line":"    elif alphabet \u003d\u003d \u0027base64url\u0027:"},{"line_number":79,"context_line":"        decoder \u003d base64.urlsafe_b64decode"},{"line_number":80,"context_line":"    else:"},{"line_number":81,"context_line":"        raise ValueError(\"unknown alphabet \u0027%s\u0027\" % (alphabet))"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    try:"},{"line_number":84,"context_line":"        decoder(text)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdP0%3D","line":81,"updated":"2013-10-15 23:08:45.000000000","message":"(SEE note on line 78).  If this is kept, used _() around the string for localization","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":78,"context_line":"    elif alphabet \u003d\u003d \u0027base64url\u0027:"},{"line_number":79,"context_line":"        decoder \u003d base64.urlsafe_b64decode"},{"line_number":80,"context_line":"    else:"},{"line_number":81,"context_line":"        raise ValueError(\"unknown alphabet \u0027%s\u0027\" % (alphabet))"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    try:"},{"line_number":84,"context_line":"        decoder(text)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLaE%3D","line":81,"in_reply_to":"AAAATH%2F%2FdP0%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":88,"context_line":""},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"def filter_whitespace(text):"},{"line_number":91,"context_line":"    \u0027\u0027\u0027Return input text sans any whitespace"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    Strips all whitespace from the input text. The location of the"},{"line_number":94,"context_line":"    whitespace does not matter, leading, trailing and embedded"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FINQ%3D","line":91,"updated":"2013-10-03 20:59:45.000000000","message":"is sans supposed to be sanitizes?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":88,"context_line":""},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"def filter_whitespace(text):"},{"line_number":91,"context_line":"    \u0027\u0027\u0027Return input text sans any whitespace"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    Strips all whitespace from the input text. The location of the"},{"line_number":94,"context_line":"    whitespace does not matter, leading, trailing and embedded"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdR4%3D","line":91,"in_reply_to":"AAAAS3%2F%2FINQ%3D","updated":"2013-10-15 23:08:45.000000000","message":"@ldbragst, sans \u003d without (borrowed from french)","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":88,"context_line":""},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"def filter_whitespace(text):"},{"line_number":91,"context_line":"    \u0027\u0027\u0027Return input text sans any whitespace"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    Strips all whitespace from the input text. The location of the"},{"line_number":94,"context_line":"    whitespace does not matter, leading, trailing and embedded"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLeM%3D","line":91,"in_reply_to":"AAAAS3%2F%2FINQ%3D","updated":"2013-10-25 16:17:19.000000000","message":"http://dictionary.reference.com/browse/sans?s\u003dt\n\nsans means without, given you didn\u0027t know what sans meant I\u0027ve changed it to without","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    This function is commonly used to strip out whitespace formatting"},{"line_number":116,"context_line":"    present in a base64 block of text. Note however that all"},{"line_number":117,"context_line":"    non-alphabet characters are stripped, not just whitespace. The"},{"line_number":118,"context_line":"    returned string is a continuous string of base64 text."},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    :param text: input text to filter"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FINA%3D","line":117,"updated":"2013-10-03 20:59:45.000000000","message":"How do I know what characters those will be? Should a doc be linked here to official documentation?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    This function is commonly used to strip out whitespace formatting"},{"line_number":116,"context_line":"    present in a base64 block of text. Note however that all"},{"line_number":117,"context_line":"    non-alphabet characters are stripped, not just whitespace. The"},{"line_number":118,"context_line":"    returned string is a continuous string of base64 text."},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    :param text: input text to filter"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLc0%3D","line":117,"in_reply_to":"AAAAS3%2F%2FINA%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done\n\nAlthough many of the doc strings reference RFC-4648 I noticed the RFC was missing the the module doc string, I added the RFC in the module doc string, that should be sufficient to point anyone looking for clarification to find the definitions.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":227,"context_line":"    \u0027\u0027\u0027"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":230,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    text_len \u003d len(text)"},{"line_number":233,"context_line":"    if text_len \u003e 0 and text_len % 4 \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIMs%3D","line":230,"updated":"2013-10-03 20:59:45.000000000","message":"We can  use the keystone.openstack.common.log module to log output here, this is what the rest of keystone uses as well.This applies to all places where logging should happen in this file. Line 236, 240, 263, etc...","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":227,"context_line":"    \u0027\u0027\u0027"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":230,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    text_len \u003d len(text)"},{"line_number":233,"context_line":"    if text_len \u003e 0 and text_len % 4 \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLbs%3D","line":230,"in_reply_to":"AAAAS3%2F%2FIMs%3D","updated":"2013-10-25 16:17:19.000000000","message":"Sorry, I disagree. Places where exceptions are raised are not where logging should occur. Where the exception is caught is right place to log the error. Also this module is designed to eventually be a common module in oslo hence there shouldn\u0027t be anything Keystone specific in it.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":227,"context_line":"    \u0027\u0027\u0027"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":230,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    text_len \u003d len(text)"},{"line_number":233,"context_line":"    if text_len \u003e 0 and text_len % 4 \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdOs%3D","line":230,"in_reply_to":"AAAAS3%2F%2FIMs%3D","updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":227,"context_line":"    \u0027\u0027\u0027"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":230,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    text_len \u003d len(text)"},{"line_number":233,"context_line":"    if text_len \u003e 0 and text_len % 4 \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLaQ%3D","line":230,"in_reply_to":"AAAATH%2F%2FdOs%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":235,"context_line":"        if pad_index \u003e\u003d 0 and pad_index \u003c text_len - 2:"},{"line_number":236,"context_line":"            raise InvalidBase64Error(\"text is multiple of 4, \""},{"line_number":237,"context_line":"                                     \"but pad \u0027%s\u0027 occurs before \""},{"line_number":238,"context_line":"                                     \"2nd to last char\" % pad)"},{"line_number":239,"context_line":"        if pad_index \u003d\u003d text_len - 2 and text[-1] !\u003d pad:"},{"line_number":240,"context_line":"            raise InvalidBase64Error(\"text is multiple of 4, \""},{"line_number":241,"context_line":"                                     \"but pad \u0027%s\u0027 occurs before \""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdOk%3D","line":238,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":235,"context_line":"        if pad_index \u003e\u003d 0 and pad_index \u003c text_len - 2:"},{"line_number":236,"context_line":"            raise InvalidBase64Error(\"text is multiple of 4, \""},{"line_number":237,"context_line":"                                     \"but pad \u0027%s\u0027 occurs before \""},{"line_number":238,"context_line":"                                     \"2nd to last char\" % pad)"},{"line_number":239,"context_line":"        if pad_index \u003d\u003d text_len - 2 and text[-1] !\u003d pad:"},{"line_number":240,"context_line":"            raise InvalidBase64Error(\"text is multiple of 4, \""},{"line_number":241,"context_line":"                                     \"but pad \u0027%s\u0027 occurs before \""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLaA%3D","line":238,"in_reply_to":"AAAATH%2F%2FdOk%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        if pad_index \u003d\u003d text_len - 2 and text[-1] !\u003d pad:"},{"line_number":240,"context_line":"            raise InvalidBase64Error(\"text is multiple of 4, \""},{"line_number":241,"context_line":"                                     \"but pad \u0027%s\u0027 occurs before \""},{"line_number":242,"context_line":"                                     \"non-pad last char\" % pad)"},{"line_number":243,"context_line":"        return True"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    if text.find(pad) \u003e\u003d 0:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdOg%3D","line":242,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        if pad_index \u003d\u003d text_len - 2 and text[-1] !\u003d pad:"},{"line_number":240,"context_line":"            raise InvalidBase64Error(\"text is multiple of 4, \""},{"line_number":241,"context_line":"                                     \"but pad \u0027%s\u0027 occurs before \""},{"line_number":242,"context_line":"                                     \"non-pad last char\" % pad)"},{"line_number":243,"context_line":"        return True"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    if text.find(pad) \u003e\u003d 0:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLZ8%3D","line":242,"in_reply_to":"AAAATH%2F%2FdOg%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    if text.find(pad) \u003e\u003d 0:"},{"line_number":246,"context_line":"        raise InvalidBase64Error(\"text is not a multiple of 4, \""},{"line_number":247,"context_line":"                                 \"but contains pad \u0027%s\u0027\" % pad)"},{"line_number":248,"context_line":"    return False"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdOc%3D","line":247,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    if text.find(pad) \u003e\u003d 0:"},{"line_number":246,"context_line":"        raise InvalidBase64Error(\"text is not a multiple of 4, \""},{"line_number":247,"context_line":"                                 \"but contains pad \u0027%s\u0027\" % pad)"},{"line_number":248,"context_line":"    return False"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLZ0%3D","line":247,"in_reply_to":"AAAATH%2F%2FdOc%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":261,"context_line":""},{"line_number":262,"context_line":"    if len(text) % 4 !\u003d 0:"},{"line_number":263,"context_line":"        raise InvalidBase64Error(\"padded base64url text must be \""},{"line_number":264,"context_line":"                                 \"multiple of 4 characters\")"},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"    return urllib.quote(text)"},{"line_number":267,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdOY%3D","line":264,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.\n\n(NIT): Use \u0027 consistently instead of \". [This should probably be changed throughout the file for strings]","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":261,"context_line":""},{"line_number":262,"context_line":"    if len(text) % 4 !\u003d 0:"},{"line_number":263,"context_line":"        raise InvalidBase64Error(\"padded base64url text must be \""},{"line_number":264,"context_line":"                                 \"multiple of 4 characters\")"},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"    return urllib.quote(text)"},{"line_number":267,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLY0%3D","line":264,"in_reply_to":"AAAATH%2F%2FdOY%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"61f033bb815208b2410814a15c1f84638d74fbbf","unresolved":false,"context_lines":[{"line_number":280,"context_line":"    return urllib.unquote(text)"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":""},{"line_number":283,"context_line":"def base64_strip_padding(text, pad\u003d\u0027\u003d\u0027):"},{"line_number":284,"context_line":"    \u0027\u0027\u0027Remove padding from input base64 text"},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"    :param text: text containing ONLY characters in a base64 alphabet"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FF5o%3D","line":283,"updated":"2013-10-04 15:32:41.000000000","message":"Can\u0027t this be implemented with str.rstrip?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":280,"context_line":"    return urllib.unquote(text)"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":""},{"line_number":283,"context_line":"def base64_strip_padding(text, pad\u003d\u0027\u003d\u0027):"},{"line_number":284,"context_line":"    \u0027\u0027\u0027Remove padding from input base64 text"},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"    :param text: text containing ONLY characters in a base64 alphabet"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLYg%3D","line":283,"in_reply_to":"AAAAS3%2F%2FF5o%3D","updated":"2013-10-25 16:17:19.000000000","message":"No, rstrip() does not respect the base64 padding rules. This module is meant to do things correctly and not take short-cuts such as just blindly stripping any number of trailing pad characters.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":285,"context_line":""},{"line_number":286,"context_line":"    :param text: text containing ONLY characters in a base64 alphabet"},{"line_number":287,"context_line":"    :param pad: pad character (must be single character)"},{"line_number":288,"context_line":"    :returns: base64 text sans padding"},{"line_number":289,"context_line":"    \u0027\u0027\u0027"},{"line_number":290,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":291,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIMM%3D","line":288,"updated":"2013-10-03 20:59:45.000000000","message":"Is sans suppose to be sanitized?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":285,"context_line":""},{"line_number":286,"context_line":"    :param text: text containing ONLY characters in a base64 alphabet"},{"line_number":287,"context_line":"    :param pad: pad character (must be single character)"},{"line_number":288,"context_line":"    :returns: base64 text sans padding"},{"line_number":289,"context_line":"    \u0027\u0027\u0027"},{"line_number":290,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":291,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLYY%3D","line":288,"in_reply_to":"AAAAS3%2F%2FIMM%3D","updated":"2013-10-25 16:17:19.000000000","message":"see above, changed \u0027sans\u0027 to \u0027without\u0027","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":288,"context_line":"    :returns: base64 text sans padding"},{"line_number":289,"context_line":"    \u0027\u0027\u0027"},{"line_number":290,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":291,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"    # Can\u0027t be padded if text is less than 4 characters."},{"line_number":294,"context_line":"    if len(text) \u003c 4:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdOM%3D","line":291,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":288,"context_line":"    :returns: base64 text sans padding"},{"line_number":289,"context_line":"    \u0027\u0027\u0027"},{"line_number":290,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":291,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"    # Can\u0027t be padded if text is less than 4 characters."},{"line_number":294,"context_line":"    if len(text) \u003c 4:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLYQ%3D","line":291,"in_reply_to":"AAAATH%2F%2FdOM%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":341,"context_line":"    \u0027\u0027\u0027"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":344,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":345,"context_line":""},{"line_number":346,"context_line":"    if text.endswith(pad):"},{"line_number":347,"context_line":"        return text"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdN8%3D","line":344,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":341,"context_line":"    \u0027\u0027\u0027"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"    if len(pad) !\u003d 1:"},{"line_number":344,"context_line":"        raise ValueError(\u0027pad must be single character\u0027)"},{"line_number":345,"context_line":""},{"line_number":346,"context_line":"    if text.endswith(pad):"},{"line_number":347,"context_line":"        return text"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLYM%3D","line":344,"in_reply_to":"AAAATH%2F%2FdN8%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"61f033bb815208b2410814a15c1f84638d74fbbf","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        yield text[x:x + width]"},{"line_number":376,"context_line":""},{"line_number":377,"context_line":""},{"line_number":378,"context_line":"def base64_wrap(text, width\u003d64):"},{"line_number":379,"context_line":"    \u0027\u0027\u0027Fold text into lines of text with max line length\u0027"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    Input is assumed to consist only of members of a base64"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FF6w%3D","line":378,"updated":"2013-10-04 15:32:41.000000000","message":"Can\u0027t this and the function above be implemented with textwrap?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        yield text[x:x + width]"},{"line_number":376,"context_line":""},{"line_number":377,"context_line":""},{"line_number":378,"context_line":"def base64_wrap(text, width\u003d64):"},{"line_number":379,"context_line":"    \u0027\u0027\u0027Fold text into lines of text with max line length\u0027"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    Input is assumed to consist only of members of a base64"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLWw%3D","line":378,"in_reply_to":"AAAAS3%2F%2FF6w%3D","updated":"2013-10-25 16:17:19.000000000","message":"textwrap was explicitly not used. textwrap is overkill, it has way more functionality than is needed much of which has to be disabled to produce the output we need (e.g. break_long_words, break_on_hyphens). If textwrap is ever changed this function may no longer function correctly for it\u0027s intended purpose. It\u0027s better to assure we produce exactly what is required (and do it more efficiently)","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":376,"context_line":""},{"line_number":377,"context_line":""},{"line_number":378,"context_line":"def base64_wrap(text, width\u003d64):"},{"line_number":379,"context_line":"    \u0027\u0027\u0027Fold text into lines of text with max line length\u0027"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    Input is assumed to consist only of members of a base64"},{"line_number":382,"context_line":"    alphabet (i.e no whitepace). Fold the text into lines whose"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdNw%3D","line":379,"updated":"2013-10-15 23:08:45.000000000","message":"spurious \u0027 at the end of the line.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":376,"context_line":""},{"line_number":377,"context_line":""},{"line_number":378,"context_line":"def base64_wrap(text, width\u003d64):"},{"line_number":379,"context_line":"    \u0027\u0027\u0027Fold text into lines of text with max line length\u0027"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    Input is assumed to consist only of members of a base64"},{"line_number":382,"context_line":"    alphabet (i.e no whitepace). Fold the text into lines whose"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLWs%3D","line":379,"in_reply_to":"AAAATH%2F%2FdNw%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"}],"keystone/common/base64utils.py":[{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":57,"context_line":"whitespace_strip_re \u003d re.compile(r\u0027\\s+\u0027)"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"base64_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9+/\u003d]+$\u0027)"},{"line_number":60,"context_line":"base64url_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9---_\u003d]+$\u0027)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"base64_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9+/\u003d]+\u0027)"},{"line_number":63,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsOQ%3D","line":60,"updated":"2013-10-30 11:50:51.000000000","message":"These two aren\u0027t used anywhere","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":57,"context_line":"whitespace_strip_re \u003d re.compile(r\u0027\\s+\u0027)"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"base64_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9+/\u003d]+$\u0027)"},{"line_number":60,"context_line":"base64url_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9---_\u003d]+$\u0027)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"base64_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9+/\u003d]+\u0027)"},{"line_number":63,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlPc%3D","line":60,"in_reply_to":"AAAATn%2F%2FsOQ%3D","updated":"2013-11-07 00:26:32.000000000","message":"No they aren\u0027t, but their compliment is. Users of the module may find it useful so why not make it available? One of the frustrations I had with the Python core base64 module was lack of access to seemingly useful items I thought it should have defined (especially with respect to alphabet definitions). Given that experience I see value in allowing a utility module to export potentially useful items even if the module itself does not make use of them.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":65,"context_line":"base64_to_base64url_trans \u003d string.maketrans(\u0027+/\u0027, \u0027-_\u0027)"},{"line_number":66,"context_line":"base64url_to_base64_trans \u003d string.maketrans(\u0027-_\u0027, \u0027+/\u0027)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"#------------------------------------------------------------------------------"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"def is_valid_base64(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsNc%3D","line":68,"updated":"2013-10-30 11:50:51.000000000","message":"Are these comment-separators really needed?  They look weird to me.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":65,"context_line":"base64_to_base64url_trans \u003d string.maketrans(\u0027+/\u0027, \u0027-_\u0027)"},{"line_number":66,"context_line":"base64url_to_base64_trans \u003d string.maketrans(\u0027-_\u0027, \u0027+/\u0027)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"#------------------------------------------------------------------------------"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"def is_valid_base64(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlWs%3D","line":68,"in_reply_to":"AAAATn%2F%2FsNc%3D","updated":"2013-11-07 00:26:32.000000000","message":"They\u0027re there to divide the file into logical sections. I\u0027m happy to remove them.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":84,"context_line":"    try:"},{"line_number":85,"context_line":"        return base64_is_padded(text)"},{"line_number":86,"context_line":"    except InvalidBase64Error:"},{"line_number":87,"context_line":"        return False"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"def is_valid_base64url(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsT8%3D","line":87,"updated":"2013-10-30 11:50:51.000000000","message":"Why do all this, instead of just trying to decode text, then returning false if we catch an exception?","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":84,"context_line":"    try:"},{"line_number":85,"context_line":"        return base64_is_padded(text)"},{"line_number":86,"context_line":"    except InvalidBase64Error:"},{"line_number":87,"context_line":"        return False"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"def is_valid_base64url(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlWQ%3D","line":87,"in_reply_to":"AAAATn%2F%2FsT8%3D","updated":"2013-11-07 00:26:32.000000000","message":"Your excellent suggestion of attempting to decode and catching an error is exactly how this was originally coded (please see prior submissions and review comments). During further testing I discovered the stock decoders didn\u0027t always raise an exception, instead they returned a zero length result. I could have also tested for zero length results as well as raised exceptions, but one wonders how reliable the decoders are and what corner cases they might miss, thus I concluded this was a more reliable and robust test and possibly more efficient than doing a full decode.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":104,"context_line":"    try:"},{"line_number":105,"context_line":"        return base64_is_padded(text)"},{"line_number":106,"context_line":"    except InvalidBase64Error:"},{"line_number":107,"context_line":"        return False"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"def filter_whitespace(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsTw%3D","line":107,"updated":"2013-10-30 11:50:51.000000000","message":"Same, why not just try urlsafe_b64decode-ing?","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":104,"context_line":"    try:"},{"line_number":105,"context_line":"        return base64_is_padded(text)"},{"line_number":106,"context_line":"    except InvalidBase64Error:"},{"line_number":107,"context_line":"        return False"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"def filter_whitespace(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlWI%3D","line":107,"in_reply_to":"AAAATn%2F%2FsTw%3D","updated":"2013-11-07 00:26:32.000000000","message":"see above, exact same reason.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":114,"context_line":"    whitespace does not matter, leading, trailing and embedded"},{"line_number":115,"context_line":"    whitespace all stripped."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"    This is potentially a safter filter to use than"},{"line_number":118,"context_line":"    filter_base64_alphabet() or filter_base64url_alphabet() because"},{"line_number":119,"context_line":"    those filters remove all non-alphabet characters. Valid base64"},{"line_number":120,"context_line":"    text should contain only members of the alphabet and whitespace"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsZM%3D","line":117,"updated":"2013-10-30 11:50:51.000000000","message":"typo s/safter/safer","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":114,"context_line":"    whitespace does not matter, leading, trailing and embedded"},{"line_number":115,"context_line":"    whitespace all stripped."},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"    This is potentially a safter filter to use than"},{"line_number":118,"context_line":"    filter_base64_alphabet() or filter_base64url_alphabet() because"},{"line_number":119,"context_line":"    those filters remove all non-alphabet characters. Valid base64"},{"line_number":120,"context_line":"    text should contain only members of the alphabet and whitespace"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlWA%3D","line":117,"in_reply_to":"AAAATn%2F%2FsZM%3D","updated":"2013-11-07 00:26:32.000000000","message":"Good catch, thank you, fixed.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":124,"context_line":"    :type text: string"},{"line_number":125,"context_line":"    :returns: string -- filtered text without whitespace"},{"line_number":126,"context_line":"    \"\"\""},{"line_number":127,"context_line":"    return whitespace_strip_re.sub(\u0027\u0027, text)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"def filter_base64_alphabet(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsYc%3D","line":127,"updated":"2013-10-30 11:50:51.000000000","message":"This is hardly a base64 specific function, so does it make sense to expose it as a top-level interface of this utility module?  Seems like something you want to use internally as a private helper in a utility class to me..","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":124,"context_line":"    :type text: string"},{"line_number":125,"context_line":"    :returns: string -- filtered text without whitespace"},{"line_number":126,"context_line":"    \"\"\""},{"line_number":127,"context_line":"    return whitespace_strip_re.sub(\u0027\u0027, text)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"def filter_base64_alphabet(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlVE%3D","line":127,"in_reply_to":"AAAATn%2F%2FsYc%3D","updated":"2013-11-07 00:26:32.000000000","message":"This function has been renamed to filter_formatting().\n\nBase64 text is often formatted. It\u0027s also often the case we need to work with just the alphabet characters. It\u0027s useful for the module to include such a utility because it\u0027s used so frequently.  It is often useful in the context of working with base64 data and PEM formatted data. Transforming from PEM based CMS signatures to OpenStack token ID\u0027s is one such use.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    This function is commonly used to strip out whitespace formatting"},{"line_number":137,"context_line":"    present in a base64 block of text. Note however that all"},{"line_number":138,"context_line":"    non-alphabet characters are stripped, not just whitespace. The"},{"line_number":139,"context_line":"    returned string is a continuous string of base64 text."},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    :param text: input text to filter"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsTE%3D","line":138,"updated":"2013-10-30 11:50:51.000000000","message":"This sounds like a fantastic way to take some malformed, corrupted or otherwise incorrect input, and produce seemingly valid but totally meaningless decoded output to me..","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    This function is commonly used to strip out whitespace formatting"},{"line_number":137,"context_line":"    present in a base64 block of text. Note however that all"},{"line_number":138,"context_line":"    non-alphabet characters are stripped, not just whitespace. The"},{"line_number":139,"context_line":"    returned string is a continuous string of base64 text."},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    :param text: input text to filter"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlUQ%3D","line":138,"in_reply_to":"AAAATn%2F%2FsTE%3D","updated":"2013-11-07 00:26:32.000000000","message":"After considering this I\u0027ve come to agree with you these functions do not serve a useful purpose and can be abused. They pre-dated the inclusion of the filter_whitespace() function (now called filter_formatting()). The filter_formatting() is really the correct filter, you are right one should not strip non-formatting characters, as such I\u0027ve removed these two filter functions.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":218,"context_line":"    :type text: string"},{"line_number":219,"context_line":"    :returns: string -- base64url text"},{"line_number":220,"context_line":"    \"\"\""},{"line_number":221,"context_line":"    return text.translate(base64_to_base64url_trans)"},{"line_number":222,"context_line":""},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"def base64url_to_base64(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsNU%3D","line":221,"updated":"2013-10-30 11:50:51.000000000","message":"Do you actually need all these one-line functions, or could you have one function which takes an argument?","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":218,"context_line":"    :type text: string"},{"line_number":219,"context_line":"    :returns: string -- base64url text"},{"line_number":220,"context_line":"    \"\"\""},{"line_number":221,"context_line":"    return text.translate(base64_to_base64url_trans)"},{"line_number":222,"context_line":""},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"def base64url_to_base64(text):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlTs%3D","line":221,"in_reply_to":"AAAATn%2F%2FsNU%3D","updated":"2013-11-07 00:26:32.000000000","message":"Argh ..., everyone one has their own opinion, I just got done modifying a previous submission that used a function argument because the reviewer thought using a function argument was a bad idea and was quite emphatic about not using a function argument for this purpose.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":239,"context_line":"    return text.translate(base64url_to_base64_trans)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"def base64_is_padded(text, pad\u003d\u0027\u003d\u0027):"},{"line_number":243,"context_line":"    \"\"\"Test if the text is base64 padded."},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    The input text must be in a base64 alphabet. The pad must be a"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsME%3D","line":242,"updated":"2013-10-30 11:50:51.000000000","message":"Seeing all these base64_foo functions makes me wonder if this would be better as a utility class, which you initialize with text.\n\nI mean, as written this is going to lead to horrible base64-naming-overload and needlessly long lines:\n\nfrom keystone.common import base64utils\n\nbase64utils.base64url_to_base64(\"blah\")","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":239,"context_line":"    return text.translate(base64url_to_base64_trans)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"def base64_is_padded(text, pad\u003d\u0027\u003d\u0027):"},{"line_number":243,"context_line":"    \"\"\"Test if the text is base64 padded."},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    The input text must be in a base64 alphabet. The pad must be a"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlSw%3D","line":242,"in_reply_to":"AAAATn%2F%2FsME%3D","updated":"2013-11-07 00:26:32.000000000","message":"I understand your suggestion for encapsulating this in a class, in fact I did consider that. In actual practice using these functions (including those in pemutils) it seemed easier to have a toolbox of functions that could be applied to any Python basestring rather than having to serialize into and out of a class object as different \"transforms\" are applied.\n\nI have sympathy for your observation concerning long names, I suppose the \u0027base64\u0027 components of the identifiers could be shortened to \u0027b64\u0027. I\u0027d be happy to make that change if you like.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"e6b477bbc1a88b7afae68aeff86a53b4a01a43c6","unresolved":false,"context_lines":[{"line_number":310,"context_line":"    :returns: string -- percent-decoded base64url text"},{"line_number":311,"context_line":"    \"\"\""},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"    return urllib.unquote(text)"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"def base64_strip_padding(text, pad\u003d\u0027\u003d\u0027):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FsL8%3D","line":313,"updated":"2013-10-30 11:50:51.000000000","message":"Do you really need to wrap something as common and non-base64-specific as quote/unquote?","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"960114261b146b8c7ad789aca5e0f6f8cdd68890","unresolved":false,"context_lines":[{"line_number":310,"context_line":"    :returns: string -- percent-decoded base64url text"},{"line_number":311,"context_line":"    \"\"\""},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"    return urllib.unquote(text)"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"def base64_strip_padding(text, pad\u003d\u0027\u003d\u0027):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2FlQ4%3D","line":313,"in_reply_to":"AAAATn%2F%2FsL8%3D","updated":"2013-11-07 00:26:32.000000000","message":"The idea is not to require a user of the module from having to know specific escaping rules and which Python function provides the matching semantics and where to find it. Also these functions do some extra validation to catch any mangled text helping to assure the text is valid. I just noticed the decode function omitted the validation and the next submission fixes that omission. It\u0027s also appropriate to have the API be symmetric offering both encode and decode operations.\n\nFWIW urllib.unquote() is actually overkill if one follows the rules because of the constrained set of characters in base64url context, so these functions could have implemented differently.","commit_id":"1f872abb80c262e10730d86d1ef068bda0dea989"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":52,"context_line":"whitespace_strip_re \u003d re.compile(r\u0027\\s+\u0027)"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"base64_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9+/\u003d]+$\u0027)"},{"line_number":55,"context_line":"base64url_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9---_\u003d]+$\u0027)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"base64_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9+/\u003d]+\u0027)"},{"line_number":58,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdm8%3D","line":55,"updated":"2013-11-05 14:52:32.000000000","message":"These are still unused, arent\u0027 they?","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":52,"context_line":"whitespace_strip_re \u003d re.compile(r\u0027\\s+\u0027)"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"base64_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9+/\u003d]+$\u0027)"},{"line_number":55,"context_line":"base64url_alphabet_re \u003d re.compile(r\u0027^[^A-Za-z0-9---_\u003d]+$\u0027)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"base64_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9+/\u003d]+\u0027)"},{"line_number":58,"context_line":"base64url_non_alphabet_re \u003d re.compile(r\u0027[^A-Za-z0-9---_\u003d]+\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2FdCI%3D","line":55,"in_reply_to":"AAAATn%2F%2Fdm8%3D","updated":"2013-11-07 00:28:17.000000000","message":"I answered you previously but you didn\u0027t see that response because I inadvertently failed to publish the comment. Please see my earlier reply.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    text \u003d filter_whitespace(text)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    if base64_non_alphabet_re.search(text):"},{"line_number":75,"context_line":"        return False"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdms%3D","line":74,"updated":"2013-11-05 14:52:32.000000000","message":"Why is this needed. won\u0027t the try/catch do the same thing?","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    text \u003d filter_whitespace(text)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    if base64_non_alphabet_re.search(text):"},{"line_number":75,"context_line":"        return False"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2FalQ%3D","line":74,"in_reply_to":"AAAATn%2F%2Fdjw%3D","updated":"2013-11-07 00:28:17.000000000","message":"I answered you previously but you didn\u0027t see that response because I inadvertently failed to publish the comment. Please see my earlier reply.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"6d95c08c04a981ff6c9f9cc3d021c7edc6909c0c","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    text \u003d filter_whitespace(text)"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    if base64_non_alphabet_re.search(text):"},{"line_number":75,"context_line":"        return False"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdjw%3D","line":74,"in_reply_to":"AAAATn%2F%2Fdms%3D","updated":"2013-11-05 15:09:23.000000000","message":"Oh wait, I see you\u0027ve ignored my previous comment about just trying the decode and catching the error.  I\u0027m still not clear what benefit this indirect approach has, other than being slower and less obvious, clarification would be appreciated :)","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":92,"context_line":"    text \u003d filter_whitespace(text)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    if base64url_non_alphabet_re.search(text):"},{"line_number":95,"context_line":"        return False"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"    try:"},{"line_number":98,"context_line":"        return base64_is_padded(text)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdmo%3D","line":95,"updated":"2013-11-05 14:52:32.000000000","message":"Likewise","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":92,"context_line":"    text \u003d filter_whitespace(text)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    if base64url_non_alphabet_re.search(text):"},{"line_number":95,"context_line":"        return False"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"    try:"},{"line_number":98,"context_line":"        return base64_is_padded(text)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2FdCA%3D","line":95,"in_reply_to":"AAAATn%2F%2Fdmo%3D","updated":"2013-11-07 00:28:17.000000000","message":"I answered you previously but you didn\u0027t see that response because I inadvertently failed to publish the comment. Please see my earlier reply.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":303,"context_line":"    :returns: string -- percent-decoded base64url text"},{"line_number":304,"context_line":"    \"\"\""},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"    return urllib.unquote(text)"},{"line_number":307,"context_line":""},{"line_number":308,"context_line":""},{"line_number":309,"context_line":"def base64_strip_padding(text, pad\u003d\u0027\u003d\u0027):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdmk%3D","line":306,"updated":"2013-11-05 14:52:32.000000000","message":"I maintain, this sort of interface redefinition is pointless obfuscation, it\u0027s not providing any useful abtraction IMHO.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":303,"context_line":"    :returns: string -- percent-decoded base64url text"},{"line_number":304,"context_line":"    \"\"\""},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"    return urllib.unquote(text)"},{"line_number":307,"context_line":""},{"line_number":308,"context_line":""},{"line_number":309,"context_line":"def base64_strip_padding(text, pad\u003d\u0027\u003d\u0027):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2FakY%3D","line":306,"in_reply_to":"AAAATn%2F%2Fdmk%3D","updated":"2013-11-07 00:28:17.000000000","message":"base64url_percent_encode() above does a validation check on the input text. Thank you for calling attention to the fact an equivalent check was omitted from the decode operation.  The API should be symmetric providing both encode and decode. The idea behind these \"helper\" functions is to utilize the context in which the operation is occurring. In this case it\u0027s not just any text being encoded/decoded, rather it\u0027s base64 that has to meet certain specific criteria. Also the helper functions frees the user of the module from having to research the specific escape mechanism as defined in the RFC and locate the appropriate function in another unrelated Python module.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"}],"keystone/common/pem_utils.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":31,"context_line":"implementations have adopted it."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"Unfortunately PEM format has never been officialy standarized. It\u0027s"},{"line_number":34,"context_line":"basic format is a follows:"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"1) A header consisting of 5 hyphens followed by the word BEGIN and a"},{"line_number":37,"context_line":"single space. Then an upper case string describing the contents of the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FILY%3D","line":34,"updated":"2013-10-03 20:59:45.000000000","message":"as follows","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":31,"context_line":"implementations have adopted it."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"Unfortunately PEM format has never been officialy standarized. It\u0027s"},{"line_number":34,"context_line":"basic format is a follows:"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"1) A header consisting of 5 hyphens followed by the word BEGIN and a"},{"line_number":37,"context_line":"single space. Then an upper case string describing the contents of the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLNc%3D","line":34,"in_reply_to":"AAAAS3%2F%2FILY%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":80,"context_line":"endings. This makes PEM format particularity attractive for transport"},{"line_number":81,"context_line":"and storage of binary data."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"This module provides a number of utiliies supporting the generation"},{"line_number":84,"context_line":"and consumption of PEM formatted data including:"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    * parse text and find all PEM blocks contained in the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIKk%3D","line":83,"updated":"2013-10-03 20:59:45.000000000","message":"utilities","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":80,"context_line":"endings. This makes PEM format particularity attractive for transport"},{"line_number":81,"context_line":"and storage of binary data."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"This module provides a number of utiliies supporting the generation"},{"line_number":84,"context_line":"and consumption of PEM formatted data including:"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    * parse text and find all PEM blocks contained in the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLNY%3D","line":83,"in_reply_to":"AAAAS3%2F%2FIKk%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":123,"context_line":""},{"line_number":124,"context_line":"# This is not a 1-to-1 reverse map of pem_type_to_header"},{"line_number":125,"context_line":"# because it includes deprecated headers that map to 1 pem_type."},{"line_number":126,"context_line":"pem_header_to_type \u003d {"},{"line_number":127,"context_line":"    \u0027CMS\u0027: \u0027cms\u0027,"},{"line_number":128,"context_line":"    \u0027DSA PRIVATE KEY\u0027: \u0027dsa-private\u0027,"},{"line_number":129,"context_line":"    \u0027DSA PUBLIC KEY\u0027: \u0027dsa-public\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdG8%3D","line":126,"updated":"2013-10-15 23:08:45.000000000","message":"See my other comment about constants.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":123,"context_line":""},{"line_number":124,"context_line":"# This is not a 1-to-1 reverse map of pem_type_to_header"},{"line_number":125,"context_line":"# because it includes deprecated headers that map to 1 pem_type."},{"line_number":126,"context_line":"pem_header_to_type \u003d {"},{"line_number":127,"context_line":"    \u0027CMS\u0027: \u0027cms\u0027,"},{"line_number":128,"context_line":"    \u0027DSA PRIVATE KEY\u0027: \u0027dsa-private\u0027,"},{"line_number":129,"context_line":"    \u0027DSA PUBLIC KEY\u0027: \u0027dsa-public\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLNQ%3D","line":126,"in_reply_to":"AAAATH%2F%2FdG8%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":158,"context_line":"#------------------------------------------------------------------------------"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"class PEMParseResult(object):"},{"line_number":162,"context_line":"    \u0027\u0027\u0027Information returned when a PEM block is found in text"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"    PEMParseResult contains information about a PEM block discovered"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIKA%3D","line":161,"updated":"2013-10-03 20:59:45.000000000","message":"(NIT): In the interest of object oriented naming, this might make sense to be named \u0027PEMParser\u0027","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":158,"context_line":"#------------------------------------------------------------------------------"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"class PEMParseResult(object):"},{"line_number":162,"context_line":"    \u0027\u0027\u0027Information returned when a PEM block is found in text"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"    PEMParseResult contains information about a PEM block discovered"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLM8%3D","line":161,"in_reply_to":"AAAAS3%2F%2FIKA%3D","updated":"2013-10-25 16:17:19.000000000","message":"But it\u0027s not a class implementing parsing, rather it\u0027s a result object","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"61f033bb815208b2410814a15c1f84638d74fbbf","unresolved":false,"context_lines":[{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    \u0027\u0027\u0027"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    def __init__(self, pem_type\u003dNone, pem_header\u003dNone,"},{"line_number":197,"context_line":"                 pem_start\u003dNone, pem_end\u003dNone,"},{"line_number":198,"context_line":"                 base64_start\u003dNone, base64_end\u003dNone,"},{"line_number":199,"context_line":"                 binary_data\u003dNone):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FF4k%3D","line":196,"updated":"2013-10-04 15:32:41.000000000","message":"Is everything really optional here?  It seems like all of the property code in this class is just compensating for a lack of required types.  I\u0027d rather see a couple of class methods like from_pem_type and from_pem_header to create instances of this class.  As is there are strange corner cases that can happen like providing unmatching type and header to the __init__.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":226,"context_line":"            pem_header \u003d pem_type_to_header.get(pem_type)"},{"line_number":227,"context_line":"            if pem_header is None:"},{"line_number":228,"context_line":"                raise ValueError(\"unknown pem_type \u0027%s\u0027, \""},{"line_number":229,"context_line":"                                 \"valid types are: %s\" %"},{"line_number":230,"context_line":"                                 (pem_type, \u0027, \u0027.join(pem_types)))"},{"line_number":231,"context_line":"            self._pem_type \u003d pem_type"},{"line_number":232,"context_line":"            self._pem_header \u003d pem_header"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIJY%3D","line":229,"updated":"2013-10-03 20:59:45.000000000","message":"(NIT): allow \"unknown .... and \"valid.. to be at the same indentation levels even though they are on different lines. This helps readability.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":226,"context_line":"            pem_header \u003d pem_type_to_header.get(pem_type)"},{"line_number":227,"context_line":"            if pem_header is None:"},{"line_number":228,"context_line":"                raise ValueError(\"unknown pem_type \u0027%s\u0027, \""},{"line_number":229,"context_line":"                                 \"valid types are: %s\" %"},{"line_number":230,"context_line":"                                 (pem_type, \u0027, \u0027.join(pem_types)))"},{"line_number":231,"context_line":"            self._pem_type \u003d pem_type"},{"line_number":232,"context_line":"            self._pem_header \u003d pem_header"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdLg%3D","line":229,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":226,"context_line":"            pem_header \u003d pem_type_to_header.get(pem_type)"},{"line_number":227,"context_line":"            if pem_header is None:"},{"line_number":228,"context_line":"                raise ValueError(\"unknown pem_type \u0027%s\u0027, \""},{"line_number":229,"context_line":"                                 \"valid types are: %s\" %"},{"line_number":230,"context_line":"                                 (pem_type, \u0027, \u0027.join(pem_types)))"},{"line_number":231,"context_line":"            self._pem_type \u003d pem_type"},{"line_number":232,"context_line":"            self._pem_header \u003d pem_header"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLMs%3D","line":229,"in_reply_to":"AAAAS3%2F%2FIJY%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":226,"context_line":"            pem_header \u003d pem_type_to_header.get(pem_type)"},{"line_number":227,"context_line":"            if pem_header is None:"},{"line_number":228,"context_line":"                raise ValueError(\"unknown pem_type \u0027%s\u0027, \""},{"line_number":229,"context_line":"                                 \"valid types are: %s\" %"},{"line_number":230,"context_line":"                                 (pem_type, \u0027, \u0027.join(pem_types)))"},{"line_number":231,"context_line":"            self._pem_type \u003d pem_type"},{"line_number":232,"context_line":"            self._pem_header \u003d pem_header"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLMo%3D","line":229,"in_reply_to":"AAAATH%2F%2FdLg%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":244,"context_line":"            pem_type \u003d pem_header_to_type.get(pem_header)"},{"line_number":245,"context_line":"            if pem_type is None:"},{"line_number":246,"context_line":"                raise ValueError(\"unknown pem header \u0027%s\u0027, \""},{"line_number":247,"context_line":"                                 \"valid headers are: %s\" %"},{"line_number":248,"context_line":"                                 (pem_header,"},{"line_number":249,"context_line":"                                  \u0027, \u0027.join(\"\u0027%s\u0027\" % x for x in pem_headers)))"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIJM%3D","line":247,"updated":"2013-10-03 20:59:45.000000000","message":"Same comment here as above.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":244,"context_line":"            pem_type \u003d pem_header_to_type.get(pem_header)"},{"line_number":245,"context_line":"            if pem_type is None:"},{"line_number":246,"context_line":"                raise ValueError(\"unknown pem header \u0027%s\u0027, \""},{"line_number":247,"context_line":"                                 \"valid headers are: %s\" %"},{"line_number":248,"context_line":"                                 (pem_header,"},{"line_number":249,"context_line":"                                  \u0027, \u0027.join(\"\u0027%s\u0027\" % x for x in pem_headers)))"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdLc%3D","line":247,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":244,"context_line":"            pem_type \u003d pem_header_to_type.get(pem_header)"},{"line_number":245,"context_line":"            if pem_type is None:"},{"line_number":246,"context_line":"                raise ValueError(\"unknown pem header \u0027%s\u0027, \""},{"line_number":247,"context_line":"                                 \"valid headers are: %s\" %"},{"line_number":248,"context_line":"                                 (pem_header,"},{"line_number":249,"context_line":"                                  \u0027, \u0027.join(\"\u0027%s\u0027\" % x for x in pem_headers)))"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLMk%3D","line":247,"in_reply_to":"AAAAS3%2F%2FIJM%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":244,"context_line":"            pem_type \u003d pem_header_to_type.get(pem_header)"},{"line_number":245,"context_line":"            if pem_type is None:"},{"line_number":246,"context_line":"                raise ValueError(\"unknown pem header \u0027%s\u0027, \""},{"line_number":247,"context_line":"                                 \"valid headers are: %s\" %"},{"line_number":248,"context_line":"                                 (pem_header,"},{"line_number":249,"context_line":"                                  \u0027, \u0027.join(\"\u0027%s\u0027\" % x for x in pem_headers)))"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLMg%3D","line":247,"in_reply_to":"AAAATH%2F%2FdLc%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"def pem_search(text, start\u003d0):"},{"line_number":258,"context_line":"    \u0027\u0027\u0027Search for a block of PEM formatted data"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"    Search for a PEM block in a text string. The search begins at"},{"line_number":261,"context_line":"    start. If a PEM block is found a PEMParseResult object is"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIIs%3D","line":258,"updated":"2013-10-03 20:59:45.000000000","message":"Follow docstring convention specified in keystone/HACKING.rst\n\n\nhttps://github.com/openstack/keystone/blob/master/HACKING.rst#docstrings\n\n\nmainly \"\"\" instead of \u0027\u0027\u0027\n\nThis applies to all instances in this module","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"def pem_search(text, start\u003d0):"},{"line_number":258,"context_line":"    \u0027\u0027\u0027Search for a block of PEM formatted data"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"    Search for a PEM block in a text string. The search begins at"},{"line_number":261,"context_line":"    start. If a PEM block is found a PEMParseResult object is"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLMc%3D","line":258,"in_reply_to":"AAAAS3%2F%2FIIs%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":295,"context_line":"            base64_end \u003d match.start()"},{"line_number":296,"context_line":"            end_pem_header \u003d match.group(1).strip()"},{"line_number":297,"context_line":"        else:"},{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIIg%3D","line":298,"updated":"2013-10-03 20:59:45.000000000","message":"Use common logging solution (keystone/openstack/common/log.py)","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":295,"context_line":"            base64_end \u003d match.start()"},{"line_number":296,"context_line":"            end_pem_header \u003d match.group(1).strip()"},{"line_number":297,"context_line":"        else:"},{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdHk%3D","line":298,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":295,"context_line":"            base64_end \u003d match.start()"},{"line_number":296,"context_line":"            end_pem_header \u003d match.group(1).strip()"},{"line_number":297,"context_line":"        else:"},{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLME%3D","line":298,"in_reply_to":"AAAAS3%2F%2FIIg%3D","updated":"2013-10-25 16:17:19.000000000","message":"You don\u0027t log where the exception is raised you log where it\u0027s caught. Plus this module is meant for Oslo common code, we don\u0027t want anything Keystone specific in it.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":295,"context_line":"            base64_end \u003d match.start()"},{"line_number":296,"context_line":"            end_pem_header \u003d match.group(1).strip()"},{"line_number":297,"context_line":"        else:"},{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLMA%3D","line":298,"in_reply_to":"AAAATH%2F%2FdHk%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""},{"line_number":302,"context_line":"                             \"(%s !\u003d %s)\","},{"line_number":303,"context_line":"                             begin_pem_header, end_pem_header)"},{"line_number":304,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIIc%3D","line":301,"updated":"2013-10-03 20:59:45.000000000","message":"Use common logging.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""},{"line_number":302,"context_line":"                             \"(%s !\u003d %s)\","},{"line_number":303,"context_line":"                             begin_pem_header, end_pem_header)"},{"line_number":304,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdHo%3D","line":301,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""},{"line_number":302,"context_line":"                             \"(%s !\u003d %s)\","},{"line_number":303,"context_line":"                             begin_pem_header, end_pem_header)"},{"line_number":304,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLL8%3D","line":301,"in_reply_to":"AAAAS3%2F%2FIIc%3D","updated":"2013-10-25 16:17:19.000000000","message":"see above","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":298,"context_line":"            raise ValueError(\"failed to find end matching \u0027%s\u0027\" % begin_text)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        if begin_pem_header !\u003d end_pem_header:"},{"line_number":301,"context_line":"            raise ValueError(\"beginning \u0026 end PEM headers do not match \""},{"line_number":302,"context_line":"                             \"(%s !\u003d %s)\","},{"line_number":303,"context_line":"                             begin_pem_header, end_pem_header)"},{"line_number":304,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLL4%3D","line":301,"in_reply_to":"AAAATH%2F%2FdHo%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":342,"context_line":"        except IndexError:"},{"line_number":343,"context_line":"            raise ValueError(\u0027no cert found\u0027)"},{"line_number":344,"context_line":""},{"line_number":345,"context_line":"    :param string text: The text to search for PEM blocks"},{"line_number":346,"context_line":"    :param string pem_type: Only return data for this pem_type."},{"line_number":347,"context_line":"                            Valid types are: csr, cert, crl, cms, key."},{"line_number":348,"context_line":"                            If pem_type is None no filtering is performed."}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIH4%3D","line":345,"updated":"2013-10-03 20:59:45.000000000","message":"probably don\u0027t need to explicitly say \u0027string\u0027 in the docstring, example given in: \n\nhttps://github.com/openstack/keystone/blob/master/HACKING.rst#docstrings\n\nThis applies for all occurrences in this module.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":342,"context_line":"        except IndexError:"},{"line_number":343,"context_line":"            raise ValueError(\u0027no cert found\u0027)"},{"line_number":344,"context_line":""},{"line_number":345,"context_line":"    :param string text: The text to search for PEM blocks"},{"line_number":346,"context_line":"    :param string pem_type: Only return data for this pem_type."},{"line_number":347,"context_line":"                            Valid types are: csr, cert, crl, cms, key."},{"line_number":348,"context_line":"                            If pem_type is None no filtering is performed."}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLLw%3D","line":345,"in_reply_to":"AAAAS3%2F%2FIH4%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":365,"context_line":"                if b.pem_type \u003d\u003d pem_type:"},{"line_number":366,"context_line":"                    pem_blocks.append(b)"},{"line_number":367,"context_line":"            except KeyError:"},{"line_number":368,"context_line":"                raise ValueError(\u0027unknown pem_type: %s\u0027 % (pem_type))"},{"line_number":369,"context_line":""},{"line_number":370,"context_line":"        if max_items is not None and len(pem_blocks) \u003e\u003d max_items:"},{"line_number":371,"context_line":"            break"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdHg%3D","line":368,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":365,"context_line":"                if b.pem_type \u003d\u003d pem_type:"},{"line_number":366,"context_line":"                    pem_blocks.append(b)"},{"line_number":367,"context_line":"            except KeyError:"},{"line_number":368,"context_line":"                raise ValueError(\u0027unknown pem_type: %s\u0027 % (pem_type))"},{"line_number":369,"context_line":""},{"line_number":370,"context_line":"        if max_items is not None and len(pem_blocks) \u003e\u003d max_items:"},{"line_number":371,"context_line":"            break"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLLo%3D","line":368,"in_reply_to":"AAAATH%2F%2FdHg%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":370,"context_line":"        if max_items is not None and len(pem_blocks) \u003e\u003d max_items:"},{"line_number":371,"context_line":"            break"},{"line_number":372,"context_line":""},{"line_number":373,"context_line":"    for b in pem_blocks:"},{"line_number":374,"context_line":"        base64_data \u003d text[b.base64_start:b.base64_end]"},{"line_number":375,"context_line":"        try:"},{"line_number":376,"context_line":"            binary_data \u003d base64.b64decode(base64_data)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIHo%3D","line":373,"updated":"2013-10-03 20:59:45.000000000","message":"(NIT): suggest renaming variable \u0027b\u0027 to \u0027block\u0027. helps readability.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":370,"context_line":"        if max_items is not None and len(pem_blocks) \u003e\u003d max_items:"},{"line_number":371,"context_line":"            break"},{"line_number":372,"context_line":""},{"line_number":373,"context_line":"    for b in pem_blocks:"},{"line_number":374,"context_line":"        base64_data \u003d text[b.base64_start:b.base64_end]"},{"line_number":375,"context_line":"        try:"},{"line_number":376,"context_line":"            binary_data \u003d base64.b64decode(base64_data)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLLU%3D","line":373,"in_reply_to":"AAAAS3%2F%2FIHo%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"56d3f6c2885684baaa291047a8f7fb2ccc94c932","unresolved":false,"context_lines":[{"line_number":377,"context_line":"        except Exception as e:"},{"line_number":378,"context_line":"            b.binary_data \u003d None"},{"line_number":379,"context_line":"            raise base64_utils.InvalidBase64Error("},{"line_number":380,"context_line":"                \"failed to base64 decode %s PEM at position %d: %s\" %"},{"line_number":381,"context_line":"                (b.pem_type, b.pem_start, e))"},{"line_number":382,"context_line":"        else:"},{"line_number":383,"context_line":"            b.binary_data \u003d binary_data"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FdHc%3D","line":380,"updated":"2013-10-15 23:08:45.000000000","message":"Wrap strings in _() for localization.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":377,"context_line":"        except Exception as e:"},{"line_number":378,"context_line":"            b.binary_data \u003d None"},{"line_number":379,"context_line":"            raise base64_utils.InvalidBase64Error("},{"line_number":380,"context_line":"                \"failed to base64 decode %s PEM at position %d: %s\" %"},{"line_number":381,"context_line":"                (b.pem_type, b.pem_start, e))"},{"line_number":382,"context_line":"        else:"},{"line_number":383,"context_line":"            b.binary_data \u003d binary_data"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLLI%3D","line":380,"in_reply_to":"AAAATH%2F%2FdHc%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"}],"keystone/common/pemutils.py":[{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        self._pem_header \u003d None"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"        if pem_type is not None:"},{"line_number":199,"context_line":"            self.pem_type \u003d pem_type"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"        if pem_header is not None:"},{"line_number":202,"context_line":"            self.pem_header \u003d pem_header"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdnw%3D","line":199,"updated":"2013-11-05 14:52:32.000000000","message":"I think this should be self._pem_type, also the test and initial assignment is pointless, just do:\n\nself._pem_type \u003d pem_type\n\nOr you could get rid of all the getter/setter bloat and just access pem_type directly and use a property for the header lookup, as suggested below","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        self._pem_header \u003d None"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"        if pem_type is not None:"},{"line_number":199,"context_line":"            self.pem_type \u003d pem_type"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"        if pem_header is not None:"},{"line_number":202,"context_line":"            self.pem_header \u003d pem_header"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2FafM%3D","line":199,"in_reply_to":"AAAATn%2F%2Fdnw%3D","updated":"2013-11-07 00:28:17.000000000","message":"The tests for None prior to assignment are necessary for the constructor to function correctly, otherwise one of the properties can be left in an inconsistent state with the value None. This can easily be seen by removing the conditional and running the unit test.\n\nThe reason why there are two properties is because there isn\u0027t a 1 to 1 relationship between the pem type and the pem header. Historically several headers have been used and which are now deprecated and map onto other pem types. The pem type is the canonical information. Given a heading one needs to know what the type is. If you\u0027re producing standardized pem files you should format according to the canonical pem type. If you drop the information about the original parsed heading you lose the information about what appeared in the original pem block (for instance you may want to issue a deprecation warning). Thus both the type and heading are related and need to be maintained, if you change one you must change the other or you\u0027\u0027ll get an inconsistent representation.\n\nIt could be slightly simplified if setting the type was prohibited. In practice it\u0027s unlikely one would need to set the type during parsing. The type and header both have a setter and getter, that\u0027s 4 methods. If one removes the type setter it reduces the code from 4 methods to 3 methods with a corresponding loss of symmetric generality, I\u0027m not seeing the huge win in that.\n\nA good question to ask is why the parse result isn\u0027t just a named tuple. The reason why it\u0027s own class as opposed to a named tuple is there has to be logic for mapping between the header and the type, if this wasn\u0027t it\u0027s own class then that logic would have to factored out into utility functions and independently applied. It\u0027s better to have this logic encapsulated in a class where setting an attribute automatically updates matching properties and no additional logic needs to be invoked.\n\nFWIW the list of pem headers in the module is only a subset of possible headers (the ones in common use outside of OpenSSL). If it\u0027s ever necessary to augment the set of headers (not necessarily the types) it\u0027s really best to have this encapsulated in one place. That\u0027s the reason why it\u0027s done the way it is.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"c6056f36492faa2c2149705a6c654aa1c256579e","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    @property"},{"line_number":230,"context_line":"    def pem_header(self):"},{"line_number":231,"context_line":"        return self._pem_header"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    @pem_header.setter"},{"line_number":234,"context_line":"    def pem_header(self, pem_header):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2Fdnc%3D","line":231,"updated":"2013-11-05 14:52:32.000000000","message":"Why not get rid of all the bloat here, and just return PEM_TYPE_TO_HEADER.get(self.pem_type), and not bother with the property/setter stuff at all, it\u0027s only a dict lookup so personally I see no need for the additional code here","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"03c7467d74d0242e3eb65ca24d3e557f6c5114a7","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    @property"},{"line_number":230,"context_line":"    def pem_header(self):"},{"line_number":231,"context_line":"        return self._pem_header"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    @pem_header.setter"},{"line_number":234,"context_line":"    def pem_header(self, pem_header):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2FafI%3D","line":231,"in_reply_to":"AAAATn%2F%2Fdnc%3D","updated":"2013-11-07 00:28:17.000000000","message":"see my comments above.","commit_id":"09e87618400333c7fd3abc0a80af0801f8d794a6"}],"keystone/tests/test_base64_utils.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone.common import base64_utils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import unittest"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"base64_alphabet \u003d (\u0027ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0027"},{"line_number":22,"context_line":"                   \u0027abcdefghijklmnopqrstuvwxyz\u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIG4%3D","line":19,"updated":"2013-10-03 20:59:45.000000000","message":"I think we have unittest in keystone already","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"61f033bb815208b2410814a15c1f84638d74fbbf","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone.common import base64_utils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import unittest"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"base64_alphabet \u003d (\u0027ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0027"},{"line_number":22,"context_line":"                   \u0027abcdefghijklmnopqrstuvwxyz\u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FF1c%3D","line":19,"updated":"2013-10-04 15:32:41.000000000","message":"I think you want to use keystone.test.TestCase instead of unittest.TestCase.  This applies to all test cases below.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone.common import base64_utils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import unittest"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"base64_alphabet \u003d (\u0027ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0027"},{"line_number":22,"context_line":"                   \u0027abcdefghijklmnopqrstuvwxyz\u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLKo%3D","line":19,"in_reply_to":"AAAAS3%2F%2FIG4%3D","updated":"2013-10-25 16:17:19.000000000","message":"I\u0027m trying not to make this Keystone specific so it can eventually be moved to Oslo","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":29,"context_line":"                      \u0027-_\u003d\u0027)    # includes pad char"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class TestValid(unittest.TestCase):"},{"line_number":33,"context_line":"    def test_is_valid(self):"},{"line_number":34,"context_line":"        self.assertRaises(ValueError,"},{"line_number":35,"context_line":"                          base64_utils.is_valid_base64, \u0027ABCD\u0027, \u0027xxx\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIG8%3D","line":32,"updated":"2013-10-03 20:59:45.000000000","message":"Can we make the test case name a little more descriptive? Here we are testing base64_utils.is_valid_base64 so why not dedicate this test case to that?","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":29,"context_line":"                      \u0027-_\u003d\u0027)    # includes pad char"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class TestValid(unittest.TestCase):"},{"line_number":33,"context_line":"    def test_is_valid(self):"},{"line_number":34,"context_line":"        self.assertRaises(ValueError,"},{"line_number":35,"context_line":"                          base64_utils.is_valid_base64, \u0027ABCD\u0027, \u0027xxx\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLKE%3D","line":32,"in_reply_to":"AAAAS3%2F%2FIG8%3D","updated":"2013-10-25 16:17:19.000000000","message":"renamed to test_valid_base64","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class TestValid(unittest.TestCase):"},{"line_number":33,"context_line":"    def test_is_valid(self):"},{"line_number":34,"context_line":"        self.assertRaises(ValueError,"},{"line_number":35,"context_line":"                          base64_utils.is_valid_base64, \u0027ABCD\u0027, \u0027xxx\u0027)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"        self.assertTrue(base64_utils.is_valid_base64(\u0027+/\u003d\u003d\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIFU%3D","line":34,"updated":"2013-10-03 20:59:45.000000000","message":"This assert kind of goes against the grain of this test. By the naming \u0027test_is_valid\u0027 we assume the positive path of the test, and the first assert checks to make sure a negative path is caught. Maybe we should have a second unit test to explicitly check the bad path cases. \n\ndef test_base64_utils_is_valid(self): \n    .... \n\n\ndef test_base64_utils_not_valid(self): \n    ..... \n\n\nor something along those lines.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class TestValid(unittest.TestCase):"},{"line_number":33,"context_line":"    def test_is_valid(self):"},{"line_number":34,"context_line":"        self.assertRaises(ValueError,"},{"line_number":35,"context_line":"                          base64_utils.is_valid_base64, \u0027ABCD\u0027, \u0027xxx\u0027)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"        self.assertTrue(base64_utils.is_valid_base64(\u0027+/\u003d\u003d\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLKI%3D","line":34,"in_reply_to":"AAAAS3%2F%2FIFU%3D","updated":"2013-10-25 16:17:19.000000000","message":"renamed to test_valid_base64","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"}],"keystone/tests/test_base64utils.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"64d387ac222d0e65b70c3218a4260a71c6ad7486","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        self.assertTrue(base64utils.is_valid_base64(\u0027abcdef\u003d\u003d\u0027))"},{"line_number":46,"context_line":"        self.assertFalse(base64utils.is_valid_base64(\u0027abcdefg\u0027))"},{"line_number":47,"context_line":"        self.assertTrue(base64utils.is_valid_base64(\u0027abcdefg\u003d\u0027))"},{"line_number":48,"context_line":"        self.assertTrue(base64utils.is_valid_base64(\u0027abcdefgh\u0027))"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"        self.assertFalse(base64utils.is_valid_base64(\u0027-_\u003d\u003d\u0027))"},{"line_number":51,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BD1Y%3D","line":48,"updated":"2013-12-03 19:01:23.000000000","message":"Suggest adding a non hex-string for testing, but not insanely important.","commit_id":"6ba5e3683bc597b24a9447bf1f52ada5be3ec921"}],"keystone/tests/test_pem_utils.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"61f033bb815208b2410814a15c1f84638d74fbbf","unresolved":false,"context_lines":[{"line_number":15,"context_line":"#    under the License."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import base64"},{"line_number":18,"context_line":"import unittest"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from keystone.common import pem_utils"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FF1A%3D","line":18,"updated":"2013-10-04 15:32:41.000000000","message":"keystone.tests.TestCase instead of unittest.TestCase as I mentioned in the other test module.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":15,"context_line":"#    under the License."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import base64"},{"line_number":18,"context_line":"import unittest"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from keystone.common import pem_utils"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLJ8%3D","line":18,"in_reply_to":"AAAAS3%2F%2FF1A%3D","updated":"2013-10-25 16:17:19.000000000","message":"Trying not to make this Keystone specific so it can be moved to Oslo","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91957d3159b932d2d9fc6841f13fcf4799b15726","unresolved":false,"context_lines":[{"line_number":15,"context_line":"#    under the License."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import base64"},{"line_number":18,"context_line":"import unittest"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from keystone.common import pem_utils"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2F41U%3D","line":18,"in_reply_to":"AAAATH%2F%2FLJ8%3D","updated":"2013-10-25 17:02:25.000000000","message":"(preference, no need to change) I would make this keystone specific, since it is keystone specific, and when you move it to OSLO make the minor changes to make it non-keystone specific.  We will need to import from a different location once it\u0027s in oslo in either case.","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9daab3b59255daffdd6a3f513e71c8c061e4ff41","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"class PEM(object):"},{"line_number":53,"context_line":"    \u0027\u0027\u0027PEM text and it\u0027s associated data broken out, used for testing"},{"line_number":54,"context_line":"    \u0027\u0027\u0027"},{"line_number":55,"context_line":"    def __init__(self, pem_header\u003d\u0027CERTIFICATE\u0027, pem_type\u003d\u0027cert\u0027,"},{"line_number":56,"context_line":"                 data_size\u003d70, data_offset\u003d0):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAS3%2F%2FIHQ%3D","line":53,"updated":"2013-10-03 20:59:45.000000000","message":"Follow docstring conventions defined in keystone/HACKING.rst","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"},{"author":{"_account_id":8116,"name":"John Dennis","email":"jdennis@redhat.com","username":"jdennis"},"change_message_id":"154659998f70fbc517013863df3f54fe21c0731e","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"class PEM(object):"},{"line_number":53,"context_line":"    \u0027\u0027\u0027PEM text and it\u0027s associated data broken out, used for testing"},{"line_number":54,"context_line":"    \u0027\u0027\u0027"},{"line_number":55,"context_line":"    def __init__(self, pem_header\u003d\u0027CERTIFICATE\u0027, pem_type\u003d\u0027cert\u0027,"},{"line_number":56,"context_line":"                 data_size\u003d70, data_offset\u003d0):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATH%2F%2FLJ4%3D","line":53,"in_reply_to":"AAAAS3%2F%2FIHQ%3D","updated":"2013-10-25 16:17:19.000000000","message":"Done","commit_id":"917eb0665fa8e391fb58daf28438cab010d5a606"}]}
