Commits

Marc-Alexandre Chan committed e2ebe43

Reorganised minibot.py into module's __init__.py and eventscheduler.py

Comments (0)

Files changed (3)

minibot/__init__.py

+#-------------------------------------------------------------------------------
+# The Daily Prompt Mini-Bot - A Shut Up and Write Project
+# Author: Marc-Alexandre Chan <laogeodritt at arenthil.net>
+#-------------------------------------------------------------------------------
+#
+# Copyright (c) 2012 Marc-Alexandre Chan. Licensed under the GNU GPL version 3
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+#-------------------------------------------------------------------------------
 
+""" Minibot main driver and event scheduler. """
+
+from os.path import realpath
+
+logger = None # TODO: set up global log because laziness
+
+class MinibotError(StandardError):
+    """ Abstract base class for DailyPromptMinibot errors. """
+    pass
+
+class InvalidRedditError(RuntimeError, MinibotError):
+    """ Raised when specified reddit cannot be found. """
+    pass
+
+class LoginError(RuntimeError, MinibotError):
+    """ Raised when an error occurs upon login. """
+    pass
+
+class DailyPromptMinibot(object):
+    """ The Daily Prompt Minibot. Collects writing prompts sent to it via Reddit
+    private messages, queues them, and posts them daily on the Daily Prompt
+    subreddit.
+
+    This class automatically loads the configuration, sets up the main
+    background events in the scheduler, and runs the scheduler. To run the bot,
+    instantiate this class and call the ``run`` method().
+
+    """
+    def __init__(self, config_filepath):
+        pass
+        # TODO: logging setup
+
+

minibot/eventscheduler.py

+#-------------------------------------------------------------------------------
+# The Daily Prompt Mini-Bot - A Shut Up and Write Project
+# Author: Marc-Alexandre Chan <laogeodritt at arenthil.net>
+#-------------------------------------------------------------------------------
+#
+# Copyright (c) 2012 Marc-Alexandre Chan. Licensed under the GNU GPL version 3
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+#-------------------------------------------------------------------------------
+
+import logging
+import os.devnull
+from os.path import realpath
+
+class EventScheduler(object):
+    """ Event scheduler. Manages and runs events at specified times and
+    repetition intervals. This class acts as the kernel/event scheduler to the
+    bot's main processes.
+
+    The scheduler checks the event queue at the ``refresh_rate`` specified
+    in the config, and executes all tasks that are due or overdue at the current
+    time. This occurs synchronously. If an event is queued but misses its
+    execution time due to other events taking too long to run, it is executed
+    at the next iteration; more overdue tasks are prioritised. When
+    calculating the time a periodic (repeating) event should next execute,
+    it is scheduled for the next FUTURE time (so if it takes longer than its
+    interval time to run, it will skip a run). As such, exact timing is never
+    guaranteed.
+
+    The scheduler is NOT designed for threading, although it probably should!
+
+    Events can be queued in the scheduler in any order. You are not restricted
+    to adding events to the end of the queue, like with Python's ``sched``
+    module.
+
+    Events will always have an ``owner`` attribute set by the scheduler before
+    starting or running. This is a reference back to the EventScheduler object,
+    and can be used to modify events in the queue.
+
+    Call ``queue_event()`` to queue event objects. Call ``run()`` to run the
+    scheduler; this method will exit when no events exist in the queue. Note
+    that
+
+    Attributes (need not be modified, documented for informational purposes):
+
+    approved
+        List of usernames approved to access the bot.
+
+    config
+        Configuration object. This object should allow configuration options to
+        be accessed via config.section_name.option_name. See the
+        ``minibot.config`` module for a reference implementation.
+
+    stdin_path
+    stdout_path
+    stderr_path
+        *Default: os.devnull*
+
+        The path to which to redirect ``stdin``. ``stdout`` and ``stderr`` when
+        run via DaemonRunner. These can be ignored in most cases, as the
+        standard I/O streams aren't used by the Minibot.
+
+
+    pidfile_path
+        *Default: 'minibot.pid' (script directory)*
+
+        The absolute filepath for the daemon's pidfile. Only applicable if the
+        minibot is run as a daemon using the ``daemon`` package.
+
+    pidfile_timeout
+        *Default: 300 (5 minutes)*
+
+        Used as the default acquisition timeout value supplied to the runner's
+        PID lock file. Only applicable if the minibot is run as a daemon using
+        the ``daemon`` package.
+
+    """
+
+    # for DaemonRunner
+    stdin_path  = os.devnull
+    stdout_path = os.devnull
+    stderr_path = os.devnull
+
+    def __init__(self, config, logger=None):
+        """ Initialise the Minibot. ``config`` should be an instance of the
+        ``minibot.Config`` class with a loaded configuration file, or an
+        instance of a class with the same accessible attributes. """
+
+        # attributes
+        self.approved = [u for u in config.users.list()\
+                         if config.users.get_level(u) >= 100]
+        self.config = config
+
+        # for DaemonRunner
+        self.pidfile_path = realpath(config.minibot.pidfile_path)
+        self.pidfile_timeout = 5*60
+
+        # state
+        self.exit_flag = False
+
+        # components
+        self.logger = logger if logger is not None\
+                        else logging.getLogger('dailyprompt.scheduler')
+
+        # extra processing
+        # TODO: anything else?
+        if not self.pidfile_path.endswith('.pid'):
+            self.pidfile_path += '.pid'
+
+        # schedule initial/infinite tasks
+        # TODO
+
+    def run(self):
+        self.check_config()
+
+        # TODO: the rest of this
+
+    def check_config(self):
+        pass
+
+    def queue_event(self, command):
+        pass
+
+    def prepare_event(self, command, res=None):
+        """ Prepare a command for entry into the queue. This fills the resources
+        requested by the command (including the ``owner`` parameter) and checks
+        the parameters. A dict of resources may be specified in ``res``;
+        resources in this dict will be used instead of the regular resources if
+        available. This method is intended for public use by events that may
+        want to chain other events to run under this queue. """
+        pass
+
+    def get_events(type=None):
+        """ Return a generator of event objects currently in the queue. """
+        pass
+
+    def handle_sigterm():
+        pass
+
+    # TODO: exception handling inside events (+ handlers in events)
+    # TODO: validate target?
+
+# old stuff
+
+    def isTargetValid(self):
+        pass
+
+    def postNextPrompt(self):
+        pass
+
+    def checkMessages(self):
+        pass
+
+    def _checkMessage(self):
+        pass
+
+    def addPrompt(self):
+        pass
+
+    def removePrompt(self):
+        pass
+
+    def listPrompts(self):
+        pass
+
+    def handleTerminateSignal(self):
+        pass
+

minibot/minibot.py

-#-------------------------------------------------------------------------------
-# The Daily Prompt Mini-Bot - A Shut Up and Write Project
-# Author: Marc-Alexandre Chan <laogeodritt at arenthil.net>
-#-------------------------------------------------------------------------------
-#
-# Copyright (c) 2012 Marc-Alexandre Chan. Licensed under the GNU GPL version 3
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-#-------------------------------------------------------------------------------
-
-""" Minibot main driver and event scheduler. """
-
-import os.devnull
-from os.path import realpath
-
-class MinibotError(StandardError):
-    """ Abstract base class for DailyPromptMinibot errors. """
-    pass
-
-class InvalidRedditError(RuntimeError, MinibotError):
-    """ Raised when specified reddit cannot be found. """
-    pass
-
-class LoginError(RuntimeError, MinibotError):
-    """ Raised when an error occurs upon login. """
-    pass
-
-class DailyPromptMinibot(object):
-    """ The Daily Prompt Minibot. Collects writing prompts sent to it via Reddit
-    private messages, queues them, and posts them daily on the Daily Prompt
-    subreddit.
-
-    To run the bot, instantiate this class, set its attributes, and
-    then call the run() method. You could also forego the run() method and use
-    the public methods (not prefixed with ``_``) to control the bot using other
-    code.
-
-    This class acts as the kernel/event scheduler to the bot's main processes.
-
-    Attributes (need not be modified, documented for informational purposes):
-
-    approved
-        List of usernames approved to access the bot.
-
-    config
-        Configuration object. This object should allow configuration options to
-        be accessed via config.section_name.option_name. See the
-        ``minibot.config`` module for a reference implementation.
-
-    stdin_path
-    stdout_path
-    stderr_path
-        *Default: os.devnull*
-
-        The path to which to redirect ``stdin``. ``stdout`` and ``stderr`` when
-        run via DaemonRunner. These can be ignored in most cases, as the
-        standard I/O streams aren't used by the Minibot.
-
-
-    pidfile_path
-        *Default: 'minibot.pid' (script directory)*
-
-        The absolute filepath for the daemon's pidfile. Only applicable if the
-        minibot is run as a daemon using the ``daemon`` package.
-
-    pidfile_timeout
-        *Default: 300 (5 minutes)*
-
-        Used as the default acquisition timeout value supplied to the runner's
-        PID lock file. Only applicable if the minibot is run as a daemon using
-        the ``daemon`` package.
-
-    """
-    def __init__(self, config):
-        """ Initialise the Minibot. ``config`` should be an instance of the
-        ``minibot.Config`` class with a loaded configuration file, or an
-        instance of a class with the same accessible attributes. """
-
-        # attributes
-        self.approved = [u for u in config.users.list()\
-                         if config.users.get_level(u) >= 100]
-        self.config = config
-
-        # for DaemonRunner
-        self.stdin_path  = os.devnull
-        self.stdout_path = os.devnull
-        self.stderr_path = os.devnull
-
-        self.pidfile_path = realpath(config.minibot.pidfile_path)
-        self.pidfile_timeout = 5*60
-
-        # state
-        self.exit_flag = False
-
-        # components
-        self.logger = None # TODO: logger
-
-        # extra processing
-        # TODO: anything else?
-        if not self.pidfile_path.endswith('.pid'):
-            self.pidfile_path += '.pid'
-
-        # schedule initial/infinite tasks
-        # TODO
-
-    def run(self):
-        self.check_config()
-
-        # TODO: the rest of this
-
-    def check_config(self):
-        pass
-
-    def queue_event(self, command):
-        pass
-
-    def prepare_event(self, command, res=None):
-        """ Prepare a command for entry into the queue. This fills the resources
-        requested by the command (including the ``owner`` parameter) and checks
-        the parameters. A dict of resources may be specified in ``res``;
-        resources in this dict will be used instead of the regular resources if
-        available. This method is intended for public use by events that may
-        want to chain other events to run under this queue. """
-        pass
-
-    def get_events(type=None):
-        """ Return a generator of event objects currently in the queue. """
-        pass
-
-    # TODO: exception handling inside events (+ handlers in events)
-
-# old stuff
-
-    def isTargetValid(self):
-        pass
-
-    def postNextPrompt(self):
-        pass
-
-    def checkMessages(self):
-        pass
-
-    def _checkMessage(self):
-        pass
-
-    def addPrompt(self):
-        pass
-
-    def removePrompt(self):
-        pass
-
-    def listPrompts(self):
-        pass
-
-    def handleTerminateSignal(self):
-        pass
-