compatible python3

This commit is contained in:
Mathieu Agopian
2013-07-28 00:16:43 +02:00
parent 5ed407560d
commit 971a3a393c
9 changed files with 70 additions and 29 deletions

View File

@@ -1,10 +1,12 @@
language: python language: python
python: python:
- "2.6"
- "2.7" - "2.7"
- "3.3"
install: install:
- pip install --use-mirrors imapclient unittest2 flake8 mock - pip install --use-mirrors flake8 mock
- python setup.py develop - if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install --use-mirrors unittest2py3k; fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors unittest2; fi
- pip install -e .
script: script:
- unit2 discover mailbot.tests - unit2 discover mailbot.tests
- flake8 mailbot - flake8 mailbot

View File

@@ -2,6 +2,7 @@
bin/python: bin/python:
virtualenv . --python python2 virtualenv . --python python2
bin/pip install -U setuptools
bin/python setup.py develop bin/python setup.py develop
test: bin/python test: bin/python
@@ -10,7 +11,7 @@ test: bin/python
livetest: bin/python livetest: bin/python
bin/pip install tox bin/pip install tox
bin/tox -e py26-live,py27-live bin/tox -e py27-live,py33-live
docs: docs:
bin/pip install sphinx bin/pip install sphinx

View File

@@ -11,7 +11,7 @@ MailBot: register callbacks to be executed on mail reception.
* Authors: Mathieu Agopian and `contributors * Authors: Mathieu Agopian and `contributors
<https://github.com/magopian/mailbot/contributors>`_ <https://github.com/magopian/mailbot/contributors>`_
* Licence: BSD * Licence: BSD
* Compatibility: Django 1.4+, python2.6 up to python3.3 * Compatibility: Python 2.7 and Python 3.3
* Project URL: https://github.com/magopian/mailbot * Project URL: https://github.com/magopian/mailbot
* Documentation: http://mailbot.rtfd.org/ * Documentation: http://mailbot.rtfd.org/
@@ -27,7 +27,7 @@ Setup your environment:
cd mailbot cd mailbot
Hack and run the tests using `Tox <https://pypi.python.org/pypi/tox>`_ to test Hack and run the tests using `Tox <https://pypi.python.org/pypi/tox>`_ to test
on all the supported python and Django versions: on all the supported python versions:
:: ::

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# django-mail-factory documentation build configuration file, created by # mailbot documentation build configuration file, created by
# sphinx-quickstart on Wed Jan 23 17:31:52 2013. # sphinx-quickstart on Wed Jan 23 17:31:52 2013.
# #
# This file is execfile()d with the current directory set to its containing dir. # This file is execfile()d with the current directory set to its containing dir.
@@ -40,8 +40,8 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'
# General information about the project. # General information about the project.
project = u'django-mail-factory' project = u'mailbot'
copyright = u'2013, Rémy HUBSCHER' copyright = u'2013, Mathieu Agopian'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@@ -164,7 +164,7 @@ html_static_path = ['_static']
#html_file_suffix = None #html_file_suffix = None
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'django-mail-factorydoc' htmlhelp_basename = 'mailbotdoc'
# -- Options for LaTeX output -------------------------------------------------- # -- Options for LaTeX output --------------------------------------------------
@@ -183,8 +183,8 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'django-mail-factory.tex', u'django-mail-factory Documentation', ('index', 'mailbot.tex', u'mailbot Documentation',
u'Rémy HUBSCHER', 'manual'), u'Mathieu Agopian', 'manual'),
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
@@ -213,8 +213,8 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'django-mail-factory', u'django-mail-factory Documentation', ('index', 'mailbot', u'mailbot Documentation',
[u'Rémy HUBSCHER'], 1) [u'Mathieu Agopian'], 1)
] ]
# If true, show URL addresses after external links. # If true, show URL addresses after external links.
@@ -227,8 +227,8 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
('index', 'django-mail-factory', u'django-mail-factory Documentation', ('index', 'mailbot', u'mailbot Documentation',
u'Rémy HUBSCHER', 'django-mail-factory', 'One line description of project.', u'Mathieu Agopian', 'mailbot', 'One line description of project.',
'Miscellaneous'), 'Miscellaneous'),
] ]

View File

@@ -1,9 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import
from collections import defaultdict from collections import defaultdict
from email.header import decode_header from email.header import decode_header
from re import findall from re import findall
from .compat import text_type, encoded_padding
class Callback(object): class Callback(object):
"""Base class for callbacks.""" """Base class for callbacks."""
@@ -27,7 +31,7 @@ class Callback(object):
return True return True
rules_tests = [self.check_item(item, regexps) rules_tests = [self.check_item(item, regexps)
for item, regexps in rules.iteritems()] for item, regexps in rules.items()]
return all(rules_tests) # True only if at least one value is return all(rules_tests) # True only if at least one value is
@@ -53,8 +57,10 @@ class Callback(object):
else: else:
value = message[item] value = message[item]
# decode header (might be encoded as latin-1, utf-8... # decode header (might be encoded as latin-1, utf-8...
value = ' '.join(chunk.decode(encoding or 'ASCII') value = encoded_padding.join(
for chunk, encoding in decode_header(value)) chunk.decode(encoding or 'ASCII')
if not isinstance(chunk, text_type) else chunk
for chunk, encoding in decode_header(value))
for regexp in regexps: # store all captures for easy access for regexp in regexps: # store all captures for easy access
self.matches[item] += findall(regexp, value) self.matches[item] += findall(regexp, value)
@@ -80,7 +86,10 @@ class Callback(object):
if content_type == 'text/plain' and filename is None: if content_type == 'text/plain' and filename is None:
# text body of the mail, not an attachment # text body of the mail, not an attachment
encoding = part.get_content_charset() or 'ASCII' encoding = part.get_content_charset() or 'ASCII'
return part.get_payload(decode=True).decode(encoding) content = part.get_payload()
if not isinstance(content, text_type):
content = part.get_payload(decode=True).decode(encoding)
return content
return '' return ''

13
mailbot/compat.py Normal file
View File

@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
import sys
# encoded padding is to cope with this ugly bug:
# http://bugs.python.org/issue1467619
# For some reason, in py27, the whitespace separating encoded pieces is eaten
# up
encoded_padding = ''
text_type = str
if sys.version < '3':
encoded_padding = ' '
text_type = unicode # noqa

View File

@@ -80,7 +80,7 @@ class MailBot(object):
# compare datetimes without tzinfo, as UTC # compare datetimes without tzinfo, as UTC
date_pivot = datetime.utcnow() - timedelta(seconds=self.timeout) date_pivot = datetime.utcnow() - timedelta(seconds=self.timeout)
to_reset = [msg_id for msg_id, data in messages.iteritems() to_reset = [msg_id for msg_id, data in messages.items()
if data['INTERNALDATE'].replace(tzinfo=None) < date_pivot] if data['INTERNALDATE'].replace(tzinfo=None) < date_pivot]
if to_reset: if to_reset:

View File

@@ -25,7 +25,11 @@ if __name__ == '__main__': # ``import setup`` doesn't trigger setup().
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License', 'License :: OSI Approved :: BSD License',
'Natural Language :: English', 'Natural Language :: English',
'Programming Language :: Python'], 'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3'],
keywords='mail callback', keywords='mail callback',
author='Mathieu Agopian', author='Mathieu Agopian',
author_email='mathieu.agopian@gmail.com', author_email='mathieu.agopian@gmail.com',

26
tox.ini
View File

@@ -1,26 +1,38 @@
[tox] [tox]
envlist = py26, py27 envlist = py27, py33
toxworkdir = {homedir}/.tox-mailbot
[testenv] [testenv]
commands = commands =
python setup.py develop python setup.py develop
coverage run --branch --source=mailbot bin/unit2 discover mailbot.tests coverage run --branch --source=mailbot {envbindir}/unit2 discover mailbot.tests
coverage report -m --omit=mailbot/tests/*,mailbot/livetests/* coverage report -m --omit=mailbot/tests/*,mailbot/livetests/*
flake8 mailbot flake8 mailbot
deps = deps =
imapclient
unittest2
mock mock
flake8 flake8
coverage coverage
[testenv:py26-live] [testenv:py27]
basepython = python2.7
deps =
unittest2
{[testenv]deps}
[testenv:py33]
basepython = python3.3
deps =
unittest2py3k
{[testenv]deps}
[testenv:py27-live]
basepython = python2.7
commands = commands =
python setup.py develop python setup.py develop
unit2 discover mailbot.livetests unit2 discover mailbot.livetests
[testenv:py27-live] [testenv:py33-live]
basepython = python3.3
commands = commands =
python setup.py develop python setup.py develop
unit2 discover mailbot.livetests unit2 discover mailbot.livetests