flexget.utils.simple_persistence
Covered: 98 lines
Missed: 6 lines
Skipped 31 lines
Percent: 94 %
  1
"""
  2
NOTE:
  4
Avoid using this module on your own or in plugins, this was originally made for 0.9 -> 1.0 transition.
  6
You can safely use feed.simple_persistence and manager.persist, if we implement something better we
  7
can replace underlying mechanism in single point (and provide transparent switch).
  8
"""
 10
import logging
 11
from datetime import datetime
 12
import pickle
 13
from sqlalchemy import Column, Integer, String, DateTime, PickleType, select
 14
from UserDict import DictMixin
 15
from flexget import schema
 16
from flexget.manager import Session
 17
from flexget.utils.database import safe_pickle_synonym
 18
from flexget.utils.sqlalchemy_utils import table_schema
 20
log = logging.getLogger('util.simple_persistence')
 21
Base = schema.versioned_base('simple_persistence', 1)
 24
@schema.upgrade('simple_persistence')
 25
def upgrade(ver, session):
 26
    if ver is None:
 28
        ver = 0
 29
    if ver == 0:
 31
        table = table_schema('simple_persistence', session)
 32
        for row in session.execute(select([table.c.id, table.c.plugin, table.c.key, table.c.value])):
 33
            try:
 34
                p = pickle.loads(row['value'])
 35
            except Exception, e:
 36
                log.warning('Couldn\'t load %s:%s removing from db: %s' % (row['plugin'], row['key'], e))
 37
                session.execute(table.delete().where(table.c.id == row['id']))
 38
        ver = 1
 39
    return ver
 42
class SimpleKeyValue(Base):
 43
    """Declarative"""
 45
    __tablename__ = 'simple_persistence'
 47
    id = Column(Integer, primary_key=True)
 48
    feed = Column(String)
 49
    plugin = Column(String)
 50
    key = Column(String)
 51
    _value = Column('value', PickleType)
 52
    value = safe_pickle_synonym('_value')
 53
    added = Column(DateTime, default=datetime.now())
 55
    def __init__(self, feed, plugin, key, value):
 56
        self.feed = feed
 57
        self.plugin = plugin
 58
        self.key = key
 59
        self.value = value
 61
    def __repr__(self):
 62
        return "<SimpleKeyValue('%s','%s','%s')>" % (self.feed, self.key, self.value)
 65
class SimplePersistence(DictMixin):
 67
    def __init__(self, plugin, session=None):
 68
        self.feedname = None
 69
        self.plugin = plugin
 70
        self.session = session
 72
    def __setitem__(self, key, value):
 73
        session = self.session or Session()
 74
        skv = session.query(SimpleKeyValue).filter(SimpleKeyValue.feed == self.feedname).\
 75
                filter(SimpleKeyValue.plugin == self.plugin).filter(SimpleKeyValue.key == key).first()
 76
        if skv:
 78
            log.debug('updating key %s value %s' % (key, repr(value)))
 79
            skv.value = value
 80
        else:
 82
            skv = SimpleKeyValue(self.feedname, self.plugin, key, value)
 83
            log.debug('adding key %s value %s' % (key, repr(value)))
 84
            session.add(skv)
 85
        if not self.session:
 87
            session.commit()
 88
            session.close()
 90
    def __getitem__(self, key):
 91
        session = self.session or Session()
 92
        skv = session.query(SimpleKeyValue).filter(SimpleKeyValue.feed == self.feedname).\
 93
            filter(SimpleKeyValue.plugin == self.plugin).filter(SimpleKeyValue.key == key).first()
 94
        if not self.session:
 95
            session.close()
 96
        if not skv:
 97
            raise KeyError('%s is not contained in the simple_persistence table.' % key)
 98
        else:
 99
            return skv.value
101
    def __delitem__(self, key):
102
        session = self.session or Session()
103
        session.query(SimpleKeyValue).filter(SimpleKeyValue.feed == self.feedname).\
104
            filter(SimpleKeyValue.plugin == self.plugin).filter(SimpleKeyValue.key == key).delete()
105
        if not self.session:
106
            session.commit()
107
            session.close()
109
    def keys(self):
110
        session = self.session or Session()
111
        query = session.query(SimpleKeyValue.key).filter(SimpleKeyValue.feed == self.feedname).\
112
             filter(SimpleKeyValue.plugin == self.plugin).all()
113
        if query:
114
            return [item.key for item in query]
115
        else:
116
            return []
119
class SimpleFeedPersistence(SimplePersistence):
121
    def __init__(self, feed):
122
        self.feed = feed
124
    @property
125
    def plugin(self):
126
        return self.feed.current_plugin
128
    @property
129
    def feedname(self):
130
        return self.feed.name
132
    @property
133
    def session(self):
134
        return self.feed.session