view backend/sqlalchemy/SqlAlchemyBackend.py @ 155:a05719a6175e

move common functionality into an abstract backend class, have both backends inherit from it. Implement enough of the couchdb backend that reading feeds (and marking feed entries as read) is possible
author Dirk Olmes <dirk@xanthippe.ping.de>
date Sat, 27 Aug 2011 08:52:03 +0200
parents 2682db280be0
children a3c945ce434c
line wrap: on
line source


from Feed import Feed
from FeedEntry import FeedEntry
from Preferences import Preferences
from backend.AbstractBackend import AbstractBackend
from datetime import datetime, timedelta
from sqlalchemy.orm import joinedload
from sqlalchemy.sql import and_
import Database
import FeedUpdater
import Mapping
import logging
import util

class SqlAlchemyBackend(AbstractBackend):
    '''
    Backend that uses sqlalchemy for persistence
    '''

    def __init__(self):
        AbstractBackend.__init__(self)
        self._initLogging()
        self.session = Database.createSession()
        self.prefs = Preferences(self.session)
        self.updater = None

    def _initLogging(self):
        logging.getLogger("sqlalchemy.orm").setLevel(logging.WARN)

        sqlalchemyLogLevel = logging.ERROR
        if util.databaseLoggingEnabled():
            sqlalchemyLogLevel = logging.INFO
        logging.getLogger("sqlalchemy").setLevel(sqlalchemyLogLevel)

    def preferences(self):
        return self.prefs

    def dispose(self):
        # save all uncommitted state, just in case
        self.session.commit()
        self.session.close()

    #
    # handling of feeds
    #

    def getFeeds(self):
        if self.preferences().showOnlyUnreadFeeds():
            self.feeds = self._getUnreadFeeds()
        else:
            self.feeds = Feed.all(self.session)
        return self.feeds

    def _getUnreadFeeds(self):
        query = self.session.query(FeedEntry).filter(FeedEntry.read == 0)
        queryWithOptions = query.options(joinedload("feed"))
        result = queryWithOptions.all()
        return self._collectFeeds(result)

    def _collectFeeds(self, feedEntries):
        feeds = [entry.feed for entry in feedEntries]
        uniqueFeeds = set(feeds)
        return list(uniqueFeeds)

    def _retrieveEntriesForSelectedFeed(self, hideReadEntries):
        return self.selectedFeed.entriesSortedByUpdateDate(hideReadEntries)

    def markSelectedFeedAsRead(self):
        self.selectedFeed.markAllEntriesRead()
        self.session.commit()

    def deleteSelectedFeed(self):
        self.session.delete(self.selectedFeed)
        self.session.commit()

    def createFeed(self, url):
        try:
            FeedUpdater.createNewFeed(url, self.session)
            self.session.commit()
        except AttributeError as ae:
            self.session.rollback()
            raise ae

    def updateAllFeeds(self):
        FeedUpdater.updateAllFeeds(self.session)
        self.session.commit()

    def updateFeed(self, feed, changes):
        feed.takeChangesFrom(changes)
        feed.incrementNextUpdateDate()
        self.session.commit()

    #
    # handling of the selected feed entry
    #

    def _markSelectedFeedEntryRead(self):
        self.selectedFeedEntry.markRead()

    def markFeedEntriesAsRead(self, indices):
        for index in indices:
            self.feedEntries[index].markRead()
        self.session.commit()

    def toggleSelectedFeedEntryRead(self):
        self.selectedFeedEntry.toggleRead()
        self.session.commit()

    def expireFeedEntries(self):
        logger = logging.getLogger("feedupdater")
        expireDate = self._calculateExpireDate()
        logger.info("expiring entries older than " + str(expireDate))
        feedEntry = Mapping.feedEntryTable
        deleteStatement = feedEntry.delete().where(
            and_(feedEntry.c.create_timestamp < expireDate, feedEntry.c.read == 1)
        )
        deleteStatement.execute()
        self.session.commit()

    def _calculateExpireDate(self):
        now = datetime.now()
        daysToKeepFeedEntries = self.prefs.daysToKeepFeedEntries()
        delta = timedelta(days=daysToKeepFeedEntries)
        return now - delta