Skip to content

Commit

Permalink
Unification of release information, setup script, and setup configura…
Browse files Browse the repository at this point in the history
…tion and now correct use of internal exceptions upon message failure.
  • Loading branch information
amcgregor committed Aug 19, 2011
1 parent c9b5763 commit b7dd6ef
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 81 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -1,2 +1,6 @@
*.egg-info
*.pyc
.coverage
build/
dist/
examples/local.py
3 changes: 0 additions & 3 deletions marrow/mailer/address.py
Expand Up @@ -197,9 +197,6 @@ def __get__(self, instance, owner):
if value is None:
return self.cls() if self.can else None

if not isinstance(value, self.cls):
return self.cls(value)

return value

def __set__(self, instance, value):
Expand Down
5 changes: 4 additions & 1 deletion marrow/mailer/exc.py
Expand Up @@ -70,7 +70,10 @@ class TransportFailedException(TransportException):
class MessageFailedException(TransportException):
"""The transport has failed to deliver the message due to a problem with
the message itself, and no attempt should be made to retry delivery of
this message. The transport may still be re-used, however."""
this message. The transport may still be re-used, however.
The reason for the failure should be the first argument.
"""

pass

Expand Down
6 changes: 5 additions & 1 deletion marrow/mailer/manager/futures.py
Expand Up @@ -2,7 +2,7 @@

from functools import partial

from marrow.mailer.exc import TransportFailedException, TransportExhaustedException
from marrow.mailer.exc import TransportFailedException, TransportExhaustedException, MessageFailedException, DeliveryFailedException
from marrow.mailer.manager.util import TransportPool

try:
Expand All @@ -25,6 +25,10 @@ def worker(pool, message):
try:
result = transport.deliver(message)

except MessageFailedException:
e = sys.exc_info()[1]
raise DeliveryFailedException(message, e.args[0] if e.args else "No reason given.")

except TransportFailedException:
# The transport has suffered an internal error or has otherwise
# requested to not be recycled. Delivery should be attempted
Expand Down
6 changes: 5 additions & 1 deletion marrow/mailer/manager/immediate.py
@@ -1,6 +1,6 @@
# encoding: utf-8

from marrow.mailer.exc import TransportExhaustedException, TransportFailedException
from marrow.mailer.exc import TransportExhaustedException, TransportFailedException, DeliveryFailedException, MessageFailedException
from marrow.mailer.manager.util import TransportPool


Expand Down Expand Up @@ -42,6 +42,10 @@ def deliver(self, message):
try:
result = transport.deliver(message)

except MessageFailedException:
e = sys.exc_info()[1]
raise DeliveryFailedException(message, e.args[0] if e.args else "No reason given.")

except TransportFailedException:
# The transport has suffered an internal error or has otherwise
# requested to not be recycled. Delivery should be attempted
Expand Down
2 changes: 1 addition & 1 deletion marrow/mailer/release.py
Expand Up @@ -10,4 +10,4 @@

version_info = namedtuple('version_info', ('major', 'minor', 'micro', 'releaselevel', 'serial'))(4, 0, 0, 'beta', 3)

version = ".".join([str(i) for i in version_info[:3]]) + (version_info.releaselevel[0] + str(version_info.serial)) if version_info.releaselevel != 'final' else ''
version = ".".join([str(i) for i in version_info[:3]]) + ((version_info.releaselevel[0] + str(version_info.serial)) if version_info.releaselevel != 'final' else '')
4 changes: 2 additions & 2 deletions marrow/mailer/transport/imap.py
Expand Up @@ -4,7 +4,7 @@

from datetime import datetime

from marrow.mailer.exc import TransportException, DeliveryFailedException
from marrow.mailer.exc import TransportException, MessageFailedException


__all__ = ['IMAPTransport']
Expand Down Expand Up @@ -46,7 +46,7 @@ def deliver(self, message):
)

if result[0] != b'OK':
raise DeliveryFailedException(message, "\n".join(result[1]))
raise MessageFailedException("\n".join(result[1]))

def shutdown(self):
self.connection.logout()
5 changes: 3 additions & 2 deletions marrow/mailer/transport/sendmail.py
Expand Up @@ -2,7 +2,7 @@

import os

from marrow.mailer.exc import DeliveryFailedException
from marrow.mailer.exc import MessageFailedException


__all__ = ['SendmailTransport']
Expand All @@ -22,12 +22,13 @@ def startup(self):

def __call__(self, message):
# TODO: Utilize -F full_name (sender full name), -f sender (envelope sender), -V envid (envelope ID), and space-separated BCC recipients
# TODO: Record the output of STDOUT and STDERR to capture errors.
proc = os.popen('%s -t -i' % (self.executable, ), 'w')
proc.write(bytes(message))
status = proc.close()

if status != 0:
raise DeliveryFailedException("Sendmail delivery failed with status code %d." % (status, ), status)
raise MessageFailedException("Status code %d." % (status, ))

def shutdown(self):
pass
4 changes: 2 additions & 2 deletions marrow/mailer/transport/smtp.py
Expand Up @@ -126,14 +126,14 @@ def send_with_smtp(self, message):
# The envelope sender was refused. This is bad.
e = sys.exc_info()[1]
log.error("%s REFUSED %s %s", message.id, e.__class__.__name__, e)
raise MessageFailedException(e)
raise MessageFailedException(str(e))

except SMTPRecipientsRefused:
# All recipients were refused. Log which recipients.
# This allows you to automatically parse your logs for bad e-mail addresses.
e = sys.exc_info()[1]
log.warning("%s REFUSED %s %s", message.id, e.__class__.__name__, e)
raise MessageFailedException(e)
raise MessageFailedException(str(e))

except SMTPServerDisconnected:
if message.retries >= 0:
Expand Down
11 changes: 7 additions & 4 deletions setup.cfg
@@ -1,8 +1,11 @@
[nosetests]
with-coverage = 1
quiet = true
with-coverage = true
cover-package = marrow.mailer
cover-erase = 1
;cover-inclusive = 1
cover-inclusive = true
where = tests
detailed-errors = true
with-achievements = true

[aliases]
;test = nosetests
test = nosetests
136 changes: 72 additions & 64 deletions setup.py
@@ -1,79 +1,87 @@
#!/usr/bin/env python
# encoding: utf-8

import sys
import os
import sys

from setuptools import setup, find_packages


if sys.version_info < (2, 6):
raise SystemExit("Python 2.6 or later is required.")

exec(open(os.path.join("marrow", "mailer", "release.py")).read())
exec(open(os.path.join("marrow", "mailer", "release.py")))



setup(
name="marrow.mailer",
version=version,

description="""
A highly efficient and modular mail delivery framework for
Python 2.6+ and 3.1+, formerly called TurboMail.""",
author="Alice Bevan-McGregor",
author_email="alice+marrow@gothcandy.com",
url="https://github.com/marrow/marrow.mailer",
download_url="http://pypi.python.org/pypi/marrow.mailer",
license="MIT",
keywords="",

install_requires=["marrow.util", "marrow.interface"],

test_suite="nose.collector",
tests_require=["nose", "coverage"],

classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Console",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.1",
"Programming Language :: Python :: 3.2",
"Topic :: Software Development :: Libraries :: Python Modules"
],

packages=find_packages(exclude=["examples", "tests"]),
zip_safe=True,
include_package_data=True,
package_data={
"": ["README.textile", "LICENSE", "distribute_setup.py"]
},

namespace_packages=["marrow"],
entry_points = {
'marrow.mailer.manager': [
"immediate = marrow.mailer.manager.immediate:ImmediateManager",
"futures = marrow.mailer.manager.futures:FuturesManager",
"dynamic = marrow.mailer.manager.dynamic:DynamicManager",
"transactional = marrow.mailer.manager.transactional:TransactionalDynamicManager"
name = "marrow.mailer",
version = version,

description = "A highly efficient and modular mail delivery framework for Python 2.6+ and 3.1+, formerly called TurboMail.",
long_description = """\
For full documentation, see the README.textile file present in the package,
or view it online on the GitHub project page:
https://github.com/marrow/marrow.mailer""",

author = "Alice Bevan-McGregor",
author_email = "alice+marrow@gothcandy.com",
url = "https://github.com/marrow/marrow.wsgi.objects",
license = "MIT",

install_requires = [
'marrow.util < 2.0',
'marrow.interface < 2.0'
],

test_suite = 'nose.collector',
tests_require = [
'nose',
'coverage'
],

classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Console",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.1",
"Programming Language :: Python :: 3.2",
"Topic :: Software Development :: Libraries :: Python Modules"
],
'marrow.mailer.transport': [
"amazon = marrow.mailer.transport.ses:AmazonTransport",
"mock = marrow.mailer.transport.mock:MockTransport",
"smtp = marrow.mailer.transport.smtp:SMTPTransport",
"mbox = marrow.mailer.transport.mbox:MailboxTransport",
"mailbox = marrow.mailer.transport.mbox:MailboxTransport",
"maildir = marrow.mailer.transport.maildir:MaildirTransport",
"sendmail = marrow.mailer.transport.sendmail:SendmailTransport",
"imap = marrow.mailer.transport.imap:IMAPTransport",
"appengine = marrow.mailer.transport.gae:AppEngineTransport",
"logging = marrow.mailer.transport.log:LoggingTransport",
"sms = marrow.mailer.transport.sms:SMSTransport",
]
}
)

packages = find_packages(exclude=['examples', 'tests']),
zip_safe = True,
include_package_data = True,
package_data = {'': ['README.textile', 'LICENSE']},

namespace_packages = ['marrow'],

entry_points = {
'marrow.mailer.manager': [
'immediate = marrow.mailer.manager.immediate:ImmediateManager',
'futures = marrow.mailer.manager.futures:FuturesManager',
'dynamic = marrow.mailer.manager.dynamic:DynamicManager',
'transactional = marrow.mailer.manager.transactional:TransactionalDynamicManager'
],
'marrow.mailer.transport': [
'amazon = marrow.mailer.transport.ses:AmazonTransport',
'mock = marrow.mailer.transport.mock:MockTransport',
'smtp = marrow.mailer.transport.smtp:SMTPTransport',
'mbox = marrow.mailer.transport.mbox:MailboxTransport',
'mailbox = marrow.mailer.transport.mbox:MailboxTransport',
'maildir = marrow.mailer.transport.maildir:MaildirTransport',
'sendmail = marrow.mailer.transport.sendmail:SendmailTransport',
'imap = marrow.mailer.transport.imap:IMAPTransport',
'appengine = marrow.mailer.transport.gae:AppEngineTransport',
'logging = marrow.mailer.transport.log:LoggingTransport',
'sms = marrow.mailer.transport.sms:SMSTransport',
]
}
)
2 changes: 2 additions & 0 deletions tests/test_addresses.py
Expand Up @@ -158,6 +158,8 @@ def tearDown(self):

def test_assignment(self):
eq_([], self.addresses)
self.addresses = ['me@example.com']
eq_(['me@example.com'], self.addresses)

def test_assign_single_address(self):
address = 'user@example.com'
Expand Down

0 comments on commit b7dd6ef

Please sign in to comment.