<commit_before>APPVER="0.0.0+github"
ABOUT="""\
Mailpile.py          a tool          Copyright 2011-2013, <NAME>
               for searching and                      <http://bre.klaki.net/>
           organizing piles of e-mail

This program is free software: you can redistribute it and/or modify it under
the terms of either the GNU Affero General Public License as published by the
Free Software Foundation or the Apache License 2.0 as published by the Apache
Software Foundation. See the file COPYING.md for details.
"""
###############################################################################
import cgi
import codecs
import datetime
import email.parser
import getopt
import hashlib
import locale
import mailbox
import os
import cPickle
import random
import re
import rfc822
import socket
import struct
import subprocess
import sys
import tempfile
import threading
import time
import SocketServer
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
from urlparse import parse_qs, urlparse
import lxml.html

import mailpile.util
from mailpile.commands import COMMANDS, Action, Help, Load, Rescan
from mailpile.vcard import SimpleVCard
from mailpile.mailutils import *
from mailpile.httpd import *
from mailpile.search import *
from mailpile.ui import *
from mailpile.util import *

Help.ABOUT = ABOUT
DEFAULT_SENDMAIL = '|/usr/sbin/sendmail -i %(rcpt)s'


##[ Specialized threads ]######################################################

class Cron(threading.Thread):

  def __init__(self, name, session):
    threading.Thread.__init__(self)
    self.ALIVE = False
    self.name = name
    self.session = session
    self.schedule = {}
    self.sleep = 10

  def add_task(self, name, interval, task):
    self.schedule[name] = [name, interval, task, time.time()]
    self.sleep = 60
    for i in range(1, 61):
      ok = True
      for tn in self.schedule:
        if (self.schedule[tn][1] % i) != 0: ok = False
      if ok: self.sleep = i

  def cancel_task(self, name):
    if name in self.schedule:
      del self.schedule[name]

  def run(self):
    self.ALIVE = True
    while self.ALIVE and not mailpile.util.QUITTING:
      now = time.time()
      for task_spec in self.schedule.values():
        name, interval, task, last = task_spec
        if task_spec[3] + task_spec[1] <= now:
          task_spec[3] = now
          task()

      # Some tasks take longer than others...
      delay = time.time() - now + self.sleep
      while delay > 0 and self.ALIVE:
        time.sleep(min(1, delay))
        delay -= 1

  def quit(self, session=None, join=True):
    self.ALIVE = False
    if join: self.join()


class Worker(threading.Thread):

  def __init__(self, name, session):
    threading.Thread.__init__(self)
    self.NAME = name or 'Worker'
    self.ALIVE = False
    self.JOBS = []<commit_msg>Add cron docs & improve GCD algorithms<commit_after>APPVER="0.0.0+github"
ABOUT="""\
Mailpile.py          a tool          Copyright 2011-2013, <NAME>
               for searching and                      <http://bre.klaki.net/>
           organizing piles of e-mail

This program is free software: you can redistribute it and/or modify it under
the terms of either the GNU Affero General Public License as published by the
Free Software Foundation or the Apache License 2.0 as published by the Apache
Software Foundation. See the file COPYING.md for details.
"""
###############################################################################
import cgi
import codecs
import datetime
import email.parser
import getopt
import hashlib
import locale
import mailbox
import os
import cPickle
import random
import re
import rfc822
import socket
import struct
import subprocess
import sys
import tempfile
import threading
import time
import SocketServer
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
from urlparse import parse_qs, urlparse
import lxml.html

import mailpile.util
from mailpile.commands import COMMANDS, Action, Help, Load, Rescan
from mailpile.vcard import SimpleVCard
from mailpile.mailutils import *
from mailpile.httpd import *
from mailpile.search import *
from mailpile.ui import *
from mailpile.util import *

Help.ABOUT = ABOUT
DEFAULT_SENDMAIL = '|/usr/sbin/sendmail -i %(rcpt)s'


##[ Specialized threads ]######################################################

class Cron(threading.Thread):
  """
  An instance of this class represents a cron-like worker thread
  that manages and executes tasks in regular intervals
  """

  def __init__(self, name, session):
    threading.Thread.__init__(self)
    self.ALIVE = False
    self.name = name
    self.session = session
    self.schedule = {}
    self.sleep = 10

  def add_task(self, name, interval, task):
    """
    Add a task to the cron worker queue
    
    Keyword arguments:
    name -- The name of the task to add
    interval -- The interval (in seconds) of the task
    task  -- A task function
    """
    self.schedule[name] = (name, interval, task, time.time())
    self.sleep = 1
    # (Re)alculate how long we can sleep between tasks
    #  (sleep min. 1 sec, max. 61 sec)
    # --> Calculate the GCD of the task intervals
    for i in range(2, 61): #i = second
      # Check if any scheduled task intervals are != 0 mod i
      filterFunc = lambda task: (task[1] % i) != 0
      filteredTasks = filter(filterFunc, self.schedule)
      # We can sleep for i seconds if i divides all intervals
      if (len(filteredTasks) == 0): self.sleep = i

  def cancel_task(self, name):
    """
    Cancel a task in the current Cron instance.
    If a task with the given name does not exist,
    ignore the request.
    
    Keyword arguments:
    name -- The name of the task to cancel
    """
    if name in self.schedule:
      del self.schedule[name]

  def run(self):
    """
    Thread main function for a Cron instance.
    
    """
    self.ALIVE = True
    # Main thread loop
    while self.ALIVE and not mailpile.util.QUITTING:
      now = time.time()
      # Check if any of the task is (over)due
      for task_spec in self.schedule.values():
        name, interval, task, last = task_spec
        if last + interval <= now:
          task_spec[3] = now
          task()

      # Some tasks take longer than others...
      delay = time.time() - now + self.sleep
      # Sleep for max. 1 sec to react to the quit
      #  signal in time
      while delay > 0 and self.ALIVE:
        time.sleep(min(1, delay))
        delay -= 1

  def quit(self, session=None, join=True):
    """
    Send a signal to the current Cron instance
    to stop operation.
    
    Keyword arguments:
    join -- If this is True, this method will wait until
            the Cron thread exits.
    """
    self.ALIVE = False
    if join: self.join()


class Worker(threading.Thread):

  def __init__(self, name, session):
    threading.Thread.__init__(self)
    self.NAME = name or 'Worker'
    self.ALIVE = False
    self.JOBS = []
{'fraction_non_alphanumeric': 0.11985072484570117, 'fraction_numerical': 0.009329697143677335, 'mean_word_length': 2.9817142857142858, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6765229', 'n_tokens_mistral': 2087, 'n_tokens_neox': 1973, 'n_words': 749}