)]}'
{"nova/db/sqlalchemy/models.py":[{"author":{"_account_id":67,"name":"Vish Ishaya","email":"vishvananda@gmail.com","username":"vishvananda"},"change_message_id":"5ac91d0de4e7c5bedeebdc28ad71f7a7e065db86","unresolved":false,"context_lines":[{"line_number":58,"context_line":"            err_msg \u003d str(e).split(\" u\u0027\")[0]"},{"line_number":59,"context_line":"            if err_msg.endswith(\"not unique\"):"},{"line_number":60,"context_line":"                raise exception.Duplicate(str(e))"},{"line_number":61,"context_line":"            raise e"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def delete(self, session\u003dNone):"},{"line_number":64,"context_line":"        \"\"\"Delete this object.\"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAMH%2F%2F4Ew%3D","line":61,"updated":"2012-11-19 01:56:35.000000000","message":"this should be a bare raise or we lose the original traceback.","commit_id":"7f8b5b7dd898981e249d33dc7ea1125f8ee911f5"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"d7bbe7f3f6a5b2f6158842cd13030884a2371c9f","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        try:"},{"line_number":56,"context_line":"            session.flush()"},{"line_number":57,"context_line":"        except exception.DBError, e:"},{"line_number":58,"context_line":"            err_msg \u003d str(e).split(\" u\u0027\")[0]"},{"line_number":59,"context_line":"            if err_msg.endswith(\"not unique\"):"},{"line_number":60,"context_line":"                raise exception.Duplicate(str(e))"},{"line_number":61,"context_line":"            raise"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAMH%2F%2F22Q%3D","line":58,"updated":"2012-11-19 22:04:27.000000000","message":"why is this line needed?","commit_id":"73c63b15dec81710e250a5418d72cc53e4fa3d62"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"fa66df9cdf0eaee262c7d1e80e50b8ee407d3057","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        try:"},{"line_number":56,"context_line":"            session.flush()"},{"line_number":57,"context_line":"        except exception.DBError, e:"},{"line_number":58,"context_line":"            err_msg \u003d str(e).split(\" u\u0027\")[0]"},{"line_number":59,"context_line":"            if err_msg.endswith(\"not unique\"):"},{"line_number":60,"context_line":"                raise exception.Duplicate(str(e))"},{"line_number":61,"context_line":"            raise"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAMH%2F%2F2zM%3D","line":58,"in_reply_to":"AAAAMH%2F%2F22Q%3D","updated":"2012-11-19 22:32:16.000000000","message":"SqlAlchemy raise IntegrityError exception. In session it is wrapped by DBError. IntegrityError is raised not only when unique constraint is not satisfied. So it is sad but true, we must check this in this way.","commit_id":"73c63b15dec81710e250a5418d72cc53e4fa3d62"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"9e864e5780496e20b457eb625fb5c56a9da82d6a","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        try:"},{"line_number":56,"context_line":"            session.flush()"},{"line_number":57,"context_line":"        except exception.DBError, e:"},{"line_number":58,"context_line":"            err_msg \u003d str(e).split(\" u\u0027\")[0]"},{"line_number":59,"context_line":"            if err_msg.endswith(\"not unique\"):"},{"line_number":60,"context_line":"                raise exception.Duplicate(str(e))"},{"line_number":61,"context_line":"            raise"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAMH%2F%2F1UI%3D","line":58,"in_reply_to":"AAAAMH%2F%2F2RA%3D","updated":"2012-11-20 21:13:53.000000000","message":"Can you add a #NOTE(username) above this line, and put the explanation there.","commit_id":"73c63b15dec81710e250a5418d72cc53e4fa3d62"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0825975077e5261ba4235533b891e3ea41917b3b","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        try:"},{"line_number":56,"context_line":"            session.flush()"},{"line_number":57,"context_line":"        except exception.DBError, e:"},{"line_number":58,"context_line":"            err_msg \u003d str(e).split(\" u\u0027\")[0]"},{"line_number":59,"context_line":"            if err_msg.endswith(\"not unique\"):"},{"line_number":60,"context_line":"                raise exception.Duplicate(str(e))"},{"line_number":61,"context_line":"            raise"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAMH%2F%2F2RA%3D","line":58,"in_reply_to":"AAAAMH%2F%2F2ps%3D","updated":"2012-11-20 07:54:10.000000000","message":"This is also hack \u003d(\nMessage syntax is something like this: \n\"IntegrityError columns? column1(, columnN)* (are|is) not unique u\u0027SQL request\u0027 \"\nSo first of all I split message and then use only description. \nThis is required because we can not guaranty that sql request doesn\u0027t contain \u0027no unique\u0027 string.","commit_id":"73c63b15dec81710e250a5418d72cc53e4fa3d62"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"ff7972dfb28ee632b6634987730ab1721ad3c6b8","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        try:"},{"line_number":56,"context_line":"            session.flush()"},{"line_number":57,"context_line":"        except exception.DBError, e:"},{"line_number":58,"context_line":"            err_msg \u003d str(e).split(\" u\u0027\")[0]"},{"line_number":59,"context_line":"            if err_msg.endswith(\"not unique\"):"},{"line_number":60,"context_line":"                raise exception.Duplicate(str(e))"},{"line_number":61,"context_line":"            raise"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAMH%2F%2F2ps%3D","line":58,"in_reply_to":"AAAAMH%2F%2F2zM%3D","updated":"2012-11-19 23:25:56.000000000","message":"Why do you need to split the error message on \" u\u0027\"?","commit_id":"73c63b15dec81710e250a5418d72cc53e4fa3d62"}],"nova/db/sqlalchemy/session.py":[{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"eda768b069d1f63a44c64f416cb4a4ed62431673","unresolved":false,"context_lines":[{"line_number":253,"context_line":"        # note(boris-42): UniqueConstraint name convention:"},{"line_number":254,"context_line":"        # \"uniqcons__c1_x_c2_x_c3\" means that columns c1, c2, c3 are in"},{"line_number":255,"context_line":"        # UniqueConstraint."},{"line_number":256,"context_line":"        uniqbase \u003d \"uniqcons__\""},{"line_number":257,"context_line":"        if not columns.startswith(uniqbase):"},{"line_number":258,"context_line":"            if engine_name \u003d\u003d \"postgresql\":"},{"line_number":259,"context_line":"                return [columns[columns.index(\"_\") + 1:columns.rindex(\"_\")]]"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F34E%3D","line":256,"updated":"2012-12-11 15:22:21.000000000","message":"Personal preference here, I would rather see the index name prefix of just \"uniq_\" or \"unique_\". There is a max length limit, so saving a few chars might matter somewhere.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"eda768b069d1f63a44c64f416cb4a4ed62431673","unresolved":false,"context_lines":[{"line_number":261,"context_line":"        return columns[len(uniqbase):].split(\"_x_\")"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":"    if engine_name not in [\"mysql\", \"sqlite\", \"postgresql\"]:"},{"line_number":264,"context_line":"        raise NotImplementedError()"},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"    # note(boris-42): In current versions of DB backends unique constraint"},{"line_number":267,"context_line":"    # violation messages follow the structure:"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F34I%3D","line":264,"updated":"2012-12-11 15:22:21.000000000","message":"This should just return, not raise a new exception, because it may obfuscate the real exception when raising NotImplemented from within an except: block.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":67,"name":"Vish Ishaya","email":"vishvananda@gmail.com","username":"vishvananda"},"change_message_id":"6e7db30c5fca468d200ab854a74c51cc32d9b0f5","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        \"sqlite\": re.compile(r\"^.*columns?([^)]+)(is|are)\\s+not\\s+unique$\"),"},{"line_number":286,"context_line":"        \"postgresql\": re.compile(r\"^.*duplicate\\s+key.*\\\"([^\\\"]+)\\\"\\s*\\n.*$\"),"},{"line_number":287,"context_line":"        \"mysql\": re.compile(r\"^.*\\(1062,.*\u0027([^\\\u0027]+)\u0027\\\"\\)$\")"},{"line_number":288,"context_line":"    }"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    m \u003d re_db[engine_name].match(integrity_error.message)"},{"line_number":291,"context_line":"    if not m:"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F480%3D","line":288,"updated":"2012-12-10 17:24:53.000000000","message":"minor performance optimization.\nIf you compile these at import time (out of function scope) then it doesn\u0027t need to recompile them every time the method is called.\n\n _RE_DB \u003d {...}\n\n\n def raise_if_duplicate_entry_error(..","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"9ad4007dc3d8fb63b40bb9eee5e143641a6028c0","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        \"sqlite\": re.compile(r\"^.*columns?([^)]+)(is|are)\\s+not\\s+unique$\"),"},{"line_number":286,"context_line":"        \"postgresql\": re.compile(r\"^.*duplicate\\s+key.*\\\"([^\\\"]+)\\\"\\s*\\n.*$\"),"},{"line_number":287,"context_line":"        \"mysql\": re.compile(r\"^.*\\(1062,.*\u0027([^\\\u0027]+)\u0027\\\"\\)$\")"},{"line_number":288,"context_line":"    }"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    m \u003d re_db[engine_name].match(integrity_error.message)"},{"line_number":291,"context_line":"    if not m:"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F4wk%3D","line":288,"in_reply_to":"AAAAMX%2F%2F480%3D","updated":"2012-12-10 20:02:42.000000000","message":"These regexps are simple and fast compiled so I thought that it is more important to make it locally. However, If you prefer to move it out of function scope, I will move it.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"eda768b069d1f63a44c64f416cb4a4ed62431673","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        \"sqlite\": re.compile(r\"^.*columns?([^)]+)(is|are)\\s+not\\s+unique$\"),"},{"line_number":286,"context_line":"        \"postgresql\": re.compile(r\"^.*duplicate\\s+key.*\\\"([^\\\"]+)\\\"\\s*\\n.*$\"),"},{"line_number":287,"context_line":"        \"mysql\": re.compile(r\"^.*\\(1062,.*\u0027([^\\\u0027]+)\u0027\\\"\\)$\")"},{"line_number":288,"context_line":"    }"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    m \u003d re_db[engine_name].match(integrity_error.message)"},{"line_number":291,"context_line":"    if not m:"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F34Q%3D","line":288,"in_reply_to":"AAAAMX%2F%2F4wk%3D","updated":"2012-12-11 15:22:21.000000000","message":"I agree with Vish here. Moving the re\u0027s outside the function is better IMO.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"eda768b069d1f63a44c64f416cb4a4ed62431673","unresolved":false,"context_lines":[{"line_number":302,"context_line":"def wrap_duplicate_error(f):"},{"line_number":303,"context_line":"    def _wrap(*args, **kwargs):"},{"line_number":304,"context_line":"        try:"},{"line_number":305,"context_line":"            engine_name \u003d get_engine().name"},{"line_number":306,"context_line":"            return f(*args, **kwargs)"},{"line_number":307,"context_line":"        # note(boris-42): We should catch unique constraint violation and"},{"line_number":308,"context_line":"        # wrap it by our own DBDuplicateEntry exception. Unique constraint"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F34M%3D","line":305,"updated":"2012-12-11 15:22:21.000000000","message":"Is it possible to move the get_engine call into the except block? It seems wasteful to add this call to every single database query, instead of only calling it when an exception is raised.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":67,"name":"Vish Ishaya","email":"vishvananda@gmail.com","username":"vishvananda"},"change_message_id":"6e7db30c5fca468d200ab854a74c51cc32d9b0f5","unresolved":false,"context_lines":[{"line_number":322,"context_line":"    \"\"\"Return a session whose exceptions are wrapped.\"\"\""},{"line_number":323,"context_line":"    wrap_db_error \u003d nova.exception.wrap_db_error"},{"line_number":324,"context_line":"    session.query \u003d wrap_db_error(wrap_duplicate_error(session.query))"},{"line_number":325,"context_line":"    session.flush \u003d wrap_db_error(wrap_duplicate_error(session.flush))"},{"line_number":326,"context_line":"    return session"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F48s%3D","line":325,"updated":"2012-12-10 17:24:53.000000000","message":"not really sure it is necessary to have both wraps. I would just move wrap_db_error here and add the extra duplicate check to wrap_db_error since it is the only place where it is is used.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0ecd1bf585e7612772acb9abb7dd909045d82a39","unresolved":false,"context_lines":[{"line_number":322,"context_line":"    \"\"\"Return a session whose exceptions are wrapped.\"\"\""},{"line_number":323,"context_line":"    wrap_db_error \u003d nova.exception.wrap_db_error"},{"line_number":324,"context_line":"    session.query \u003d wrap_db_error(wrap_duplicate_error(session.query))"},{"line_number":325,"context_line":"    session.flush \u003d wrap_db_error(wrap_duplicate_error(session.flush))"},{"line_number":326,"context_line":"    return session"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F4vE%3D","line":325,"in_reply_to":"AAAAMX%2F%2F48s%3D","updated":"2012-12-10 20:13:56.000000000","message":"wrap_db_error() can be used by different backends, wrap_duplicate_error() is used only by sqlalchemy. I thought that when we make support for some other db backends we will  need to write one more \"wrap_db_error()\". So maybe two separate methods are ok in this situation?","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"eda768b069d1f63a44c64f416cb4a4ed62431673","unresolved":false,"context_lines":[{"line_number":322,"context_line":"    \"\"\"Return a session whose exceptions are wrapped.\"\"\""},{"line_number":323,"context_line":"    wrap_db_error \u003d nova.exception.wrap_db_error"},{"line_number":324,"context_line":"    session.query \u003d wrap_db_error(wrap_duplicate_error(session.query))"},{"line_number":325,"context_line":"    session.flush \u003d wrap_db_error(wrap_duplicate_error(session.flush))"},{"line_number":326,"context_line":"    return session"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAMX%2F%2F32w%3D","line":325,"in_reply_to":"AAAAMX%2F%2F4vE%3D","updated":"2012-12-11 15:22:21.000000000","message":"it\u0027s not necessary, but I believe it should be okay to move wrap_db_error into this file and condense the functions. I had done that in my db retry patch several months back. You may need to change a few imports, but it wasn\u0027t that bad. \n\nAlso, a lot of this should get moved to db-common eventually, but let\u0027s land it here first.","commit_id":"248e88f677916cc825db4d4460ba10f382b479fc"}]}
