)]}'
{"keystone/common/sql/migrate_repo/versions/089_add_identity_table_from_user_table.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"219a2a5397b7d0f4ae9a5a7dfa5da69c8ae52281","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":2,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":3,"context_line":"# a copy of the License at"},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":11,"id":"3a57f1b5_57fd53b2","line":1,"updated":"2016-02-12 21:57:20.000000000","message":"nit: this file could almost be: \n\n    089_rename_user_table_to_identity_table.py\n\ntook me a few minutes to figure out what was going on ;)","commit_id":"eee596d03a32a119da80e11d90fdf95ddee63cfa"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c44d62f257c916d7c4f7d7889e0a21ea45f6c469","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":2,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":3,"context_line":"# a copy of the License at"},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":11,"id":"1a54edaf_3d463fc0","line":1,"in_reply_to":"3a57f1b5_57fd53b2","updated":"2016-02-13 11:30:53.000000000","message":"Done","commit_id":"eee596d03a32a119da80e11d90fdf95ddee63cfa"}],"keystone/common/sql/migrate_repo/versions/089_rename_user_table_to_identity_table.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    meta \u003d sql.MetaData()"},{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dFalse)"},{"line_number":23,"context_line":"    if not identity_table.exists():"},{"line_number":24,"context_line":"        user_table \u003d sql.Table(\u0027user\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"        user_group_table \u003d sql.Table(\u0027user_group_membership\u0027, meta,"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_f00dae38","line":22,"range":{"start_line":22,"start_character":4,"end_line":22,"end_character":64},"updated":"2016-02-14 07:22:05.000000000","message":"it may help to add as comments the columns of the resulting identity table -- i was wondering what happened to the default_project_id, extra and enabled columns in migration 90, only to realize they are here, like:\n\n# the identity table will have the following columns:\n# id, extra, default_project_id, enabled\n# to be dropped: domain_id, name","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"64120c1cb9102f39803ec7f2021d33a40019d393","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    meta \u003d sql.MetaData()"},{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dFalse)"},{"line_number":23,"context_line":"    if not identity_table.exists():"},{"line_number":24,"context_line":"        user_table \u003d sql.Table(\u0027user\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"        user_group_table \u003d sql.Table(\u0027user_group_membership\u0027, meta,"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_5ec10480","line":22,"range":{"start_line":22,"start_character":4,"end_line":22,"end_character":64},"in_reply_to":"dae33548_f00dae38","updated":"2016-02-14 17:23:27.000000000","message":"Done","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dFalse)"},{"line_number":23,"context_line":"    if not identity_table.exists():"},{"line_number":24,"context_line":"        user_table \u003d sql.Table(\u0027user\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"        user_group_table \u003d sql.Table(\u0027user_group_membership\u0027, meta,"},{"line_number":26,"context_line":"                                     autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_9549b4d3","line":23,"range":{"start_line":23,"start_character":4,"end_line":23,"end_character":35},"updated":"2016-02-14 07:22:05.000000000","message":"i feel this check is unnecessary, but harmless","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"64120c1cb9102f39803ec7f2021d33a40019d393","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dFalse)"},{"line_number":23,"context_line":"    if not identity_table.exists():"},{"line_number":24,"context_line":"        user_table \u003d sql.Table(\u0027user\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"        user_group_table \u003d sql.Table(\u0027user_group_membership\u0027, meta,"},{"line_number":26,"context_line":"                                     autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_2344e972","line":23,"range":{"start_line":23,"start_character":4,"end_line":23,"end_character":35},"in_reply_to":"dae33548_9549b4d3","updated":"2016-02-14 17:23:27.000000000","message":"Agree, it\u0027s not needed, but was useful during dev testing and as you say, is harmless","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":27,"context_line":""},{"line_number":28,"context_line":"        # remove user indexes and contstraints"},{"line_number":29,"context_line":"        if migrate_engine.name !\u003d \u0027sqlite\u0027:"},{"line_number":30,"context_line":"            for index in user_table.indexes:"},{"line_number":31,"context_line":"                index.drop(migrate_engine)"},{"line_number":32,"context_line":"            fk_constraint \u003d [{\u0027table\u0027: user_group_table,"},{"line_number":33,"context_line":"                              \u0027fk_column\u0027: \u0027user_id\u0027,"},{"line_number":34,"context_line":"                              \u0027ref_column\u0027: user_table.c.id}]"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_751d10bd","line":31,"range":{"start_line":30,"start_character":12,"end_line":31,"end_character":42},"updated":"2016-02-14 07:22:05.000000000","message":"what about adding these indexes back?","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"594dc298880ccac828ddd0de4c44f3d89a296583","unresolved":false,"context_lines":[{"line_number":27,"context_line":""},{"line_number":28,"context_line":"        # remove user indexes and contstraints"},{"line_number":29,"context_line":"        if migrate_engine.name !\u003d \u0027sqlite\u0027:"},{"line_number":30,"context_line":"            for index in user_table.indexes:"},{"line_number":31,"context_line":"                index.drop(migrate_engine)"},{"line_number":32,"context_line":"            fk_constraint \u003d [{\u0027table\u0027: user_group_table,"},{"line_number":33,"context_line":"                              \u0027fk_column\u0027: \u0027user_id\u0027,"},{"line_number":34,"context_line":"                              \u0027ref_column\u0027: user_table.c.id}]"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_e38e8126","line":31,"range":{"start_line":30,"start_character":12,"end_line":31,"end_character":42},"in_reply_to":"dae33548_751d10bd","updated":"2016-02-14 16:35:01.000000000","message":"The unique index is added back in the new user table; no longer needed in this table.","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"        # allow domain_id and name to be null for now"},{"line_number":38,"context_line":"        # will drop these columns in a subsequent release"},{"line_number":39,"context_line":"        user_table.c.domain_id.alter(nullable\u003dTrue)"},{"line_number":40,"context_line":"        user_table.c.name.alter(nullable\u003dTrue)"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"        # rename user table to identity"},{"line_number":43,"context_line":"        user_table.rename(\u0027identity\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_1020129b","line":40,"range":{"start_line":39,"start_character":8,"end_line":40,"end_character":46},"updated":"2016-02-14 07:22:05.000000000","message":"what about the password column? https://github.com/openstack/keystone/blob/master/keystone/common/sql/migrate_repo/versions/067_kilo.py#L165","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"594dc298880ccac828ddd0de4c44f3d89a296583","unresolved":false,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"        # allow domain_id and name to be null for now"},{"line_number":38,"context_line":"        # will drop these columns in a subsequent release"},{"line_number":39,"context_line":"        user_table.c.domain_id.alter(nullable\u003dTrue)"},{"line_number":40,"context_line":"        user_table.c.name.alter(nullable\u003dTrue)"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"        # rename user table to identity"},{"line_number":43,"context_line":"        user_table.rename(\u0027identity\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_c3937d4e","line":40,"range":{"start_line":39,"start_character":8,"end_line":40,"end_character":46},"in_reply_to":"dae33548_1020129b","updated":"2016-02-14 16:35:01.000000000","message":"The password column is already nullable","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"7d33b468794092cb1cb40bbdc812ea3d80e8f850","unresolved":false,"context_lines":[{"line_number":23,"context_line":"    # id, extra, default_project_id, enabled"},{"line_number":24,"context_line":"    # To be dropped in a later release: domain_id, name, password"},{"line_number":25,"context_line":"    identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dFalse)"},{"line_number":26,"context_line":"    if not identity_table.exists():"},{"line_number":27,"context_line":"        user_table \u003d sql.Table(\u0027user\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"        user_group_table \u003d sql.Table(\u0027user_group_membership\u0027, meta,"},{"line_number":29,"context_line":"                                     autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_46d71623","line":26,"updated":"2016-02-16 19:48:39.000000000","message":"What is this for?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"49799a4454b5995ead77f06d2187dd34a72c8f8a","unresolved":false,"context_lines":[{"line_number":23,"context_line":"    # id, extra, default_project_id, enabled"},{"line_number":24,"context_line":"    # To be dropped in a later release: domain_id, name, password"},{"line_number":25,"context_line":"    identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dFalse)"},{"line_number":26,"context_line":"    if not identity_table.exists():"},{"line_number":27,"context_line":"        user_table \u003d sql.Table(\u0027user\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"        user_group_table \u003d sql.Table(\u0027user_group_membership\u0027, meta,"},{"line_number":29,"context_line":"                                     autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_862abe2a","line":26,"updated":"2016-02-16 19:27:57.000000000","message":"the migration shouldn\u0027t need to be idempotent - we don\u0027t expect to run them more than once.","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"49799a4454b5995ead77f06d2187dd34a72c8f8a","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            fk_constraint \u003d [{\u0027table\u0027: user_group_table,"},{"line_number":36,"context_line":"                              \u0027fk_column\u0027: \u0027user_id\u0027,"},{"line_number":37,"context_line":"                              \u0027ref_column\u0027: user_table.c.id}]"},{"line_number":38,"context_line":"            migration_helpers.remove_constraints(fk_constraint)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"        # Allow domain_id and name to be null for now;"},{"line_number":41,"context_line":"        # will drop these columns in a subsequent release"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_46643648","line":38,"updated":"2016-02-16 19:27:57.000000000","message":"with L46, do we need L31-38, L48-54?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6fe50523c753ed7b0e94358f892697cb9009a4b3","unresolved":false,"context_lines":[{"line_number":40,"context_line":"        # Allow domain_id and name to be null for now;"},{"line_number":41,"context_line":"        # will drop these columns in a subsequent release"},{"line_number":42,"context_line":"        user_table.c.domain_id.alter(nullable\u003dTrue)"},{"line_number":43,"context_line":"        user_table.c.name.alter(nullable\u003dTrue)"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"        # Rename user table to identity"},{"line_number":46,"context_line":"        user_table.rename(\u0027identity\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_49ba87c1","line":43,"updated":"2016-02-16 19:59:41.000000000","message":"If we\u0027re not pursuing minimal downtime migrations, we can just drop these in a subsequent migration (not need to make them nullable).","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"7d33b468794092cb1cb40bbdc812ea3d80e8f850","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        # Rename user table to identity"},{"line_number":46,"context_line":"        user_table.rename(\u0027identity\u0027)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        # Add user_group_membership fk contstraint back"},{"line_number":49,"context_line":"        identity_table \u003d sql.Table(\u0027identity\u0027, meta, autoload\u003dTrue)"},{"line_number":50,"context_line":"        if migrate_engine.name !\u003d \u0027sqlite\u0027:"},{"line_number":51,"context_line":"            constraint \u003d [{\u0027table\u0027: user_group_table,"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_662cda02","line":48,"updated":"2016-02-16 19:48:39.000000000","message":"What about the indexes? Do they need to be added back in?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":38,"context_line":"            migration_helpers.remove_constraints(fk_constraint)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"        # Allow domain_id and name to be null for now;"},{"line_number":41,"context_line":"        # will drop these columns in a subsequent release"},{"line_number":42,"context_line":"        user_table.c.domain_id.alter(nullable\u003dTrue)"},{"line_number":43,"context_line":"        user_table.c.name.alter(nullable\u003dTrue)"},{"line_number":44,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_bef6c2f6","line":41,"range":{"start_line":41,"start_character":8,"end_line":41,"end_character":57},"updated":"2016-02-17 12:59:18.000000000","message":"why?","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"0db516621b9e875c02347bb2aabcdfb1bd9b5e37","unresolved":false,"context_lines":[{"line_number":38,"context_line":"            migration_helpers.remove_constraints(fk_constraint)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"        # Allow domain_id and name to be null for now;"},{"line_number":41,"context_line":"        # will drop these columns in a subsequent release"},{"line_number":42,"context_line":"        user_table.c.domain_id.alter(nullable\u003dTrue)"},{"line_number":43,"context_line":"        user_table.c.name.alter(nullable\u003dTrue)"},{"line_number":44,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_7e66cd2a","line":41,"range":{"start_line":41,"start_character":8,"end_line":41,"end_character":57},"in_reply_to":"dae33548_bef6c2f6","updated":"2016-02-18 05:12:05.000000000","message":"We actually talked about this and I think we decided to drop them in this review, but in a later migration. It\u0027s still WIP so I\u0027m assuming that\u0027s coming soon.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"}],"keystone/common/sql/migrate_repo/versions/090_add_local_identity_and_local_identity_password_tables.py":[{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":23,"context_line":"        \u0027local_identity\u0027,"},{"line_number":24,"context_line":"        meta,"},{"line_number":25,"context_line":"        sql.Column(\u0027id\u0027, sql.String(64),"},{"line_number":26,"context_line":"                   sql.ForeignKey(identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":27,"context_line":"                   primary_key\u003dTrue),"},{"line_number":28,"context_line":"        sql.Column(\u0027domain_id\u0027, sql.String(64), nullable\u003dFalse),"},{"line_number":29,"context_line":"        sql.Column(\u0027name\u0027, sql.String(255), nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_9e4f7e6a","line":26,"range":{"start_line":26,"start_character":19,"end_line":26,"end_character":74},"updated":"2016-02-17 12:59:18.000000000","message":"I don\u0027t understand this. In the next migration things are copied from identity_table to local_identity_table. Either the copying is not needed or this Fk.\n\nThis is also inconsistent with what\u0027s in identity/backends/sql.py","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"0db516621b9e875c02347bb2aabcdfb1bd9b5e37","unresolved":false,"context_lines":[{"line_number":23,"context_line":"        \u0027local_identity\u0027,"},{"line_number":24,"context_line":"        meta,"},{"line_number":25,"context_line":"        sql.Column(\u0027id\u0027, sql.String(64),"},{"line_number":26,"context_line":"                   sql.ForeignKey(identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":27,"context_line":"                   primary_key\u003dTrue),"},{"line_number":28,"context_line":"        sql.Column(\u0027domain_id\u0027, sql.String(64), nullable\u003dFalse),"},{"line_number":29,"context_line":"        sql.Column(\u0027name\u0027, sql.String(255), nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_1e2a2190","line":26,"range":{"start_line":26,"start_character":19,"end_line":26,"end_character":74},"in_reply_to":"dae33548_9e4f7e6a","updated":"2016-02-18 05:12:05.000000000","message":"This is to make a 1-to-1 relationship between the identity and local_identity. We decided that due to issues with how the users can currently use their UUID to auth, that we would just say only 1 local identity per user.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    local_identity_table \u003d sql.Table("},{"line_number":23,"context_line":"        \u0027local_identity\u0027,"},{"line_number":24,"context_line":"        meta,"},{"line_number":25,"context_line":"        sql.Column(\u0027id\u0027, sql.String(64),"},{"line_number":26,"context_line":"                   sql.ForeignKey(identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":27,"context_line":"                   primary_key\u003dTrue),"},{"line_number":28,"context_line":"        sql.Column(\u0027domain_id\u0027, sql.String(64), nullable\u003dFalse),"},{"line_number":29,"context_line":"        sql.Column(\u0027name\u0027, sql.String(255), nullable\u003dFalse),"},{"line_number":30,"context_line":"        sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027))"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_fac22d33","line":27,"range":{"start_line":25,"start_character":0,"end_line":27,"end_character":37},"updated":"2016-02-17 06:59:10.000000000","message":"shouldn\u0027t the `id` an uuid?","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"0db516621b9e875c02347bb2aabcdfb1bd9b5e37","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    local_identity_table \u003d sql.Table("},{"line_number":23,"context_line":"        \u0027local_identity\u0027,"},{"line_number":24,"context_line":"        meta,"},{"line_number":25,"context_line":"        sql.Column(\u0027id\u0027, sql.String(64),"},{"line_number":26,"context_line":"                   sql.ForeignKey(identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":27,"context_line":"                   primary_key\u003dTrue),"},{"line_number":28,"context_line":"        sql.Column(\u0027domain_id\u0027, sql.String(64), nullable\u003dFalse),"},{"line_number":29,"context_line":"        sql.Column(\u0027name\u0027, sql.String(255), nullable\u003dFalse),"},{"line_number":30,"context_line":"        sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027))"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_be11755f","line":27,"range":{"start_line":25,"start_character":0,"end_line":27,"end_character":37},"in_reply_to":"dae33548_fac22d33","updated":"2016-02-18 05:12:05.000000000","message":"Nope. See above.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    password_table \u003d sql.Table("},{"line_number":34,"context_line":"        \u0027local_identity_password\u0027,"},{"line_number":35,"context_line":"        meta,"},{"line_number":36,"context_line":"        sql.Column(\u0027id\u0027, sql.Integer, primary_key\u003dTrue, nullable\u003dFalse),"},{"line_number":37,"context_line":"        sql.Column(\u0027local_identity_id\u0027, sql.String(64),"},{"line_number":38,"context_line":"                   sql.ForeignKey(local_identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027)),"},{"line_number":39,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_eb9d2a0b","line":36,"range":{"start_line":36,"start_character":8,"end_line":36,"end_character":72},"updated":"2016-02-17 12:59:18.000000000","message":"same question as Dave\u0027s above.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":36,"context_line":"        sql.Column(\u0027id\u0027, sql.Integer, primary_key\u003dTrue, nullable\u003dFalse),"},{"line_number":37,"context_line":"        sql.Column(\u0027local_identity_id\u0027, sql.String(64),"},{"line_number":38,"context_line":"                   sql.ForeignKey(local_identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027)),"},{"line_number":39,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":41,"context_line":"    password_table.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_e67c54b7","line":39,"range":{"start_line":39,"start_character":8,"end_line":39,"end_character":64},"updated":"2016-02-17 06:59:10.000000000","message":"\u0027password\u0027 is nullable, or else this will cause the migration fail.\n\n17460 TRACE keystone DBError: (pymysql.err.IntegrityError) (1048, u\"Column \u0027password\u0027 cannot be null\") [SQL: u\u0027INSERT INTO password (id, user_id, password) VALUES (%s, %s, %s), (%s, %s, %s), (%s, %s, %s), (%s, %s, %s), ...)","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        sql.Column(\u0027local_identity_id\u0027, sql.String(64),"},{"line_number":38,"context_line":"                   sql.ForeignKey(local_identity_table.c.id, ondelete\u003d\u0027CASCADE\u0027)),"},{"line_number":39,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":41,"context_line":"    password_table.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_3ec4725d","line":40,"range":{"start_line":40,"start_character":8,"end_line":40,"end_character":64},"updated":"2016-02-17 12:59:18.000000000","message":"this is out of scope of the current blueprint","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"}],"keystone/common/sql/migrate_repo/versions/090_add_local_user_and_password_tables.py":[{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    local_user \u003d sql.Table("},{"line_number":23,"context_line":"        \u0027local_user\u0027,"},{"line_number":24,"context_line":"        meta,"},{"line_number":25,"context_line":"        sql.Column(\u0027id\u0027, sql.Integer, primary_key\u003dTrue, nullable\u003dFalse),"},{"line_number":26,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":27,"context_line":"                   sql.ForeignKey(user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":28,"context_line":"                   nullable\u003dFalse, unique\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_5c03c073","line":25,"updated":"2016-02-19 15:46:38.000000000","message":"curious - since when we moved to integers?\nI am assuming this would be a new user_id for the rest of the services like nova,cinder?","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    local_user \u003d sql.Table("},{"line_number":23,"context_line":"        \u0027local_user\u0027,"},{"line_number":24,"context_line":"        meta,"},{"line_number":25,"context_line":"        sql.Column(\u0027id\u0027, sql.Integer, primary_key\u003dTrue, nullable\u003dFalse),"},{"line_number":26,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":27,"context_line":"                   sql.ForeignKey(user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":28,"context_line":"                   nullable\u003dFalse, unique\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_eb02c13d","line":25,"in_reply_to":"bae84128_5c03c073","updated":"2016-02-19 19:42:33.000000000","message":"This ID column would not be exposed to the API, so Morgan suggested that we use auto incrementing integers here.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":28,"context_line":"                   nullable\u003dFalse, unique\u003dTrue),"},{"line_number":29,"context_line":"        sql.Column(\u0027domain_id\u0027, sql.String(64), nullable\u003dFalse),"},{"line_number":30,"context_line":"        sql.Column(\u0027name\u0027, sql.String(255), nullable\u003dFalse),"},{"line_number":31,"context_line":"        sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027))"},{"line_number":32,"context_line":"    local_user.create(migrate_engine, checkfirst\u003dTrue)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    password \u003d sql.Table("}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_19d82a53","line":31,"updated":"2016-02-19 15:46:38.000000000","message":"I see user table have them too and the constraint is also created on {domain_id,name} pair. If the reason for duplication of domain_id and name attributes here is the fact, that keystone will always reach local_user table while validating tokens and so on, and we want to avoid lookups in another table than it\u0027s fine. I\u0027d add a comment with this reasoning.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":28,"context_line":"                   nullable\u003dFalse, unique\u003dTrue),"},{"line_number":29,"context_line":"        sql.Column(\u0027domain_id\u0027, sql.String(64), nullable\u003dFalse),"},{"line_number":30,"context_line":"        sql.Column(\u0027name\u0027, sql.String(255), nullable\u003dFalse),"},{"line_number":31,"context_line":"        sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027))"},{"line_number":32,"context_line":"    local_user.create(migrate_engine, checkfirst\u003dTrue)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    password \u003d sql.Table("}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_0ba8c51e","line":31,"in_reply_to":"bae84128_19d82a53","updated":"2016-02-19 19:42:33.000000000","message":"The columns in the \"user\" table get removed.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":39,"context_line":"                   sql.ForeignKey(local_user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":40,"context_line":"                   nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_99c71a45","line":42,"updated":"2016-02-19 15:46:38.000000000","message":"was this added for a future use (i see clear use case for that)? I don\u0027t think shadow users are going to implement password/user expiration. \nIf we are still adding it for a future use I\u0027d vote for adding \u0027date_created\u0027 and \u0027expires_at\u0027 parameters in the local_user table.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"231da935b80c4ceccf30bb3435fca73b639f6de3","unresolved":false,"context_lines":[{"line_number":39,"context_line":"                   sql.ForeignKey(local_user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":40,"context_line":"                   nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_d9d87020","line":42,"in_reply_to":"bae84128_66b9c3e9","updated":"2016-02-19 21:32:22.000000000","message":"yes, please remove it. It will definitely cause misunderstanding.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"7295eb61dabb62c0974ce7f673f29b00acb1b636","unresolved":false,"context_lines":[{"line_number":39,"context_line":"                   sql.ForeignKey(local_user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":40,"context_line":"                   nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_8bb680da","line":42,"in_reply_to":"bae84128_6b4a3185","updated":"2016-02-20 10:59:40.000000000","message":"Done","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"fe87564aa9765ca195bfb4f9ac59b32a5d70a879","unresolved":false,"context_lines":[{"line_number":39,"context_line":"                   sql.ForeignKey(local_user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":40,"context_line":"                   nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_66b9c3e9","line":42,"in_reply_to":"bae84128_6b4a3185","updated":"2016-02-19 21:00:34.000000000","message":"Leaving expires_at in for now.  If folks have a big issue with this, I\u0027ll take it out.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":39,"context_line":"                   sql.ForeignKey(local_user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":40,"context_line":"                   nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_6b4a3185","line":42,"in_reply_to":"bae84128_99c71a45","updated":"2016-02-19 19:42:33.000000000","message":"Correct, it\u0027s for future use. I don\u0027t want to rabbit hole on things outside the scope of this patch so I\u0027d rather see this removed for now if there are any questions that cannot wait for Newton.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"7295eb61dabb62c0974ce7f673f29b00acb1b636","unresolved":false,"context_lines":[{"line_number":39,"context_line":"                   sql.ForeignKey(local_user.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":40,"context_line":"                   nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_6bbb3cc5","line":42,"in_reply_to":"bae84128_d9d87020","updated":"2016-02-20 10:59:40.000000000","message":"Done","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"}],"keystone/common/sql/migrate_repo/versions/090_add_user_and_password_tables.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":40,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027)),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password_table.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_b5c038e2","line":42,"updated":"2016-02-14 07:22:05.000000000","message":"i wasn\u0027t clear on why we were adding a password table, instead of having it be a column like it was in the old table (https://github.com/openstack/keystone/blob/master/keystone/common/sql/migrate_repo/versions/067_kilo.py#L165), but this kinda explains it... for future work here i guess?","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"594dc298880ccac828ddd0de4c44f3d89a296583","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":40,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027)),"},{"line_number":41,"context_line":"        sql.Column(\u0027password\u0027, sql.String(128), nullable\u003dFalse),"},{"line_number":42,"context_line":"        sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue))"},{"line_number":43,"context_line":"    password_table.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_e3b5e1d0","line":42,"in_reply_to":"dae33548_b5c038e2","updated":"2016-02-14 16:35:01.000000000","message":"Yes, to accommodate future use cases, such as supporting multiple passwords and rules around password history.","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"}],"keystone/common/sql/migrate_repo/versions/091_migrate_data_to_local_identity_and_local_identity_password_tables.py":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":29,"context_line":"            sql.select([local_table.c.id])))"},{"line_number":30,"context_line":"    )"},{"line_number":31,"context_line":"    rows \u003d sel.execute()"},{"line_number":32,"context_line":"    local_identity_dict \u003d []"},{"line_number":33,"context_line":"    for row in rows:"},{"line_number":34,"context_line":"        local_identity_dict.append({\u0027id\u0027: row[\u0027id\u0027],"},{"line_number":35,"context_line":"                                    \u0027domain_id\u0027: row[\u0027domain_id\u0027],"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_a61fec06","line":32,"range":{"start_line":32,"start_character":4,"end_line":32,"end_character":23},"updated":"2016-02-17 06:59:10.000000000","message":"[] is not a dict.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"0db516621b9e875c02347bb2aabcdfb1bd9b5e37","unresolved":false,"context_lines":[{"line_number":29,"context_line":"            sql.select([local_table.c.id])))"},{"line_number":30,"context_line":"    )"},{"line_number":31,"context_line":"    rows \u003d sel.execute()"},{"line_number":32,"context_line":"    local_identity_dict \u003d []"},{"line_number":33,"context_line":"    for row in rows:"},{"line_number":34,"context_line":"        local_identity_dict.append({\u0027id\u0027: row[\u0027id\u0027],"},{"line_number":35,"context_line":"                                    \u0027domain_id\u0027: row[\u0027domain_id\u0027],"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_1e018106","line":32,"range":{"start_line":32,"start_character":4,"end_line":32,"end_character":23},"in_reply_to":"dae33548_a61fec06","updated":"2016-02-18 05:12:05.000000000","message":"I don\u0027t think this is meant to show the type of the object, but rather the type of the objects in the list. I think \u0027local_indentity_dicts\u0027 would be clearer.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"}],"keystone/common/sql/migrate_repo/versions/091_migrate_user_and_password_data.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6fe50523c753ed7b0e94358f892697cb9009a4b3","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    # migrate data - user table"},{"line_number":27,"context_line":"    sel \u003d ("},{"line_number":28,"context_line":"        identity_table.select().where(identity_table.c.id.notin_("},{"line_number":29,"context_line":"            sql.select([user_table.c.identity_id])))"},{"line_number":30,"context_line":"    )"},{"line_number":31,"context_line":"    rows \u003d sel.execute()"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_09f99f4d","line":28,"updated":"2016-02-16 19:59:41.000000000","message":"If this is an offline migration, then we don\u0027t need idempotence here. Simplify! :D","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6fe50523c753ed7b0e94358f892697cb9009a4b3","unresolved":false,"context_lines":[{"line_number":43,"context_line":"        sql.select([identity_table, user_table], use_labels\u003dTrue)"},{"line_number":44,"context_line":"           .select_from(identity_table.join(user_table, identity_table.c.id \u003d\u003d"},{"line_number":45,"context_line":"                                            user_table.c.identity_id))"},{"line_number":46,"context_line":"           .where(user_table.c.id.notin_("},{"line_number":47,"context_line":"               sql.select([password_table.c.user_id])))"},{"line_number":48,"context_line":"    )"},{"line_number":49,"context_line":"    rows \u003d sel.execute()"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_a9b7d384","line":46,"updated":"2016-02-16 19:59:41.000000000","message":"same as above","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6fe50523c753ed7b0e94358f892697cb9009a4b3","unresolved":false,"context_lines":[{"line_number":47,"context_line":"               sql.select([password_table.c.user_id])))"},{"line_number":48,"context_line":"    )"},{"line_number":49,"context_line":"    rows \u003d sel.execute()"},{"line_number":50,"context_line":"    password_dict \u003d []"},{"line_number":51,"context_line":"    for row in rows:"},{"line_number":52,"context_line":"        password_dict.append({\u0027id\u0027: row[\u0027identity_id\u0027],"},{"line_number":53,"context_line":"                              \u0027user_id\u0027: row[\u0027user_id\u0027],"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_2c4d916c","line":50,"updated":"2016-02-16 19:59:41.000000000","message":"_dict implies this is a {}, not a []\n\nMaybe \"password_values \u003d []\" instead?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"95e8120d69ad8c1a44f26fbb54e316d91867878b","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    rows \u003d sel.execute()"},{"line_number":50,"context_line":"    password_dict \u003d []"},{"line_number":51,"context_line":"    for row in rows:"},{"line_number":52,"context_line":"        password_dict.append({\u0027id\u0027: row[\u0027identity_id\u0027],"},{"line_number":53,"context_line":"                              \u0027user_id\u0027: row[\u0027user_id\u0027],"},{"line_number":54,"context_line":"                              \u0027password\u0027: row[\u0027identity_password\u0027]})"},{"line_number":55,"context_line":"    if password_dict:"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_4df481f1","line":52,"range":{"start_line":52,"start_character":36,"end_line":52,"end_character":54},"updated":"2016-02-16 06:27:20.000000000","message":"i think having this as a random uuid was the right move","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"b256328e0416f7881430bd7691ceb6844247c15c","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    rows \u003d sel.execute()"},{"line_number":50,"context_line":"    password_dict \u003d []"},{"line_number":51,"context_line":"    for row in rows:"},{"line_number":52,"context_line":"        password_dict.append({\u0027id\u0027: row[\u0027identity_id\u0027],"},{"line_number":53,"context_line":"                              \u0027user_id\u0027: row[\u0027user_id\u0027],"},{"line_number":54,"context_line":"                              \u0027password\u0027: row[\u0027identity_password\u0027]})"},{"line_number":55,"context_line":"    if password_dict:"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_88000e03","line":52,"range":{"start_line":52,"start_character":36,"end_line":52,"end_character":54},"in_reply_to":"dae33548_4df481f1","updated":"2016-02-16 18:06:05.000000000","message":"Nice catch Steve :)  I was using the identity_id so that I could easily test the password migration.  I think this should actually be okay, what is your concern?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"}],"keystone/identity/backends/sql.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":204,"context_line":"            session.add(user_ref)"},{"line_number":205,"context_line":"        return identity.filter_user(user_ref.to_dict())"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def _add_create_user_ids(self, user_ref):"},{"line_number":208,"context_line":"        if user_ref.users:"},{"line_number":209,"context_line":"            user_ref.users[0].id \u003d uuid.uuid4().hex"},{"line_number":210,"context_line":"        if user_ref.users and user_ref.users[0].passwords:"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_906262d7","line":207,"range":{"start_line":207,"start_character":8,"end_line":207,"end_character":28},"updated":"2016-02-14 07:22:05.000000000","message":"this needs a comment describing what\u0027s going on, it\u0027s non-obvious","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"64120c1cb9102f39803ec7f2021d33a40019d393","unresolved":false,"context_lines":[{"line_number":204,"context_line":"            session.add(user_ref)"},{"line_number":205,"context_line":"        return identity.filter_user(user_ref.to_dict())"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def _add_create_user_ids(self, user_ref):"},{"line_number":208,"context_line":"        if user_ref.users:"},{"line_number":209,"context_line":"            user_ref.users[0].id \u003d uuid.uuid4().hex"},{"line_number":210,"context_line":"        if user_ref.users and user_ref.users[0].passwords:"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_bebe50fd","line":207,"range":{"start_line":207,"start_character":8,"end_line":207,"end_character":28},"in_reply_to":"dae33548_906262d7","updated":"2016-02-14 17:23:27.000000000","message":"Done","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"7d33b468794092cb1cb40bbdc812ea3d80e8f850","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import uuid"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from oslo_config import cfg"},{"line_number":18,"context_line":"from sqlalchemy import and_"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_49f28770","line":15,"updated":"2016-02-16 19:48:39.000000000","message":"Why is this in here?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"7d33b468794092cb1cb40bbdc812ea3d80e8f850","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import uuid"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from oslo_config import cfg"},{"line_number":18,"context_line":"from sqlalchemy import and_"},{"line_number":19,"context_line":"from sqlalchemy.ext.hybrid import hybrid_property"},{"line_number":20,"context_line":"from sqlalchemy import orm"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_29fe2337","line":18,"updated":"2016-02-16 19:48:39.000000000","message":"or this...","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"7d33b468794092cb1cb40bbdc812ea3d80e8f850","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    def domain_id(cls):"},{"line_number":101,"context_line":"        return User.domain_id"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def to_dict(self, include_extra_dict\u003dFalse):"},{"line_number":104,"context_line":"        d \u003d super(UserIdentity, self).to_dict("},{"line_number":105,"context_line":"            include_extra_dict\u003dinclude_extra_dict)"},{"line_number":106,"context_line":"        if \u0027default_project_id\u0027 in d and d[\u0027default_project_id\u0027] is None:"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_497d67e6","line":103,"updated":"2016-02-16 19:48:39.000000000","message":"Is there anything that will depend on this returning domain_id, password, etc?","commit_id":"9048e88bed22108f1547c14b88d959246ac4a029"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    default_project_id \u003d sql.Column(sql.String(64))"},{"line_number":39,"context_line":"    # Unique constraint across two columns to create the separation"},{"line_number":40,"context_line":"    # rather than just only \u0027name\u0027 being unique"},{"line_number":41,"context_line":"    __table_args__ \u003d (sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027), {})"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def to_dict(self, include_extra_dict\u003dFalse):"},{"line_number":44,"context_line":"        d \u003d super(User, self).to_dict(include_extra_dict\u003dinclude_extra_dict)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_b7a560a3","side":"PARENT","line":41,"range":{"start_line":41,"start_character":4,"end_line":41,"end_character":68},"updated":"2016-02-17 06:59:10.000000000","message":"Does that mean name needn\u0027t be unique within the domain in identity table anymore? uniqueness only needed when it is mapped into local identity?","commit_id":"3eb718b9dca5e15b5b9154ecdf5b7cd512d76607"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"0db516621b9e875c02347bb2aabcdfb1bd9b5e37","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    default_project_id \u003d sql.Column(sql.String(64))"},{"line_number":39,"context_line":"    # Unique constraint across two columns to create the separation"},{"line_number":40,"context_line":"    # rather than just only \u0027name\u0027 being unique"},{"line_number":41,"context_line":"    __table_args__ \u003d (sql.UniqueConstraint(\u0027domain_id\u0027, \u0027name\u0027), {})"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def to_dict(self, include_extra_dict\u003dFalse):"},{"line_number":44,"context_line":"        d \u003d super(User, self).to_dict(include_extra_dict\u003dinclude_extra_dict)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_52349ddc","side":"PARENT","line":41,"range":{"start_line":41,"start_character":4,"end_line":41,"end_character":68},"in_reply_to":"dae33548_b7a560a3","updated":"2016-02-18 05:12:05.000000000","message":"This is now being forced in the local_identity.","commit_id":"3eb718b9dca5e15b5b9154ecdf5b7cd512d76607"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":67,"context_line":"            return None"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    @password.setter"},{"line_number":70,"context_line":"    def password(self, value):"},{"line_number":71,"context_line":"        if not value:"},{"line_number":72,"context_line":"            if self.users and self.users[0].passwords:"},{"line_number":73,"context_line":"                self.users[0].passwords \u003d []"},{"line_number":74,"context_line":"        else:"},{"line_number":75,"context_line":"            if not self.users:"},{"line_number":76,"context_line":"                self.users.append(User())"},{"line_number":77,"context_line":"            if not self.users[0].passwords:"},{"line_number":78,"context_line":"                self.users[0].passwords.append(Password())"},{"line_number":79,"context_line":"            self.users[0].passwords[0].password \u003d value"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    @password.expression"},{"line_number":82,"context_line":"    def password(cls):"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_062e98a4","line":79,"range":{"start_line":70,"start_character":0,"end_line":79,"end_character":55},"updated":"2016-02-17 06:59:10.000000000","message":"possible to add some testcases to verify the methods like this?","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":67,"context_line":"            return None"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    @password.setter"},{"line_number":70,"context_line":"    def password(self, value):"},{"line_number":71,"context_line":"        if not value:"},{"line_number":72,"context_line":"            if self.users and self.users[0].passwords:"},{"line_number":73,"context_line":"                self.users[0].passwords \u003d []"},{"line_number":74,"context_line":"        else:"},{"line_number":75,"context_line":"            if not self.users:"},{"line_number":76,"context_line":"                self.users.append(User())"},{"line_number":77,"context_line":"            if not self.users[0].passwords:"},{"line_number":78,"context_line":"                self.users[0].passwords.append(Password())"},{"line_number":79,"context_line":"            self.users[0].passwords[0].password \u003d value"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    @password.expression"},{"line_number":82,"context_line":"    def password(cls):"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_9e065e84","line":79,"range":{"start_line":70,"start_character":0,"end_line":79,"end_character":55},"in_reply_to":"dae33548_062e98a4","updated":"2016-02-17 12:59:18.000000000","message":"there must be a testcase for this. Basically setting a password creates a local user. I am not sure that this is intentional decision and that it should be done this way.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"0db516621b9e875c02347bb2aabcdfb1bd9b5e37","unresolved":false,"context_lines":[{"line_number":67,"context_line":"            return None"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    @password.setter"},{"line_number":70,"context_line":"    def password(self, value):"},{"line_number":71,"context_line":"        if not value:"},{"line_number":72,"context_line":"            if self.users and self.users[0].passwords:"},{"line_number":73,"context_line":"                self.users[0].passwords \u003d []"},{"line_number":74,"context_line":"        else:"},{"line_number":75,"context_line":"            if not self.users:"},{"line_number":76,"context_line":"                self.users.append(User())"},{"line_number":77,"context_line":"            if not self.users[0].passwords:"},{"line_number":78,"context_line":"                self.users[0].passwords.append(Password())"},{"line_number":79,"context_line":"            self.users[0].passwords[0].password \u003d value"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    @password.expression"},{"line_number":82,"context_line":"    def password(cls):"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_9229058d","line":79,"range":{"start_line":70,"start_character":0,"end_line":79,"end_character":55},"in_reply_to":"dae33548_9e065e84","updated":"2016-02-18 05:12:05.000000000","message":"This is intentional. These methods are designed to hide the extra tables from the code already using it. Definitely needs tests.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"class User(sql.ModelBase, sql.DictBase):"},{"line_number":112,"context_line":"    __tablename__ \u003d \u0027user\u0027"},{"line_number":113,"context_line":"    attributes \u003d [\u0027id\u0027, \u0027identity_id\u0027, \u0027domain_id\u0027, \u0027name\u0027]"},{"line_number":114,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue)"},{"line_number":115,"context_line":"    identity_id \u003d sql.Column(sql.String(64),"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_7aa9fd8f","line":112,"range":{"start_line":112,"start_character":4,"end_line":112,"end_character":26},"updated":"2016-02-17 06:59:10.000000000","message":"change the table name to \"local_identity\" to consistent with the upgrade scripts, change schema as well.\n\nhttps://review.openstack.org/#/c/278570/16/keystone/common/sql/migrate_repo/versions/090_add_local_identity_and_local_identity_password_tables.py@23","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":121,"context_line":""},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"class Password(sql.ModelBase, sql.DictBase):"},{"line_number":124,"context_line":"    __tablename__ \u003d \u0027password\u0027"},{"line_number":125,"context_line":"    attributes \u003d [\u0027id\u0027, \u0027user_id\u0027, \u0027password\u0027, \u0027expires_at\u0027]"},{"line_number":126,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue)"},{"line_number":127,"context_line":"    user_id \u003d sql.Column(sql.String(64),"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_9a94c143","line":124,"range":{"start_line":124,"start_character":4,"end_line":124,"end_character":30},"updated":"2016-02-17 06:59:10.000000000","message":"same here.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":54,"context_line":"    def name(cls):"},{"line_number":55,"context_line":"        return LocalUser.name"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    # password property"},{"line_number":58,"context_line":"    @hybrid_property"},{"line_number":59,"context_line":"    def password(self):"},{"line_number":60,"context_line":"        if self.local_user and self.local_user.passwords:"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_7c20449c","line":57,"updated":"2016-02-19 15:46:38.000000000","message":"i don\u0027t think this comment has too much of a value :-)","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":54,"context_line":"    def name(cls):"},{"line_number":55,"context_line":"        return LocalUser.name"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    # password property"},{"line_number":58,"context_line":"    @hybrid_property"},{"line_number":59,"context_line":"    def password(self):"},{"line_number":60,"context_line":"        if self.local_user and self.local_user.passwords:"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_cb09bd33","line":57,"in_reply_to":"bae84128_7c20449c","updated":"2016-02-19 19:42:33.000000000","message":"Somewhat ironic ^","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":66,"context_line":"    def password(self, value):"},{"line_number":67,"context_line":"        if not self.local_user:"},{"line_number":68,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":69,"context_line":"        if not self.local_user.passwords:"},{"line_number":70,"context_line":"            self.local_user.passwords.append(Password())"},{"line_number":71,"context_line":"        self.local_user.passwords[0].password \u003d value"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_3c5ebce9","line":69,"updated":"2016-02-19 15:46:38.000000000","message":"can we have a situation where a local exists and he has no password or it\u0027s just handling a case where self.local_user was empty 3 lines before? If that\u0027s the case I\u0027d suggest appending Password()object right after the LocalUser() object was created:\n\nif not self.local_user:\n    self.local_user \u003d LocalUser()\n    self.local_user.passwords.append(Password())\n[...]","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":66,"context_line":"    def password(self, value):"},{"line_number":67,"context_line":"        if not self.local_user:"},{"line_number":68,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":69,"context_line":"        if not self.local_user.passwords:"},{"line_number":70,"context_line":"            self.local_user.passwords.append(Password())"},{"line_number":71,"context_line":"        self.local_user.passwords[0].password \u003d value"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_962518ad","line":69,"in_reply_to":"bae84128_3c5ebce9","updated":"2016-02-19 19:42:33.000000000","message":"We\u0027ve traditionally allowed users to be created in SQL without passwords, yes.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        if self.local_user:"},{"line_number":81,"context_line":"            return self.local_user.domain_id"},{"line_number":82,"context_line":"        else:"},{"line_number":83,"context_line":"            return None"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    @domain_id.setter"},{"line_number":86,"context_line":"    def domain_id(self, value):"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_dceeb0eb","line":83,"updated":"2016-02-19 15:46:38.000000000","message":"you could also do:\n\nself.get(\u0027local_user\u0027,{}).get(\u0027domain_id\u0027,None)","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        if self.local_user:"},{"line_number":81,"context_line":"            return self.local_user.domain_id"},{"line_number":82,"context_line":"        else:"},{"line_number":83,"context_line":"            return None"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    @domain_id.setter"},{"line_number":86,"context_line":"    def domain_id(self, value):"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_965cf826","line":83,"in_reply_to":"bae84128_dceeb0eb","updated":"2016-02-19 19:42:33.000000000","message":"The existing code is much easier to read than a chain of .get()s, IMO.\n\nIf you want to simplify things, methods \"return None\" by default in Python anyway, so you could just delete L82-83 without any consequence.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":8978,"name":"Marek Denis","email":"marek.denis+openstack@gmail.com","username":"marek-denis"},"change_message_id":"3c918942604ba00e2c45b739a42f8d8188112877","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    @domain_id.setter"},{"line_number":86,"context_line":"    def domain_id(self, value):"},{"line_number":87,"context_line":"        if not self.local_user:"},{"line_number":88,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":89,"context_line":"        self.local_user.domain_id \u003d value"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"    @domain_id.expression"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_bc7c8c21","line":88,"updated":"2016-02-19 15:46:38.000000000","message":"you can add a private method doing that.\n1) Cleaner code\n2) You will not repeat those lines","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"b91300d162c94fe7ae00717a355977b9d24800d6","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    @domain_id.setter"},{"line_number":86,"context_line":"    def domain_id(self, value):"},{"line_number":87,"context_line":"        if not self.local_user:"},{"line_number":88,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":89,"context_line":"        self.local_user.domain_id \u003d value"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"    @domain_id.expression"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_967358b1","line":88,"in_reply_to":"bae84128_bc7c8c21","updated":"2016-02-19 19:42:33.000000000","message":"A 3 line private method to replace 3 instances of 2 lines of trivial code is not a particularly beneficial refactor.","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"1b0bbeb6dc2709ac564e1c81a5f2404c498fb68d","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    @name.expression"},{"line_number":54,"context_line":"    def name(cls):"},{"line_number":55,"context_line":"        return LocalUser.name"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    # password property"},{"line_number":58,"context_line":"    @hybrid_property"}],"source_content_type":"text/x-python","patch_set":39,"id":"bae84128_b34eeb6c","line":55,"updated":"2016-02-23 13:29:02.000000000","message":"I had to play with this a little to figure out what it does. sqlalchemy will turn a filter on \"name\u003d?\" into a join of the user and local_user tables.","commit_id":"312a041862dc48b776715ccb2585d21cc479f5fb"}],"keystone/tests/unit/test_backend_sql.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"        self.assertItemsEqual(expected_schema, actual_schema)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def test_identity_model(self):"},{"line_number":126,"context_line":"        cols \u003d ((\u0027id\u0027, sql.String, 64),"},{"line_number":127,"context_line":"                (\u0027default_project_id\u0027, sql.String, 64),"},{"line_number":128,"context_line":"                (\u0027enabled\u0027, sql.Boolean, None),"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_d0818a4f","line":125,"range":{"start_line":125,"start_character":8,"end_line":125,"end_character":27},"updated":"2016-02-14 07:22:05.000000000","message":"shouldn\u0027t this have domain_id and name and password, those were only set to null? i didn\u0027t see that they were dropped","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"594dc298880ccac828ddd0de4c44f3d89a296583","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"        self.assertItemsEqual(expected_schema, actual_schema)"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    def test_identity_model(self):"},{"line_number":126,"context_line":"        cols \u003d ((\u0027id\u0027, sql.String, 64),"},{"line_number":127,"context_line":"                (\u0027default_project_id\u0027, sql.String, 64),"},{"line_number":128,"context_line":"                (\u0027enabled\u0027, sql.Boolean, None),"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_23e7c9e5","line":125,"range":{"start_line":125,"start_character":8,"end_line":125,"end_character":27},"in_reply_to":"dae33548_d0818a4f","updated":"2016-02-14 16:35:01.000000000","message":"There is a comment here stating that the columns will be dropped in a later release:\nhttps://review.openstack.org/#/c/278570/13/keystone/common/sql/migrate_repo/versions/089_rename_user_table_to_identity_table.py\n\nDo we really need to test for them as they are no longer needed?","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"}],"keystone/tests/unit/test_sql_upgrade.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"9431863871b003e9681cf948c76ac4264114ad28","unresolved":false,"context_lines":[{"line_number":753,"context_line":"                                 \u0027password\u0027,"},{"line_number":754,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":755,"context_line":""},{"line_number":756,"context_line":"    def test_migrate_user_password_tables(self):"},{"line_number":757,"context_line":"        identity_table \u003d \u0027identity\u0027"},{"line_number":758,"context_line":"        user_table \u003d \u0027user\u0027"},{"line_number":759,"context_line":"        password_table \u003d \u0027password\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_d036aab3","line":756,"range":{"start_line":756,"start_character":4,"end_line":756,"end_character":48},"updated":"2016-02-14 07:22:05.000000000","message":"what data is it actually migrating?\n\ni think we\u0027re missing some cases, where default_project_id is created, and extras is used, and where a user lives in a non-default domain","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"64120c1cb9102f39803ec7f2021d33a40019d393","unresolved":false,"context_lines":[{"line_number":753,"context_line":"                                 \u0027password\u0027,"},{"line_number":754,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":755,"context_line":""},{"line_number":756,"context_line":"    def test_migrate_user_password_tables(self):"},{"line_number":757,"context_line":"        identity_table \u003d \u0027identity\u0027"},{"line_number":758,"context_line":"        user_table \u003d \u0027user\u0027"},{"line_number":759,"context_line":"        password_table \u003d \u0027password\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_fe3618b3","line":756,"range":{"start_line":756,"start_character":4,"end_line":756,"end_character":48},"in_reply_to":"dae33548_d036aab3","updated":"2016-02-14 17:23:27.000000000","message":"Also, renamed this test to be more clear","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"594dc298880ccac828ddd0de4c44f3d89a296583","unresolved":false,"context_lines":[{"line_number":753,"context_line":"                                 \u0027password\u0027,"},{"line_number":754,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":755,"context_line":""},{"line_number":756,"context_line":"    def test_migrate_user_password_tables(self):"},{"line_number":757,"context_line":"        identity_table \u003d \u0027identity\u0027"},{"line_number":758,"context_line":"        user_table \u003d \u0027user\u0027"},{"line_number":759,"context_line":"        password_table \u003d \u0027password\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_63f8b17d","line":756,"range":{"start_line":756,"start_character":4,"end_line":756,"end_character":48},"in_reply_to":"dae33548_d036aab3","updated":"2016-02-14 16:35:01.000000000","message":"The data in the old user table (now identity table) is being moved to new user and password tables. The default_project_id and extra columns remain in the parent identity table. While we\u0027re separating this data out now to support future uses cases, the user behavior hasn\u0027t changed in this patch.","commit_id":"24813105a9bae02e11fb59ec55e4e3e9df01e767"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":242,"context_line":"                                 \u0027({3})\u0027.format(table1_name, table1_count,"},{"line_number":243,"context_line":"                                                table2_name, table2_count))"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    def assertTableValuesMatch(self, table1_name, table1_join_id, table1_cols,"},{"line_number":246,"context_line":"                               table2_name, table2_join_id, table2_cols,"},{"line_number":247,"context_line":"                               max_row_count):"},{"line_number":248,"context_line":"        self.assertTableCountsMatch(table1_name, table2_name)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_c185a707","line":245,"range":{"start_line":245,"start_character":50,"end_line":245,"end_character":64},"updated":"2016-02-17 12:59:18.000000000","message":"wha\u0027t this for?","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":243,"context_line":"                                                table2_name, table2_count))"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    def assertTableValuesMatch(self, table1_name, table1_join_id, table1_cols,"},{"line_number":246,"context_line":"                               table2_name, table2_join_id, table2_cols,"},{"line_number":247,"context_line":"                               max_row_count):"},{"line_number":248,"context_line":"        self.assertTableCountsMatch(table1_name, table2_name)"},{"line_number":249,"context_line":"        table1 \u003d sqlalchemy.Table(table1_name, self.metadata, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_818f1f29","line":246,"range":{"start_line":246,"start_character":44,"end_line":246,"end_character":58},"updated":"2016-02-17 12:59:18.000000000","message":"what\u0027s this for?","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    def assertTableValuesMatch(self, table1_name, table1_join_id, table1_cols,"},{"line_number":246,"context_line":"                               table2_name, table2_join_id, table2_cols,"},{"line_number":247,"context_line":"                               max_row_count):"},{"line_number":248,"context_line":"        self.assertTableCountsMatch(table1_name, table2_name)"},{"line_number":249,"context_line":"        table1 \u003d sqlalchemy.Table(table1_name, self.metadata, autoload\u003dTrue)"},{"line_number":250,"context_line":"        table2 \u003d sqlalchemy.Table(table2_name, self.metadata, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_61c77b64","line":247,"range":{"start_line":247,"start_character":31,"end_line":247,"end_character":44},"updated":"2016-02-17 12:59:18.000000000","message":"what\u0027s this for?","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":248,"context_line":"        self.assertTableCountsMatch(table1_name, table2_name)"},{"line_number":249,"context_line":"        table1 \u003d sqlalchemy.Table(table1_name, self.metadata, autoload\u003dTrue)"},{"line_number":250,"context_line":"        table2 \u003d sqlalchemy.Table(table2_name, self.metadata, autoload\u003dTrue)"},{"line_number":251,"context_line":"        stmt \u003d ("},{"line_number":252,"context_line":"            sqlalchemy.select([table1, table2], use_labels\u003dTrue)"},{"line_number":253,"context_line":"            .select_from(table1.join(table2, table1.c[table1_join_id] \u003d\u003d"},{"line_number":254,"context_line":"                                     table2.c[table2_join_id]))"},{"line_number":255,"context_line":"        )"},{"line_number":256,"context_line":"        rows \u003d stmt.execute()"},{"line_number":257,"context_line":"        row_count \u003d 0"},{"line_number":258,"context_line":"        for row in rows:"},{"line_number":259,"context_line":"            if row_count \u003e\u003d max_row_count:"},{"line_number":260,"context_line":"                break"},{"line_number":261,"context_line":"            for i in range(0, len(table1_cols)):"},{"line_number":262,"context_line":"                table1_column_name \u003d table1_name + \"_\" + table1_cols[i]"},{"line_number":263,"context_line":"                table2_column_name \u003d table2_name + \"_\" + table2_cols[i]"},{"line_number":264,"context_line":"                if row[table1_column_name] !\u003d row[table2_column_name]:"},{"line_number":265,"context_line":"                    raise AssertionError(\u0027Values do not match {0}: {1}, {2}: \u0027"},{"line_number":266,"context_line":"                                         \u0027{3}\u0027.format(table1_column_name,"},{"line_number":267,"context_line":"                                                      row[table1_column_name],"},{"line_number":268,"context_line":"                                                      table2_column_name,"},{"line_number":269,"context_line":"                                                      row[table2_column_name]))"},{"line_number":270,"context_line":"            row_count +\u003d 1"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"    def upgrade(self, *args, **kwargs):"},{"line_number":273,"context_line":"        self._migrate(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_21c73397","line":270,"range":{"start_line":251,"start_character":0,"end_line":270,"end_character":26},"updated":"2016-02-17 12:59:18.000000000","message":"Also, please add a docstring describing the method and some comments. My puny human mind took a lot of time to understand what\u0027s going on here.","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":727,"context_line":""},{"line_number":728,"context_line":"    def test_create_identity_user_password_tables(self):"},{"line_number":729,"context_line":"        identity_table \u003d \u0027identity\u0027"},{"line_number":730,"context_line":"        user_table \u003d \u0027user\u0027"},{"line_number":731,"context_line":"        password_table \u003d \u0027password\u0027"},{"line_number":732,"context_line":"        self.upgrade(88)"},{"line_number":733,"context_line":"        self.assertTableDoesNotExist(identity_table)"},{"line_number":734,"context_line":"        self.assertTableDoesNotExist(password_table)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_0172ef7a","line":731,"range":{"start_line":730,"start_character":0,"end_line":731,"end_character":35},"updated":"2016-02-17 12:59:18.000000000","message":"fix these","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"7e99f753000090f08e8e6301d246b80c95176bf7","unresolved":false,"context_lines":[{"line_number":755,"context_line":""},{"line_number":756,"context_line":"    def test_migrate_data_to_user_password_tables(self):"},{"line_number":757,"context_line":"        identity_table \u003d \u0027identity\u0027"},{"line_number":758,"context_line":"        user_table \u003d \u0027user\u0027"},{"line_number":759,"context_line":"        password_table \u003d \u0027password\u0027"},{"line_number":760,"context_line":"        self.upgrade(91)"},{"line_number":761,"context_line":"        self.assertTableCountsMatch(identity_table, user_table)"},{"line_number":762,"context_line":"        self.assertTableCountsMatch(identity_table, password_table)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_813eff89","line":759,"range":{"start_line":758,"start_character":0,"end_line":759,"end_character":35},"updated":"2016-02-17 12:59:18.000000000","message":"fix these","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d9c2fdf7d5a624876abd178e0a494673438c7af9","unresolved":false,"context_lines":[{"line_number":758,"context_line":"        user_table \u003d \u0027user\u0027"},{"line_number":759,"context_line":"        password_table \u003d \u0027password\u0027"},{"line_number":760,"context_line":"        self.upgrade(91)"},{"line_number":761,"context_line":"        self.assertTableCountsMatch(identity_table, user_table)"},{"line_number":762,"context_line":"        self.assertTableCountsMatch(identity_table, password_table)"},{"line_number":763,"context_line":"        join_id \u003d \u0027id\u0027"},{"line_number":764,"context_line":"        columns \u003d [\u0027name\u0027, \u0027domain_id\u0027]"},{"line_number":765,"context_line":"        self.assertTableValuesMatch(identity_table, join_id, columns,"}],"source_content_type":"text/x-python","patch_set":16,"id":"dae33548_60ae6c99","line":762,"range":{"start_line":761,"start_character":0,"end_line":762,"end_character":67},"updated":"2016-02-17 06:59:10.000000000","message":"no need to assert this explicitly, it has been asserted within this method: assertTableValuesMatch(...).","commit_id":"7a560646d3061eb09840c4ee248b6b414aa22ed1"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"ffbf0b6a9293a59e557498b4d09ce2512c59b161","unresolved":false,"context_lines":[{"line_number":742,"context_line":"        self.upgrade(91)"},{"line_number":743,"context_line":"        self.assertTableCountsMatch(user_table_name, local_user_table_name)"},{"line_number":744,"context_line":"        self.assertTableCountsMatch(local_user_table_name, password_table_name)"},{"line_number":745,"context_line":"        # TODO(rderose): add test to compare data before and after migration"},{"line_number":746,"context_line":""},{"line_number":747,"context_line":"    def populate_user_table(self, with_pass_enab\u003dFalse,"},{"line_number":748,"context_line":"                            with_pass_enab_domain\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_b6cadc9f","line":745,"updated":"2016-02-19 19:44:36.000000000","message":"This is the one thing I\u0027d like to see addressed: more testing!","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0a26bd6404ded90da3afb61b541daa9ae47320ec","unresolved":false,"context_lines":[{"line_number":742,"context_line":"        self.upgrade(91)"},{"line_number":743,"context_line":"        self.assertTableCountsMatch(user_table_name, local_user_table_name)"},{"line_number":744,"context_line":"        self.assertTableCountsMatch(local_user_table_name, password_table_name)"},{"line_number":745,"context_line":"        # TODO(rderose): add test to compare data before and after migration"},{"line_number":746,"context_line":""},{"line_number":747,"context_line":"    def populate_user_table(self, with_pass_enab\u003dFalse,"},{"line_number":748,"context_line":"                            with_pass_enab_domain\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":33,"id":"bae84128_86268766","line":745,"in_reply_to":"bae84128_b6cadc9f","updated":"2016-02-19 20:59:06.000000000","message":"Done","commit_id":"98194f84cbd99379c8d95e03c1fc4985a7f7de48"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a3686bd050dfe75a6d12da7b79915c330995c7a6","unresolved":false,"context_lines":[{"line_number":700,"context_line":""},{"line_number":701,"context_line":"        session.close()"},{"line_number":702,"context_line":""},{"line_number":703,"context_line":"    def populate_user_table(self, with_pass_enab\u003dFalse,"},{"line_number":704,"context_line":"                            with_pass_enab_domain\u003dFalse):"},{"line_number":705,"context_line":"        # Populate the appropriate fields in the user"},{"line_number":706,"context_line":"        # table, depending on the parameters:"}],"source_content_type":"text/x-python","patch_set":34,"id":"bae84128_66ec23c8","side":"PARENT","line":703,"range":{"start_line":703,"start_character":8,"end_line":703,"end_character":27},"updated":"2016-02-19 21:05:21.000000000","message":"Some housekeeping, removing these methods as they didn\u0027t work and are no longer being used:\n* populate_user_table()\n* populate_tenant_table()\n* _mysql_check_all_tables_innodb()","commit_id":"8d7d49edaf99f0915ad7226b02b3d51218833cd4"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"12c00407cb1821a1f438bce767784d5df8374985","unresolved":false,"context_lines":[{"line_number":814,"context_line":"                                          autoload\u003dTrue)"},{"line_number":815,"context_line":"        actual_users \u003d get_users_from_db(user_table, local_user_table,"},{"line_number":816,"context_line":"                                         password_table)"},{"line_number":817,"context_line":"        self.assertListEqual(expected_users, actual_users)"},{"line_number":818,"context_line":""},{"line_number":819,"context_line":""},{"line_number":820,"context_line":"class VersionTests(SqlMigrateBase):"}],"source_content_type":"text/x-python","patch_set":39,"id":"bae84128_017f8466","line":817,"updated":"2016-02-23 13:12:09.000000000","message":"yay, python!","commit_id":"312a041862dc48b776715ccb2585d21cc479f5fb"}]}
