)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"6ec39f574bd14494ee29e6c6b86733814f0dba8a","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Boris Bobrov \u003cbbobrov@mirantis.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2015-07-14 14:06:48 +0300"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Check revision after a module finished upgrading"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: I89b02d7ad479da6bff3c492c88edfee9c19abc22"},{"line_number":10,"context_line":"Closes-Bug: 1474067"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"9a41bdd9_33f7c5f6","line":7,"updated":"2015-07-14 13:33:29.000000000","message":"We need to be more clearer in the commit message. Please add more details.\n\n\"When we have multiple plugins, we call upgrade on each one of them, however, if the operation succeeds and we have reached the specific revision we wanted, we should not continue to call the rest of the plugins, In this fix, we check the revision number and break out of the loop when we detect this condition and prevent errors\" \n\nor something like that.\n\nthanks,\ndims","commit_id":"fb2dd22a1d2f482690bb68a3d83e08bd934867c4"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"ca63b8050dcfbfdcde041858215f3023c2f46227","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Boris Bobrov \u003cbbobrov@mirantis.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2015-07-14 14:06:48 +0300"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Check revision after a module finished upgrading"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: I89b02d7ad479da6bff3c492c88edfee9c19abc22"},{"line_number":10,"context_line":"Closes-Bug: 1474067"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"9a41bdd9_b22f4e87","line":7,"in_reply_to":"9a41bdd9_33f7c5f6","updated":"2015-07-14 14:02:54.000000000","message":"Done","commit_id":"fb2dd22a1d2f482690bb68a3d83e08bd934867c4"}],"oslo_db/sqlalchemy/migration_cli/ext_base.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"62d2d9c2aaf62282e8c3d8c1a6383da7c606f356","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        \"\"\"Checks whether the repo contains a revision"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"        :param rev_id: Revision to check"},{"line_number":77,"context_line":"        :type rev_id: string"},{"line_number":78,"context_line":"        :returns: Whether the revision is in the repo"},{"line_number":79,"context_line":"        :rtype: bool"},{"line_number":80,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a4dcd0f_95e1e1d2","line":77,"updated":"2015-08-05 11:37:03.000000000","message":"nit: this is not true for all plugins. I suggest we either declare it plugin specific (and skip the type here), or allow to pass strings and e.g. cast the passed string to an integer value for sqlalchemy-migrate","commit_id":"2748c1e0ff1b709b43aceb59846bafc49f06e1d2"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"653ba9631f47cf86b607247e9efad686659e0600","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        \"\"\"Checks whether the repo contains a revision"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"        :param rev_id: Revision to check"},{"line_number":77,"context_line":"        :type rev_id: string"},{"line_number":78,"context_line":"        :returns: Whether the revision is in the repo"},{"line_number":79,"context_line":"        :rtype: bool"},{"line_number":80,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a4dcd0f_06c12980","line":77,"in_reply_to":"1a4dcd0f_95e1e1d2","updated":"2015-08-05 12:18:50.000000000","message":"Done","commit_id":"2748c1e0ff1b709b43aceb59846bafc49f06e1d2"}],"oslo_db/sqlalchemy/migration_cli/manager.py":[{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"6ec39f574bd14494ee29e6c6b86733814f0dba8a","unresolved":false,"context_lines":[{"line_number":55,"context_line":"            results.append(plugin.upgrade(revision))"},{"line_number":56,"context_line":"            # NOTE(breton): type cast is required here because `revision` can"},{"line_number":57,"context_line":"            # be either int or str."},{"line_number":58,"context_line":"            if str(self.version()) \u003d\u003d str(revision):"},{"line_number":59,"context_line":"                return results"},{"line_number":60,"context_line":"        return results"},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9a41bdd9_3871e2e0","line":58,"updated":"2015-07-14 13:33:29.000000000","message":"Is this better explanation? Also the code would look better if we break out of the loop than just return i feel. what do you think? One more thing was using six.text_type instead of str() for better py34 support. And remember we should do this check only if revision has a valid value.\n\n   # NOTE(breton): When we have multiple plugins, if we already reached\n   # the revision we want, we should not try the rest of the plugins.\n   if revision and six.text_type(self.version()) \u003d\u003d six.text_type(revision):\n       break","commit_id":"fb2dd22a1d2f482690bb68a3d83e08bd934867c4"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"ca63b8050dcfbfdcde041858215f3023c2f46227","unresolved":false,"context_lines":[{"line_number":55,"context_line":"            results.append(plugin.upgrade(revision))"},{"line_number":56,"context_line":"            # NOTE(breton): type cast is required here because `revision` can"},{"line_number":57,"context_line":"            # be either int or str."},{"line_number":58,"context_line":"            if str(self.version()) \u003d\u003d str(revision):"},{"line_number":59,"context_line":"                return results"},{"line_number":60,"context_line":"        return results"},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9a41bdd9_527602a5","line":58,"in_reply_to":"9a41bdd9_3871e2e0","updated":"2015-07-14 14:02:54.000000000","message":"Done","commit_id":"fb2dd22a1d2f482690bb68a3d83e08bd934867c4"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"c3da9ff96a8998a455c90d40ab99586eff68cf8a","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        \"\"\"Downgrade database with available backends.\"\"\""},{"line_number":67,"context_line":"        # downgrading should be performed in reversed order"},{"line_number":68,"context_line":"        results \u003d []"},{"line_number":69,"context_line":"        for plugin in reversed(self._plugins):"},{"line_number":70,"context_line":"            results.append(plugin.downgrade(revision))"},{"line_number":71,"context_line":"        return results"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"9a41bdd9_38b23807","line":69,"updated":"2015-07-14 15:55:15.000000000","message":"shouldn\u0027t we also do the same for downgrades?","commit_id":"d70661835c57e487f37cc089571e77865314168e"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"2db1410a3122890b3113973309f1fb3c9495fc11","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        \"\"\"Downgrade database with available backends.\"\"\""},{"line_number":67,"context_line":"        # downgrading should be performed in reversed order"},{"line_number":68,"context_line":"        results \u003d []"},{"line_number":69,"context_line":"        for plugin in reversed(self._plugins):"},{"line_number":70,"context_line":"            results.append(plugin.downgrade(revision))"},{"line_number":71,"context_line":"        return results"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"9a41bdd9_5b7056dc","line":69,"in_reply_to":"9a41bdd9_38b23807","updated":"2015-07-14 16:22:56.000000000","message":"https://review.openstack.org/201651","commit_id":"d70661835c57e487f37cc089571e77865314168e"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"281650c3cf7272fd2e53172481223d30a976f8eb","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        return self._plugins[-1].stamp(revision)"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"    def has_revision(self, rev_id):"},{"line_number":114,"context_line":"        \"\"\"Check whether the revision is in any of the plugins\"\"\""}],"source_content_type":"text/x-python","patch_set":8,"id":"3a50d1a3_8fd04555","line":114,"updated":"2015-07-20 13:35:44.000000000","message":"oops, seems like return is missing","commit_id":"c1601b20651bbbfdfe3b10ff92f7b75b6fb4bf2d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"09d3b8f526673a726b86bf340523ab1a6b69d898","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        return self._plugins[-1].stamp(revision)"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"    def has_revision(self, rev_id):"},{"line_number":114,"context_line":"        \"\"\"Check whether the revision is in any of the plugins\"\"\""}],"source_content_type":"text/x-python","patch_set":8,"id":"3a50d1a3_7aa49556","line":114,"in_reply_to":"3a50d1a3_8fd04555","updated":"2015-07-20 13:55:28.000000000","message":"Done","commit_id":"c1601b20651bbbfdfe3b10ff92f7b75b6fb4bf2d"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"3bc20974c7cbb013e84a5304a813c074115733b2","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def upgrade(self, revision):"},{"line_number":54,"context_line":"        \"\"\"Upgrade database with all available backends.\"\"\""},{"line_number":55,"context_line":"        good_targets \u003d [\u0027head\u0027, None]"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."}],"source_content_type":"text/x-python","patch_set":9,"id":"3a50d1a3_bbcd11b9","line":55,"updated":"2015-07-21 09:34:00.000000000","message":"Left as is, good targets like \u0027head\u0027 expose the implementation details (i.e. this is alembic specific). \n\nCan we incorporate this logic into plugins? So that e.g. has_revision() would return True for alembic if \u0027head\u0027 was passed as a value of revision argument here?","commit_id":"b3a19d4ee461d9af564674dc416e030fa4e742cb"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6e6a5e9fd777a708be86a7f2d63887d69cd9bd38","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def upgrade(self, revision):"},{"line_number":54,"context_line":"        \"\"\"Upgrade database with all available backends.\"\"\""},{"line_number":55,"context_line":"        good_targets \u003d [\u0027head\u0027, None]"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."}],"source_content_type":"text/x-python","patch_set":9,"id":"3a50d1a3_e15d277a","line":55,"in_reply_to":"3a50d1a3_2dba28c1","updated":"2015-07-21 10:54:57.000000000","message":"Well, yeah, but we treat None as \u0027the latest revision\u0027 for all plugins, so it\u0027s kind of a special case here.\n\nWhy can\u0027t we upgrade to None, if a revision hasn\u0027t been found for a plugin?","commit_id":"b3a19d4ee461d9af564674dc416e030fa4e742cb"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"ca0c56e6d329092f561537c37ba0bcc746e14a90","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def upgrade(self, revision):"},{"line_number":54,"context_line":"        \"\"\"Upgrade database with all available backends.\"\"\""},{"line_number":55,"context_line":"        good_targets \u003d [\u0027head\u0027, None]"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."}],"source_content_type":"text/x-python","patch_set":9,"id":"3a50d1a3_2dba28c1","line":55,"in_reply_to":"3a50d1a3_bbcd11b9","updated":"2015-07-21 09:53:14.000000000","message":"Roman, well, we can do it only partially. We need this knowledge for lines 66-70. Also, it is not alembic-specific -- it is both migrate- and alembic- specific.","commit_id":"b3a19d4ee461d9af564674dc416e030fa4e742cb"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"c052b7735017e28c9991de98c1a61240d739519e","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def upgrade(self, revision):"},{"line_number":54,"context_line":"        \"\"\"Upgrade database with all available backends.\"\"\""},{"line_number":55,"context_line":"        good_targets \u003d [\u0027head\u0027, None]"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."}],"source_content_type":"text/x-python","patch_set":9,"id":"3a50d1a3_97f581cc","line":55,"in_reply_to":"3a50d1a3_e15d277a","updated":"2015-07-21 11:30:23.000000000","message":"We treat None and \u0027head\u0027 the same way for both plugins, check out the code in ext_migrate.py.\n\nI will try to simplify this code a bit now. has_revision() cannot return True for \u0027head\u0027 because it will be True for both migrate and alembic and the execution will stop after migrate, not reaching alembic.","commit_id":"b3a19d4ee461d9af564674dc416e030fa4e742cb"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"3bc20974c7cbb013e84a5304a813c074115733b2","unresolved":false,"context_lines":[{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def downgrade(self, revision):"},{"line_number":74,"context_line":"        \"\"\"Downgrade database with available backends.\"\"\""},{"line_number":75,"context_line":"        good_targets \u003d [\u0027base\u0027, None]"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":78,"context_line":"        # should downgrade to the plugins\u0027 bases."}],"source_content_type":"text/x-python","patch_set":9,"id":"3a50d1a3_5bc5ed8b","line":75,"updated":"2015-07-21 09:34:00.000000000","message":"ditto","commit_id":"b3a19d4ee461d9af564674dc416e030fa4e742cb"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"1f6b25f6efd8658829c7826894d71987f2be4597","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."},{"line_number":59,"context_line":"        rev_in_plugins \u003d [p.has_revision(revision) for p in self._plugins]"},{"line_number":60,"context_line":"        if revision not in good_targets and not any(rev_in_plugins):"},{"line_number":61,"context_line":"            raise exception.DbMigrationError(\u0027Revision does not exist\u0027)"},{"line_number":62,"context_line":"        results \u003d []"},{"line_number":63,"context_line":"        for plugin, has_revision in zip(self._plugins, rev_in_plugins):"}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_b2b44bf2","line":60,"updated":"2015-07-21 11:39:55.000000000","message":"we still need good_targets here and I don\u0027t know how to remove it (and don\u0027t see much sense)","commit_id":"1ef817c804c8293a789d745a932bb44c86426f27"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"c7c2bb40c2e563a2db15dca58d44993c1347a36a","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."},{"line_number":59,"context_line":"        rev_in_plugins \u003d [p.has_revision(revision) for p in self._plugins]"},{"line_number":60,"context_line":"        if revision not in good_targets and not any(rev_in_plugins):"},{"line_number":61,"context_line":"            raise exception.DbMigrationError(\u0027Revision does not exist\u0027)"},{"line_number":62,"context_line":"        results \u003d []"},{"line_number":63,"context_line":"        for plugin, has_revision in zip(self._plugins, rev_in_plugins):"}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_20825bc9","line":60,"in_reply_to":"3a50d1a3_1dfd486e","updated":"2015-07-24 14:50:07.000000000","message":"Roman, migrate supports \u0027head\u0027 and None revisions. Alembic supports \u0027head\u0027 and None revisions. Any other plugin will have to support \u0027head\u0027 and None revisions, because users usually type `smth-manage db_sync` or `smth-manage db_sync head`. It\u0027s a standard used by all upgrade engine.\n\nWe cannot hide it in has_version(), because has_version() should return True only for one plugin. Only one plugin can ever have a specific revision. The logic of the code below is built on this. If a plugin returns True -- upgrade stops.\n\nI see a way to write this with hiding good_targets inside plugins. But:\n\n1. This will make code over-complicated. 2. Both migrate and alembic will have absolutely the same lines \"good_targets \u003d [\u0027head\u0027, None]\".","commit_id":"1ef817c804c8293a789d745a932bb44c86426f27"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"c7600b2ae657ea5bf0fa7eed953e74b9f4825dbe","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."},{"line_number":59,"context_line":"        rev_in_plugins \u003d [p.has_revision(revision) for p in self._plugins]"},{"line_number":60,"context_line":"        if revision not in good_targets and not any(rev_in_plugins):"},{"line_number":61,"context_line":"            raise exception.DbMigrationError(\u0027Revision does not exist\u0027)"},{"line_number":62,"context_line":"        results \u003d []"},{"line_number":63,"context_line":"        for plugin, has_revision in zip(self._plugins, rev_in_plugins):"}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_ba5573c2","line":60,"in_reply_to":"3a50d1a3_20825bc9","updated":"2015-07-29 17:12:02.000000000","message":"We discussed this with Boris on IRC - Boris will try to come up with a solution that will put this logic into plugins implementation","commit_id":"1ef817c804c8293a789d745a932bb44c86426f27"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"7257223275b3fea5921b7f528771e295e52f205d","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        # a revision exists only in a single plugin. Until we reached it, we"},{"line_number":58,"context_line":"        # should upgrade to the plugins\u0027 heads."},{"line_number":59,"context_line":"        rev_in_plugins \u003d [p.has_revision(revision) for p in self._plugins]"},{"line_number":60,"context_line":"        if revision not in good_targets and not any(rev_in_plugins):"},{"line_number":61,"context_line":"            raise exception.DbMigrationError(\u0027Revision does not exist\u0027)"},{"line_number":62,"context_line":"        results \u003d []"},{"line_number":63,"context_line":"        for plugin, has_revision in zip(self._plugins, rev_in_plugins):"}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_1dfd486e","line":60,"in_reply_to":"3a50d1a3_b2b44bf2","updated":"2015-07-24 14:27:37.000000000","message":"Well, my point is that good_target expose implementation details of a particular plugin (like \u0027head\u0027 for alembic), while extension manager should really be unaware of those and just use public API of plugins.\n\nI\u0027d like to see those details be hidden in implementations themselves. E.g. we could extend has_version() in alembic plugin to understand specific targets like \u0027head\u0027 or \u0027base\u0027 and treat them as existing revisions.","commit_id":"1ef817c804c8293a789d745a932bb44c86426f27"}],"oslo_db/tests/sqlalchemy/test_migrate_cli.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"281650c3cf7272fd2e53172481223d30a976f8eb","unresolved":false,"context_lines":[{"line_number":95,"context_line":"        version \u003d self.alembic.version()"},{"line_number":96,"context_line":"        self.assertIsNone(version)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    def test_has_revision(self, command):"},{"line_number":99,"context_line":"        with mock.patch((\u0027oslo_db.sqlalchemy.migration_cli.\u0027"},{"line_number":100,"context_line":"                         \u0027ext_alembic.alembic_script\u0027)) as mocked:"},{"line_number":101,"context_line":"            self.alembic.config.get_main_option \u003d mock.Mock()"}],"source_content_type":"text/x-python","patch_set":8,"id":"3a50d1a3_cf764d3e","line":98,"updated":"2015-07-20 13:35:44.000000000","message":"can we also test the negative case when an exception is raised?","commit_id":"c1601b20651bbbfdfe3b10ff92f7b75b6fb4bf2d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"09d3b8f526673a726b86bf340523ab1a6b69d898","unresolved":false,"context_lines":[{"line_number":95,"context_line":"        version \u003d self.alembic.version()"},{"line_number":96,"context_line":"        self.assertIsNone(version)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    def test_has_revision(self, command):"},{"line_number":99,"context_line":"        with mock.patch((\u0027oslo_db.sqlalchemy.migration_cli.\u0027"},{"line_number":100,"context_line":"                         \u0027ext_alembic.alembic_script\u0027)) as mocked:"},{"line_number":101,"context_line":"            self.alembic.config.get_main_option \u003d mock.Mock()"}],"source_content_type":"text/x-python","patch_set":8,"id":"3a50d1a3_3a004d34","line":98,"in_reply_to":"3a50d1a3_cf764d3e","updated":"2015-07-20 13:55:28.000000000","message":"Done","commit_id":"c1601b20651bbbfdfe3b10ff92f7b75b6fb4bf2d"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"281650c3cf7272fd2e53172481223d30a976f8eb","unresolved":false,"context_lines":[{"line_number":168,"context_line":"            self.migration_config[\u0027init_version\u0027],"},{"line_number":169,"context_line":"            init_version\u003dself.migration_config[\u0027init_version\u0027])"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    def test_has_revision(self, command):"},{"line_number":172,"context_line":"        with mock.patch((\u0027oslo_db.sqlalchemy.migration_cli.\u0027"},{"line_number":173,"context_line":"                         \u0027ext_migrate.migrate_version\u0027)) as mocked:"},{"line_number":174,"context_line":"            self.migrate.has_revision(\u0027test\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"3a50d1a3_af942137","line":171,"updated":"2015-07-20 13:35:44.000000000","message":"ditto","commit_id":"c1601b20651bbbfdfe3b10ff92f7b75b6fb4bf2d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"09d3b8f526673a726b86bf340523ab1a6b69d898","unresolved":false,"context_lines":[{"line_number":168,"context_line":"            self.migration_config[\u0027init_version\u0027],"},{"line_number":169,"context_line":"            init_version\u003dself.migration_config[\u0027init_version\u0027])"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    def test_has_revision(self, command):"},{"line_number":172,"context_line":"        with mock.patch((\u0027oslo_db.sqlalchemy.migration_cli.\u0027"},{"line_number":173,"context_line":"                         \u0027ext_migrate.migrate_version\u0027)) as mocked:"},{"line_number":174,"context_line":"            self.migrate.has_revision(\u0027test\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"3a50d1a3_faf9854e","line":171,"in_reply_to":"3a50d1a3_af942137","updated":"2015-07-20 13:55:28.000000000","message":"Done","commit_id":"c1601b20651bbbfdfe3b10ff92f7b75b6fb4bf2d"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"62d2d9c2aaf62282e8c3d8c1a6383da7c606f356","unresolved":false,"context_lines":[{"line_number":112,"context_line":"            mocked.ScriptDirectory().revision.side_effect \u003d ("},{"line_number":113,"context_line":"                alembic.util.CommandError)"},{"line_number":114,"context_line":"            self.alembic.config.get_main_option \u003d mock.Mock()"},{"line_number":115,"context_line":"            self.alembic.has_revision(\u0027test\u0027)"},{"line_number":116,"context_line":"            mocked.ScriptDirectory().get_revision.assert_called_once_with("},{"line_number":117,"context_line":"                \u0027test\u0027)"},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a4dcd0f_1579512f","line":115,"updated":"2015-08-05 11:37:03.000000000","message":"nit: assert on False here?","commit_id":"2748c1e0ff1b709b43aceb59846bafc49f06e1d2"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"653ba9631f47cf86b607247e9efad686659e0600","unresolved":false,"context_lines":[{"line_number":112,"context_line":"            mocked.ScriptDirectory().revision.side_effect \u003d ("},{"line_number":113,"context_line":"                alembic.util.CommandError)"},{"line_number":114,"context_line":"            self.alembic.config.get_main_option \u003d mock.Mock()"},{"line_number":115,"context_line":"            self.alembic.has_revision(\u0027test\u0027)"},{"line_number":116,"context_line":"            mocked.ScriptDirectory().get_revision.assert_called_once_with("},{"line_number":117,"context_line":"                \u0027test\u0027)"},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a4dcd0f_26f465f0","line":115,"in_reply_to":"1a4dcd0f_1579512f","updated":"2015-08-05 12:18:50.000000000","message":"Done","commit_id":"2748c1e0ff1b709b43aceb59846bafc49f06e1d2"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"62d2d9c2aaf62282e8c3d8c1a6383da7c606f356","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        with mock.patch((\u0027oslo_db.sqlalchemy.migration_cli.\u0027"},{"line_number":194,"context_line":"                         \u0027ext_migrate.migrate_version\u0027)) as mocked:"},{"line_number":195,"context_line":"            mocked.Collection().version.side_effect \u003d ValueError"},{"line_number":196,"context_line":"            self.migrate.has_revision(\u0027test\u0027)"},{"line_number":197,"context_line":"            mocked.Collection().version.assert_called_once_with(\u0027test\u0027)"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a4dcd0f_b5ae5d83","line":196,"updated":"2015-08-05 11:37:03.000000000","message":"nit: assert on False here?","commit_id":"2748c1e0ff1b709b43aceb59846bafc49f06e1d2"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"653ba9631f47cf86b607247e9efad686659e0600","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        with mock.patch((\u0027oslo_db.sqlalchemy.migration_cli.\u0027"},{"line_number":194,"context_line":"                         \u0027ext_migrate.migrate_version\u0027)) as mocked:"},{"line_number":195,"context_line":"            mocked.Collection().version.side_effect \u003d ValueError"},{"line_number":196,"context_line":"            self.migrate.has_revision(\u0027test\u0027)"},{"line_number":197,"context_line":"            mocked.Collection().version.assert_called_once_with(\u0027test\u0027)"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a4dcd0f_46f731f5","line":196,"in_reply_to":"1a4dcd0f_b5ae5d83","updated":"2015-08-05 12:18:50.000000000","message":"Done","commit_id":"2748c1e0ff1b709b43aceb59846bafc49f06e1d2"}]}
