)]}'
{".testr.conf":[{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"19f56a696ebd27244e39050873d4cbc10b87f4d8","unresolved":false,"context_lines":[{"line_number":7,"context_line":"test_id_option\u003d--load-list $IDFILE"},{"line_number":8,"context_line":"test_list_option\u003d--list"},{"line_number":9,"context_line":"# NOTE(cdent): Only used/matches on gabbi-related tests."},{"line_number":10,"context_line":"group_regex\u003d(gabbi\\.(?:driver|suitemaker)\\.test_placement_api_([^_]+))"}],"source_content_type":"text/plain","patch_set":47,"id":"dada55a8_41cc3f61","line":10,"updated":"2016-07-25 12:58:21.000000000","message":"We should probably describe how this changes the test run order / grouping. This is such an undocumented testr feature that it\u0027s not super clear.","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"c3993a814bd05d7316baa5cdbc961ab0db7f53a8","unresolved":false,"context_lines":[{"line_number":7,"context_line":"test_id_option\u003d--load-list $IDFILE"},{"line_number":8,"context_line":"test_list_option\u003d--list"},{"line_number":9,"context_line":"# NOTE(cdent): Only used/matches on gabbi-related tests."},{"line_number":10,"context_line":"group_regex\u003d(gabbi\\.(?:driver|suitemaker)\\.test_placement_api_([^_]+))"}],"source_content_type":"text/plain","patch_set":47,"id":"dada55a8_92b96731","line":10,"in_reply_to":"dada55a8_41cc3f61","updated":"2016-07-25 13:57:28.000000000","message":"Not sure I get why we need to explicitly remove the parallel testing for gabbi functional tests ? Is that due to a gabbi bug ? If so, please comment with a TODO mentioning to remove that once the bugfix is landed because that could be a performance impact for those running tests.\nhttp://testrepository.readthedocs.io/en/latest/MANUAL.html#grouping-tests","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"48815fcafd1807c6fa992f6cf075909d006eae1e","unresolved":false,"context_lines":[{"line_number":7,"context_line":"test_id_option\u003d--load-list $IDFILE"},{"line_number":8,"context_line":"test_list_option\u003d--list"},{"line_number":9,"context_line":"# NOTE(cdent): Only used/matches on gabbi-related tests."},{"line_number":10,"context_line":"group_regex\u003d(gabbi\\.(?:driver|suitemaker)\\.test_placement_api_([^_]+))"}],"source_content_type":"text/plain","patch_set":47,"id":"bacf61ea_3f1b4d74","line":10,"in_reply_to":"dada55a8_8d2665b8","updated":"2016-07-28 10:46:18.000000000","message":"Done","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"394d8764bab5c04042d9bff2e1b286efef852908","unresolved":false,"context_lines":[{"line_number":7,"context_line":"test_id_option\u003d--load-list $IDFILE"},{"line_number":8,"context_line":"test_list_option\u003d--list"},{"line_number":9,"context_line":"# NOTE(cdent): Only used/matches on gabbi-related tests."},{"line_number":10,"context_line":"group_regex\u003d(gabbi\\.(?:driver|suitemaker)\\.test_placement_api_([^_]+))"}],"source_content_type":"text/plain","patch_set":47,"id":"dada55a8_8d2665b8","line":10,"in_reply_to":"dada55a8_92b96731","updated":"2016-07-25 14:28:32.000000000","message":"I\u0027ll leave a longer comment on what\u0027s going on here.","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"}],"/COMMIT_MSG":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"fdcc3cc4842467fac95eb41511a1d172ca1033f0","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"* orchestrated by Paste to compose wsgi pipeline, but no routing"},{"line_number":18,"context_line":"  in paste"},{"line_number":19,"context_line":"* uses the Routes with declarative mapping defined in"},{"line_number":20,"context_line":"  ROUTE_DECLARATIONS"},{"line_number":21,"context_line":"* basic wsgi apps, with webob and the request class, for each handler"},{"line_number":22,"context_line":"  define as functions"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":23,"id":"1aa78d24_21f7dfd3","line":19,"updated":"2016-07-07 19:42:17.000000000","message":"s/Routes/Routes library?","commit_id":"87c79775b895490653610570a1b4422e23d451bb"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"0ef6f2180c7dc61c44a1d31eb7a46babff3f6c51","unresolved":false,"context_lines":[{"line_number":26,"context_line":"providers and their inventories."},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"In order to ensure that this change can be merged in an atomic"},{"line_number":29,"context_line":"fashion it includes microversion support that was previous in its"},{"line_number":30,"context_line":"own commit."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"The microversion_parse library is used in a WSGI middleware"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":25,"id":"1aa78d24_3799ddc4","line":29,"range":{"start_line":29,"start_character":50,"end_line":29,"end_character":58},"updated":"2016-07-07 20:26:24.000000000","message":"nit: previously","commit_id":"4951bb8b268a53a6ce85b7151c927a70ffde69b4"}],"etc/nova/api-paste.ini":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"055577de0f6e389483ad893d96e4fa2386098744","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"7aa08908_7bf468f0","updated":"2016-06-17 12:20:17.000000000","message":"It occurs to me that now this is running, it would be easy and beneficial to not use paste at all. We don\u0027t want to require config files at all.","commit_id":"994754294a037aedb9a90dcb0c2876ba0b79da0c"},{"author":{"_account_id":15648,"name":"Yingxin","email":"yingxin.cheng@intel.com","username":"Yingxin"},"change_message_id":"004467846a7ebfaf79fb624ec323e0bdbf1a9180","unresolved":false,"context_lines":[{"line_number":3,"context_line":"#############"},{"line_number":4,"context_line":"[composite:placement]"},{"line_number":5,"context_line":"use \u003d egg:Paste#urlmap"},{"line_number":6,"context_line":"/: placement_pipe"},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"[pipeline:placement_pipe]"},{"line_number":9,"context_line":"pipeline \u003d cors compute_req_id placement_api"}],"source_content_type":"text/x-properties","patch_set":15,"id":"1aa78d24_7cc16e80","line":6,"updated":"2016-07-04 02:16:33.000000000","message":"Maybe what you want is to add the home app to \"/\" without any auth filters, and move the placement_pipe(that requires authentication) to \"/v1\".","commit_id":"1550437bcda4a86c45d4e850dbf81e44907f4892"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"5fb927eb674d51cdc93e39ffea79ee3be316a29b","unresolved":false,"context_lines":[{"line_number":3,"context_line":"#############"},{"line_number":4,"context_line":"[composite:placement]"},{"line_number":5,"context_line":"use \u003d egg:Paste#urlmap"},{"line_number":6,"context_line":"/: placement_pipe"},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"[pipeline:placement_pipe]"},{"line_number":9,"context_line":"pipeline \u003d cors compute_req_id placement_api"}],"source_content_type":"text/x-properties","patch_set":15,"id":"1aa78d24_60308557","line":6,"in_reply_to":"1aa78d24_7cc16e80","updated":"2016-07-04 15:31:29.000000000","message":"In discussions in IRC we decided we didn\u0027t want any paths (except for the root of the single application) in paste.ini. Earlier in the changes I did have two different paths we decided that was incorrect.\n\nWith regard to /v1 we\u0027ve also decided that there shouldn\u0027t be any version indicators in the URL. Since we are using microversions from the start we can just use them as the indicators of the version and have more reasonable URLs.","commit_id":"1550437bcda4a86c45d4e850dbf81e44907f4892"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"91fb7d10866accf3405f923662440718455810e3","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"[composite:placement_api]"},{"line_number":12,"context_line":"use \u003d call:nova.api.auth:pipeline_factory_v21"},{"line_number":13,"context_line":"noauth2 \u003d noauth2 placement_app"},{"line_number":14,"context_line":"keystone \u003d authtoken keystonecontext placement_app"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"[app:placement_app]"}],"source_content_type":"text/x-properties","patch_set":42,"id":"dada55a8_6f13130e","line":13,"updated":"2016-07-19 20:49:42.000000000","message":"maybe add a todo to remove noauth2 if we can use a fixture for tests.","commit_id":"adc8e497266702d6facc178c5c59483e68561385"}],"nova/api/openstack/placement/auth.py":[{"author":{"_account_id":7166,"name":"Sylvain Bauza","email":"sbauza@redhat.com","username":"sbauza"},"change_message_id":"c3993a814bd05d7316baa5cdbc961ab0db7f53a8","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        return self.application"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"# NOTE(cdent): This is duplicated from nova.api.auth, for the sake"},{"line_number":66,"context_line":"# of easing later extraction, modified to use oslo.context and"},{"line_number":67,"context_line":"# remove unused behaviors."},{"line_number":68,"context_line":"class PlacementKeystoneContext(Middleware):"},{"line_number":69,"context_line":"    \"\"\"Make a request context from keystone headers.\"\"\""}],"source_content_type":"text/x-python","patch_set":47,"id":"dada55a8_d2d2bf33","line":66,"range":{"start_line":65,"start_character":54,"end_line":66,"end_character":29},"updated":"2016-07-25 13:57:28.000000000","message":"not sure we basically need that in the NOTE, but fair enough. I think we all know why you\u0027re not inheriting or reusing some portions of the API code already :-)","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"48815fcafd1807c6fa992f6cf075909d006eae1e","unresolved":false,"context_lines":[{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"# NOTE(cdent): This is duplicated from nova.api.auth, for the sake"},{"line_number":66,"context_line":"# of easing later extraction, modified to use oslo.context and"},{"line_number":67,"context_line":"# remove unused behaviors."},{"line_number":68,"context_line":"class PlacementKeystoneContext(Middleware):"},{"line_number":69,"context_line":"    \"\"\"Make a request context from keystone headers.\"\"\""}],"source_content_type":"text/x-python","patch_set":47,"id":"bacf61ea_9f26b9b8","line":66,"in_reply_to":"dada55a8_d2d2bf33","updated":"2016-07-28 10:46:18.000000000","message":"Done","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"19f56a696ebd27244e39050873d4cbc10b87f4d8","unresolved":false,"context_lines":[{"line_number":65,"context_line":"# NOTE(cdent): This is duplicated from nova.api.auth, for the sake"},{"line_number":66,"context_line":"# of easing later extraction, modified to use oslo.context and"},{"line_number":67,"context_line":"# remove unused behaviors."},{"line_number":68,"context_line":"class PlacementKeystoneContext(Middleware):"},{"line_number":69,"context_line":"    \"\"\"Make a request context from keystone headers.\"\"\""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    @webob.dec.wsgify"}],"source_content_type":"text/x-python","patch_set":47,"id":"dada55a8_0138873c","line":68,"updated":"2016-07-25 12:58:21.000000000","message":"once the from_environ patch lands we should tweak this to match it - https://review.openstack.org/#/c/341896/2/nova/api/auth.py","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"48815fcafd1807c6fa992f6cf075909d006eae1e","unresolved":false,"context_lines":[{"line_number":65,"context_line":"# NOTE(cdent): This is duplicated from nova.api.auth, for the sake"},{"line_number":66,"context_line":"# of easing later extraction, modified to use oslo.context and"},{"line_number":67,"context_line":"# remove unused behaviors."},{"line_number":68,"context_line":"class PlacementKeystoneContext(Middleware):"},{"line_number":69,"context_line":"    \"\"\"Make a request context from keystone headers.\"\"\""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    @webob.dec.wsgify"}],"source_content_type":"text/x-python","patch_set":47,"id":"bacf61ea_7f2b0583","line":68,"in_reply_to":"dada55a8_0138873c","updated":"2016-07-28 10:46:18.000000000","message":"Done","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"}],"nova/api/openstack/placement/handler.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"fdcc3cc4842467fac95eb41511a1d172ca1033f0","unresolved":false,"context_lines":[{"line_number":33,"context_line":"# URLs and Handlers"},{"line_number":34,"context_line":"ROUTE_DECLARATIONS \u003d {"},{"line_number":35,"context_line":"    \u0027/\u0027: {"},{"line_number":36,"context_line":"        \u0027GET\u0027: root.home,"},{"line_number":37,"context_line":"    },"},{"line_number":38,"context_line":"}"},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"1aa78d24_810213b2","line":36,"updated":"2016-07-07 19:42:17.000000000","message":"\\o/ so, so nice to be able to see the entire url route map in a *single* place for the entire placement API. ++","commit_id":"87c79775b895490653610570a1b4422e23d451bb"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"d45044703adba50fc914ad171ecde41af3bd1b46","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        headers[\u0027allow\u0027] \u003d _methods"},{"line_number":67,"context_line":"    raise webob.exc.HTTPMethodNotAllowed("},{"line_number":68,"context_line":"        \u0027The method specified is not allowed for this resource.\u0027,"},{"line_number":69,"context_line":"        headers\u003dheaders, json_formatter\u003dutil.json_error_formatter)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"def make_map(declarations):"}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_83e98de8","line":69,"updated":"2016-07-13 11:38:08.000000000","message":"It would be convenient to see which methods are allowed.\nCould this function be in handlers directory?","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"70fb260d1be071ec90fdd82622f9f101db8e46c1","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        headers[\u0027allow\u0027] \u003d _methods"},{"line_number":67,"context_line":"    raise webob.exc.HTTPMethodNotAllowed("},{"line_number":68,"context_line":"        \u0027The method specified is not allowed for this resource.\u0027,"},{"line_number":69,"context_line":"        headers\u003dheaders, json_formatter\u003dutil.json_error_formatter)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"def make_map(declarations):"}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_614d34c4","line":69,"in_reply_to":"1aa78d24_716ce7d0","updated":"2016-07-14 14:05:40.000000000","message":"Ah, okay. That\u0027s already in the Allow: header, but having it in the body would be useful to, I\u0027ll change that.","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"978ef31a535d36c0baed7878acd1c51c81c74985","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        headers[\u0027allow\u0027] \u003d _methods"},{"line_number":67,"context_line":"    raise webob.exc.HTTPMethodNotAllowed("},{"line_number":68,"context_line":"        \u0027The method specified is not allowed for this resource.\u0027,"},{"line_number":69,"context_line":"        headers\u003dheaders, json_formatter\u003dutil.json_error_formatter)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"def make_map(declarations):"}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_c8644023","line":69,"in_reply_to":"1aa78d24_83e98de8","updated":"2016-07-13 16:05:08.000000000","message":"I don\u0027t think I understand what you\u0027re asking here?","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"2ac476c66f800babfe25a4589c3a716d89544335","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        headers[\u0027allow\u0027] \u003d _methods"},{"line_number":67,"context_line":"    raise webob.exc.HTTPMethodNotAllowed("},{"line_number":68,"context_line":"        \u0027The method specified is not allowed for this resource.\u0027,"},{"line_number":69,"context_line":"        headers\u003dheaders, json_formatter\u003dutil.json_error_formatter)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"def make_map(declarations):"}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_716ce7d0","line":69,"in_reply_to":"1aa78d24_c8644023","updated":"2016-07-14 12:28:24.000000000","message":"I mean http body can be like:\n\"The method specified is not allowed for this resource. Only POST, PUT are alowed.\".","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"391d7cc06c7a3951262eb41b0429c1d8cb0569bd","unresolved":false,"context_lines":[{"line_number":99,"context_line":"        # but using nova\u0027s is convenient for now."},{"line_number":100,"context_line":"        if environ[\u0027PATH_INFO\u0027] !\u003d \u0027/\u0027:"},{"line_number":101,"context_line":"            context \u003d environ[\u0027nova.context\u0027]"},{"line_number":102,"context_line":"            if not context.is_admin:"},{"line_number":103,"context_line":"                raise webob.exc.HTTPForbidden("},{"line_number":104,"context_line":"                    \u0027admin required\u0027,"},{"line_number":105,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_a1f2af6c","line":102,"updated":"2016-07-13 17:06:57.000000000","message":"This should not be a hardcoded check for admin it should use the policy framework instead. Requiring admin is a decent default though.\n\nBecause there\u0027s some setup work required in order to use a policy check here doing this is fine for now but I would prefer to have a TODO about moving to using a policy check.","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"84cc0d29031389c57e8208cdcb83cf8f4ed9f046","unresolved":false,"context_lines":[{"line_number":99,"context_line":"        # but using nova\u0027s is convenient for now."},{"line_number":100,"context_line":"        if environ[\u0027PATH_INFO\u0027] !\u003d \u0027/\u0027:"},{"line_number":101,"context_line":"            context \u003d environ[\u0027nova.context\u0027]"},{"line_number":102,"context_line":"            if not context.is_admin:"},{"line_number":103,"context_line":"                raise webob.exc.HTTPForbidden("},{"line_number":104,"context_line":"                    \u0027admin required\u0027,"},{"line_number":105,"context_line":"                    json_formatter\u003dutil.json_error_formatter)"}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_9f0703c9","line":102,"in_reply_to":"1aa78d24_a1f2af6c","updated":"2016-07-13 18:47:30.000000000","message":"✔","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"}],"nova/api/openstack/placement/handlers/root.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ab067f9d56c763b3c46234d54ad8a650e8e09edf","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"@webob.dec.wsgify"},{"line_number":18,"context_line":"def home(req):"},{"line_number":19,"context_line":"    req.response.body \u003d \u0027I should be some kind of json home thing\u0027"},{"line_number":20,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_02c50e5a","line":19,"updated":"2016-07-05 17:33:56.000000000","message":"...and fixed before we merge this, right?","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f27ac57d32dc2cf796e0d4a2fef8e1b5b50c264b","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"@webob.dec.wsgify"},{"line_number":18,"context_line":"def home(req):"},{"line_number":19,"context_line":"    req.response.body \u003d \u0027I should be some kind of json home thing\u0027"},{"line_number":20,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_4d83c756","line":19,"in_reply_to":"1aa78d24_02c50e5a","updated":"2016-07-05 17:48:58.000000000","message":"That\u0027s a question I have actually. The fix for it will be in the changeset above which provides microversion handling. Should I collapse that into this one?","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9f8cb7324b31d283965b23d2465e7b6079db26a5","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"@webob.dec.wsgify"},{"line_number":18,"context_line":"def home(req):"},{"line_number":19,"context_line":"    req.response.body \u003d \u0027I should be some kind of json home thing\u0027"},{"line_number":20,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_735ca2ed","line":19,"in_reply_to":"1aa78d24_4d83c756","updated":"2016-07-05 18:28:33.000000000","message":"Yeah, I meant to say also that I think this should be landing with microversion support from the get-go, even if it\u0027s somewhat simplified.","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"d9573c3ee7eba8b7ace8e08c30258cca22456c25","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    # added to this output to align with the guidelines at"},{"line_number":27,"context_line":"    # http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html#version-discovery"},{"line_number":28,"context_line":"    version_data \u003d {"},{"line_number":29,"context_line":"        \u0027id\u0027: \u0027v%s\u0027 % min_version,"},{"line_number":30,"context_line":"        \u0027max_version\u0027: max_version,"},{"line_number":31,"context_line":"        \u0027min_version\u0027: min_version,"},{"line_number":32,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":48,"id":"dada55a8_30b3ee4e","line":29,"range":{"start_line":29,"start_character":15,"end_line":29,"end_character":18},"updated":"2016-07-27 06:14:55.000000000","message":"There should be \u0027v%s\u0027 % max_version? otherwise this id is always changed.","commit_id":"c9e5d54f07fbd428720a366c37dd67303fad675b"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"10d1a5c7cb25697f48106e573e9486b1b3730d6f","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    # added to this output to align with the guidelines at"},{"line_number":27,"context_line":"    # http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html#version-discovery"},{"line_number":28,"context_line":"    version_data \u003d {"},{"line_number":29,"context_line":"        \u0027id\u0027: \u0027v%s\u0027 % min_version,"},{"line_number":30,"context_line":"        \u0027max_version\u0027: max_version,"},{"line_number":31,"context_line":"        \u0027min_version\u0027: min_version,"},{"line_number":32,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":48,"id":"bacf61ea_4db25807","line":29,"in_reply_to":"bacf61ea_1765bee0","updated":"2016-08-01 08:37:54.000000000","message":"Oops, I think I just missed the code, this is ok at here","commit_id":"c9e5d54f07fbd428720a366c37dd67303fad675b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f01cb460fc75629ec641379ad0b343c96f827601","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    # added to this output to align with the guidelines at"},{"line_number":27,"context_line":"    # http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html#version-discovery"},{"line_number":28,"context_line":"    version_data \u003d {"},{"line_number":29,"context_line":"        \u0027id\u0027: \u0027v%s\u0027 % min_version,"},{"line_number":30,"context_line":"        \u0027max_version\u0027: max_version,"},{"line_number":31,"context_line":"        \u0027min_version\u0027: min_version,"},{"line_number":32,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":48,"id":"bacf61ea_1765bee0","line":29,"in_reply_to":"dada55a8_30b3ee4e","updated":"2016-07-27 15:12:57.000000000","message":"As currently implemented, the min_version is the default version. It\u0027s not actually clear to me what \u0027id\u0027 is supposed to mean, but I took from the nova implementation that it is the overarching version of the api as in \"This is the v2.1 API, of which there are microversions from min to max_version\".\n\nI don\u0027t understand what you mean by \"this id is always changed\". If min_version is the default and isn\u0027t raised, it doesn\u0027t change.","commit_id":"c9e5d54f07fbd428720a366c37dd67303fad675b"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8ef914ddcb346423a7ae628501057a7395507b66","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    }"},{"line_number":33,"context_line":"    version_json \u003d jsonutils.dumps({\u0027versions\u0027: [version_data]})"},{"line_number":34,"context_line":"    req.response.body \u003d version_json"},{"line_number":35,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":36,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_5bb4d180","line":35,"range":{"start_line":35,"start_character":17,"end_line":35,"end_character":29},"updated":"2016-08-01 08:46:08.000000000","message":"Should we reject for invalid context_type? I didn\u0027t find anywhere process this.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"bcc784bc5bde339d5c29ffd85edf1f27c8c41585","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    }"},{"line_number":33,"context_line":"    version_json \u003d jsonutils.dumps({\u0027versions\u0027: [version_data]})"},{"line_number":34,"context_line":"    req.response.body \u003d version_json"},{"line_number":35,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":36,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_0fe1692d","line":35,"in_reply_to":"bacf61ea_29ed4db7","updated":"2016-08-01 12:35:56.000000000","message":"ok, cool","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8a6d38bc2b3305d3590d03d70903efda84d3685f","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    }"},{"line_number":33,"context_line":"    version_json \u003d jsonutils.dumps({\u0027versions\u0027: [version_data]})"},{"line_number":34,"context_line":"    req.response.body \u003d version_json"},{"line_number":35,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":36,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_e65c024d","line":35,"in_reply_to":"bacf61ea_52af8b29","updated":"2016-08-01 11:55:27.000000000","message":"Basically we only have json response...so using decorator is another annoy thing for all resources. But yes, we can change that later, and we should add that decorator to this handler also?","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"a0808dd503049d75b4a81291c0e8aac6c469e558","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    }"},{"line_number":33,"context_line":"    version_json \u003d jsonutils.dumps({\u0027versions\u0027: [version_data]})"},{"line_number":34,"context_line":"    req.response.body \u003d version_json"},{"line_number":35,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":36,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_52af8b29","line":35,"in_reply_to":"bacf61ea_5bb4d180","updated":"2016-08-01 11:04:51.000000000","message":"In the patch above this one for resource provider urls there is a decorator that requires a specific content-type (or multiple types) and will reject if the content-type is wrong.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"cd6a132c9f1ade3f296abd87661e198fafb5db9d","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    }"},{"line_number":33,"context_line":"    version_json \u003d jsonutils.dumps({\u0027versions\u0027: [version_data]})"},{"line_number":34,"context_line":"    req.response.body \u003d version_json"},{"line_number":35,"context_line":"    req.response.content_type \u003d \u0027application/json\u0027"},{"line_number":36,"context_line":"    return req.response"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_29ed4db7","line":35,"in_reply_to":"bacf61ea_e65c024d","updated":"2016-08-01 12:11:13.000000000","message":"Oh, sorry, the decorator I was describing is for checking the request body content-type and since this one does not have a request body it doesn\u0027t get it.\n\nFor setting the response body, there are lots of responses where the content-type is None, so I felt it was better to be explicit rather than implicit.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"}],"nova/api/openstack/placement/microversion.py":[{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"391d7cc06c7a3951262eb41b0429c1d8cb0569bd","unresolved":false,"context_lines":[{"line_number":44,"context_line":"def parse_version_string(version_string):"},{"line_number":45,"context_line":"    \"\"\"Turn a version string into a Version"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    :param version_string: A string of two numerals: X.Y"},{"line_number":48,"context_line":"    :returns: a Version"},{"line_number":49,"context_line":"    :raises: ValueError"},{"line_number":50,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_617a87bb","line":47,"updated":"2016-07-13 17:06:57.000000000","message":"nit: version string can also be \u0027latest\u0027.","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"84cc0d29031389c57e8208cdcb83cf8f4ed9f046","unresolved":false,"context_lines":[{"line_number":44,"context_line":"def parse_version_string(version_string):"},{"line_number":45,"context_line":"    \"\"\"Turn a version string into a Version"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    :param version_string: A string of two numerals: X.Y"},{"line_number":48,"context_line":"    :returns: a Version"},{"line_number":49,"context_line":"    :raises: ValueError"},{"line_number":50,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_5f675bb7","line":47,"in_reply_to":"1aa78d24_617a87bb","updated":"2016-07-13 18:47:30.000000000","message":"✔","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"96c0c60b516ef0db06aa9f3db4ebf08b82b4a6c2","unresolved":false,"context_lines":[{"line_number":28,"context_line":"MICROVERSION_ENVIRON \u003d \u0027%s.microversion\u0027 % SERVICE_TYPE"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"# The Canonical Version List"},{"line_number":31,"context_line":"VERSIONS \u003d ["},{"line_number":32,"context_line":"    \u00271.0\u0027,"},{"line_number":33,"context_line":"]"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"dada55a8_2495c2dd","line":31,"updated":"2016-07-19 20:45:43.000000000","message":"TODO: doc these like the nova REST API version history doc?\n\nhttp://docs.openstack.org/developer/nova/api_microversion_history.html","commit_id":"adc8e497266702d6facc178c5c59483e68561385"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"ad8ab15f8135b0e3a84a026da7051ec6de7c05d0","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        return Version(*(int(value) for value"},{"line_number":60,"context_line":"                         in version_string.split(\u0027.\u0027, 1)))"},{"line_number":61,"context_line":"    except (ValueError, TypeError):"},{"line_number":62,"context_line":"        raise ValueError(\u0027invalid version string: %s\u0027 % version_string)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"class MicroversionMiddleware(object):"}],"source_content_type":"text/x-python","patch_set":47,"id":"dada55a8_52952f3e","line":62,"range":{"start_line":62,"start_character":14,"end_line":62,"end_character":71},"updated":"2016-07-25 13:52:25.000000000","message":"Emm....we return 400 in nova for this case. And we didn\u0027t clarify what return value for this case in the API-WG guideline :( But I think it is worth to check this case now.","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"48815fcafd1807c6fa992f6cf075909d006eae1e","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        return Version(*(int(value) for value"},{"line_number":60,"context_line":"                         in version_string.split(\u0027.\u0027, 1)))"},{"line_number":61,"context_line":"    except (ValueError, TypeError):"},{"line_number":62,"context_line":"        raise ValueError(\u0027invalid version string: %s\u0027 % version_string)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"class MicroversionMiddleware(object):"}],"source_content_type":"text/x-python","patch_set":47,"id":"bacf61ea_1f3be9d2","line":62,"in_reply_to":"dada55a8_10b0ce42","updated":"2016-07-28 10:46:18.000000000","message":"Done","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"394d8764bab5c04042d9bff2e1b286efef852908","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        return Version(*(int(value) for value"},{"line_number":60,"context_line":"                         in version_string.split(\u0027.\u0027, 1)))"},{"line_number":61,"context_line":"    except (ValueError, TypeError):"},{"line_number":62,"context_line":"        raise ValueError(\u0027invalid version string: %s\u0027 % version_string)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"class MicroversionMiddleware(object):"}],"source_content_type":"text/x-python","patch_set":47,"id":"dada55a8_10b0ce42","line":62,"in_reply_to":"dada55a8_52952f3e","updated":"2016-07-25 14:28:32.000000000","message":"Conversation in irc suggests that we want 400 for poorly formed and 406 for unavailable which will require some changes through here (I\u0027ve noted it on my todo list).","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8ef914ddcb346423a7ae628501057a7395507b66","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        # extraneous whitespace."},{"line_number":59,"context_line":"        return Version(*(int(value) for value"},{"line_number":60,"context_line":"                         in version_string.split(\u0027.\u0027, 1)))"},{"line_number":61,"context_line":"    except (ValueError, TypeError) as exc:"},{"line_number":62,"context_line":"        raise TypeError(\u0027invalid version string: %s; %s\u0027 % ("},{"line_number":63,"context_line":"            version_string, exc))"},{"line_number":64,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_db3281f1","line":61,"range":{"start_line":61,"start_character":24,"end_line":61,"end_character":33},"updated":"2016-08-01 08:46:08.000000000","message":"I feel there isn\u0027t any TypeError will be triggered.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8a6d38bc2b3305d3590d03d70903efda84d3685f","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        # extraneous whitespace."},{"line_number":59,"context_line":"        return Version(*(int(value) for value"},{"line_number":60,"context_line":"                         in version_string.split(\u0027.\u0027, 1)))"},{"line_number":61,"context_line":"    except (ValueError, TypeError) as exc:"},{"line_number":62,"context_line":"        raise TypeError(\u0027invalid version string: %s; %s\u0027 % ("},{"line_number":63,"context_line":"            version_string, exc))"},{"line_number":64,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_a63deade","line":61,"in_reply_to":"bacf61ea_00fdbeb3","updated":"2016-08-01 11:55:27.000000000","message":"ah, thanks :)","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"a0808dd503049d75b4a81291c0e8aac6c469e558","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        # extraneous whitespace."},{"line_number":59,"context_line":"        return Version(*(int(value) for value"},{"line_number":60,"context_line":"                         in version_string.split(\u0027.\u0027, 1)))"},{"line_number":61,"context_line":"    except (ValueError, TypeError) as exc:"},{"line_number":62,"context_line":"        raise TypeError(\u0027invalid version string: %s; %s\u0027 % ("},{"line_number":63,"context_line":"            version_string, exc))"},{"line_number":64,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_00fdbeb3","line":61,"in_reply_to":"bacf61ea_db3281f1","updated":"2016-08-01 11:04:51.000000000","message":"If the version string is \u00275\u0027 then only one arg will be passed to Version and that will cause a TypeError","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8ef914ddcb346423a7ae628501057a7395507b66","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        except ValueError as exc:"},{"line_number":78,"context_line":"            raise webob.exc.HTTPNotAcceptable("},{"line_number":79,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"},{"line_number":80,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":81,"context_line":"        except TypeError as exc:"},{"line_number":82,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":83,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_7b01d537","line":80,"range":{"start_line":80,"start_character":31,"end_line":80,"end_character":56},"updated":"2016-08-01 08:46:08.000000000","message":"A little annoy specific a formatter in any exception raise, maybe Fault middleware in Nova is good idea.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"a0808dd503049d75b4a81291c0e8aac6c469e558","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        except ValueError as exc:"},{"line_number":78,"context_line":"            raise webob.exc.HTTPNotAcceptable("},{"line_number":79,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"},{"line_number":80,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":81,"context_line":"        except TypeError as exc:"},{"line_number":82,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":83,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_b22d27aa","line":80,"in_reply_to":"bacf61ea_7b01d537","updated":"2016-08-01 11:04:51.000000000","message":"Yes, I agree it is a bit annoying but in my mind I kept going back and forth between the DRYness of using a middleware and the explicitness of not. Since one of the overall goals of this style of doing things is visibility in to what\u0027s happening, I went with the latter.\n\nBut you\u0027re right: We can change it without too much difficulty if it proves too annoying.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8a6d38bc2b3305d3590d03d70903efda84d3685f","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        except ValueError as exc:"},{"line_number":78,"context_line":"            raise webob.exc.HTTPNotAcceptable("},{"line_number":79,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"},{"line_number":80,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":81,"context_line":"        except TypeError as exc:"},{"line_number":82,"context_line":"            raise webob.exc.HTTPBadRequest("},{"line_number":83,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_c611fe5e","line":80,"in_reply_to":"bacf61ea_b22d27aa","updated":"2016-08-01 11:55:27.000000000","message":"yea, let us change it when it\u0027s really annoying.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8ef914ddcb346423a7ae628501057a7395507b66","unresolved":false,"context_lines":[{"line_number":83,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"},{"line_number":84,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":85,"context_line":"        response \u003d req.get_response(self.application)"},{"line_number":86,"context_line":"        response.headers.add(Version.HEADER,"},{"line_number":87,"context_line":"                             \u0027%s %s\u0027 % (SERVICE_TYPE,"},{"line_number":88,"context_line":"                                        req.environ[MICROVERSION_ENVIRON]))"},{"line_number":89,"context_line":"        response.headers.add(\u0027vary\u0027, Version.HEADER)"},{"line_number":90,"context_line":"        return response"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_3bd47dbb","line":89,"range":{"start_line":86,"start_character":8,"end_line":89,"end_character":52},"updated":"2016-08-01 08:46:08.000000000","message":"If there is an exception raised from handler, those Microversion header won\u0027t be added?\n\nEmm... I think I can find some bugs in Nova.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8a6d38bc2b3305d3590d03d70903efda84d3685f","unresolved":false,"context_lines":[{"line_number":83,"context_line":"                \u0027Invalid microversion: %s\u0027 % exc,"},{"line_number":84,"context_line":"                json_formatter\u003dutil.json_error_formatter)"},{"line_number":85,"context_line":"        response \u003d req.get_response(self.application)"},{"line_number":86,"context_line":"        response.headers.add(Version.HEADER,"},{"line_number":87,"context_line":"                             \u0027%s %s\u0027 % (SERVICE_TYPE,"},{"line_number":88,"context_line":"                                        req.environ[MICROVERSION_ENVIRON]))"},{"line_number":89,"context_line":"        response.headers.add(\u0027vary\u0027, Version.HEADER)"},{"line_number":90,"context_line":"        return response"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_4606ae20","line":89,"range":{"start_line":86,"start_character":8,"end_line":89,"end_character":52},"in_reply_to":"bacf61ea_3bd47dbb","updated":"2016-08-01 11:55:27.000000000","message":"I guess you are missing this comment","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"cd6a132c9f1ade3f296abd87661e198fafb5db9d","unresolved":false,"context_lines":[{"line_number":86,"context_line":"        response.headers.add(Version.HEADER,"},{"line_number":87,"context_line":"                             \u0027%s %s\u0027 % (SERVICE_TYPE,"},{"line_number":88,"context_line":"                                        req.environ[MICROVERSION_ENVIRON]))"},{"line_number":89,"context_line":"        response.headers.add(\u0027vary\u0027, Version.HEADER)"},{"line_number":90,"context_line":"        return response"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_49aa411a","line":89,"in_reply_to":"bacf61ea_4606ae20","updated":"2016-08-01 12:11:13.000000000","message":"Yeah, sorry, did miss this.\n\nIf there is an exception in the application these headers are not added, but the body of the error response will include microversion information if it is available. Is that sufficient or do you think we should catch all exceptions here and adjust the headers accordingly?","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"bcc784bc5bde339d5c29ffd85edf1f27c8c41585","unresolved":false,"context_lines":[{"line_number":86,"context_line":"        response.headers.add(Version.HEADER,"},{"line_number":87,"context_line":"                             \u0027%s %s\u0027 % (SERVICE_TYPE,"},{"line_number":88,"context_line":"                                        req.environ[MICROVERSION_ENVIRON]))"},{"line_number":89,"context_line":"        response.headers.add(\u0027vary\u0027, Version.HEADER)"},{"line_number":90,"context_line":"        return response"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_4f6241d9","line":89,"in_reply_to":"bacf61ea_49aa411a","updated":"2016-08-01 12:35:56.000000000","message":"Only when 406 returned, the microversion info will be included in the error response I guess. For other normal error response, I think they need microversion the headers, As the error response is also under the control of microversion.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"}],"nova/api/openstack/placement/util.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ab067f9d56c763b3c46234d54ad8a650e8e09edf","unresolved":false,"context_lines":[{"line_number":28,"context_line":"            \u0027detail\u0027: body"},{"line_number":29,"context_line":"            # TODO(cdent): Missing fields see:"},{"line_number":30,"context_line":"            # http://specs.openstack.org/openstack/api-wg/guidelines/errors.html"},{"line_number":31,"context_line":"            # code, links, request_id"},{"line_number":32,"context_line":"        }]"},{"line_number":33,"context_line":"    }"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_a2835a03","line":31,"updated":"2016-07-05 17:33:56.000000000","message":"Before we merge so the API isn\u0027t changing, right?","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f27ac57d32dc2cf796e0d4a2fef8e1b5b50c264b","unresolved":false,"context_lines":[{"line_number":28,"context_line":"            \u0027detail\u0027: body"},{"line_number":29,"context_line":"            # TODO(cdent): Missing fields see:"},{"line_number":30,"context_line":"            # http://specs.openstack.org/openstack/api-wg/guidelines/errors.html"},{"line_number":31,"context_line":"            # code, links, request_id"},{"line_number":32,"context_line":"        }]"},{"line_number":33,"context_line":"    }"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_0de9bf14","line":31,"in_reply_to":"1aa78d24_a2835a03","updated":"2016-07-05 17:48:58.000000000","message":"I\u0027m currently adding request_id right now, the values for \u0027code\u0027 and \u0027links\u0027 are undefined so I\u0027m not sure what they will ever be. It might be that we just leave them out.","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"dc48e4f5c80b2f3ae0225f2859a0db19c04efffd","unresolved":false,"context_lines":[{"line_number":21,"context_line":"def json_error_formatter(body, status, title, environ):"},{"line_number":22,"context_line":"    \"\"\"A json_formatter for webob exceptions."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    Follows, as possible, API-WG guidelines at"},{"line_number":25,"context_line":"    http://specs.openstack.org/openstack/api-wg/guidelines/errors.html"},{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    # Clear out the html that webob sneaks in."}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_30bcbeba","line":24,"updated":"2016-07-11 19:53:37.000000000","message":"It either follows or doesn\u0027t follow :)","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8ef914ddcb346423a7ae628501057a7395507b66","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    microversion \u003d nova.api.openstack.placement.microversion"},{"line_number":44,"context_line":"    # Get status code out of status message. webob\u0027s error formatter"},{"line_number":45,"context_line":"    # only passes entire status string."},{"line_number":46,"context_line":"    code \u003d status.split(None, 1)[0]"},{"line_number":47,"context_line":"    if code \u003d\u003d \u0027406\u0027 and microversion.MICROVERSION_ENVIRON not in environ:"},{"line_number":48,"context_line":"        error_dict[\u0027max_version\u0027] \u003d microversion.max_version_string()"},{"line_number":49,"context_line":"        error_dict[\u0027min_version\u0027] \u003d microversion.max_version_string()"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_adedd4b8","line":46,"range":{"start_line":46,"start_character":11,"end_line":46,"end_character":17},"updated":"2016-08-01 08:46:08.000000000","message":"status field in the response isn\u0027t a integer of status code?","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"8a6d38bc2b3305d3590d03d70903efda84d3685f","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    microversion \u003d nova.api.openstack.placement.microversion"},{"line_number":44,"context_line":"    # Get status code out of status message. webob\u0027s error formatter"},{"line_number":45,"context_line":"    # only passes entire status string."},{"line_number":46,"context_line":"    code \u003d status.split(None, 1)[0]"},{"line_number":47,"context_line":"    if code \u003d\u003d \u0027406\u0027 and microversion.MICROVERSION_ENVIRON not in environ:"},{"line_number":48,"context_line":"        error_dict[\u0027max_version\u0027] \u003d microversion.max_version_string()"},{"line_number":49,"context_line":"        error_dict[\u0027min_version\u0027] \u003d microversion.max_version_string()"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_e6008236","line":46,"in_reply_to":"bacf61ea_60d91a57","updated":"2016-08-01 11:55:27.000000000","message":"From the api guideline http://specs.openstack.org/openstack/api-wg/guidelines/errors.html  the status is just a integer status code. I mean we should put the integer at line 31","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"a0808dd503049d75b4a81291c0e8aac6c469e558","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    microversion \u003d nova.api.openstack.placement.microversion"},{"line_number":44,"context_line":"    # Get status code out of status message. webob\u0027s error formatter"},{"line_number":45,"context_line":"    # only passes entire status string."},{"line_number":46,"context_line":"    code \u003d status.split(None, 1)[0]"},{"line_number":47,"context_line":"    if code \u003d\u003d \u0027406\u0027 and microversion.MICROVERSION_ENVIRON not in environ:"},{"line_number":48,"context_line":"        error_dict[\u0027max_version\u0027] \u003d microversion.max_version_string()"},{"line_number":49,"context_line":"        error_dict[\u0027min_version\u0027] \u003d microversion.max_version_string()"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_60d91a57","line":46,"in_reply_to":"bacf61ea_adedd4b8","updated":"2016-08-01 11:04:51.000000000","message":"In the formatters we don\u0027t have access to the request object, just body, status, title and environ and status is the entire status response value.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"cd6a132c9f1ade3f296abd87661e198fafb5db9d","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    microversion \u003d nova.api.openstack.placement.microversion"},{"line_number":44,"context_line":"    # Get status code out of status message. webob\u0027s error formatter"},{"line_number":45,"context_line":"    # only passes entire status string."},{"line_number":46,"context_line":"    code \u003d status.split(None, 1)[0]"},{"line_number":47,"context_line":"    if code \u003d\u003d \u0027406\u0027 and microversion.MICROVERSION_ENVIRON not in environ:"},{"line_number":48,"context_line":"        error_dict[\u0027max_version\u0027] \u003d microversion.max_version_string()"},{"line_number":49,"context_line":"        error_dict[\u0027min_version\u0027] \u003d microversion.max_version_string()"}],"source_content_type":"text/x-python","patch_set":51,"id":"bacf61ea_543494dc","line":46,"in_reply_to":"bacf61ea_e6008236","updated":"2016-08-01 12:11:13.000000000","message":"Ah, yeah, good point. Missed that. I\u0027ve made a note to do it in a followup.","commit_id":"2ae10ce5225f593dd6b0d784adafa34939c26260"}],"nova/cmd/placement_api.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"91fb7d10866accf3405f923662440718455810e3","unresolved":false,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":"def main():"},{"line_number":32,"context_line":"    config.parse_args(sys.argv)"},{"line_number":33,"context_line":"    logging.setup(CONF, \"nova\")"},{"line_number":34,"context_line":"    utils.monkey_patch()"},{"line_number":35,"context_line":"    objects.register_all()"},{"line_number":36,"context_line":"    api_name \u003d \u0027placement\u0027"}],"source_content_type":"text/x-python","patch_set":42,"id":"dada55a8_0f1c1711","line":33,"range":{"start_line":33,"start_character":25,"end_line":33,"end_character":29},"updated":"2016-07-19 20:49:42.000000000","message":"There is a later change in this series that changes this to placement, which do we want?","commit_id":"adc8e497266702d6facc178c5c59483e68561385"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"d38202b98493db7fc687a4efee4e5da306efded5","unresolved":false,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":"def main():"},{"line_number":32,"context_line":"    config.parse_args(sys.argv)"},{"line_number":33,"context_line":"    logging.setup(CONF, \"nova\")"},{"line_number":34,"context_line":"    utils.monkey_patch()"},{"line_number":35,"context_line":"    objects.register_all()"},{"line_number":36,"context_line":"    api_name \u003d \u0027placement\u0027"}],"source_content_type":"text/x-python","patch_set":42,"id":"dada55a8_47ea7310","line":33,"in_reply_to":"dada55a8_0f1c1711","updated":"2016-07-19 23:20:07.000000000","message":"There\u0027s also a change that gets rid of this file entirely and the placement service only runs under a wsgi container (such as mod wsgi, nginx, gunicorn). Do we require this file?","commit_id":"adc8e497266702d6facc178c5c59483e68561385"}],"nova/tests/functional/api/openstack/placement/fixtures.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ab067f9d56c763b3c46234d54ad8a650e8e09edf","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self.main_db_fixture.reset()"},{"line_number":59,"context_line":"        self.api_db_fixture.reset()"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        objects.register_all()"},{"line_number":62,"context_line":"        rpc.init(self.conf)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def stop_fixture(self):"}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_42bef6d4","line":61,"updated":"2016-07-05 17:33:56.000000000","message":"All this does is import things, so it doesn\u0027t need to be run every time you start the fixture.","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f27ac57d32dc2cf796e0d4a2fef8e1b5b50c264b","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self.main_db_fixture.reset()"},{"line_number":59,"context_line":"        self.api_db_fixture.reset()"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        objects.register_all()"},{"line_number":62,"context_line":"        rpc.init(self.conf)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def stop_fixture(self):"}],"source_content_type":"text/x-python","patch_set":17,"id":"1aa78d24_0d6edf94","line":61,"in_reply_to":"1aa78d24_42bef6d4","updated":"2016-07-05 17:48:58.000000000","message":"Thanks will move to module level.","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"fdcc3cc4842467fac95eb41511a1d172ca1033f0","unresolved":false,"context_lines":[{"line_number":49,"context_line":"                          init_rpc\u003dFalse)"},{"line_number":50,"context_line":"        self.conf \u003d CONF \u003d conf.CONF"},{"line_number":51,"context_line":"        self.messaging_conf \u003d messaging_conffixture.ConfFixture(self.conf)"},{"line_number":52,"context_line":"        self.messaging_conf.transport_driver \u003d \u0027fake\u0027"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        self.conf.set_override(\u0027rpc_backend\u0027, \u0027fake\u0027)"},{"line_number":55,"context_line":"        self.conf.set_override(\u0027auth_strategy\u0027, \u0027noauth2\u0027)"}],"source_content_type":"text/x-python","patch_set":23,"id":"1aa78d24_61fd67b0","line":52,"updated":"2016-07-07 19:42:17.000000000","message":"Why do we need messaging or RPC set up? The placement engine does not transmit messages or communicate over RPC.","commit_id":"87c79775b895490653610570a1b4422e23d451bb"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"796d90f935e48b36990c6ea9e2e7cb3f8401f86d","unresolved":false,"context_lines":[{"line_number":49,"context_line":"                          init_rpc\u003dFalse)"},{"line_number":50,"context_line":"        self.conf \u003d CONF \u003d conf.CONF"},{"line_number":51,"context_line":"        self.messaging_conf \u003d messaging_conffixture.ConfFixture(self.conf)"},{"line_number":52,"context_line":"        self.messaging_conf.transport_driver \u003d \u0027fake\u0027"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        self.conf.set_override(\u0027rpc_backend\u0027, \u0027fake\u0027)"},{"line_number":55,"context_line":"        self.conf.set_override(\u0027auth_strategy\u0027, \u0027noauth2\u0027)"}],"source_content_type":"text/x-python","patch_set":23,"id":"1aa78d24_c1c9bb27","line":52,"in_reply_to":"1aa78d24_61fd67b0","updated":"2016-07-07 19:51:28.000000000","message":"Good point, this is probably hiding something in the tests that is trying to do something remotely.","commit_id":"87c79775b895490653610570a1b4422e23d451bb"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"dc48e4f5c80b2f3ae0225f2859a0db19c04efffd","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self.main_db_fixture \u003d fixtures.Database(\u0027main\u0027)"},{"line_number":59,"context_line":"        self.api_db_fixture \u003d fixtures.Database(\u0027api\u0027)"},{"line_number":60,"context_line":"        self.main_db_fixture.reset()"},{"line_number":61,"context_line":"        self.api_db_fixture.reset()"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def stop_fixture(self):"},{"line_number":64,"context_line":"        self.main_db_fixture.cleanup()"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_90adb286","line":61,"updated":"2016-07-11 19:53:37.000000000","message":"This really seems like something that should be in a separate fixture, no? Mixing config setup with DB setup seems like a poor coupling.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"48733dd7c97906cd547894f70e80b240416fa943","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self.main_db_fixture \u003d fixtures.Database(\u0027main\u0027)"},{"line_number":59,"context_line":"        self.api_db_fixture \u003d fixtures.Database(\u0027api\u0027)"},{"line_number":60,"context_line":"        self.main_db_fixture.reset()"},{"line_number":61,"context_line":"        self.api_db_fixture.reset()"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def stop_fixture(self):"},{"line_number":64,"context_line":"        self.main_db_fixture.cleanup()"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_a7e515a5","line":61,"updated":"2016-07-11 20:44:18.000000000","message":"Yeah, no worries. I actually figured you did it this way to keep from having to list multiple fixtures in the gabbits fixtures: definition space... no need to change anything but if you respin for any reason, might want to rename this fixture...","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"eb320ddfe216a0655e56dac293421f6aea2e1448","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self.main_db_fixture \u003d fixtures.Database(\u0027main\u0027)"},{"line_number":59,"context_line":"        self.api_db_fixture \u003d fixtures.Database(\u0027api\u0027)"},{"line_number":60,"context_line":"        self.main_db_fixture.reset()"},{"line_number":61,"context_line":"        self.api_db_fixture.reset()"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def stop_fixture(self):"},{"line_number":64,"context_line":"        self.main_db_fixture.cleanup()"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_44538f17","line":61,"in_reply_to":"1aa78d24_90adb286","updated":"2016-07-11 20:09:04.000000000","message":"In that case I\u0027d argue the mistake is in the name of the fixture, not what the fixture is doing. Basically this fixture is \"do all the basic crap necessary to make the api runnable via wsgi-intercept, including set up the config, start the db, etc\". That is, without what\u0027s here, running the gabbi tests won\u0027t work. This is the atom.\n\nBut happy to tune it otherwise if it is a bit more consumable that way.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"391d7cc06c7a3951262eb41b0429c1d8cb0569bd","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"API_SERVICE \u003d \u0027placement\u0027"},{"line_number":24,"context_line":"# Hack around our need to have a global oslo config."},{"line_number":25,"context_line":"CONF \u003d None"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_bcef7285","line":24,"updated":"2016-07-13 17:06:57.000000000","message":"What needs a global config?","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"84cc0d29031389c57e8208cdcb83cf8f4ed9f046","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"API_SERVICE \u003d \u0027placement\u0027"},{"line_number":24,"context_line":"# Hack around our need to have a global oslo config."},{"line_number":25,"context_line":"CONF \u003d None"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_ff3e078a","line":24,"in_reply_to":"1aa78d24_bcef7285","updated":"2016-07-13 18:47:30.000000000","message":"Both of these conf things are blind duplication from a similar file from back in the days when gabbi was first developed and used with ceilometer. I\u0027ll do some experimentation to make sure which of the three are necessary (if any) and make some comments to make sure it is explained properly.","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"391d7cc06c7a3951262eb41b0429c1d8cb0569bd","unresolved":false,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def setup_app():"},{"line_number":33,"context_line":"    global CONF"},{"line_number":34,"context_line":"    loader \u003d wsgi.Loader()"},{"line_number":35,"context_line":"    return loader.load_app(API_SERVICE)"},{"line_number":36,"context_line":""}],"source_content_type":"text/x-python","patch_set":35,"id":"1aa78d24_dcd19ecd","line":33,"range":{"start_line":33,"start_character":4,"end_line":33,"end_character":15},"updated":"2016-07-13 17:06:57.000000000","message":"It\u0027s not clear why this is here.","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"}],"nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml":[{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"391d7cc06c7a3951262eb41b0429c1d8cb0569bd","unresolved":false,"context_lines":[{"line_number":37,"context_line":"  response_strings:"},{"line_number":38,"context_line":"      - \"Unacceptable version header: 0.5\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"- name: latest microversion is 1.0"},{"line_number":41,"context_line":"  GET: /"},{"line_number":42,"context_line":"  request_headers:"},{"line_number":43,"context_line":"      openstack-api-version: placement latest"}],"source_content_type":"text/x-yaml","patch_set":35,"id":"1aa78d24_1c2206b9","line":40,"updated":"2016-07-13 17:06:57.000000000","message":"So this test needs to be updated for each microversion which is fine. But I\u0027m not sure that the three tests above this one should and my understanding is that they will.","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"84cc0d29031389c57e8208cdcb83cf8f4ed9f046","unresolved":false,"context_lines":[{"line_number":37,"context_line":"  response_strings:"},{"line_number":38,"context_line":"      - \"Unacceptable version header: 0.5\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"- name: latest microversion is 1.0"},{"line_number":41,"context_line":"  GET: /"},{"line_number":42,"context_line":"  request_headers:"},{"line_number":43,"context_line":"      openstack-api-version: placement latest"}],"source_content_type":"text/x-yaml","patch_set":35,"id":"1aa78d24_7f8e977a","line":40,"in_reply_to":"1aa78d24_1c2206b9","updated":"2016-07-13 18:47:30.000000000","message":"This can be improved now that Change-Id: Ibee53862d2225014f22a780237832c23effd38db has merged (bumping to a new version of gabbi)","commit_id":"f8d45bdc33376fc67f39440965c7e9884423ade0"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"d9573c3ee7eba8b7ace8e08c30258cca22456c25","unresolved":false,"context_lines":[{"line_number":35,"context_line":"      $.errors.[0].max_version: /^\\d+\\.\\d+$/"},{"line_number":36,"context_line":"      $.errors.[0].min_version: /^\\d+\\.\\d+$/"},{"line_number":37,"context_line":"  response_strings:"},{"line_number":38,"context_line":"      - \"Unacceptable version header: 0.5\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"- name: latest microversion is 1.0"},{"line_number":41,"context_line":"  GET: /"}],"source_content_type":"text/x-yaml","patch_set":48,"id":"dada55a8_f06f968f","line":38,"range":{"start_line":38,"start_character":8,"end_line":38,"end_character":42},"updated":"2016-07-27 06:14:55.000000000","message":"Accroding the api-wg guideline, there should be a dict body, not just a string. https://github.com/openstack/api-wg/blame/master/guidelines/microversion_specification.rst#L155","commit_id":"c9e5d54f07fbd428720a366c37dd67303fad675b"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"10d1a5c7cb25697f48106e573e9486b1b3730d6f","unresolved":false,"context_lines":[{"line_number":35,"context_line":"      $.errors.[0].max_version: /^\\d+\\.\\d+$/"},{"line_number":36,"context_line":"      $.errors.[0].min_version: /^\\d+\\.\\d+$/"},{"line_number":37,"context_line":"  response_strings:"},{"line_number":38,"context_line":"      - \"Unacceptable version header: 0.5\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"- name: latest microversion is 1.0"},{"line_number":41,"context_line":"  GET: /"}],"source_content_type":"text/x-yaml","patch_set":48,"id":"bacf61ea_6d7bdc28","line":38,"in_reply_to":"bacf61ea_17c13e81","updated":"2016-08-01 08:37:54.000000000","message":"thanks, I got it.","commit_id":"c9e5d54f07fbd428720a366c37dd67303fad675b"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f01cb460fc75629ec641379ad0b343c96f827601","unresolved":false,"context_lines":[{"line_number":35,"context_line":"      $.errors.[0].max_version: /^\\d+\\.\\d+$/"},{"line_number":36,"context_line":"      $.errors.[0].min_version: /^\\d+\\.\\d+$/"},{"line_number":37,"context_line":"  response_strings:"},{"line_number":38,"context_line":"      - \"Unacceptable version header: 0.5\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"- name: latest microversion is 1.0"},{"line_number":41,"context_line":"  GET: /"}],"source_content_type":"text/x-yaml","patch_set":48,"id":"bacf61ea_17c13e81","line":38,"in_reply_to":"dada55a8_f06f968f","updated":"2016-07-27 15:12:57.000000000","message":"Is it is a dict body (see response_json_paths above). response_strings checks for string fragments anywhere in a response, even if it is a json object. So what this is doing is testing the \u0027detail\u0027 response.","commit_id":"c9e5d54f07fbd428720a366c37dd67303fad675b"}],"nova/tests/unit/api/openstack/placement/test_handler.py":[{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"839bc1c6c68ae61b3b284ce4a8e9c75c1c929b10","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_f3afffe0","line":44,"updated":"2016-07-11 10:35:36.000000000","message":"I don\u0027t think you should to use mapper as an attribute because the tests are expected to be executed in parallel. In each tests mapper is updated with new routes, we need that each tests to be isolated.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e0f43a0a4c873eedd797e13eb52c9eace304aae8","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_9b94bb8b","line":44,"updated":"2016-07-11 16:53:42.000000000","message":"sahid: Although test methods are indeed run in parallel, the internal state of the test case class is thread-safe. The parallel testr processes instantiate a test case class instance each and execute various methods. The thing you need to be careful about is modifying (and relying on those modfications) to **global state** -- i.e. a shared database instance. In this case, Chris is simply modifying the test case class\u0027 mapper attribute, which isn\u0027t global state -- it\u0027s state for just the test case class instance and is safe within the testr test process.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"3ddd418c1ef0aff9ac3e48e8e612766e1a20a79f","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_5bcc13bb","line":44,"in_reply_to":"1aa78d24_5147d976","updated":"2016-07-11 16:55:20.000000000","message":"Are you meaning because we are in a situation where eventlet\u0027s monkey patching may have caused some concurrency situations? If that\u0027s not what you mean, I\u0027m still confused, could you clarify?\n\nI\u0027ll go ahead and change it as you suggest, but if you could repsond to clarify that would be great.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"785c13e20612ea86919b487b6fdad784745ef666","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_6ffad244","line":44,"in_reply_to":"1aa78d24_9b94bb8b","updated":"2016-07-12 06:43:42.000000000","message":"Yes It\u0027s true. I don\u0027t know why I was sure I experienced a problem in the same situation. Sorry for the disagreement.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"0d2cfa3fce1e8c6490f1051b43347e2d0971b22b","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_5147d976","line":44,"in_reply_to":"1aa78d24_d6a57f47","updated":"2016-07-11 16:13:11.000000000","message":"No it\u0027s not because setUp of test_no_match_with_map can be executed, then setUp of test_simple_match to finally enter in test_no_match_with_map with a bad context for mapper.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"0c5857d9ddb5fc15d26a87d5d57dafa1591beaa7","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_d6a57f47","line":44,"in_reply_to":"1aa78d24_f3afffe0","updated":"2016-07-11 15:58:18.000000000","message":"Yes, the tests are run in parallel but setUp is run for each test method, so mapper is fresh for each test, so the mapper is isolated.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"839bc1c6c68ae61b3b284ce4a8e9c75c1c929b10","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"},{"line_number":48,"context_line":"        self.assertRaises(webob.exc.HTTPNotFound,"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_10e1e19a","line":45,"updated":"2016-07-11 10:35:36.000000000","message":"suggest: To have this mock a little bit more stronger you can use the keyword \u0027spec\u0027 and so refer do the module handler.\n\n  Mock(spec\u003dhandler)","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"0c5857d9ddb5fc15d26a87d5d57dafa1591beaa7","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    def setUp(self):"},{"line_number":43,"context_line":"        super(DispatchTest, self).setUp()"},{"line_number":44,"context_line":"        self.mapper \u003d routes.Mapper()"},{"line_number":45,"context_line":"        self.handler \u003d mock.MagicMock()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def test_no_match_null_map(self):"},{"line_number":48,"context_line":"        self.assertRaises(webob.exc.HTTPNotFound,"}],"source_content_type":"text/x-python","patch_set":30,"id":"1aa78d24_36ee838b","line":45,"in_reply_to":"1aa78d24_10e1e19a","updated":"2016-07-11 15:58:18.000000000","message":"I don\u0027t want it to refer to the module handler. It is simply providing an empty mock on which we can assert that dispatch() has processed the mapping as we expect. I\u0027ll rename the variable to make that a bit more clear.","commit_id":"5c700e0aa76d142cb4958b640d98997459b10e98"}],"tox.ini":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ab067f9d56c763b3c46234d54ad8a650e8e09edf","unresolved":false,"context_lines":[{"line_number":62,"context_line":"       LANGUAGE\u003den_US"},{"line_number":63,"context_line":"commands \u003d"},{"line_number":64,"context_line":"  find . -type f -name \"*.pyc\" -delete"},{"line_number":65,"context_line":"  bash tools/pretty_tox.sh \u0027{posargs}\u0027"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"[testenv:api-samples]"}],"source_content_type":"text/x-properties","patch_set":17,"id":"1aa78d24_22f48a84","line":65,"updated":"2016-07-05 17:33:56.000000000","message":"This is just a convenience target for running just those gabbi tests?\n\nI guess I\u0027m not sure why we need this (or the api-samples one below)...","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f27ac57d32dc2cf796e0d4a2fef8e1b5b50c264b","unresolved":false,"context_lines":[{"line_number":62,"context_line":"       LANGUAGE\u003den_US"},{"line_number":63,"context_line":"commands \u003d"},{"line_number":64,"context_line":"  find . -type f -name \"*.pyc\" -delete"},{"line_number":65,"context_line":"  bash tools/pretty_tox.sh \u0027{posargs}\u0027"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"[testenv:api-samples]"}],"source_content_type":"text/x-properties","patch_set":17,"id":"1aa78d24_ad918b54","line":65,"in_reply_to":"1aa78d24_22f48a84","updated":"2016-07-05 17:48:58.000000000","message":"Yeah, a convenience. Test runs with just gabbi are faster because we don\u0027t need to do discovery across all the functional tests. Since I\u0027ve been doing TDD at least some of the time, the minor speedup has been helpful.","commit_id":"db2c0e4fea046a00d841f7048bc80d3e30c78367"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"96c0c60b516ef0db06aa9f3db4ebf08b82b4a6c2","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"[testenv:gabbi]"},{"line_number":57,"context_line":"# don\u0027t use constraints until they are updated to newer gabbi"},{"line_number":58,"context_line":"install_command \u003d pip install {opts} {packages}"},{"line_number":59,"context_line":"usedevelop \u003d True"},{"line_number":60,"context_line":"setenv \u003d VIRTUAL_ENV\u003d{envdir}"}],"source_content_type":"text/x-properties","patch_set":42,"id":"dada55a8_444ef696","line":57,"updated":"2016-07-19 20:45:43.000000000","message":"What version do we need? Why can\u0027t we just raise it and use it now?","commit_id":"adc8e497266702d6facc178c5c59483e68561385"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"ec5d3d1231e28a28ff15d66cd5e15a94f4b5c973","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"[testenv:gabbi]"},{"line_number":57,"context_line":"# don\u0027t use constraints until they are updated to newer gabbi"},{"line_number":58,"context_line":"install_command \u003d pip install {opts} {packages}"},{"line_number":59,"context_line":"usedevelop \u003d True"},{"line_number":60,"context_line":"setenv \u003d VIRTUAL_ENV\u003d{envdir}"}],"source_content_type":"text/x-properties","patch_set":42,"id":"dada55a8_af1ceb13","line":57,"in_reply_to":"dada55a8_444ef696","updated":"2016-07-19 20:50:09.000000000","message":"It\u0027s already done, I just forgot to change this comment. Will do.\n\nin Change-Id: Ibee53862d2225014f22a780237832c23effd38db","commit_id":"adc8e497266702d6facc178c5c59483e68561385"},{"author":{"_account_id":2750,"name":"Sean Dague","email":"sean@dague.net","username":"sdague"},"change_message_id":"19f56a696ebd27244e39050873d4cbc10b87f4d8","unresolved":false,"context_lines":[{"line_number":60,"context_line":"       LANGUAGE\u003den_US"},{"line_number":61,"context_line":"commands \u003d"},{"line_number":62,"context_line":"  find . -type f -name \"*.pyc\" -delete"},{"line_number":63,"context_line":"  bash tools/pretty_tox.sh \u0027{posargs}\u0027"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"[testenv:api-samples]"}],"source_content_type":"text/x-properties","patch_set":47,"id":"dada55a8_a1e53ba9","line":63,"updated":"2016-07-25 12:58:21.000000000","message":"is there a reason to really add this rule in? Won\u0027t\n\ntox -e functional placement \n\ndo the same thing?","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"394d8764bab5c04042d9bff2e1b286efef852908","unresolved":false,"context_lines":[{"line_number":60,"context_line":"       LANGUAGE\u003den_US"},{"line_number":61,"context_line":"commands \u003d"},{"line_number":62,"context_line":"  find . -type f -name \"*.pyc\" -delete"},{"line_number":63,"context_line":"  bash tools/pretty_tox.sh \u0027{posargs}\u0027"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"[testenv:api-samples]"}],"source_content_type":"text/x-properties","patch_set":47,"id":"dada55a8_adaec995","line":63,"in_reply_to":"dada55a8_a1e53ba9","updated":"2016-07-25 14:28:32.000000000","message":"Doing it this way is a local optimization to avoid some of the cost (which isn\u0027t really all that huge) of test discovery. It\u0027s not a big deal, I can remove it to keep things tidy.","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"48815fcafd1807c6fa992f6cf075909d006eae1e","unresolved":false,"context_lines":[{"line_number":60,"context_line":"       LANGUAGE\u003den_US"},{"line_number":61,"context_line":"commands \u003d"},{"line_number":62,"context_line":"  find . -type f -name \"*.pyc\" -delete"},{"line_number":63,"context_line":"  bash tools/pretty_tox.sh \u0027{posargs}\u0027"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"[testenv:api-samples]"}],"source_content_type":"text/x-properties","patch_set":47,"id":"bacf61ea_9f74f99c","line":63,"in_reply_to":"dada55a8_adaec995","updated":"2016-07-28 10:46:18.000000000","message":"Done","commit_id":"1c38309529ae7f22426b0dcfaa2d9adccbe9073f"}]}
