~sambuddhabasu1/mailman/fix_mailman_run_error

« back to all changes in this revision

Viewing changes to Mailman/Digester.py

  • Committer: bwarsaw
  • Date: 2006-12-29 22:20:25 UTC
  • Revision ID: vcs-imports@canonical.com-20061229222025-tt02gyfmt4133pgy
Merged revisions 8113-8121 via svnmerge from 
https://mailman.svn.sourceforge.net/svnroot/mailman/branches/tmp-sqlalchemy-branch

................
  r8114 | bwarsaw | 2006-12-06 00:16:54 -0500 (Wed, 06 Dec 2006) | 44 lines
  
  Initial take on using SQLAlchemy to store list data in lieu of Python pickles.
  While all the list data (including OldStyleMemberships attributes) are stored
  in the database, many attributes are stored as PickleTypes binary data.  This
  isn't idea but it gets things working until a more sophisticated schema can be
  developed.
  
  MailList class is now a new-style class, as is required by SQLAlchemy.  This
  makes several things, er, interesting.  Rip out all the low-level pickle
  reading and writing stuff.  Hook SA transaction events into Lock() and
  Unlock().  Move the hooking of the _memberadaptor into InitTempVars(), which
  gets called by the SQLAlchemy hooks (MailList.__init__() never is).
  
  Add an initialize.py module which centralizes all the initialization bits that
  command line scripts have to do, including configuration, logging, and atabase
  initialization.
  
  This change also converts bin/withlist to mmshell wrapper.
  
  Update to SQLAlchemy 0.3.1.
  
  Revamp paths.py.in considerably.  There were several problems with the old
  way.  We no longer disable default loading of site-packages so we don't need
  to add Python's site-packages back to sys.path.  Also, because
  site.addsitedir() causes things like .pth paths to be /appended/ to sys.path,
  they actually won't override any site-installed packages.  E.g. if SQLAlchemy
  is installed in the system Python, our version will not override.  IIUC,
  setuptools-based packages can be configured to work properly in the face of
  package versions, however not all packages we currently depend on are
  setuptools-based.  So instead, we steal a bit of stuff from site.py but change
  things so the prepend .pth stuff to sys.path.
  
  Update several modules to use True/False and whitespace normalization.
  Convert from mm_cfg to config object.  Modernize a few coding constructs.
  
  Add a couple of exceptions to handle database problems.
  
  In the export script, include the widget type in the elements.  This helped in
  my stupid little throw away conversion script, but I think it will be more
  generally useful.
  
  Add an interact.py module which refactors interactive interpreter access.
  Mostly this is used by withlist -i, but it lets us import Mailman.interact and
  drop into a prompt just about anywhere (e.g. debugging).
................
  r8115 | bwarsaw | 2006-12-07 09:13:56 -0500 (Thu, 07 Dec 2006) | 22 lines
  
  Start to flesh out more of the SQLAlchemy mechanisms.
  
  Added a MailList.__new__() which hooks instantiation to use a query on
  dbcontext to get an existing mailing list.  A 'no-args' call means we're doing
  a Create(), though eventually that will change too.
  
  For now, disable the CheckVersion() call.  Eventually this will be folded into
  schema migration.
  
  list_exists(): Rewrite to use the dbcontext query to determine if the named
  mailing list exists or not.  Requires the fqdn_listname.
  
  Eradicate two failed member adaptors: BDBMemberAdaptor and SAMemberships.
  
  Change the way the DBContext holds onto tables.  It now keeps a dictionary
  mapping the table's name to the SA Table instance.  This makes it easier to
  look up and use the individual tables.
  
  Add 'web_page_url' as an attribute managed by SA, and remove a debugging
  print.
................
  r8116 | bwarsaw | 2006-12-11 07:27:47 -0500 (Mon, 11 Dec 2006) | 29 lines
  
  Rework the whole dbcontext and transaction framework.  SA already handles
  nested transactions so we don't have to worry about them.  However, we do have
  the weird situation where some transactions are tied to MailList
  .Lock()/.Unlock()/.Save() and some are tied to non-mlist actions.  So now we
  use an @txn decorator to put methods in a session transaction, but then we
  also hook into the above MailList methods as possibly sub-transactions.  We
  use a weakref subclass to manage the MailList interface, with a dictionary
  mapping MailList fqdn_listnames against transactions.  The weakrefs come in by
  giving us a callback when a MailList gets derefed such that we're guaranteed
  to rollback any outstanding transaction.
  
  Also, we have one global DBContext instance but rather than force the rest of
  Mailman to deal with context objects, instead we expose API methods on that
  object into the Mailman.database module, which the rest of the code will use.
  Such methods must be prepended with 'api_' to get exposed this way.
  
  bin/rmlist now works with the SA-backend.  I refactored the code here so that
  other code (namely, the test suite) can more easily and consistently remove a
  mailing list.  This isn't the best place for it ultimately, but it's good
  enough for now.
  
  New convenience functions Utils.split_listname(), .fqdn_listname().
  
  Convert testall to use Mailman.initialize.initialize().  Not all tests work,
  but I'm down to only 8 failures and 7 errors.  Also, do a better job of
  recovering from failures in setUp().
  
  MailList.__new__() now takes keyword arguments.
................
  r8117 | bwarsaw | 2006-12-11 22:58:06 -0500 (Mon, 11 Dec 2006) | 7 lines
  
  Unit test repairs; even though the unit tests are still pretty fragile,
  everything now passes with the SQLAlchemy storage of list data.
  
  Added missing 'personalize' column.  Converted mailmanctl and qrunner to
  initialize() interface.  Fixed _cookie_path() to not fail if SCRIPT_NAME is
  not in the environment.
................
  r8118 | bwarsaw | 2006-12-27 18:45:41 -0500 (Wed, 27 Dec 2006) | 21 lines
  
  Utils.list_names(): Use a database query to get all the list names.
  
  dbcontext.py: Added api_get_list_names() to support Utils.list_names().
  
  listdata.py: Added two additional MailList attributes which need to be stored
  in the database.  The first is 'admin_member_chunksize' which isn't modifiable
  from the web.  The second is 'password' which holds the list's password.
  
  HTMLFormatObject: item strings can now be unicodes.
  
  bin/list_lists.py: Must call initialize() to get the database properly
  initialized, not just config.load().  This will be a common theme.
  
  SecurityManager.py:
      - Remove md5 and crypt support
      - Added mailman.debug logger, though it will be only used during
        debugging.
      - The 'secret' can be a unicode now.
      - A few coding style updates; repr() instead of backticks, 'key in dict'
        instead of 'dict.has_key(key)'
................
  r8119 | bwarsaw | 2006-12-27 19:13:09 -0500 (Wed, 27 Dec 2006) | 2 lines
  
  genaliases.py: config.load() -> initialize()
................
  r8120 | bwarsaw | 2006-12-27 19:17:26 -0500 (Wed, 27 Dec 2006) | 9 lines
  
  Blocked revisions 8113 via svnmerge
  
  ........
    r8113 | bwarsaw | 2006-12-05 23:54:30 -0500 (Tue, 05 Dec 2006) | 3 lines
    
    Initialized merge tracking via "svnmerge" with revisions "1-8112" from 
    https://mailman.svn.sourceforge.net/svnroot/mailman/branches/tmp-sqlalchemy-branch
  ........
................
  r8121 | bwarsaw | 2006-12-28 23:34:52 -0500 (Thu, 28 Dec 2006) | 20 lines
  
  Remove SIGTERM handling from all the CGI scripts.  This messes with HTTPRunner
  because when you issue "mailmanctl stop" after the signal handler has been
  installed, the process will get a SIGTERM, the signal handler will run, and
  the process will exit with a normal zero code.  This will cause mailmanctl to
  try to restart the HTTPRunner.
  
  I don't think we need that stuff at all when running under wsgi with a
  SQLAlchemy backend.  If mailmanctl kills the HTTPRunner in the middle of the
  process, I believe (but have not tested) that the transaction should get
  properly rolled back at process exit.  We need to make sure about this, and
  also we need to test the signal handling functionality under traditional CGI
  environment (if we even still want to support that).
  
  Also, make sure that we don't try to initialize the loggers twice in qrunner.
  This was the cause of all the double entries in logs/qrunner.
  
  Fix a coding style nit in mailmanctl.py.
  
  De-DOS-ify line endings in loginit.py.
................

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
 
1
# Copyright (C) 1998-2006 by the Free Software Foundation, Inc.
2
2
#
3
3
# This program is free software; you can redistribute it and/or
4
4
# modify it under the terms of the GNU General Public License
5
5
# as published by the Free Software Foundation; either version 2
6
6
# of the License, or (at your option) any later version.
7
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software 
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
16
# USA.
16
17
 
17
18
 
18
19
"""Mixin class with list-digest handling methods and settings."""
19
20
 
20
21
import os
21
 
from stat import ST_SIZE
22
22
import errno
23
23
 
24
 
from Mailman import mm_cfg
 
24
from Mailman import Errors
25
25
from Mailman import Utils
26
 
from Mailman import Errors
27
26
from Mailman.Handlers import ToDigest
 
27
from Mailman.configuration import config
28
28
from Mailman.i18n import _
29
29
 
30
30
 
31
31
 
32
32
class Digester:
33
33
    def InitVars(self):
34
 
        # Configurable
35
 
        self.digestable = mm_cfg.DEFAULT_DIGESTABLE
36
 
        self.digest_is_default = mm_cfg.DEFAULT_DIGEST_IS_DEFAULT
37
 
        self.mime_is_default_digest = mm_cfg.DEFAULT_MIME_IS_DEFAULT_DIGEST
38
 
        self.digest_size_threshhold = mm_cfg.DEFAULT_DIGEST_SIZE_THRESHHOLD
39
 
        self.digest_send_periodic = mm_cfg.DEFAULT_DIGEST_SEND_PERIODIC
40
 
        self.next_post_number = 1
41
 
        self.digest_header = mm_cfg.DEFAULT_DIGEST_HEADER
42
 
        self.digest_footer = mm_cfg.DEFAULT_DIGEST_FOOTER
43
 
        self.digest_volume_frequency = mm_cfg.DEFAULT_DIGEST_VOLUME_FREQUENCY
44
 
        # Non-configurable.
 
34
        # Configurable
 
35
        self.digestable = config.DEFAULT_DIGESTABLE
 
36
        self.digest_is_default = config.DEFAULT_DIGEST_IS_DEFAULT
 
37
        self.mime_is_default_digest = config.DEFAULT_MIME_IS_DEFAULT_DIGEST
 
38
        self.digest_size_threshhold = config.DEFAULT_DIGEST_SIZE_THRESHHOLD
 
39
        self.digest_send_periodic = config.DEFAULT_DIGEST_SEND_PERIODIC
 
40
        self.next_post_number = 1
 
41
        self.digest_header = config.DEFAULT_DIGEST_HEADER
 
42
        self.digest_footer = config.DEFAULT_DIGEST_FOOTER
 
43
        self.digest_volume_frequency = config.DEFAULT_DIGEST_VOLUME_FREQUENCY
 
44
        # Non-configurable.
45
45
        self.one_last_digest = {}
46
 
        self.digest_members = {}
47
 
        self.next_digest_number = 1
 
46
        self.digest_members = {}
 
47
        self.next_digest_number = 1
48
48
        self.digest_last_sent_at = 0
49
49
 
50
50
    def send_digest_now(self):
55
55
            try:
56
56
                mboxfp = None
57
57
                # See if there's a digest pending for this mailing list
58
 
                if os.stat(digestmbox)[ST_SIZE] > 0:
 
58
                if os.stat(digestmbox).st_size > 0:
59
59
                    mboxfp = open(digestmbox)
60
60
                    ToDigest.send_digests(self, mboxfp)
61
61
                    os.unlink(digestmbox)
63
63
                if mboxfp:
64
64
                    mboxfp.close()
65
65
        except OSError, e:
66
 
            if e.errno <> errno.ENOENT: raise
 
66
            if e.errno <> errno.ENOENT:
 
67
                raise
67
68
            # List has no outstanding digests
68
 
            return 0
69
 
        return 1
 
69
            return False
 
70
        return True
70
71
 
71
72
    def bump_digest_volume(self):
72
73
        self.volume += 1