Fix loading of recipes from source. New code use imp module and temporary files.

This commit is contained in:
Kovid Goyal 2008-03-27 01:11:58 +00:00
parent 00f29406ce
commit fea37f24ae

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
''' '''
@ -8,11 +7,13 @@ Builtin recipes.
recipes = ['newsweek', 'atlantic', 'economist', 'dilbert', 'portfolio', recipes = ['newsweek', 'atlantic', 'economist', 'dilbert', 'portfolio',
'nytimes', 'usatoday', 'outlook_india', 'bbc'] 'nytimes', 'usatoday', 'outlook_india', 'bbc']
import re, time import re, imp, inspect, time
from libprs500.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe from libprs500.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe
from libprs500.ebooks.lrf.web.profiles import DefaultProfile, FullContentProfile from libprs500.ebooks.lrf.web.profiles import DefaultProfile, FullContentProfile
from libprs500.ebooks.lrf.web import builtin_profiles from libprs500.ebooks.lrf.web import builtin_profiles
from libprs500.ebooks.BeautifulSoup import BeautifulSoup from libprs500.ebooks.BeautifulSoup import BeautifulSoup
from libprs500.path import path
from libprs500.ptempfile import PersistentTemporaryDirectory
basic_recipes = (BasicNewsRecipe, AutomaticNewsRecipe, CustomIndexRecipe, DefaultProfile, FullContentProfile) basic_recipes = (BasicNewsRecipe, AutomaticNewsRecipe, CustomIndexRecipe, DefaultProfile, FullContentProfile)
basic_recipe_names = (i.__name__ for i in basic_recipes) basic_recipe_names = (i.__name__ for i in basic_recipes)
@ -37,7 +38,8 @@ def load_recipe(module, package='libprs500.web.feeds.recipes'):
recipes = [load_recipe(i) for i in recipes] recipes = [load_recipe(i) for i in recipes]
_tdir = None
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 the first object that is a recipe or profile.
@ -45,15 +47,23 @@ def compile_recipe(src):
@type src: string @type src: string
@return: Recipe/Profile class or None, if no such class was found in C{src} @return: Recipe/Profile class or None, if no such class was found in C{src}
''' '''
locals = {} global _tdir
exec src in globals(), locals if _tdir is None:
for obj in locals.values(): _tdir = path(PersistentTemporaryDirectory('_recipes'))
if type(obj) is type and obj.__name__ not in basic_recipe_names: temp = _tdir/('recipe%d.py'%time.time())
for base in obj.__bases__: f = open(temp, 'wb')
if base in basic_recipes: f.write(src)
return obj f.close()
module = imp.find_module(temp.namebase, [temp.dirname()])
module = imp.load_module(temp.namebase, *module)
classes = inspect.getmembers(module,
lambda x : inspect.isclass(x) and \
issubclass(x, (DefaultProfile, BasicNewsRecipe)) and \
x not in basic_recipes)
if not classes:
return None
return None return classes[0][1]
def get_builtin_recipe(title): def get_builtin_recipe(title):