mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
News download system: Allow use of __future__ in recipes, and do not change line numbers of code in the recipe when compiling it
This commit is contained in:
parent
1962d12290
commit
959afbd350
@ -4,20 +4,14 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
'''
|
'''
|
||||||
Builtin recipes.
|
Builtin recipes.
|
||||||
'''
|
'''
|
||||||
import re, imp, inspect, time, os
|
import re, time, io
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, \
|
from calibre.web.feeds.news import (BasicNewsRecipe, CustomIndexRecipe,
|
||||||
AutomaticNewsRecipe, CalibrePeriodical
|
AutomaticNewsRecipe, CalibrePeriodical)
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
|
||||||
from calibre import __appname__, english_sort
|
|
||||||
from calibre.utils.config import JSONConfig
|
from calibre.utils.config import JSONConfig
|
||||||
|
|
||||||
BeautifulSoup, time, english_sort
|
|
||||||
|
|
||||||
basic_recipes = (BasicNewsRecipe, AutomaticNewsRecipe, CustomIndexRecipe,
|
basic_recipes = (BasicNewsRecipe, AutomaticNewsRecipe, CustomIndexRecipe,
|
||||||
CalibrePeriodical)
|
CalibrePeriodical)
|
||||||
_tdir = None
|
|
||||||
_crep = 0
|
|
||||||
|
|
||||||
custom_recipes = JSONConfig('custom_recipes/index.json')
|
custom_recipes = JSONConfig('custom_recipes/index.json')
|
||||||
|
|
||||||
@ -28,39 +22,33 @@ def custom_recipe_filename(id_, title):
|
|||||||
|
|
||||||
def compile_recipe(src):
|
def compile_recipe(src):
|
||||||
'''
|
'''
|
||||||
Compile the code in src and return the first object that is a recipe or profile.
|
Compile the code in src and return a recipe object, if found.
|
||||||
@param src: Python source code
|
|
||||||
@type src: string
|
:param src: Python source code as bytestring or unicode object
|
||||||
@return: Recipe class or None, if no such class was found in C{src}
|
|
||||||
|
:return: Recipe class or None, if no such class was found in src
|
||||||
'''
|
'''
|
||||||
global _tdir, _crep
|
|
||||||
if _tdir is None or not os.path.exists(_tdir):
|
|
||||||
_tdir = PersistentTemporaryDirectory('_recipes')
|
|
||||||
temp = os.path.join(_tdir, 'recipe%d.py'%_crep)
|
|
||||||
_crep += 1
|
|
||||||
if not isinstance(src, unicode):
|
if not isinstance(src, unicode):
|
||||||
match = re.search(r'coding[:=]\s*([-\w.]+)', src[:200])
|
match = re.search(r'coding[:=]\s*([-\w.]+)', src[:200])
|
||||||
enc = match.group(1) if match else 'utf-8'
|
enc = match.group(1) if match else 'utf-8'
|
||||||
src = src.decode(enc)
|
src = src.decode(enc)
|
||||||
src = re.sub(r'from __future__.*', '', src)
|
# Python complains if there is a coding declaration in a unicode string
|
||||||
f = open(temp, 'wb')
|
src = re.sub(r'^#.*coding\s*[:=]\s*([-\w.]+)', '#', src, flags=re.MULTILINE)
|
||||||
src = 'from %s.web.feeds.news import BasicNewsRecipe, AutomaticNewsRecipe\n'%__appname__ + src
|
# Translate newlines to \n
|
||||||
src = '# coding: utf-8\n' + src
|
src = io.StringIO(src, newline=None).getvalue()
|
||||||
src = 'from __future__ import with_statement\n' + src
|
|
||||||
|
|
||||||
src = src.replace('from libprs500', 'from calibre').encode('utf-8')
|
namespace = {
|
||||||
f.write(src)
|
'BasicNewsRecipe':BasicNewsRecipe,
|
||||||
f.close()
|
'AutomaticNewsRecipe':AutomaticNewsRecipe,
|
||||||
module = imp.find_module(os.path.splitext(os.path.basename(temp))[0],
|
'time':time, 're':re,
|
||||||
[os.path.dirname(temp)])
|
'BeautifulSoup':BeautifulSoup
|
||||||
module = imp.load_module(os.path.splitext(os.path.basename(temp))[0], *module)
|
}
|
||||||
classes = inspect.getmembers(module,
|
exec src in namespace
|
||||||
lambda x : inspect.isclass(x) and \
|
|
||||||
issubclass(x, (BasicNewsRecipe,)) and \
|
|
||||||
x not in basic_recipes)
|
|
||||||
if not classes:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return classes[0][1]
|
for x in namespace.itervalues():
|
||||||
|
if (isinstance(x, type) and issubclass(x, BasicNewsRecipe) and x not
|
||||||
|
in basic_recipes):
|
||||||
|
return x
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user