Source code for biomajmanager.news

"""Utilities to create some news for BioMAJ"""
# from stat import S_ISREG, ST_CTIME, ST_MODE
from biomajmanager.utils import Utils
from rfeed import Item, Feed, Guid
from datetime import datetime
import os
import sys
try:
    from ConfigParser import NoOptionError, NoSectionError
except ImportError:
    from configparser import NoOptionError, NoSectionError


[docs]class News(object): """Class for creating news to be displayed for BioMAJ""" MAX_NEWS = 5
[docs] def __init__(self, news_dir=None, config=None, max_news=None): """ Initiate object building :param news_dir: Path to directory containing templates :type news_dir: str :param config: Configuration object :type config: :class:`configParser` :param max_news: Number of news to get when displaying news (default :const:`News.MAX_NEWS`) :type max_news: int :raises SystemExit: If 'news_dir' is not a directory :raises SystemExit: If 'NEWS' section is not defined in :py:data:`manager.properties` :raises SystemExit: If 'news.dir' is not set in :py:data:`manager.properties` """ self.news_dir = None self.max_news = News.MAX_NEWS self.data = None if max_news: self.max_news = max_news if news_dir is not None: Utils.verbose("[news] 'news_dir' set from %s" % str(news_dir)) if not os.path.isdir(news_dir): Utils.error("News dir %s is not a directory." % news_dir) self.news_dir = news_dir if config is not None: if not config.has_section('NEWS'): Utils.error("Configuration has no 'NEWS' section.") elif not config.has_option('NEWS', 'news.dir'): Utils.error("Configuration has no 'news.dir' key.") else: self.news_dir = config.get('NEWS', 'news.dir') Utils.verbose("[news] 'news_dir' set to %s" % str(self.news_dir))
[docs] def get_news(self, news_dir=None, reverse=True): """ Get the news to be displayed from the specific news.dir directory :param news_dir: Path to news directory :type news_dir: str :param reverse: Reverse list of news files, default True :type reverse: bool :return: news_files, list of news files found into 'news' directory :rtype: list :raises SystemExit: If path 'news_dir' does not exist :raises SystemExit: If 'news_dir' not set """ if news_dir is not None: if not os.path.isdir(news_dir): Utils.error("News dir %s is not a directory" % news_dir) else: self.news_dir = news_dir if not self.news_dir: Utils.error("Can't get news, no 'news.dir' defined.") news_data = [] item = 0 # shamefully copied from # http://stackoverflow.com/questions/168409/how-do-you-get-a-directory-listing-sorted-by-creation-date-in-python # get all entries in the directory w/ stats files = (os.path.join(self.news_dir, file) for file in os.listdir(self.news_dir)) #files = ((os.stat(path), path) for path in files) #files = ((stat[ST_CTIME], path) for stat, path in files if S_ISREG(stat[ST_MODE])) #for _, ifile in sorted(files): for ifile in sorted(files): with open(ifile) as new: Utils.verbose("[news] Reading news file %s ..." % ifile) (label, date, title) = new.readline().strip().split(':') text = '' for line in new.readlines(): text += line news_data.append({'label': label, 'date': date, 'title': title, 'text': text, 'item': item}) item += 1 new.close() if reverse: news_data.reverse() self.data = {'news': news_data} return self.data
[docs]class RSS(News): """Class for generating RSS feed from news files"""
[docs] def __init__(self, rss_file=None, *args, **kwargs): """Initiate object building""" super(RSS, self).__init__(*args, **kwargs) self.rss_file = None self.fh = None if rss_file is not None: self.rss_file = rss_file if 'config' in kwargs: self.config = kwargs['config'] if self.config.has_option('RSS', 'rss.file') and self.rss_file is None: self.rss_file = self.config.get('RSS', 'rss.file') if self.rss_file is None: self.fh = sys.stdout Utils.verbose("[rss] rss_file set to %s" % str(self.rss_file))
[docs] def generate_rss(self, rss_file=None, data=None): """ Generate RSS file from news :param rss_file: Path to file rss.xml :type rss_file: str :param data: Data to create RSS from :type data: dict data['news'] = { ... } :return: Boolean :rtype: bool :raises SystemExit: If 'news' key is not found in 'data' dict :raises SystemExit: If rss file cannot be opened """ if rss_file is not None: Utils.verbose("[rss] rss_file set to %s" % rss_file) self.rss_file = rss_file if data is None: data = self.get_news() elif 'news' not in data: Utils.error("Could not find 'news' key in data") if len(data['news']) == 0: Utils.warn("No data to display") return True items = [] try: for new in data['news']: item = Item(title=new['title'], description=new['text'], author=self.config.get('RSS', 'feed.author'), guid=Guid(self.config.get('RSS', 'feed.news.link') + '#' + str(new['item'])), pubDate=datetime.strptime(new['date'], self.config.get('RSS', 'rss.date.format') .replace('%%', '%')) ) items.append(item) feed = Feed(title=self.config.get('RSS', 'feed.title'), link=self.config.get('RSS', 'feed.link'), description=self.config.get('RSS', 'feed.description'), language=self.config.get('RSS', 'feed.language'), lastBuildDate=datetime.now(), items=items) if self.fh is None: self.fh = open(self.rss_file, 'w') Utils.uprint(feed.rss(), to=self.fh) if self.rss_file is not None: self.fh.close() except (NoOptionError, NoSectionError) as err: Utils.error("Option missing in config file: %s" % str(err)) except (OSError, IOError) as err: Utils.error("Can't open file %s: %s" % (self.rss_file, str(err))) return True