home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1445 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  12.8 KB  |  336 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
  6. import time
  7. import traceback
  8. import copy
  9. import re
  10. from lxml import html
  11. from calibre.web.feeds.feedparser import parse
  12. from calibre.utils.logging import default_log
  13. from calibre import entity_to_unicode, strftime
  14. from calibre.utils.date import dt_factory, utcnow, local_tz
  15.  
  16. class Article(object):
  17.     
  18.     def __init__(self, id, title, url, author, summary, published, content):
  19.         self.downloaded = False
  20.         self.id = id
  21.         self._title = None if title else title
  22.         
  23.         try:
  24.             self._title = re.sub('&(\\S+?);', entity_to_unicode, self._title)
  25.         except:
  26.             pass
  27.  
  28.         if not isinstance(self._title, unicode):
  29.             self._title = self._title.decode('utf-8', 'replace')
  30.         
  31.         self.url = url
  32.         self.author = author
  33.         if author and not isinstance(author, unicode):
  34.             author = author.decode('utf-8', 'replace')
  35.         
  36.         self.summary = summary
  37.         if summary and not isinstance(summary, unicode):
  38.             summary = summary.decode('utf-8', 'replace')
  39.         
  40.         if summary and '<' in summary:
  41.             
  42.             try:
  43.                 s = html.fragment_fromstring(summary, create_parent = True)
  44.                 summary = html.tostring(s, method = 'text', encoding = unicode)
  45.             print 'Failed to process article summary, deleting:'
  46.             print summary.encode('utf-8')
  47.             traceback.print_exc()
  48.             summary = u''
  49.  
  50.         
  51.         self.text_summary = summary
  52.         self.author = author
  53.         self.content = content
  54.         self.date = published
  55.         self.utctime = dt_factory(self.date, assume_utc = True, as_utc = True)
  56.         self.localtime = self.utctime.astimezone(local_tz)
  57.         self._formatted_date = None
  58.  
  59.     
  60.     def formatted_date(self):
  61.         
  62.         def fget(self):
  63.             if self._formatted_date is None:
  64.                 self._formatted_date = strftime(' [%a, %d %b %H:%M]', t = self.localtime.timetuple())
  65.             
  66.             return self._formatted_date
  67.  
  68.         
  69.         def fset(self, val):
  70.             if isinstance(val, unicode):
  71.                 self._formatted_date = val
  72.             
  73.  
  74.         return property(fget = fget, fset = fset)
  75.  
  76.     formatted_date = dynamic_property(formatted_date)
  77.     
  78.     def title(self):
  79.         
  80.         def fget(self):
  81.             t = self._title
  82.             if not isinstance(t, unicode) and hasattr(t, 'decode'):
  83.                 t = t.decode('utf-8', 'replace')
  84.             
  85.             return t
  86.  
  87.         
  88.         def fset(self, val):
  89.             self._title = val
  90.  
  91.         return property(fget = fget, fset = fset)
  92.  
  93.     title = dynamic_property(title)
  94.     
  95.     def __repr__(self):
  96.         return (u'Title       : %s\nURL         : %s\nAuthor      : %s\nSummary     : %s\nDate        : %s\nHas content : %s\n' % (self.title, self.url, self.author, self.summary[:20] + '...', self.localtime.strftime('%a, %d %b, %Y %H:%M'), bool(self.content))).encode('utf-8')
  97.  
  98.     
  99.     def __str__(self):
  100.         return repr(self)
  101.  
  102.     
  103.     def is_same_as(self, other_article):
  104.         if self.url:
  105.             return self.url == getattr(other_article, 'url', False)
  106.         return self.content == getattr(other_article, 'content', False)
  107.  
  108.  
  109.  
  110. class Feed(object):
  111.     
  112.     def __init__(self, get_article_url = (lambda item: item.get('link', None)), log = default_log):
  113.         self.logger = log
  114.         self.get_article_url = get_article_url
  115.  
  116.     
  117.     def populate_from_feed(self, feed, title = None, oldest_article = 7, max_articles_per_feed = 100):
  118.         entries = feed.entries
  119.         feed = feed.feed
  120.         self.title = None if not title else title
  121.         self.description = feed.get('description', '')
  122.         image = feed.get('image', { })
  123.         self.image_url = image.get('href', None)
  124.         self.image_width = image.get('width', 88)
  125.         self.image_height = image.get('height', 31)
  126.         self.image_alt = image.get('title', '')
  127.         self.articles = []
  128.         self.id_counter = 0
  129.         self.added_articles = []
  130.         self.oldest_article = oldest_article
  131.         for item in entries:
  132.             if len(self.articles) >= max_articles_per_feed:
  133.                 break
  134.             
  135.             self.parse_article(item)
  136.         
  137.  
  138.     
  139.     def populate_from_preparsed_feed(self, title, articles, oldest_article = 7, max_articles_per_feed = 100):
  140.         self.title = None(unicode if title else _('Unknown feed'))
  141.         self.description = ''
  142.         self.image_url = None
  143.         self.articles = []
  144.         self.added_articles = []
  145.         self.oldest_article = oldest_article
  146.         self.id_counter = 0
  147.         for item in articles:
  148.             if len(self.articles) >= max_articles_per_feed:
  149.                 break
  150.             
  151.             id = item.get('id', 'internal id#' + str(self.id_counter))
  152.             if id in self.added_articles:
  153.                 return None
  154.             self.added_articles.append(id)
  155.             self.id_counter += 1
  156.             published = time.gmtime(item.get('timestamp', time.time()))
  157.             title = item.get('title', _('Untitled article'))
  158.             link = item.get('url', None)
  159.             description = item.get('description', '')
  160.             content = item.get('content', '')
  161.             author = item.get('author', '')
  162.             article = Article(id, title, link, author, description, published, content)
  163.             delta = utcnow() - article.utctime
  164.             d = item.get('date', '')
  165.             article.formatted_date = d
  166.         
  167.  
  168.     
  169.     def parse_article(self, item):
  170.         id = item.get('id', 'internal id#' + str(self.id_counter))
  171.         if id in self.added_articles:
  172.             return None
  173.         published = item.get('date_parsed', time.gmtime())
  174.         if not published:
  175.             published = time.gmtime()
  176.         
  177.         self.id_counter += 1
  178.         self.added_articles.append(id)
  179.         title = item.get('title', _('Untitled article'))
  180.         
  181.         try:
  182.             link = self.get_article_url(item)
  183.         except:
  184.             self
  185.             self.logger.warning('Failed to get link for %s' % title)
  186.             self.logger.debug(traceback.format_exc())
  187.             link = None
  188.  
  189.         description = item.get('summary', None)
  190.         author = item.get('author', None)
  191.         content = _[1]
  192.         content = [ _[2] if isinstance(i, unicode) else i.decode('utf-8', 'replace') for i in content ]
  193.         content = u'\n'.join(content)
  194.         if not link and not content:
  195.             return None
  196.         article = Article(id, title, link, author, description, published, content)
  197.         delta = utcnow() - article.utctime
  198.  
  199.     
  200.     def reverse(self):
  201.         self.articles.reverse()
  202.  
  203.     
  204.     def __iter__(self):
  205.         return iter(self.articles)
  206.  
  207.     
  208.     def __len__(self):
  209.         return len(self.articles)
  210.  
  211.     
  212.     def __repr__(self):
  213.         res = [ ('%20s\n' % '').replace(' ', '_') + repr(art) for art in self ]
  214.         return '\n' + '\n'.join(res) + '\n'
  215.  
  216.     
  217.     def __str__(self):
  218.         return repr(self)
  219.  
  220.     
  221.     def __bool__(self):
  222.         for article in self:
  223.             if getattr(article, 'downloaded', False):
  224.                 return True
  225.         
  226.         return False
  227.  
  228.     
  229.     def has_embedded_content(self):
  230.         length = 0
  231.         for a in self:
  232.             if a.content or a.summary:
  233.                 None += None(length, max(len if a.content else '')(len if a.summary else ''))
  234.                 continue
  235.         
  236.         return length > 2000 * len(self)
  237.  
  238.     
  239.     def has_article(self, article):
  240.         for a in self:
  241.             if a.is_same_as(article):
  242.                 return True
  243.         
  244.         return False
  245.  
  246.     
  247.     def find(self, article):
  248.         for i, a in enumerate(self):
  249.             if a.is_same_as(article):
  250.                 return i
  251.         
  252.         return -1
  253.  
  254.     
  255.     def remove(self, article):
  256.         i = self.index(article)
  257.         if i > -1:
  258.             self.articles[i:i + 1] = []
  259.         
  260.  
  261.  
  262.  
  263. class FeedCollection(list):
  264.     
  265.     def __init__(self, feeds):
  266.         []([], _[1])
  267.         found_articles = set([])
  268.         duplicates = set([])
  269.         
  270.         def in_set(s, a):
  271.             for x in s:
  272.                 if a.is_same_as(x):
  273.                     return x
  274.             
  275.  
  276.         print '#feeds', len(self)
  277.         print map(len, self)
  278.         for f in self:
  279.             dups = []
  280.             for a in f:
  281.                 first = in_set(found_articles, a)
  282.                 if first is not None:
  283.                     dups.append(a)
  284.                     duplicates.add((first, f))
  285.                     continue
  286.                 found_articles.add(a)
  287.             
  288.             for x in dups:
  289.                 f.articles.remove(x)
  290.             
  291.         
  292.         self.duplicates = duplicates
  293.         print len(duplicates)
  294.         print map(len, self)
  295.  
  296.     
  297.     def find_article(self, article):
  298.         for j, f in enumerate(self):
  299.             for i, a in enumerate(f):
  300.                 if a is article:
  301.                     return (j, i)
  302.             
  303.         
  304.  
  305.     
  306.     def restore_duplicates(self):
  307.         temp = []
  308.         for article, feed in self.duplicates:
  309.             art = copy.deepcopy(article)
  310.             (j, i) = self.find_article(article)
  311.             art.url = '../feed_%d/article_%d/index.html' % (j, i)
  312.             temp.append((feed, art))
  313.         
  314.         for feed, art in temp:
  315.             feed.articles.append(art)
  316.         
  317.  
  318.  
  319.  
  320. def feed_from_xml(raw_xml, title = None, oldest_article = 7, max_articles_per_feed = 100, get_article_url = (lambda item: item.get('link', None)), log = default_log):
  321.     feed = parse(raw_xml)
  322.     pfeed = Feed(get_article_url = get_article_url, log = log)
  323.     pfeed.populate_from_feed(feed, title = title, oldest_article = oldest_article, max_articles_per_feed = max_articles_per_feed)
  324.     return pfeed
  325.  
  326.  
  327. def feeds_from_index(index, oldest_article = 7, max_articles_per_feed = 100, log = default_log):
  328.     feeds = []
  329.     for title, articles in index:
  330.         pfeed = Feed(log = log)
  331.         pfeed.populate_from_preparsed_feed(title, articles, oldest_article = oldest_article, max_articles_per_feed = max_articles_per_feed)
  332.         feeds.append(pfeed)
  333.     
  334.     return feeds
  335.  
  336.