croncommand.py

  • strict warning: Non-static method view::load() should not be called statically in /home/saturn/public_html/blog/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of views_handler_filter::options_validate() should be compatible with views_handler::options_validate($form, &$form_state) in /home/saturn/public_html/blog/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter::options_submit() should be compatible with views_handler::options_submit($form, &$form_state) in /home/saturn/public_html/blog/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter_boolean_operator::value_validate() should be compatible with views_handler_filter::value_validate($form, &$form_state) in /home/saturn/public_html/blog/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc on line 159.
  • strict warning: Declaration of views_plugin_style_default::options() should be compatible with views_object::options() in /home/saturn/public_html/blog/sites/all/modules/views/plugins/views_plugin_style_default.inc on line 24.
  • strict warning: Declaration of views_plugin_row::options_validate() should be compatible with views_plugin::options_validate(&$form, &$form_state) in /home/saturn/public_html/blog/sites/all/modules/views/plugins/views_plugin_row.inc on line 134.
  • strict warning: Declaration of views_plugin_row::options_submit() should be compatible with views_plugin::options_submit(&$form, &$form_state) in /home/saturn/public_html/blog/sites/all/modules/views/plugins/views_plugin_row.inc on line 134.

The croncommand module allows you to register a ``cron`` command with paster. The aim of this command is to give your Pylons application the ability to run a set of scheduled tasks via a UNIX cron job.

# -*- coding: utf-8 -*-

###############################################################################
# CronCommand - Cron Paste Script Command                                     #
# --------------------------------------------------------------------------- #
# Copyright (c) 2009 Raoul Snyman                                             #
# --------------------------------------------------------------------------- #
# This library is free software; you can redistribute it and/or modify it     #
# under the terms of the GNU Lesser General Public License as published by    #
# the Free Software Foundation; either version 2.1 of the License, or (at     #
# your option) any later version.                                             #
#                                                                             #
# This library is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public        #
# License for more details.                                                   #
#                                                                             #
# You should have received a copy of the GNU Lesser General Public License    #
# along with this library; if not, write to the Free Software Foundation,     #
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          #
###############################################################################

"""
The croncommand module allows you to register a ``cron`` command with paster.
The aim of this command is to give your Pylons application the ability to run a
set of scheduled tasks via a UNIX cron job. By simply giving your controllers a
``cron`` method, this command will detect all your controllers, and call the
``cron`` method when run.

To make use of this module:

1. Create a ``commands`` module in your Pylons app's directory (i.e. on the same
   level as ``controllers``).
2. Place this module file in that directory.
3. Modify setup.py in the top-most directory and add the following two lines in
   the ``entry_points`` variable::

       [paste.paster_command]
       cron = myapp.commands.croncommand:CronCommand

4. Import the ``CronInterval`` class at the top of your controller file::

       from myapp.commands.croncommand import CronInterval

5. Add a ``cron`` method to all the controllers you want responding to the cron
   system::

       def cron(self, interval):
           if interval == CronInterval.Daily:
               # do some daily stuff here
           else:
               # do some minute-level stuff here

6. In your /etc/crontab.d directory, add a file called ``myapp`` and put
   something like this in it::

       *   *   *   *   *   /usr/bin/paster cron

7. In your /etc/crontab.hourly directory, add a file called ``myapp-hourly``
   and put something like this in it::

       0   *   *   *   *   /usr/bin/paster cron hourly

8. Do the same as the above step for other cron settings like weekly.
9. Reinstall your app using the ``easy_install`` command, this will register
   the ``cron`` command in paster.

"""

import os
from inspect import getmembers, isclass
from paste.script.command import Command
from ..lib.base import BaseController

class CronInterval(object):
    """
    Enumeration-style class. This class specifies the different types of cron
    intervals.
    """
    Default = 0
    Hourly = 1
    Daily = 2
    Weekly = 3
    Monthly = 4


class CronCommand(Command):
    """
    Used as a cron job. Run a set of tasks on a regular basis.

    The cron command will run a set of actions needed by the project on a
    regular basis. By specifying an argument, you can run specify that certain
    things are run at certain intervals. If no argument is given, the command
    runs the minute-level tasks.

    Example usage::

        $ paster cron

        $ paster cron hourly

        $ paster cron daily

    **Arguments**

    (no argument)
        Run the tasks that should be run immediately or most often.

    ``hourly``
        Run the hourly tasks.

    ``daily``
        Run the daily tasks.

    ``weekly``
        Run the weekly tasks.

    ``monthly``
        Run the monthly tasks.

    """
    summary = __doc__.splitlines()[1]
    usage = '\n' + __doc__
    min_args = 0
    max_args = 1
    group_name = 'myapp'
    default_verbosity = 3
    parser = Command.standard_parser(simulate=True)

    def __init__(self, name):
        Command.__init__(self, name)
        self.controllers = []
        self.load_controllers()

    def command(self):
        """
        Run the command.
        """
        if len(self.args):
            frequency = str(self.args[0]).lower().trim()
            if frequency == u'hourly':
                for controller in self.controllers:
                    controller.cron(CronInterval.Hourly)
            elif frequency == u'daily':
                for controller in self.controllers:
                    controller.cron(CronInterval.Daily)
            elif frequency == u'weekly':
                for controller in self.controllers:
                    controller.cron(CronInterval.Weekly)
            elif frequency == 'monthly':
                for controller in self.controllers:
                    controller.cron(CronInterval.Monthly)
        else:
            for controller in self.controllers:
                controller.cron(CronInterval.Default)

    def load_controllers(self):
        base_path = os.path.abspath(os.path.join(os.path.dirname(
            os.path.abspath(__file__)), u'..', u'..'))
        project_path = os.path.abspath(os.path.join(os.path.dirname(
            os.path.abspath(__file__)), u'..'))
        controller_path = os.path.abspath(os.path.join(project_path, u'controllers'))
        for root, dirs, files in os.walk(controller_path):
            for name in files:
                if name.endswith(u'.py') and not name.startswith(u'__'):
                    path = os.path.abspath(os.path.join(root, name))
                    modulename, pyext = os.path.splitext(path)
                    prefix_len = len(os.path.commonprefix([base_path, path])) + 1
                    modulename = modulename.replace(os.path.sep, '.')[prefix_len:]
                    try:
                        members = __import__(modulename, globals(), locals(), ['*'])
                    except:
                        pass
        controller_classes = BaseController.__subclasses__()
        self.controllers = []
        for c in controller_classes:
            if hasattr(c, 'cron'):
                try:
                    controller = c()
                    self.controllers.append(controller)
                except:
                    pass