diff -r ebaad720f88b -r 526ebd3988b0 web/lib/django_extensions/management/jobs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/django_extensions/management/jobs.py Wed Jan 20 12:37:40 2010 +0100 @@ -0,0 +1,154 @@ +""" +django_extensions.management.jobs +""" + +import os +from imp import find_module + +_jobs = None + +def noneimplementation(meth): + return None + +class JobError(Exception): + pass + +class BaseJob(object): + help = "undefined job description." + when = None + + def execute(self): + raise NotImplementedError("Job needs to implement the execute method") + +class HourlyJob(BaseJob): + when = "hourly" + +class DailyJob(BaseJob): + when = "daily" + +class WeeklyJob(BaseJob): + when = "weekly" + +class MonthlyJob(BaseJob): + when = "monthly" + +def my_import(name): + imp = __import__(name) + mods = name.split('.') + if len(mods)>1: + for mod in mods[1:]: + imp = getattr(imp, mod) + return imp + +def find_jobs(jobs_dir): + try: + return [f[:-3] for f in os.listdir(jobs_dir) \ + if not f.startswith('_') and f.endswith(".py")] + except OSError: + return [] + +def find_job_module(app_name, when=None): + parts = app_name.split('.') + parts.append('jobs') + if when: + parts.append(when) + parts.reverse() + path = None + while parts: + part = parts.pop() + f, path, descr = find_module(part, path and [path] or None) + return path + +def import_job(app_name, name, when=None): + jobmodule = "%s.jobs.%s%s" % (app_name, when and "%s." % when or "", name) + job_mod = my_import(jobmodule) + # todo: more friendly message for AttributeError if job_mod does not exist + try: + job = job_mod.Job + except: + raise JobError("Job module %s does not contain class instance named 'Job'" % jobmodule) + if when and not (job.when == when or job.when == None): + raise JobError("Job %s is not a %s job." % (jobmodule, when)) + return job + +def get_jobs(when=None, only_scheduled=False): + """ + Returns a dictionary mapping of job names together with there respective + application class. + """ + global _jobs + # FIXME: HACK: make sure the project dir is on the path when executed as ./manage.py + import sys + try: + cpath = os.path.dirname(os.path.realpath(sys.argv[0])) + ppath = os.path.dirname(cpath) + if ppath not in sys.path: + sys.path.append(ppath) + except: + pass + if _jobs is None: + _jobs = {} + if True: + from django.conf import settings + for app_name in settings.INSTALLED_APPS: + scandirs = (None, 'hourly', 'daily', 'weekly', 'monthly') + if when: + scandirs = None, when + for subdir in scandirs: + try: + path = find_job_module(app_name, subdir) + for name in find_jobs(path): + if (app_name, name) in _jobs: + raise JobError("Duplicate job %s" % name) + job = import_job(app_name, name, subdir) + if only_scheduled and job.when == None: + # only include jobs which are scheduled + continue + if when and job.when != when: + # generic job not in same schedule + continue + _jobs[(app_name, name)] = job + except ImportError: + pass # No job module -- continue scanning + return _jobs + +def get_job(app_name, job_name): + jobs = get_jobs() + if app_name: + return jobs[(app_name, job_name)] + else: + for a, j in jobs.keys(): + if j==job_name: + return jobs[(a, j)] + raise KeyError("Job not found: %s" % job_name) + +def print_jobs(when=None, only_scheduled=False, show_when=True, \ + show_appname=False, show_header=True): + jobmap = get_jobs(when, only_scheduled=only_scheduled) + print "Job List: %i jobs" % len(jobmap) + jlist = jobmap.keys() + jlist.sort() + appname_spacer = "%%-%is" % max(len(e[0]) for e in jlist) + name_spacer = "%%-%is" % max(len(e[1]) for e in jlist) + when_spacer = "%%-%is" % max(len(e.when) for e in jobmap.values() if e.when) + if show_header: + line = " " + if show_appname: + line += appname_spacer % "appname" + " - " + line += name_spacer % "jobname" + if show_when: + line += " - " + when_spacer % "when" + line += " - help" + print line + print "-"*80 + + for app_name, job_name in jlist: + job = jobmap[(app_name, job_name)] + line = " " + if show_appname: + line += appname_spacer % app_name + " - " + line += name_spacer % job_name + if show_when: + line += " - " + when_spacer % (job.when and job.when or "") + line += " - " + job.help + print line