web/lib/django_extensions/management/jobs.py
changeset 3 526ebd3988b0
equal deleted inserted replaced
1:ebaad720f88b 3:526ebd3988b0
       
     1 """
       
     2 django_extensions.management.jobs
       
     3 """
       
     4 
       
     5 import os
       
     6 from imp import find_module
       
     7 
       
     8 _jobs = None
       
     9 
       
    10 def noneimplementation(meth):
       
    11     return None
       
    12 
       
    13 class JobError(Exception):
       
    14     pass
       
    15 
       
    16 class BaseJob(object):
       
    17     help = "undefined job description."
       
    18     when = None
       
    19 
       
    20     def execute(self):
       
    21         raise NotImplementedError("Job needs to implement the execute method")
       
    22 
       
    23 class HourlyJob(BaseJob):
       
    24     when = "hourly"
       
    25 
       
    26 class DailyJob(BaseJob):
       
    27     when = "daily"
       
    28 
       
    29 class WeeklyJob(BaseJob):
       
    30     when = "weekly"
       
    31 
       
    32 class MonthlyJob(BaseJob):
       
    33     when = "monthly"
       
    34 
       
    35 def my_import(name):
       
    36     imp = __import__(name)
       
    37     mods = name.split('.')
       
    38     if len(mods)>1:
       
    39         for mod in mods[1:]:
       
    40             imp = getattr(imp, mod)
       
    41     return imp
       
    42 
       
    43 def find_jobs(jobs_dir):
       
    44     try:
       
    45         return [f[:-3] for f in os.listdir(jobs_dir) \
       
    46                 if not f.startswith('_') and f.endswith(".py")]
       
    47     except OSError:
       
    48         return []
       
    49 
       
    50 def find_job_module(app_name, when=None):
       
    51     parts = app_name.split('.')
       
    52     parts.append('jobs')
       
    53     if when:
       
    54         parts.append(when)
       
    55     parts.reverse()
       
    56     path = None
       
    57     while parts:
       
    58         part = parts.pop()
       
    59         f, path, descr = find_module(part, path and [path] or None)
       
    60     return path
       
    61 
       
    62 def import_job(app_name, name, when=None):
       
    63     jobmodule = "%s.jobs.%s%s" % (app_name, when and "%s." % when or "", name)
       
    64     job_mod = my_import(jobmodule)
       
    65     # todo: more friendly message for AttributeError if job_mod does not exist
       
    66     try:
       
    67         job = job_mod.Job
       
    68     except:
       
    69         raise JobError("Job module %s does not contain class instance named 'Job'" % jobmodule)
       
    70     if when and not (job.when == when or job.when == None):
       
    71         raise JobError("Job %s is not a %s job." % (jobmodule, when))
       
    72     return job
       
    73 
       
    74 def get_jobs(when=None, only_scheduled=False):
       
    75     """
       
    76     Returns a dictionary mapping of job names together with there respective
       
    77     application class.
       
    78     """
       
    79     global _jobs
       
    80     # FIXME: HACK: make sure the project dir is on the path when executed as ./manage.py
       
    81     import sys
       
    82     try:
       
    83         cpath = os.path.dirname(os.path.realpath(sys.argv[0]))
       
    84         ppath = os.path.dirname(cpath)
       
    85         if ppath not in sys.path:
       
    86             sys.path.append(ppath)
       
    87     except:
       
    88         pass
       
    89     if _jobs is None:
       
    90         _jobs = {}
       
    91         if True:
       
    92             from django.conf import settings
       
    93             for app_name in settings.INSTALLED_APPS:
       
    94                 scandirs = (None, 'hourly', 'daily', 'weekly', 'monthly')
       
    95                 if when:
       
    96                     scandirs = None, when
       
    97                 for subdir in scandirs:
       
    98                     try:
       
    99                         path = find_job_module(app_name, subdir)
       
   100                         for name in find_jobs(path):
       
   101                             if (app_name, name) in _jobs:
       
   102                                 raise JobError("Duplicate job %s" % name)
       
   103                             job = import_job(app_name, name, subdir)
       
   104                             if only_scheduled and job.when == None:
       
   105                                 # only include jobs which are scheduled
       
   106                                 continue
       
   107                             if when and job.when != when:
       
   108                                 # generic job not in same schedule
       
   109                                 continue
       
   110                             _jobs[(app_name, name)] = job
       
   111                     except ImportError:
       
   112                         pass # No job module -- continue scanning
       
   113     return _jobs
       
   114 
       
   115 def get_job(app_name, job_name):
       
   116     jobs = get_jobs()
       
   117     if app_name:
       
   118         return jobs[(app_name, job_name)]
       
   119     else:
       
   120         for a, j in jobs.keys():
       
   121             if j==job_name:
       
   122                 return jobs[(a, j)]
       
   123         raise KeyError("Job not found: %s" % job_name)
       
   124 
       
   125 def print_jobs(when=None, only_scheduled=False, show_when=True, \
       
   126                 show_appname=False, show_header=True):
       
   127     jobmap = get_jobs(when, only_scheduled=only_scheduled)
       
   128     print "Job List: %i jobs" % len(jobmap)
       
   129     jlist = jobmap.keys()
       
   130     jlist.sort()
       
   131     appname_spacer = "%%-%is" % max(len(e[0]) for e in jlist)
       
   132     name_spacer = "%%-%is" % max(len(e[1]) for e in jlist)
       
   133     when_spacer = "%%-%is" % max(len(e.when) for e in jobmap.values() if e.when)
       
   134     if show_header:
       
   135         line = " "
       
   136         if show_appname:
       
   137             line += appname_spacer % "appname" + " - "
       
   138         line += name_spacer % "jobname"
       
   139         if show_when:
       
   140             line += " - " + when_spacer % "when"
       
   141         line += " - help"
       
   142         print line
       
   143         print "-"*80
       
   144 
       
   145     for app_name, job_name in jlist:
       
   146         job = jobmap[(app_name, job_name)]
       
   147         line = " "
       
   148         if show_appname:
       
   149             line += appname_spacer % app_name + " - "
       
   150         line += name_spacer % job_name
       
   151         if show_when:
       
   152             line += " - " + when_spacer % (job.when and job.when or "")
       
   153         line += " - " + job.help
       
   154         print line