# Buggy code
def lookup_series(name=None, tvdb_id=None, only_cached=False, session=None):
    """
    Look up information on a series. Will be returned from cache if available, and looked up online and cached if not.

    Either `name` or `tvdb_id` parameter are needed to specify the series.
    :param unicode name: Name of series.
    :param int tvdb_id: TVDb ID of series.
    :param bool only_cached: If True, will not cause an online lookup. LookupError will be raised if not available
        in the cache.
    :param session: An sqlalchemy session to be used to lookup and store to cache. Commit(s) may occur when passing in
        a session. If one is not supplied it will be created.

    :return: Instance of :class:`TVDBSeries` populated with series information. If session was not supplied, this will
        be a detached from the database, so relationships cannot be loaded.
    :raises: :class:`LookupError` if series cannot be looked up.
    """
    if not (name or tvdb_id):
        raise LookupError("No criteria specified for tvdb lookup")

    log.debug("Looking up tvdb information for %s %s", name, tvdb_id)

    series = None

    def id_str():
        return "<name=%s,tvdb_id=%s>" % (name, tvdb_id)

    if tvdb_id:
        series = session.query(TVDBSeries).filter(TVDBSeries.id == tvdb_id).first()
    if not series and name:
        found = (
            session.query(TVDBSearchResult)
            .filter(func.lower(TVDBSearchResult.search) == name.lower())
            .first()
        )
        if found and found.series:
            series = found.series
    if series:
        # Series found in cache, update if cache has expired.
        if not only_cached:
            mark_expired(session=session)
        if not only_cached and series.expired:
            log.verbose("Data for %s has expired, refreshing from tvdb", series.name)
            try:
                updated_series = TVDBSeries(id=series.id)
                series = session.merge(updated_series)
                _update_search_strings(series, search=name)
            except LookupError as e:
                log.warning(
                    "Error while updating from tvdb (%s), using cached data.", e.args[0]
                )
        else:
            log.debug("Series %s information restored from cache." % id_str())
    else:
        if only_cached:
            raise LookupError("Series %s not found from cache" % id_str())
        # There was no series found in the cache, do a lookup from tvdb
        log.debug("Series %s not found in cache, looking up from tvdb.", id_str())
        if tvdb_id:
            series = session.merge(TVDBSeries(id=tvdb_id))
            _update_search_strings(series, search=name)
        elif name:
            tvdb_id = find_series_id(name)
            if tvdb_id:
                series = (
                    session.query(TVDBSeries).filter(TVDBSeries.id == tvdb_id).first()
                )
                if not series:
                    series = session.merge(TVDBSeries(tvdb_id))
                    _update_search_strings(series, search=name)

    if not series:
        raise LookupError("No results found from tvdb for %s" % id_str())
    if not series.name:
        raise LookupError("Tvdb result for series does not have a title.")

    return series


# Traceback (OperationalError)
2016-03-29 04:00 ERROR    lazy_lookup   nC_movie-HUN    Unhandled error in lazy lookup plugin
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flexget/utils/lazy_dict.py", line 36, in __getitem__
func(self.store)
File "/usr/local/lib/python2.7/dist-packages/flexget/plugins/metainfo/imdb_lookup.py", line 235, in lazy_loader
self.lookup(entry)
File "/usr/local/lib/python2.7/dist-packages/flexget/plugin.py", line 124, in wrapped_func
return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/flexget/utils/database.py", line 30, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/flexget/plugins/metainfo/imdb_lookup.py", line 356, in lookup
entry.update_using_map(self.field_map, movie)
File "/usr/local/lib/python2.7/dist-packages/flexget/entry.py", line 266, in update_using_map
v = value(source_item)
File "/usr/local/lib/python2.7/dist-packages/flexget/plugins/metainfo/imdb_lookup.py", line 212, in <lambda>
'imdb_languages': lambda movie: [lang.language.name for lang in movie.languages],
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/attributes.py", line 237, in __get__
return self.impl.get(instance_state(instance), dict_)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/attributes.py", line 583, in get
value = self.callable_(state, passive)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/strategies.py", line 532, in _load_for_state
return self._emit_lazyload(session, state, ident_key, passive)
File "<string>", line 1, in <lambda>
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/strategies.py", line 602, in _emit_lazyload
result = q.all()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2588, in all
return list(self)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2736, in __iter__
return self._execute_and_instances(context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2751, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 914, in execute
return meth(self, multiparams, params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
exc_info
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/compat.py", line 200, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/default.py", line 450, in do_execute
cursor.execute(statement, parameters)
OperationalError: (sqlite3.OperationalError) database is locked [SQL: u'SELECT imdb_movie_languages.movie_id AS imdb_movie_languages_movie_id, imdb_movie_languages.language_id AS imdb_movie_languages_language_id, imdb_movie_languages.prominence AS imdb_movie_languages_prominence \nFROM imdb_movie_languages \nWHERE ? = imdb_movie_languages.movie_id ORDER BY imdb_movie_languages.prominence'] [parameters: (1495,)]

# Fixed code
def lookup_series(name=None, tvdb_id=None, only_cached=False, session=None):
    """
    Look up information on a series. Will be returned from cache if available, and looked up online and cached if not.

    Either `name` or `tvdb_id` parameter are needed to specify the series.
    :param unicode name: Name of series.
    :param int tvdb_id: TVDb ID of series.
    :param bool only_cached: If True, will not cause an online lookup. LookupError will be raised if not available
        in the cache.
    :param session: An sqlalchemy session to be used to lookup and store to cache. Commit(s) may occur when passing in
        a session. If one is not supplied it will be created.

    :return: Instance of :class:`TVDBSeries` populated with series information. If session was not supplied, this will
        be a detached from the database, so relationships cannot be loaded.
    :raises: :class:`LookupError` if series cannot be looked up.
    """
    if not (name or tvdb_id):
        raise LookupError("No criteria specified for tvdb lookup")

    log.debug("Looking up tvdb information for %s %s", name, tvdb_id)

    series = None

    def id_str():
        return "<name=%s,tvdb_id=%s>" % (name, tvdb_id)

    if tvdb_id:
        series = session.query(TVDBSeries).filter(TVDBSeries.id == tvdb_id).first()
    if not series and name:
        found = (
            session.query(TVDBSearchResult)
            .filter(func.lower(TVDBSearchResult.search) == name.lower())
            .first()
        )
        if found and found.series:
            series = found.series
    if series:
        # Series found in cache, update if cache has expired.
        if not only_cached:
            mark_expired(session=session)
        if not only_cached and series.expired:
            log.verbose("Data for %s has expired, refreshing from tvdb", series.name)
            try:
                updated_series = TVDBSeries(series.id)
                series = session.merge(updated_series)
                _update_search_strings(series, search=name)
            except LookupError as e:
                log.warning(
                    "Error while updating from tvdb (%s), using cached data.", e.args[0]
                )
        else:
            log.debug("Series %s information restored from cache." % id_str())
    else:
        if only_cached:
            raise LookupError("Series %s not found from cache" % id_str())
        # There was no series found in the cache, do a lookup from tvdb
        log.debug("Series %s not found in cache, looking up from tvdb.", id_str())
        if tvdb_id:
            series = session.merge(TVDBSeries(tvdb_id))
            _update_search_strings(series, search=name)
        elif name:
            tvdb_id = find_series_id(name)
            if tvdb_id:
                series = (
                    session.query(TVDBSeries).filter(TVDBSeries.id == tvdb_id).first()
                )
                if not series:
                    series = session.merge(TVDBSeries(tvdb_id))
                    _update_search_strings(series, search=name)

    if not series:
        raise LookupError("No results found from tvdb for %s" % id_str())
    if not series.name:
        raise LookupError("Tvdb result for series does not have a title.")

    return series