)]}'
{"oslo_db/exception.py":[{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"ad14193795a8229f9aafb38a2983a701adaa9bdb","unresolved":false,"context_lines":[{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    def __init__(self, inner_exception\u003dNone):"},{"line_number":61,"context_line":"        self.inner_exception \u003d inner_exception"},{"line_number":62,"context_line":"        self.caused_during_handling_by \u003d None"},{"line_number":63,"context_line":"        super(DBError, self).__init__(six.text_type(inner_exception))"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_67445b46","line":62,"updated":"2016-07-01 11:31:26.000000000","message":"You might try to define the attribute as a read-only property on Python 3 which would simply return self.__cause__.","commit_id":"871f1ced4879a9ad57e742670f0ba028a486c054"}],"oslo_db/sqlalchemy/exc_filters.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"b207d8cc31b6718075596c64135f345a45b33d46","unresolved":false,"context_lines":[{"line_number":382,"context_line":"                            except exception.DBError as dbe:"},{"line_number":383,"context_line":"                                if ("},{"line_number":384,"context_line":"                                    context.connection is not None and"},{"line_number":385,"context_line":"                                    hasattr(context.connection, \u0027info\u0027) and"},{"line_number":386,"context_line":"                                    ROLLBACK_CAUSE_KEY"},{"line_number":387,"context_line":"                                    in context.connection.info"},{"line_number":388,"context_line":"                                ):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3aaa91ec_9e710c0f","line":385,"updated":"2016-06-30 12:55:04.000000000","message":"I believe py34  tests fail due to difference in behaviour of hasattr(): in py 2.x it would quietly swallow any exceptions raised on attribute access , while in py 3.x it only excepts AttributeError (https://hynek.me/articles/hasattr/)\n\n\npy27:\n\n(Pdb) context.connection.info\n*** OperationalError: (oslo_db.tests.sqlalchemy.test_exc_filters.OperationalError) 2002 MySQL server has gone away\n(Pdb) hasattr(context.connection, \u0027info\u0027)\nFalse\n\npy34:\n\n(Pdb) context.connection.info\n*** sqlalchemy.exc.OperationalError: (oslo_db.tests.sqlalchemy.test_exc_filters.OperationalError) 2002 MySQL server has gone away\n(Pdb) hasattr(context.connection, \u0027info\u0027)\n*** sqlalchemy.exc.OperationalError: (oslo_db.tests.sqlalchemy.test_exc_filters.OperationalError) 2002 MySQL server has gone away","commit_id":"570445ede139e0aca52cd7f693c9b9807c45d82e"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"16c36c3960ca3827481adcd03dc2a4c9b5314a9c","unresolved":false,"context_lines":[{"line_number":389,"context_line":"                                ):"},{"line_number":390,"context_line":"                                    dbe.caused_during_handling_by \u003d \\"},{"line_number":391,"context_line":"                                        context.connection.info.pop("},{"line_number":392,"context_line":"                                            ROLLBACK_CAUSE_KEY)"},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"                                if isinstance("},{"line_number":395,"context_line":"                                        dbe, exception.DBConnectionError):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_b47dfd6e","line":392,"updated":"2016-06-30 15:48:45.000000000","message":"hum, it looks like you reimplemented something like Exception.__cause__ or Exception.__context__ of Python 3.\n\nOn Python 3, exception objects store traceback objects. If you keep an exception object alive too long, there is a risk of creating reference cycles and so keep a lot of objects alive longer than expected :-/\n\nMaybe you should reuse Exception.__cause__ on Python 3? (but dbe.caused_during_handling_by on Python 2?)\n\nPython 3.5 (sorry, not before) also provides a light \"view\" of execption information which don\u0027t keep traceback and so frames alive:\n\nhttps://docs.python.org/dev/library/traceback.html#tracebackexception-objects\n\nThe most simple solution working on Python 2 and Python 3 and avoiding reference cycles issues is to store the exception as text, not as an object. The traceback module contains various functions to format an exception as text.","commit_id":"871f1ced4879a9ad57e742670f0ba028a486c054"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"ad14193795a8229f9aafb38a2983a701adaa9bdb","unresolved":false,"context_lines":[{"line_number":389,"context_line":"                                ):"},{"line_number":390,"context_line":"                                    dbe.caused_during_handling_by \u003d \\"},{"line_number":391,"context_line":"                                        context.connection.info.pop("},{"line_number":392,"context_line":"                                            ROLLBACK_CAUSE_KEY)"},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"                                if isinstance("},{"line_number":395,"context_line":"                                        dbe, exception.DBConnectionError):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_2737f3e3","line":392,"in_reply_to":"3aaa91ec_4a66b4bb","updated":"2016-07-01 11:31:26.000000000","message":"\u003e but if you want to work on this, it would be a huge win.\n\nThis is not going to happen: new features are no more accepted in Python 2. Only the development branch accepts new features:\nhttps://docs.python.org/devguide/#status-of-python-branches\n\n\u003e the exception object here is not being kept alive \"too long\". It\u0027s dealt with inside of a function that is invoked within the except: block and it is discarded outside of the function and hence the \"except:\" block.\n\nExample:\n\n try: raise ValueError(\"err\")\n except Exception as exc: pass\n print(exc)\n\nOn Python 2, exc is still set after the except block. It changed in Python 3: exc is no more set after the except block. This change was motivated by the fact the exceptions in Python 3 now store traceback objects.\n\nThe problem is if the user of the API kepts the exception alive after the except block.\n\n\u003e You should know that Py2K\u0027s issue here has been my problem for many, many months. If you feel that you have new insights on solving it, that would be very helpful: (...)\n\nOh no, I wasn\u0027t aware of the issue.","commit_id":"871f1ced4879a9ad57e742670f0ba028a486c054"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"e654001e5f72f378c0b377f72bf2d6242bf25faa","unresolved":false,"context_lines":[{"line_number":389,"context_line":"                                ):"},{"line_number":390,"context_line":"                                    dbe.caused_during_handling_by \u003d \\"},{"line_number":391,"context_line":"                                        context.connection.info.pop("},{"line_number":392,"context_line":"                                            ROLLBACK_CAUSE_KEY)"},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"                                if isinstance("},{"line_number":395,"context_line":"                                        dbe, exception.DBConnectionError):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_4a66b4bb","line":392,"in_reply_to":"3aaa91ec_b47dfd6e","updated":"2016-06-30 16:34:35.000000000","message":"\u003e hum, it looks like you reimplemented something like Exception.__cause__ or Exception.__context__ of Python 3.\n\nthat is correct.\n\n\u003e Maybe you should reuse Exception.__cause__ on Python 3? (but dbe.caused_during_handling_by on Python 2?)\n\nthe problem here is that making this very specific linkage that occurs in a very specific case match that of __cause__ would be very difficult and error prone, and would always be at the risk of behaving differently, causing test suites to fail and version-specific behaviors in Openstack applications.    Ideally, if Py2 had *any* way of doing what py3.__cause__ does, that would solve this whole problem.   But it seems to be completely impossible, even by doing stack inspection (but if you want to work on this, it would be a huge win. )\n\n\u003e The most simple solution working on Python 2 and Python 3 and avoiding reference cycles issues is to store the exception as text, not as an object. The traceback module contains various functions to format an exception as text.\n\nthe exception object here is not being kept alive \"too long\".  It\u0027s dealt with inside of a function that is invoked within the except: block and it is discarded outside of the function and hence the \"except:\" block.  The overall case only occurs in an extremely specific scenario that is not frequent or widespread.\n\nException throws are very expensive in any case, the throw we\u0027re talking about here is in the context of a whole database transaction failing which is in the dozens if not hundreds of milliseconds, so even if a few more cycles were generated, that\u0027s short work for a 2 millisecond gc run.  There\u0027s lots more reference cycles than that in Openstack and its hundreds of dependencies.\n\nYou should know that Py2K\u0027s issue here has been my problem for many, many months.  If you feel that you have new insights on solving it, that would be very helpful: see https://bugs.launchpad.net/neutron/+bug/1590298 for the neutron issue and https://bitbucket.org/zzzeek/sqlalchemy/issues/2696/misleading-exception-triggered-on for the upstream.  In upstream, we merely emit a warning where we are unable to attach __cause__.  However, Neutron now needs to be able to intercept this nested error and inspect it.","commit_id":"871f1ced4879a9ad57e742670f0ba028a486c054"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"ad14193795a8229f9aafb38a2983a701adaa9bdb","unresolved":false,"context_lines":[{"line_number":404,"context_line":"    def rollback_savepoint(conn, name, context):"},{"line_number":405,"context_line":"        exc_info \u003d sys.exc_info()"},{"line_number":406,"context_line":"        if exc_info[1]:"},{"line_number":407,"context_line":"            conn.info[ROLLBACK_CAUSE_KEY] \u003d exc_info[1]"},{"line_number":408,"context_line":""},{"line_number":409,"context_line":"    # try to clear the \"cause\" ASAP outside of savepoints,"},{"line_number":410,"context_line":"    # by grabbing the end of transaction events..."}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_947533fb","line":407,"updated":"2016-07-01 11:31:26.000000000","message":"Please explicitly set exc_info to None with a comment like:\n\n# Break reference cycle\nexc_info \u003d None\n\nIt reduces a little bit the risk of unbreakable reference cycles.","commit_id":"871f1ced4879a9ad57e742670f0ba028a486c054"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"56bbc275c28a75ae0e669ab96003844ffe588edb","unresolved":false,"context_lines":[{"line_number":404,"context_line":"    def rollback_savepoint(conn, name, context):"},{"line_number":405,"context_line":"        exc_info \u003d sys.exc_info()"},{"line_number":406,"context_line":"        if exc_info[1]:"},{"line_number":407,"context_line":"            conn.info[ROLLBACK_CAUSE_KEY] \u003d exc_info[1]"},{"line_number":408,"context_line":""},{"line_number":409,"context_line":"    # try to clear the \"cause\" ASAP outside of savepoints,"},{"line_number":410,"context_line":"    # by grabbing the end of transaction events..."}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_754cfac8","line":407,"in_reply_to":"3aaa91ec_947533fb","updated":"2016-07-01 14:15:14.000000000","message":"how would the body of rollback_savepoint() (and hence the exc_info reference) be saved within a traceback object?   only if an exception is raised from within, right?  once you leave the body of rollback_savepoint(), it\u0027s not part of any traceback.  sys.exc_info() shouldn\u0027t include it either.  just trying to understand.\n\nhere\u0027s a demo:\n\n    import traceback\n    import sys\n\n\n    def foo():\n        somevar \u003d sys.exc_info()\n        traceback.print_exc()\n        return somevar[1]\n\n\n    def bar():\n        x \u003d 1 / 0\n\n    try:\n        bar()\n    except:\n        thing \u003d foo()\n        import gc\n        print(gc.collect())\n        del thing\n\n        print(gc.collect())\n\n\noutput:\n\n\tpython3 test.py \n\tTraceback (most recent call last):\n\t  File \"test.py\", line 15, in \u003cmodule\u003e\n\t    bar()\n\t  File \"test.py\", line 12, in bar\n\t    x \u003d 1 / 0\n\tZeroDivisionError: division by zero\n\t0\n        0\n\nfoo() isn\u0027t in the traceback, and gc.collect() reports zero cycles.    When we delete \"thing\", gc.collect() still reports zero cycles.","commit_id":"871f1ced4879a9ad57e742670f0ba028a486c054"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6407a79d17fb05b579c1f4d44bdd3b56c06f950f","unresolved":false,"context_lines":[{"line_number":442,"context_line":""},{"line_number":443,"context_line":"    @event.listens_for(engine, \"rollback_savepoint\")"},{"line_number":444,"context_line":"    def rollback_savepoint(conn, name, context):"},{"line_number":445,"context_line":"        exc_info \u003d sys.exc_info()"},{"line_number":446,"context_line":"        if exc_info[1]:"},{"line_number":447,"context_line":"            conn.info[ROLLBACK_CAUSE_KEY] \u003d exc_info[1]"},{"line_number":448,"context_line":"        # NOTE(zzzeek) this eliminates a reference cycle between tracebacks"}],"source_content_type":"text/x-python","patch_set":8,"id":"1aa78d24_e63252f1","line":445,"updated":"2016-07-06 18:40:27.000000000","message":"If I\u0027ve got Mike\u0027s point correctly, this code below *does not* create a reference cycle, because traceback saved in exc_info[1] will not contain a reference to this very frame and its variables (which effectively are references) including exc_info (although, we explicitly delete it here as a defensive measure)","commit_id":"38bb3fba436de53e2045df272bdae91d1a15da04"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"85d8f75b937022fd36c899ae3ac0f38474a6b651","unresolved":false,"context_lines":[{"line_number":456,"context_line":"    @event.listens_for(engine, \"rollback\")"},{"line_number":457,"context_line":"    @event.listens_for(engine, \"commit\")"},{"line_number":458,"context_line":"    def pop_exc_tx(conn):"},{"line_number":459,"context_line":"        conn.info.pop(ROLLBACK_CAUSE_KEY, None)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"    # .. as well as connection pool checkin (just in case)."},{"line_number":462,"context_line":"    # the .info dictionary lasts as long as the DBAPI connection itself"}],"source_content_type":"text/x-python","patch_set":10,"id":"5f7c97a3_b869fef8","line":459,"updated":"2018-07-03 14:10:30.000000000","message":"this itself is not doing the tests that we added above and I believe still causes failures.   see https://bugs.launchpad.net/oslo.db/+bug/1684329","commit_id":"60b5b14988b2986c161e6a25dc5030a31d41728b"}]}
