| Commit message (Collapse) | Author | Age | Files | Lines |
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
confident the Elixir branch is ready to become mainline. Also, fewer branches
makes for an easier migration to a dvcs.
Don't expect much of the old test suite to work, or even for much of the old
functionality to work. The changes here are disruptive enough to break higher
level parts of Mailman. But that's okay because I am slowly building up a new
and improved test suite, which will lead to a functional system again.
For now, only the doctests in Mailman/docs (and their related test harnesses)
will pass, but they all do pass. Note that Mailman/docs serve as system
documentation first and unit tests second. You should be able to read the
doctest files to understand the underlying data model.
Other changes included in this merge:
- Added the Mailman.ext extension package.
- zope.interfaces uses to describe major components
- SQLAlchemy/Elixir used as the database model
- Top level doinstall target renamed to justinstall
- 3rd-party packages are now installed in pythonlib/lib/python to be more
compliant with distutils standards. This allows us to use just --home
instead of all the --install-* options.
- No longer need to include the email package or pysqlite, as Python 2.5 is
required (and comes with both packages).
- munepy package is included, for Python enums
- IRosterSets are added as a way to manage a collection of IRosters. Roster
sets are named so that we can maintain the indirection between mailing lists
and rosters, where the two are maintained in different storages.
- IMailingListRosters: remove_*_roster() -> delete_*_roster()
- Remove IMember interface.
- Utils.list_names() -> config.list_manager.names
- fqdn_listname() takes an optional hostname argument.
- Added a bunch of new exceptions used throughout the new interfaces.
- Make LockFile a context manager for use with the 'with' statement.
|
| |
|
|
| |
Python 2.5 is required.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
instantiated MailList object via the mapper extension's populate_instance()
method. This based on information from the SQLAlchemy folks.
Add more useful output for LockFile debugging.
Add checks in loginit.py's emit() method (and .flush()) so that if the stream
has been closed, log messages will go to stderr. This happens under the test
suite with SQLAlchemy, because SA keeps references to the MailList objects
which it doesn't seem like we can clear before Python exits. So if say the
lock logger is at debug level, when the lock object gets cleared at Python
shutdown, the stream will have been closed by the time LockFile.__del__() gets
called. This change avoids the traceback at the expense of a little extra
stderr output.
MailList.__lock -> MailList._lock
MailList.__timestamp -> MailList._timestamp
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ConfigParser style ini file which can be used to override various default
settings for just the named loggers.
For example, if you want just the locks logger to print at DEBUG level, add
this:
etc/mailman.cfg:
LOG_CONFIG_FILE = 'etc/mailman.log'
etc/mailman.log:
[locks]
level = DEBUG
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
First off, there are several password hashing schemes added including SHA,
salted-SHA, and RFC 2989 PBKDF2 (contributed by Bob Fleck). Then we encode
the password using RFC 2307 style syntax. At least I think: specifically
things like the PRF and iteration count for PBKDF2 are encoded the way I
/think/ is intended for RFC 2307 but I could be wrong. Seems darn hard to
find definitive information about that.
In any event, even though CLEARTEXT passwords are supported, they are mostly
deprecated, even for user passwords. It also allows us to easily update all
passwords to a new hashing scheme when the existing schemes get cracked. The
default scheme (specified in Defaults.py.in) is salted-SHA with a 20 byte salt
(the salt length and PBKDF2 iteration counts can only be specified in the
passwords.py file).
These hashed passwords are used for user passwords, list owner and moderator
passwords, and site and list creator passwords.
Of course this means that user password reminders are impossible now. They've
been ripped out of the code for a while, but now we'll need to implement
password resets since user passwords cannot be recovered.
bin/export has had several changes:
- export no longer converts to dollar strings. Were assuming dollar strings
are used by default for all new lists and any imported lists will already be
converted to dollar strings.
- Likewise, rip out the password scheme stuff, since cleartext passwords can
never be exported, so we might as well always include the member's hashed
password.
- Fix exporting to stdout when that stream can only handle ascii by wrapping
stdout in a utf-8 codec writer.
Other changes:
- add a missing import to HTTPRunner.py
- Convert GUIBase.py to use Defaults.* for constants instead of mm_cfg.*
- Remove pre-Python 2.4 compatibility from Utils.py. We've already said
Python 2.4 will be a minimum requirement.
- Change the permissions on the global password file. The default 007 umask
is used and should be good enough.
- bin/newlist adds the ability to specify the password scheme (or list the
available schemes) for the list owner password. It is not possible to set
the scheme on a per-list basis. bin/mmsitepass does the same, but for the
site and list creator passwords.
- Fix a nasty problem with bin/import. The comment in the code says it best:
# XXX Here's what sucks. Some properties need to have
# _setValue() called on the gui component, because those
# methods do some pre-processing on the values before they're
# applied to the MailList instance. But we don't have a good
# way to find a category and sub-category that a particular
# property belongs to. Plus this will probably change. So
# for now, we'll just hard code the extra post-processing
# here. The good news is that not all _setValue() munging
# needs to be done -- for example, we've already converted
# everything to dollar strings.
- Set the 'debug' logger to logging.DEBUG level. It doesn't seem to make much
sense for the debugging log to ignore debug messages.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
................
|
| |
|
|
|
|
|
|
|
|
|
| |
instead of mm_cfg.py. This involved mostly mechanical replacements, but
there were a few gotchas to make sure that various calls and assignments
that ultimately referenced the config were delayed until after the config
was loaded.
Updated configuration.py to throw an exception if config.load() is called
with a non-existent filename argument.
Updated loginit.py to add the fromusenet log used by gate_news.py.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
and some of the admindb.py links. There may still be breakage in other parts
of the interface and I haven't gone back to verify that traditional CGI still
works.
Changes:
- Add wsgiref-0.1.2-py2.4.egg so that we can still do WSGI in Python 2.4,
which doesn't come with wsgiref. Of course this means we /also/ have to add
setuptools-0.5c3 because eggs require setuptools.
- Style cleanups in HTTPRunner.py and wsgi_app.py. Also, use cStringIO
instead of StringIO.
- All internal links within the listinfo and admin pages are (or at least
should be ;) relative now. This should make other things better, such as
running Mailman over https or alternative ports. It does kind of mean that
web_page_url is obsolete, but I haven't looked at whether we can completely
eradicate it.
- ValidateEmail(): Use ' ' in s instead of s.count(' ') > 0.
- GetPathPieces(): When path is false, return the empty list instead of None,
so we can still len() it.
- ScriptURL(): Much simpler. To support relative urls as the default, we
change the API so that it only takes a 'target' argument (i.e. the script we
want to link to). It no longer takes 'absolute' or 'web_page_url', and it
constructs its link from GetPathPieces(), the target, and the cgi extension.
- GetRequestURI(): code style updates.
- Mailman/bin/show_config.py: De-DOS-line-ending-ification.
- export.py: A few modifications, although this is likely still not final (I'm
still working on the import script). First, for <option> elements, don't
put the value in an attribute, put it in the text body of the element.
Second, put the list <option> tags in a <configuration> element. Third, put
the preferred language on an <option> tag with a 'preferred_language'
name attribute value.
- SecurityManager: Make sure that MakeCookie() and ZapCookie() use the same
'path' cookie value by refactoring that into a separate method. That method
now returns just the SCRIPT_NAME and the full listname. web_page_url
doesn't enter into it.
- loginit.py: Add a 'debug' logger since it's just too useful to have :)
- admin.py: Remove the extra / right before the query string in ?VARHELP
urls. That extra / turns out to be problematic with the relative url scheme
we're using now.
- Auth.py: whitespace normalization and copyright years update. Also, remove
a couple of unnecessary imports. Also, make sure that the actionurl is
relative.
- create.py: Typo.
- private.py: mm_cfg -> config object
- In MailList.py: GetScriptURL() can be written in terms of Utils.ScriptURL()
now.
|
| |
|
|
|
|
|
|
| |
Add: HTTPRunner.py ... Start/Restart/Stop HTTP Server under Runner framework.
wsgi_app.py ... WSGI to CGI wrapper. Mostly taken from scripts/driver.
loginit.py ... Add http log. Time stamp is duplicated :-(
Defaults.py ... HTTP_HOST and HTTP_PORT.
Note that WSGI server should be used under reverse proxy environment.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
configuration file. While the full conversion is not yet complete, everything
that seems to be required to run mailmanctl, qrunner, rmlist, and newlist have
been updated.
Basically, modules should no longer import mm_cfg, but instead they should
import Mailman.configuration.config. The latter is an object that's
guaranteed to exist, but not guaranteed to be initialized until some top-level
script calls config.load(). The latter should be called with the argument to
-C/--config which is a new convention the above scripts have been given.
In most cases, where mm_cfg.<variable> is used config.<variable> can be used,
but the exceptions are where the default value must be available before
config.load() is called. Sometimes you can import Mailman.Default and get the
variable from there, but other times the code has to be changed to work around
this limitation. Take each on a case-by-case basis.
Note that the various directories calculated from VAR_PREFIX, EXEC_PREFIX, and
PREFIX are now calculated in config.py, not in Defaults.py. This way a
configuration file can override the base directories and everything should
work correctly.
Other changes here include:
- mailmanctl, qrunner, and update are switched to optparse and $-strings, and
changed to the mmshell architecture
- An etc directory has been added to /usr/local/mailman and a
mailman.cfg.sample file is installed there. Sites should now edit an
etc/mailman.cfg file to do their configurations, although the mm_cfg file is
still honored. The formats of the two files are identical.
- list_lists is given the -C/--config option
- Some coding style fixes in bin/update, but not extensive
- Get rid of nested scope hacks in qrunner.py
- A start on getting EmailBase tests working (specifically test_message),
although not yet complete.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
use $-strings and optparse.
A side effect of the rewrite is that list_members -d and -n now require their
argument, whereas before they were optional (but that is counter to command
line parsing standards and not supported by optparse). Now, instead of bare
-n use '-n any' and instead of bare -d use '-d any'.
Fix ReopenableFileHandler.emit() to ensure that all lines end in a newline.
In i18n.py, create and use a subclass of string.Template so that dotted
attribute paths are legal in $-strings. So for example, if you have an object
'foo' in one of the namespaces and that has an attribute 'bar', you can say
"$foo.bar" to print the value of foo.bar. Should reduce the number of
extraneous local variables just to do the attribute path traversal.
|
| |
|
|
|
|
|
|
|
|
|
| |
- Remove the LogStdErr() calls from all the scripts/* scripts.
- Convert the LockFile.py code to use the logging logs. Also do general code
cleanup in this module. Note that the 'withlogging' argument to __init__()
has been removed, as we can use logging's mechanisms to control how much of
LockFile will get logged (by default, not much).
- Add the 'mailman.locks' logger to loginit.py
- Remove Mailman/Handlers/Sendmail.py once and for all
- Remove LIST_LOCK_DEBUGGING from Defaults.py.in
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Modify Mailman.i18n._() to understand string.Template style $-strings. The
function now looks in the frame's locals and globals for a variable
__i18n_templates__ which if True (defaults to False if missing) says that the
string being translated uses $-strings instead of %-strings.
newlist and rmlist both set __i18n_templates__ = True in their module
globals.
Rewrite ReopenableFileHandler to better ensure that nothing we log (even
random 8-bit garbage) can cause an error in the logging subsystem. First, we
open the underlying log file using a utf-8 codec, but if we get a UnicodeError
when writing a log message to the stream, we encode the string with the
'string-escape' codec, which should pretty much makes any string data
loggable.
|
| |
|
|
|
|
|
|
|
|
|
| |
I didn't update cron/mailpasswds because that is going away. cron/disabled
and cron/gate_news are only minimally tested.
- Instead of using the RotatingFileHandler for our logs, use our own
ReopenableFileHandler, which only minimally derives from FileHandler and
implements a reopen() method. I think it's generally better to leave file
rotation to external tools such as logrotate.
- Remove some Python 2.1 compatibility stuff.
- Ignore .mo files in messages/vi/LC_MESSAGES
|
|
|
traces of our crufty old Syslog. Most of this work was purely mechanical,
except for:
1) Initializing the loggers. For this, there's a new module
Mailman/loginit.py (yes all modules from now on will use PEP 8
names). We can't call this 'logging.py' because that will
interfere with importing the stdlib module of the same name (can
you say Python 2.5 and absolute imports?).
If you want to write log messages both to the log file and to
stderr, pass True to loginit.initialize(). This will turn on
propagation of log messages to the parent 'mailman' logger, which
is set up to print to stderr. This is how bin/qrunner works when
not running as a subprocess of mailmanctl.
2) The driver script. I had to untwist the StampedLogger stuff and
implement differently printing exceptions and such to log/error
because standard logging objects don't have a write() method. So
we write to a cStringIO and then pass that to the logger.
3) SMTPDirect.py because of the configurability of the log messages.
This required changing SafeDict into a dict subclass (which is
better than using UserDicts anyway -- yay Python 2.3!). It's
probably still possible to flummox things up if you change the
name of the loggers in the SMTP_LOG_* variables in mm_cfg.py.
However, the worst you can do is cause output to go to stderr and
not go to a log file.
Note too that all entry points into the Mailman system must call
Mailman.loginit.initialize() or the log output will go to stderr
(which may occasionally be what you want). Currently all CGIs and
qrunners should be working properly.
I wish I could have tested all code paths that touch the logger, but
that's infeasible. I have tested this, but it's possible that there
were some mistakes in the translation.
- Mailman.Bouncers.BounceAPI.Stop is a singleton, but not a class
instance any more.
- True/False code cleanup, PEP 8 import restructuring, whitespace
normalization, and copyright year updates, as appropriate.
|