summaryrefslogtreecommitdiff
path: root/Mailman/interfaces
Commit message (Collapse)AuthorAgeFilesLines
* Bite the bullet: rename the Mailman package to mailman.Barry Warsaw2008-02-2727-2116/+0
|
* The start of a cleaning up of Errors.py. Eventually, I want to get rid ofBarry Warsaw2008-02-196-25/+132
| | | | | | | | | this module, in favor of moving exceptions into the interface modules that they are appropriate for. For now, this is just the low-hanging fruit. Along the way, clean up by reSTifying some interfaces and implementations.
* Added a test for the built-in pipeline. Fixed some broken handler names inBarry Warsaw2008-02-171-0/+7
| | | | | | | | | | | | | the built-in pipeline. Fixed DEFAULT_SUBJECT_PREFIX to take $-names instead of %-names, although I'm not entirely sure the %%d stuff still works (we need a test for this). Added IMailingList.real_name attribute and added this to the default style. A column for this was in the database but not in the storm object. Also re-enabled the style's subject_prefix attribute. Moved some of the digest test functions into Mailman.tests.helpers.
* Reorganize the Handler architecture to a pipeline architecture with plugins.Barry Warsaw2008-02-172-0/+69
| | | | | | | | | | | | | | | | Now plugins can define additional handlers and the handlers can be organized into named pipelines. Modules are no longer the unit of a handler, now we use classes so we can assert interface conformance. The GLOBAL_PIPELINE is gone, replaced by the 'built-in' pipeline. The OWNER_PIPELINE is not yet replaced. I still need a few more tests of the basic pipeline architecture, although the individual handlers have pretty good coverage. Added the IHandler and IPipeline interfaces. Still broken, but not yet removed: Mailman/pipeline/moderate.py.
* Tweak copyright years.Barry Warsaw2008-02-0723-23/+23
|
* Convert IncomingRunner to use the new chains disposition architecture. moveBarry Warsaw2008-02-021-1/+1
| | | | | | | | | | | | | | | | | | | | | | the big explanatory text at the beginning of incoming.py to a doctest called OVERVIEW.tt (which doesn't actually contain any tests yet -- it's documentation though). Added a doctest for the incoming runner, though this will be fleshed out in more detail next. Mailman.Post renamed to Mailman.inject, and simplified. We don't need its command line script behavior because that is now handled by bin/inject. Add a 'start_chain' attribute to mailing lists. This names the chain that processing of messages for that list begins with. We were inconsistent in the use of the 'no reply' address attribute. It's now always 'no_reply_address'. Update the smtplistener helper with lessons learned about how to suppress bogus asyncore error messages. Also, switch to using a maildir mailbox instead of an mbox mailbox.
* SpamDetect is gone, so the chains/rules implementation experiment is deemed aBarry Warsaw2008-02-011-10/+0
| | | | | | | | | | | | | | | | | | | | success and will now be merged into the trunk. Move the Truth rule into the built-in rules package in a separate module, and add a test. Modify IChainLink so that the rule and chain attributes are not names but indeed the actual ILink or IChain object directly. Update the chains.process() function accordingly. Remove the IChain.get_rule() method. Don't derive BuiltInChain from Chain and don't make it an IMutableChain. It's now just an IChain, and is implemented concretely. Refactor the HeaderMatchChain and friends so that it can be used with both the global HEADER_MATCHES variable and the list-specific header_matches variable, which has exactly the same semantics. Oh yeah, get rid of the list's header_filter_rules attribute and replace it with header_matches so that the semantics match, it's easy to explain, and it's all nice and clean.
* Reorganization.Barry Warsaw2008-01-301-6/+20
| | | | | | | | | | | Create a Mailman.chains package and move a bunch of the Mailman.apps.chains classes to separate modules under this package. Also, separate out iteration from chain management. In other words, IChain and IChainIterator are separate, and the latter is retrieved from the former by the .get_links() method. This latter takes the mailing list, message, and metadata dictionary so that links can be targetted specifically to the task at hand.
* Port header matching previously described by the misnamed KNONW_SPAMMERSBarry Warsaw2008-01-261-0/+10
| | | | | | | | | | | | | | | variable to the new chain processing system. Create a header-matching chain which handles global site header matching rules defined by HEADER_MATCHES. Rip this logic out of the SpamDetect handler; really this entire handler needs to go away but the rest of it isn't ported yet. IChains now have a get_rule() method which allows them to return private (i.e. not globally registered) rules. This is used by the header matching chain. Mailman.app.chains.process() has had its parameter list reordered to be more like all other function signatures that take a mailing list, message, and message metadata.
* More changes to rules and chains.Barry Warsaw2008-01-232-26/+47
| | | | | | | | | | | | | Now a link has a rule, action, chain, and function, not all of which needs to be specified. The action is a LinkAction enum adn specifies what to do should the rule match. The use of the chain or function depends on what the action is. Several interface changes now make it easier to jump to other chains, push (i.e. detour) to chains, etc. Rules can also now specify that they should not be recorded in X-* headers. Added a TruthRule which always matches.
* Merge from trunk.Barry Warsaw2008-01-141-0/+58
|\
| * Add an interface IArchiver which is used to calculate urls and send messagesBarry Warsaw2008-01-131-0/+58
| | | | | | | | | | | | | | | | | | | | to the archiver. Also add a plugin architecture for easily overriding the archiver, and hook this into the setup.py script. Updated CookHeaders.py and Scrubber.py handlers to use the plugged archiver. Updated doctests as appropriate. Fix a typo in the setup.py file.
* | Use a more efficient way of deleting rows from a table, which coincidentallyBarry Warsaw2008-01-142-28/+68
| | | | | | | | <wink> works around the storm cache bug #178546.
* | Fix the rule api once more so that while rules themselves are still classes,Barry Warsaw2008-01-011-16/+0
| | | | | | | | | | | | | | | | they are instantiated by the IRuleSet, thus keeping the promises of the interface. The ChainJump enum is moved to interfaces/chain.py. This will be fleshed out subsequently.
* | Extended test_documentation.py to be able to find doctests in subdirectoriesBarry Warsaw2008-01-011-1/+20
| | | | | | | | | | | | called 'docs' anywhere under the Mailman package. Change the rule API to return rule classes not instances. Added the ChainJump enum, though this will likely change soon.
* | Add three new rules and their associated doctests.Barry Warsaw2007-12-301-0/+3
| | | | | | | | | | | | | | | | | | - A rule that checks to see if the sender is a moderated member. - A rule that checks to see if the sender is a non-member. - A rule that checks to see if the message has no (or an empty) Subject. Give IMembers (and the associated database implementation) an `is_moderated` flag.
* | Convert the Approve.py handler to an approved.py rule. Update the doctest toBarry Warsaw2007-12-291-1/+2
| | | | | | | | | | | | | | | | | | use the rule check instead of handler processing. Add a test for stripping the header from the text/html part to the doctest. Add Mailman.app.rules.find_rule() to return a named rule. Fix a few typos.
* | Change IRuleProcessor to IRuleSet. Plugins now provide only sets of rules,Barry Warsaw2007-12-271-10/+1
| | | | | | | | | | | | they do not do the actual rule processing. That's left up to Mailman. Further, the rule processor can be given a list of rules to run; those will be the only ones run.
* | First cut at a rules processor, separate from the disposition of rule hits.Barry Warsaw2007-12-272-1/+79
|/ | | | | | | | | | | | | | The basic idea is that we process rules on a mlist, message, metadata triplet making a list of all rules that hit. Then a different part of the system will decide on the disposition of a message based on which rules hit and their priority. The doctest and plugin architecture is in place, including the tie-in to setup.py. Ported the first rule -- emergency.py -- to the new rule processor. We no longer need SQLAlchemy as a requirement, and the setuptools/bzr plugin name has changed.
* Add .get() to our Message subclass, which ensures that returnedBarry Warsaw2007-12-101-49/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | values are unicodes if they come from the base class as a string. Get rid of the 'global id'. Now use just Message-ID. Rename X-List-ID-Hash to X-Message-ID-Hash. Do not take Date header into account when calculating this hash. Because of the above change, the assumption is that there will be no Message-ID collisions. Therefore, get rid of IMessageStore .get_message(), .get_messages_by_message_id() and .get_messages_by_hash(). Instead, it's now .get_message_by_id() and .get_message_by_hash() both of which return the message object or None. Message.hash -> Message.message_id_hash When storing a message in the message store, the final path component has the entire hash, not just the leftover parts after directory prefix splitting. MessageStore.delete_message() deletes the file too. Doctests clean up message store messages though the message store instead of directly off the filesystem.
* Fix two doctests: addresses.txt and mlist-addresses.txtBarry Warsaw2007-11-071-3/+0
| | | | | Remove flush() altogether. Yee-haw! Rework queries to be Stormy. Fix doctests to be Unicode-ish.
* Much progress, though not perfect, on migrating to SQLAlchemy 0.4 and ElixirBarry Warsaw2007-10-314-4/+52
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 0.4. Lots of things changes, which broke lots of our code. There are still a couple of failures in the test suite that I don't understand. It seems that for pending.txt and requests.txt, sometimes strings come back from the database as 8-bit strings and other times as unicodes. It's impossible to make these tests work both separately and together. users.txt is also failing intermittently. Lots of different behavior between running the full test suite all together and running individual tests. Sigh. Note also that actually, Elixir 0.4.0 doesn't work for us. There's a bug in that version that prevented zope.interfaces and Elixir working together. Get the latest 0.4.0 from source to fix this. Other changes include: - Remove Mailman/lockfile.py. While I haven't totally eliminated locking, I have released the lockfile as a separate Python package called locknix, which Mailman 3.0 now depends on. - Renamed Mailman/interfaces/messagestore.py and added an IMessage interface. - bin/testall raises turns on SQLALCHEMY_ECHO when the verbosity is above 3 (that's three -v's because the default verbosity is 1). - add_domain() in config files now allows url_host to be optional. If not given, it defaults to email_host. - Added a non-public interface IDatabase._reset() used by the test suite to zap the database between doctests. Added an implementation in the model which just runs through all rows in all entities, deleting them. - [I]Pending renamed to [I]Pended - Don't allow Pendings.add() to infloop. - In the model's User impelementations, we don't need to append or remove the address when linking and unlinking. By setting the address.user attribute, SQLAlchemy appears to do the right thing, though I'm not 100% sure of that (see the above mentioned failures).
* Remove the action.py module, move this to Mailman/interfaces/__init__.py.Barry Warsaw2007-10-103-32/+35
| | | | | | Convert IMailingList.personalize to a enum. Change all non-obsolete occurances of GetListEmail() to posting_address.
* Reorganize the enums so that they live in the most appropriate interface. TheBarry Warsaw2007-10-093-0/+88
| | | | only constant left in Mailman.constants is now actually a constant.
* Reorganize the qrunner infrastructure. First, the package has been renamedBarry Warsaw2007-09-291-0/+31
| | | | | | | | | | | | | | | | | | | | | | from Mailman.Queue to Mailman.queue (note the case change to be more PEP 8 compliant). The Switchboard and Runner classes have been moved into the package __init__.py and the previous class modules have been removed. The switchboard cache is removed; I don't think it was ultimately buying us much. Now, just import the Switchboard class and instantiate it directly. Added an IRunner interface. Renamed the ArchRunner to ArchiveRunner. bin/qrunner and bin/mailmanctl are updated accordingly. For the former, it no long accepts -r=All to run all qrunners. You can still use the short name (e.g. --runner=incoming) to run the built-in queue runners, but this design will eventually allow for plugin qrunners by allowing them to be run specifying the full package path to the class. It also now accepts a leading dot to indicate a qrunner class relative to the Mailman.queue package.
* Removed a bunch of files that are obsolete. The interfaces are all foldedBarry Warsaw2007-09-277-346/+196
| | | | | | | | | | | | | into the IMailingList interface. OTOH, MemberAdaptor.py is completely useless now (though not entirely eradicated), as is OldStyleMemberships.py. versions.py isn't necessary any longer either because we'll have to do database migrations (and conversions from MM2.1) completely differently. New command line script 'set_members' which is used to take a CSV file and syncing that to a list's membership. Added back the DeliveryStatus.unknown item because we'll need it when we migrate MM 2.1 databases.
* ListAdmin mostly gone, but not quite.Barry Warsaw2007-09-091-4/+22
| | | | | | | | | | | | | | | | Mailman/app/moderator.py: Most of the application level interface provided by ListAdmin is moved here now, including the ability to hold messages, subscriptions, and unsubscriptions, and to handle message (defer, discard, reject, accept). More work needed. Some untested conversion of API in Mailman/Cgi/admindb.py, confirm.py, bin/checkdbs.py. messagestore.py: Don't use or require the Date: header in the global message ID calculation. As described on the mailing list, we're only going to use the Message-ID header. IListRequests: added count_of() and of_type() methods.
* Interfaces IRequests and IListRequests which are substitutes for the ListAdminBarry Warsaw2007-08-073-3/+99
| | | | | | | | | | | | mixin. This latter will go away soon. Added implementation and tests. The implementation has some cruft though -- it forces us to use a flush() in the code because I don't yet know how to get to SA's last_inserted_ids(). Note that this implementation abuses the IPendings interface in order to store arbitrary string key/value pairs. Fix the auto-discovery of interfaces by allowing Enums in interface files as well. Long term, this is how it should work anyway.
* Fixed a problem where members of a deleted mailing list were hanging around.Barry Warsaw2007-08-052-2/+11
| | | | | | | | | | | | | | | | | | | | This would cause duplicate members (e.g. owners) if you created, deleted and then recreated the mailing list. Mailman.app.create -> Mailman.app.lifecycle; Mailman/doc/create.txt -> Mailman/doc/lifecycle.txt; also added a remove_list() function. Added SubscriptionError base class, made HostileSubscriptionError inherit from that, and added a new AlreadySubscribedError. Rewrote bin/rmlist to use the new lifecycle.remove_list() function. IAddress.subscribe() must now throw an AlreadySubscribedError if the address is already subscribed to the mailing list with the given role. Added a Subscribers roster, attached to the IMailingList which gives access to all subscribers of a mailing list, regardless of their role. Added a new test for this roster.
* Added a doctest for the Mailman.app.create module.Barry Warsaw2007-08-051-0/+7
| | | | | | | | | | | | | | | BadListNameError is gone. Use InvalidEmailAddress instead. Move owner registration from bin/newlist to Mailman/app/create.py, but do not verified owner email addresses here. Eventually we'll hook in the IRegistrar stuff for unverified owner addresses. IStyleManager.register() verifies that its registering an IStyle. Added IStyleManager.unregister(), along with updated interfaces and doctests. Clean up all styles except the default one in the system documentation test harness.
* It all started by trying to remove MailList.Create() and use the IListManagerBarry Warsaw2007-08-052-2/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | interface to create and delete lists. Mostly that's working now, but I need unit tests for most of the new work contained in this revision. Implemented a rudimentary 'list styles' subsystem, along with interfaces, but no tests yet. Moved all of MailList.InitVars() into a DefaultStyle, which is always available at priority zero. It's used by default if there are no matching styles for a mailing list. Because of the list styles, we can now get rid of (almost) all InitVars() methods. And because of /that/ we can get rid of the mixin clases whose sole purpose was to provide an InitVars() method. Yay for code removal! Mixin modules/classes removed: Autoresponder, GatewayManager, TopicManager. Removed the Mailman/ext crufty extension mechanism. Extensions will now be done using setuptools plugins. Hopefully this will take us everywhere we need to go, but I'll add Mailman.ext back if necessary later. Mailiman.app.create module added to implement a common, higher-level list creation feature. This is used by bin/newlist now, though some of that functionality (namely, ensuring the owners exist in the database, and notifying the owners) should be moved here. The MTA plugins aren't yet integrated into this, but need to be. Mailman.app.plugins module added to generalize setuptools plugin management. Defaults.DEFAULT_REPLY_GOES_TO_LIST now gets initialized with a proper enum. Also, the duplicate DeliveryMode and DeliveryStatus enums are removed from Defaults because they're in Mailman.constants. Added Errors.DuplicateStyleError. Updated Utils.list_exists() to use the new IListManager.get() interface, which has been changed to return None if the list doesn't exist (for consistency) instead of raising an exception. Utils.list_names() also needed to be fixed to use config.db.list_manager. bin/make_instance, bin/newlist, bin/rmlist changed to use parser.error() istead of printing to sys.stderr and sys.exit(1). bin/newlist and bin/rmlist now works with the IListManager interface, so you can create and delete lists from the command line again. The CLI for newlist has been much simplified; it no longer prompts for missing positional arguments. It now uses a more traditional CLI. newlist also accepts zero to many owners, and it ensures that the owners are all in the database. It no longer asks for a list password, because this doesn't make sense any more. bin/withlist has also been fixed to work with the IListManager interface. There are lots of XXXs and FIXMEs that need to be resolved before this can land. Also, we need to test all this stuff before it can land. Configuration.load() is now taught to search in sys.argv[0] for var/etc/mailman.cfg since this is where it is for egg development layouts. Also, VAR_DIR must be abspath'd. Added an __all__ to Mailman.constants, and added an Action enum. The listmanager implementation has to set the mlist.created_at time. There's also a bit of crufty refactoring going on to instantiate the roster objects whenever the list is created or retrieved from the database. Several MailingList column types are now set to our custom TimeDeltaType, which knows how to store a datetime.timedelta. A SQLAlchemny converter type is added to Mailman.database.types. I also fixed a bug in the EnumType implementation.
* Refactor IDatabase interface so that the user_manager, list_manager,Barry Warsaw2007-08-021-0/+3
| | | | | message_store, and pendings 'databases' hang off the IDatabase object attached to the config object. For IPending, no adaptation is necessary.
* Move the pending database into the SQLAlchemy/Elixir layer. The oldBarry Warsaw2007-08-015-1/+246
|\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Pending.py module is removed. Added an interface to this functionality such that any IPendable (essentially a key/value mapping) can be associated with a token, and that token can be confirmed and has a lifetime. Any keys and values can be stored, as long as both are unicodes. Added a doctest. Modified initialization of the database layer to support pluggability via setuptools. No longer is this layer initialized from a module, but now it's instantiated from a class that implements IDatabase. The StockDatabase class implements the SQLAchemy/Elixir layer, but this can be overridden in a setup.py. Bye bye MANAGERS_INIT_FUNCTION, we hardly knew ye. Added a package Mailman.app which will contain certain application specific functionality. Right now, the only there there is an IRegistar implementation, which didn't seem to fit anywhere else. Speaking of which, the IRegistrar interface implements all the logic related to registration and verification of email addresses. Think the equivalent of MailList.AddMember() except generalized out of a mailing list context. This latter will eventually go away. The IRegistrar sends the confirmation email. Added an IDomain interface, though the only implementation of this so far lives in the registration.txt doctest. This defines the context necessary for domain-level things, like address confirmation. A bunch of other cleanups in modules that are necessary due to the refactoring of Pending, but don't affect anything that's actually tested yet, so I won't vouch for them (except that they don't throw errors on import!). Clean up Defaults.py; also turn the functions seconds(), minutes(), hours() and days() into their datetime.timedelta equivalents. Consolidated the bogus email address exceptions. In some places where appropriate, use email 4.0 module names instead of the older brand. Switch from Mailman.Utils.unique_message_id() to email.utils.make_msgid() everywhere. This is because we need to allow sending not in the context of a mailing list (i.e. domain-wide address confirmation message). So we can't use a Message-ID generator that requires a mailing list. OTOH, this breaks Message-ID collision detection in the mail->news gateway. I'll fix that eventually. Remove the 'verified' row on the Address table. Now verification is checked by Address.verified_on not being None.
| * Add setuptools plug-in entry point for defining different database backends.Barry Warsaw2007-07-241-0/+48
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Now someone could distribute a setuptools package that provided say, a MySQL database implementation and very easily override the stock database. How awesome is setuptools? Removed MANAGERS_INIT_FUNCTION since setuptools gives us a much more standard way of defining this plug-in entry point. Remove other old crud from Defaults.py. Restructure our own 'stock' database backend to be a plugin so it's totally on par with any other package. The only special case is that if more than one such entry point is defined, we filter out the 'stock' one (i.e. ours) under the assumption that the user is overriding it. If we still have more than one plug-in, it's an error. Restructure the initialization subsystem to use the plug-in, doing all the proper assertions and what not. The IDatabase interface defines what the database back-end plugin must provide. I've no doubt this will eventually need a bit more fleshing out, but it gives all this stuff a principled hook point instead of something ad-hoc.
* | The start of a message store definition. Whether this will end up being usedBarry Warsaw2007-07-221-0/+101
|/ | | | | | | | | | | | | | | | | | | | for the archive or not is left to be seen. Define an interface, test, and implementation of a basic message store using globally unique identifiers of the form: archive/hash/seqno - archive is the base url of the archive, e.g. http://archives.example.com. This is available in the List-Archive header. - hash is the base32 encoded sha1 hash of the message's Message-ID and Date headers, which it must have. This is available in the X-List-ID-Hash header. - seqno is a sequence number specific to the archive which will uniquely identify the message should there be a Message-ID/Date collision. this is available in the X-List-Sequence-Number header. Added a MESSAGES_DIR variable to the config. Added a .message_store attribute to the config.
* More work on completing the transition to setuptools.Barry Warsaw2007-07-181-5/+13
| | | | | | | | | | | | | | | | | * Mailman/testing -> Mailman/test * Removed Mailman/testing/base.py * Fix mailmanctl by using a different way of calculating where the qrunner script is. The configuration file no longer knows what BIN_DIR is, but the mailmanctl script knows where it lives via sys.argv[0]. Also, PREFIX_DIR -> VAR_DIR. Also, * Since the overwhelmingly predominant use of ILanguageManager is to get the description, and since .get_language_data(code)[0] is not very readable, split the interface into .get_description() and .get_charset(). * In the setup, automatically add all Mailman.bin modules as command line scripts.
* Major surgery to get the setuptools based installation passing all theBarry Warsaw2007-07-162-57/+65
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | existing unit tests. Here's a summary of the changes. - Removed all dependent third party packages, since the setup.py file now claims all package dependencies such that they can be automatically installed from the cheeseshop. - Moved the misc directory into the Mailman package as Mailman/data. Moved templates and messages to Mailman subpackages. - Added an ILanguageManager interface, plus an implementation, so that we don't use Defaults.LC_DESCRIPTIONS directly anymore. Added a doctest for this interface and implementation. Defaults.LANGUAGES is moved into mailman.cfg. Defaults.LANGUAGE_DICT is moved to _DEFAULT_LANGUAGE_DATA, and LC_DESCRIPTIONS is removed. The calculation of the available and enabled languages is moved to the Configuration class, but this will probably still need work. Utils.GetLanguageDescr() and Utils.IsLanguage() are removed. I'd like to remove GetCharSet() eventually too, but there are too many uses of this currently, so I'm deferring it. - Utils.findtext(): Hacks added so that templates can be retrieved from the language catalog. The hack is that the template contents are used to find the translation, but in the one test case where this is actually flexed, the trailing newline in the file contents has to be trimmed. This is probably not right. - No more Defaults.py.in or mm_cfg.py! Defaults.py.in is moved to Defaults.py and is no longer created from a template file. The script called make_instance is added which creates an etc/mailman.cfg file from mailman.cfg.in (previously, mailman.cfg.sample) and /that/ file now has the small number of calculated values. In general, make_instance will not touch mailman.cfg if it exists, unless the --force option is given. CGIEXT is made the empty string by default (i.e. not generated). make_instance grows a --var-dir option. Fleshed out the --languages opton. - Defaults.py grows a DEFAULT_VAR_DIRECTORY variable, which is the default location of the 'var' directory. The Configuration class uses this as one of the directories it searches for its landmark, i.e. etc/mailman.cfg. RUNTIME_DIR is gone, as is VAR_PREFIX. - testall needs to write MAILMAN_USER, MAILMAN_UID, MAILMAN_GROUP, MAILMAN_GID, and LANGUAGES run time variables. - bin/withlist no longer needs to add config.BIN_DIR to sys.path, because in fact that variable doesn't exist any more. - Tweak the French catalog to make a test work. This is needed because of the conversion from %-strings to $-strings. - The setup.py now generates the .mo files before it does its thing. This will have to be fixed, but for now we must generate these files on setup build time instead of installation time. - Removed an unused interface.
* The start of a setuptools conversion. All the Makefile.in and autoconfBarry Warsaw2007-07-131-71/+0
| | | | artifacts are removed, as is the C files which we will no longer need.
* Support for case-preserving addresses. When an Address is given an emailBarry Warsaw2007-07-011-0/+13
| | | | | | | | | | | | | | | | | | address that is not lower cased, the original, case-preserved version is store on the '_original' attribute. The lower-cased version is always used as the key and thus always stored on the 'address' attribute. The IAddress interface is given a new 'original_address' property which returns the case-preserved version. Address's __str__() and __repr__() are similarly modified. The former always includes the case-preserved address; the latter does too, but now also includes the lower-cased 'key' email address (along with the object's id). Searching for an address always does so on the lower-cased version. Test suite is updated as necessary. Also, I'm adding the REPORT_ONLY_FIRST_FAILURE doctest flag so that it's easier to debug doctest failures without having pages of problems to scroll through.
* Convert the Switchboard test in test_runners.py to a doctest. Add anBarry Warsaw2007-06-271-0/+82
| | | | | | | | | | | | | | | ISwitchboard interface and modernize the Python code in the Switchboard.py implementation. The SAVE_MSGS_AS_PICKLES option is removed. Messages are always saved as pickles unless the metadata '_plaintext' key is present, though this should eventually go away too. In testall.py, put the entire VAR_PREFIX in a temporary directory. This helps the switchboard tests by not mixing their data with the installation's queue directories. The Configuration object now also ensures that all the queue and log directories exist -- one more step on the road to getting rid of the autoconf mess.
* Convert the tests for the CalcRecips handler to doc tests. There areBarry Warsaw2007-06-192-5/+50
| | | | | | | | | | | | | | | | | some XXX's in the doc test because digest recipients aren't tested (though those may go in a different doctest), and neither are urgent messages. This latter is for the same reason that the Approved handler is not yet tested; which password do you use in that header? The CalcRecips tests would also seem the natural place to test the receive_list_copy preference, but that actually gets processed in the AvoidDuplicates handler, so it isn't tested here. Add delivery_status (of type enum DeliveryStatus) to preferences. I'm not entirely sure that's the right place for it, but it lets me finish converting the test for now. Expose the rest of the preferences through the IMember interface.
* Remove both the model and interface for RosterSets. These are no longer usedBarry Warsaw2007-06-184-66/+70
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | or necessary in the current data model. Convert the test_handlers.py Python test to an acknowledge.txt doctest, and make the Acknowledge.py handler work with the new data model. There are a few XXX comments left in here due to the fact that the web stuff is a total hack in the current branch currently. Added IMailingListWeb methods and properties to the MailingList model class: web_host and script_url(). Work out how IMembers will expose the lookup-order based preferences. By getting the attribute IMember.preferences you can see exactly the preferences overridden by this member. To use the lookup order, use IMember.delivery_mode, IMember.acknowledge_posts, etc. IOW, the IMember interface now provides the properties directly and access through this mechanism supports lookup order with definitive preference values. Also added IMember.unsubscribe() which does the obvious, and IMember.options_url() which is a total hack for providing a url (but not the ultimately right one) for the user's option page. Refactor the model's roster classes. Also added IRoster.get_member() method with efficient queries to return the right results. Make AdministratorRoster.members more efficient due to a better query. Update the membership.txt doctest to eliminate a chance ordering effect, and also to test finding members with .get_member(). The clean up section uses the new .unsubscribe() method.
* profile.py -> preferences.pyBarry Warsaw2007-06-151-0/+0
| | | | | Fix the last few doctests by ensuring that other newly created Addresses have a preferences object.
* Update the IUser interface and tests, specifically as it relates toBarry Warsaw2007-06-153-22/+38
| | | | | | | | | | | | | | | | | | | | preferences. IAddresses, IUsers, and IMembers all get preferences by default, althoughthe attributes of these preferences are None by default. IMailingLists don't get preferences by default though; because these live in the user database, we can't cross-polinate them in the mailing lists. We'll figure something out later for these. IUser.register(): Add this method which registers and links an address to the user. Allow EnumType database columns to accept and return Nones. This is useful for when the columns are not defined NOT NULL. Update doctests. Removed teh hide_address preference. I can't think of a reason not to want to hide addresses for everyone.
* More test updates based on simplified data model. Rosters are gone so theBarry Warsaw2007-06-102-1/+37
| | | | | | | | | | | | | | | | | | | | mlist-rosters.txt tests are removed. Give MailingList entities a Preferences foreign key, so that they now have preferences. Member.preferences(): Watch out for unlinked addresses, i.e. which have no user and thus no user preferences. Address.controls() takes a text email address, not an IAddress. UserManager: add create_address(), delete_address(), get_address(), and 'addresses' property. Updated the address.txt and user.txt doctests as needed. Added User.register() to register an email address and immediately link it to a user.
* Repair the usermanager.txt and listmanager.txt doc tests. These repairs wereBarry Warsaw2007-06-091-2/+10
| | | | | | | | | | | | | necessary to deal with the simplified user model. Eradicate more references to rosters and roster sets. Give Users a repr. Also give them a belongs_to() link to Preferences, but change the user manager to not give a user preferences by default (the lookup schema should properly handle users with no preferences now). Also, when creating a user, set their real_name to the empty string if no real_name argument was given to create_user(). Update the IUserManager interface's create_user() method to match the implementation.
* Implement the new, simplified membership model. Rosters and RosterSets asBarry Warsaw2007-06-097-79/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | they were previously known are now gone. Rosters, rather than being a database entity that collects users, is now just a filter on the member database. This way, we can use generic rosters to search for regular members, digest members, owners, or moderators. More advanced rosters can do all kinds of other membership queries. But rosters no longer need to be a database entity. Users have a name, password, optional preferences, and a set of addresses, but users are not subscribed to mailing lists. Addresses have the email address, some verification information, and optional preferences. Members tie an address to a mailing list, through a role, with optional preferences. Other changes here include: MailList.fqdn_listname() moved to the MailingList model entity. Added MemberRole enum and SystemDefaultPreferences to Mailman.constants. Profiles are renamed to Preferences (same with the interface), but the files are not yet moved. This happens later. We mostly don't need has_*() relationships on the entity classes, because we generally don't need the reverse relationship. Use belongs_to() because that creates the foreign key, even though the wording seems counter intuitive. IAddress.subscribe() added. Tell Elixir to use shortnames for all tables. Remove the OldStyleMembership fields from MailingList. Remove all the interface elements and database fields that talk about rosters and rostersets. Convert Version entity to has_field().
* Merge exp-elixir-branch to trunk. There is enough working to make me feelbwarsaw2007-05-2819-0/+1010
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.