)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"83dc9767e63995e934bcbe1a1b891b7d18185e94","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Make use of Dict-base including extras explicit"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This change replaces the use of DictBase with the ModelDictMixin"},{"line_number":10,"context_line":"for any SQL models that do not contain an extra column and renames"},{"line_number":11,"context_line":"the DictBase to a more descriptive name of ModelDictMixinWithExtras."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"A Docstring has been added indicating the continued usage of"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"da36d5c6_6890b696","line":10,"range":{"start_line":9,"start_character":1,"end_line":10,"end_character":54},"updated":"2017-02-18 09:20:10.000000000","message":"DictBase and ModelDictMixin are not tackling with the same data, DictBase is based on the \u0027cls.attributes\u0027 and the other is based on the \u0027__table__.columns\u0027. The change is fine most of the time, but it\u0027s not true for the table like \u0027user\u0027 which has hybrid property, \u0027password\u0027 for example, it is a table attribute but not a column.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"497f582a980f58b0a0e314a2c330cdf3fa6e102a","unresolved":false,"context_lines":[{"line_number":13,"context_line":"A Docstring has been added indicating the continued usage of"},{"line_number":14,"context_line":"ModelDictMixinWithExtras should not be done for any \"new\""},{"line_number":15,"context_line":"models."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Change-Id: I9a4767cacf7620e878df70084060f3e43e1318df"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"da36d5c6_619371a4","line":16,"updated":"2017-02-18 16:27:07.000000000","message":"It would be nice for noob reviewers like me if this commit message explained the \"why\" of this change, I didn\u0027t understand until I got to the new docstring in the WithExtras class.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6bad870d3dedb4a9911d3bedce570c354c80590c","unresolved":false,"context_lines":[{"line_number":13,"context_line":"A Docstring has been added indicating the continued usage of"},{"line_number":14,"context_line":"ModelDictMixinWithExtras should not be done for any \"new\""},{"line_number":15,"context_line":"models."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Change-Id: I9a4767cacf7620e878df70084060f3e43e1318df"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"ba2be162_021b651c","line":16,"in_reply_to":"da36d5c6_619371a4","updated":"2017-03-01 16:53:42.000000000","message":"+1 The benefit of this patch is not obvious.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"}],"doc/source/devref/api_change_tutorial.rst":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"83dc9767e63995e934bcbe1a1b891b7d18185e94","unresolved":false,"context_lines":[{"line_number":87,"context_line":"First, you need to change the role model to include the description attribute."},{"line_number":88,"context_line":"Go to `keystone/assignment/role_backends/sql.py` and update it like::"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    class RoleTable(sql.ModelBase, sql.ModelDictMixin):"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        attributes \u003d [\u0027id\u0027, \u0027name\u0027, \u0027domain_id\u0027, \u0027description\u0027]"},{"line_number":93,"context_line":"        description \u003d sql.Column(sql.String(255), nullable\u003dTrue)"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da36d5c6_1572f7e5","line":90,"range":{"start_line":90,"start_character":35,"end_line":90,"end_character":53},"updated":"2017-02-18 09:20:10.000000000","message":"...hmm, this is not consistent with the code you have changed unthough I understand it\u0027s only an example. https://review.openstack.org/#/c/428472/4/keystone/assignment/role_backends/sql.py","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"497f582a980f58b0a0e314a2c330cdf3fa6e102a","unresolved":false,"context_lines":[{"line_number":87,"context_line":"First, you need to change the role model to include the description attribute."},{"line_number":88,"context_line":"Go to `keystone/assignment/role_backends/sql.py` and update it like::"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    class RoleTable(sql.ModelBase, sql.ModelDictMixin):"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        attributes \u003d [\u0027id\u0027, \u0027name\u0027, \u0027domain_id\u0027, \u0027description\u0027]"},{"line_number":93,"context_line":"        description \u003d sql.Column(sql.String(255), nullable\u003dTrue)"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da36d5c6_2b6878ba","line":90,"range":{"start_line":90,"start_character":35,"end_line":90,"end_character":53},"in_reply_to":"da36d5c6_1572f7e5","updated":"2017-02-18 16:27:07.000000000","message":"The example is supposed to be forward-looking, so I think using this mixin in the example is fine. It\u0027s just happens to be that the real class currently uses the other mixin.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"}],"keystone/common/sql/core.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6bad870d3dedb4a9911d3bedce570c354c80590c","unresolved":false,"context_lines":[{"line_number":126,"context_line":"class ModelDictMixinWithExtras(models.ModelBase):"},{"line_number":127,"context_line":"    \"\"\"Mixin making model behave with dict-like interfaces includes extras."},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    NOTE: DO NOT USE THIS FOR FUTURE SQL MODELS. \"Extra\" column is a legacy"},{"line_number":130,"context_line":"          concept that should not be carried forward with new SQL models"},{"line_number":131,"context_line":"          as the concept of \"arbitrary\" properties is not in line with"},{"line_number":132,"context_line":"          the design philosophy of Keystone."}],"source_content_type":"text/x-python","patch_set":4,"id":"ba2be162_e279f130","line":129,"updated":"2017-03-01 16:53:42.000000000","message":"You can use an RST-style note or warning here for docs:\n\n  .. note:\n\nBut, more importantly, it will be so easy to accidentally extend this class if you just copy existing model code around. Would it be possible to enumerate all the classes that are allowed to extend this class in a unit test, and fail if there are any unexpected child classes?","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"68b0324f8e0eb70693dd86f57103692019e2c289","unresolved":false,"context_lines":[{"line_number":146,"context_line":"        if not hasattr(cls, \u0027extra\u0027):"},{"line_number":147,"context_line":"            # NOTE(notmorgan): No translation here, This is an error for"},{"line_number":148,"context_line":"            # programmers NOT end users."},{"line_number":149,"context_line":"            raise AttributeError(cls._msg)  # no qa"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"        new_d[\u0027extra\u0027] \u003d {k: new_d.pop(k) for k in d.keys()"},{"line_number":152,"context_line":"                          if k not in cls.attributes and k !\u003d \u0027extra\u0027}"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa31d9ce_e7f21506","line":149,"range":{"start_line":149,"start_character":44,"end_line":149,"end_character":51},"updated":"2017-02-10 03:11:57.000000000","message":"isn\u0027t this \"noqa\" ?","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"}],"keystone/identity/backends/sql_model.py":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"83dc9767e63995e934bcbe1a1b891b7d18185e94","unresolved":false,"context_lines":[{"line_number":268,"context_line":"                                 lazy\u003d\u0027subquery\u0027,"},{"line_number":269,"context_line":"                                 backref\u003d\u0027local_user\u0027,"},{"line_number":270,"context_line":"                                 order_by\u003d\u0027Password.created_at\u0027)"},{"line_number":271,"context_line":"    failed_auth_count \u003d sql.Column(sql.Integer, nullable\u003dTrue)"},{"line_number":272,"context_line":"    failed_auth_at \u003d sql.Column(sql.DateTime, nullable\u003dTrue)"},{"line_number":273,"context_line":"    __table_args__ \u003d ("},{"line_number":274,"context_line":"        sql.UniqueConstraint(\u0027user_id\u0027),"},{"line_number":275,"context_line":"        sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027),"}],"source_content_type":"text/x-python","patch_set":4,"id":"da36d5c6_68e7d640","line":272,"range":{"start_line":271,"start_character":4,"end_line":272,"end_character":60},"updated":"2017-02-18 09:20:10.000000000","message":"Both of above are columns but not table attributes, I feel the change here is not backward compatible (the using of to_dict will show us the different data).","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"497f582a980f58b0a0e314a2c330cdf3fa6e102a","unresolved":false,"context_lines":[{"line_number":268,"context_line":"                                 lazy\u003d\u0027subquery\u0027,"},{"line_number":269,"context_line":"                                 backref\u003d\u0027local_user\u0027,"},{"line_number":270,"context_line":"                                 order_by\u003d\u0027Password.created_at\u0027)"},{"line_number":271,"context_line":"    failed_auth_count \u003d sql.Column(sql.Integer, nullable\u003dTrue)"},{"line_number":272,"context_line":"    failed_auth_at \u003d sql.Column(sql.DateTime, nullable\u003dTrue)"},{"line_number":273,"context_line":"    __table_args__ \u003d ("},{"line_number":274,"context_line":"        sql.UniqueConstraint(\u0027user_id\u0027),"},{"line_number":275,"context_line":"        sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027),"}],"source_content_type":"text/x-python","patch_set":4,"id":"da36d5c6_41af4de3","line":272,"range":{"start_line":271,"start_character":4,"end_line":272,"end_character":60},"in_reply_to":"da36d5c6_68e7d640","updated":"2017-02-18 16:27:07.000000000","message":"I don\u0027t think it matters. The only time failed_auth_count and failed_auth_at are used (like here http://git.openstack.org/cgit/openstack/keystone/tree/keystone/identity/backends/sql.py#n103) they\u0027re are referred to as object attributes, not as dict keys, so it looks safe to me.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"}],"keystone/oauth1/backends/sql.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"68b0324f8e0eb70693dd86f57103692019e2c289","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue, nullable\u003dFalse)"},{"line_number":36,"context_line":"    description \u003d sql.Column(sql.String(64), nullable\u003dTrue)"},{"line_number":37,"context_line":"    secret \u003d sql.Column(sql.String(64), nullable\u003dFalse)"},{"line_number":38,"context_line":"    extra \u003d sql.Column(sql.JsonBlob(), nullable\u003dFalse)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"class RequestToken(sql.ModelBase, sql.ModelDictMixin):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa31d9ce_aa78e4f9","line":38,"range":{"start_line":38,"start_character":4,"end_line":38,"end_character":54},"updated":"2017-02-10 03:11:57.000000000","message":"we can probably remove this","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"36224c84210c30dd321364942205d217eef2b7f2","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue, nullable\u003dFalse)"},{"line_number":36,"context_line":"    description \u003d sql.Column(sql.String(64), nullable\u003dTrue)"},{"line_number":37,"context_line":"    secret \u003d sql.Column(sql.String(64), nullable\u003dFalse)"},{"line_number":38,"context_line":"    extra \u003d sql.Column(sql.JsonBlob(), nullable\u003dFalse)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"class RequestToken(sql.ModelBase, sql.ModelDictMixin):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa31d9ce_72ca3070","line":38,"range":{"start_line":38,"start_character":4,"end_line":38,"end_character":54},"in_reply_to":"fa31d9ce_aa78e4f9","updated":"2017-02-11 05:59:31.000000000","message":"Out of scope for this patch, but likely yes.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"}],"keystone/policy/backends/sql.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"68b0324f8e0eb70693dd86f57103692019e2c289","unresolved":false,"context_lines":[{"line_number":23,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue)"},{"line_number":24,"context_line":"    blob \u003d sql.Column(sql.JsonBlob(), nullable\u003dFalse)"},{"line_number":25,"context_line":"    type \u003d sql.Column(sql.String(255), nullable\u003dFalse)"},{"line_number":26,"context_line":"    extra \u003d sql.Column(sql.JsonBlob())"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"class Policy(rules.Policy):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa31d9ce_ea82dcc7","line":26,"range":{"start_line":26,"start_character":4,"end_line":26,"end_character":38},"updated":"2017-02-10 03:11:57.000000000","message":"delete this too","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"36224c84210c30dd321364942205d217eef2b7f2","unresolved":false,"context_lines":[{"line_number":23,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue)"},{"line_number":24,"context_line":"    blob \u003d sql.Column(sql.JsonBlob(), nullable\u003dFalse)"},{"line_number":25,"context_line":"    type \u003d sql.Column(sql.String(255), nullable\u003dFalse)"},{"line_number":26,"context_line":"    extra \u003d sql.Column(sql.JsonBlob())"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"class Policy(rules.Policy):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa31d9ce_92c9647b","line":26,"range":{"start_line":26,"start_character":4,"end_line":26,"end_character":38},"in_reply_to":"fa31d9ce_ea82dcc7","updated":"2017-02-11 05:59:31.000000000","message":"Same as other one. out of scope for this patch, doable though.","commit_id":"dce7c52de91a8717e2c16ff74ce13802e7d6a573"}]}
