# Buggy code
def upgrade(ver, session):
    if ver is None:
        # Upgrade to version 0 was a failed attempt at cleaning bad entries from our table, better attempt in ver 1
        ver = 0
    if ver == 0:
        # Remove any values that are not loadable.
        table = table_schema("simple_persistence", session)
        for row in session.execute(
            select([table.c.id, table.c.plugin, table.c.key, table.c.value])
        ):
            try:
                pickle.loads(row["value"])
            except Exception as e:
                log.warning(
                    "Couldn't load %s:%s removing from db: %s"
                    % (row["plugin"], row["key"], e)
                )
                session.execute(table.delete().where(table.c.id == row["id"]))
        ver = 1
    if ver == 1:
        log.info("Creating index on simple_persistence table.")
        create_index("simple_persistence", session, "feed", "plugin", "key")
        ver = 2
    if ver == 2 or ver == 3:
        table = table_schema("simple_persistence", session)
        table_add_column(table, "json", Unicode, session)
        # Make sure we get the new schema with the added column
        table = table_schema("simple_persistence", session)
        failures = 0
        for row in session.execute(select([table.c.id, table.c.value])):
            try:
                p = pickle.loads(row["value"])
                session.execute(
                    table.update()
                    .where(table.c.id == row["id"])
                    .values(json=json.dumps(p, encode_datetime=True))
                )
            except Exception as e:
                failures += 1
        if failures > 0:
            log.error(
                "Error upgrading %s simple_persistence pickle objects. Some information has been lost.",
                failures,
            )
        ver = 4
    return ver


# Traceback (AttributeError)
2016-05-14 17:45 INFO     manager                       Database upgrade is required. Attempting now.
2016-05-14 17:45 ERROR    schema                        Failed to upgrade database for plugin simple_persistence: value
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/flexget/db_schema.py", line 150, in upgrade_wrapper
new_ver = upgrade_func(current_ver, session)
File "/usr/lib/python2.7/site-packages/flexget/utils/simple_persistence.py", line 42, in upgrade
for row in session.execute(select([table.c.id, table.c.plugin, table.c.key, table.c.value])):
File "/usr/lib/python2.7/site-packages/sqlalchemy/util/_collections.py", line 211, in __getattr__
raise AttributeError(key)
AttributeError: value
Traceback (most recent call last):
File "/usr/bin/flexget", line 11, in <module>
sys.exit(main())
File "/usr/lib/python2.7/site-packages/flexget/__init__.py", line 42, in main
manager.start()
File "/usr/lib/python2.7/site-packages/flexget/manager.py", line 309, in start
self.initialize()
File "/usr/lib/python2.7/site-packages/flexget/manager.py", line 206, in initialize
fire_event('manager.upgrade', self)
File "/usr/lib/python2.7/site-packages/flexget/event.py", line 106, in fire_event
result = event(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/flexget/event.py", line 23, in __call__
return self.func(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/flexget/db_schema.py", line 158, in upgrade_wrapper
manager.shutdown(finish_queue=False)
File "/usr/lib/python2.7/site-packages/flexget/manager.py", line 858, in shutdown
raise RuntimeError('Cannot shutdown manager that was never initialized.')
RuntimeError: Cannot shutdown manager that was never initialized.

# Fixed code
def upgrade(ver, session):
    if ver is None:
        # Upgrade to version 0 was a failed attempt at cleaning bad entries from our table, better attempt in ver 1
        ver = 0
    if ver == 0:
        try:
            # Remove any values that are not loadable.
            table = table_schema("simple_persistence", session)
            for row in session.execute(
                select([table.c.id, table.c.plugin, table.c.key, table.c.value])
            ):
                try:
                    pickle.loads(row["value"])
                except Exception as e:
                    log.warning(
                        "Couldn't load %s:%s removing from db: %s"
                        % (row["plugin"], row["key"], e)
                    )
                    session.execute(table.delete().where(table.c.id == row["id"]))
        except Exception as e:
            log.warning(
                "Couldn't upgrade the simple_persistence table. Commencing nuke. Error: %s",
                e,
            )
            raise db_schema.UpgradeImpossible
        ver = 1
    if ver == 1:
        log.info("Creating index on simple_persistence table.")
        create_index("simple_persistence", session, "feed", "plugin", "key")
        ver = 2
    if ver == 2 or ver == 3:
        table = table_schema("simple_persistence", session)
        table_add_column(table, "json", Unicode, session)
        # Make sure we get the new schema with the added column
        table = table_schema("simple_persistence", session)
        failures = 0
        for row in session.execute(select([table.c.id, table.c.value])):
            try:
                p = pickle.loads(row["value"])
                session.execute(
                    table.update()
                    .where(table.c.id == row["id"])
                    .values(json=json.dumps(p, encode_datetime=True))
                )
            except Exception as e:
                failures += 1
        if failures > 0:
            log.error(
                "Error upgrading %s simple_persistence pickle objects. Some information has been lost.",
                failures,
            )
        ver = 4
    return ver