commit
5e7b006540
@ -24,7 +24,8 @@ from threading import Event
|
|||||||
from offlineimap import folder, imaputil, imapserver, OfflineImapError
|
from offlineimap import folder, imaputil, imapserver, OfflineImapError
|
||||||
from offlineimap.repository.Base import BaseRepository
|
from offlineimap.repository.Base import BaseRepository
|
||||||
from offlineimap.threadutil import ExitNotifyThread
|
from offlineimap.threadutil import ExitNotifyThread
|
||||||
from offlineimap.utils.distro import get_os_sslcertfile, get_os_sslcertfile_searchpath
|
from offlineimap.utils.distro_utils import get_os_sslcertfile, \
|
||||||
|
get_os_sslcertfile_searchpath
|
||||||
|
|
||||||
|
|
||||||
class IMAPRepository(BaseRepository):
|
class IMAPRepository(BaseRepository):
|
||||||
@ -246,7 +247,6 @@ class IMAPRepository(BaseRepository):
|
|||||||
the above behaviour, so any explicitely-requested configuration
|
the above behaviour, so any explicitely-requested configuration
|
||||||
that doesn't result in an existing file will give an exception.
|
that doesn't result in an existing file will give an exception.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
xforms = [os.path.expanduser, os.path.expandvars, os.path.abspath]
|
xforms = [os.path.expanduser, os.path.expandvars, os.path.abspath]
|
||||||
cacertfile = self.getconf_xform('sslcacertfile', xforms, None)
|
cacertfile = self.getconf_xform('sslcacertfile', xforms, None)
|
||||||
# Can't use above cacertfile because of abspath.
|
# Can't use above cacertfile because of abspath.
|
||||||
|
@ -5,29 +5,33 @@
|
|||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# Each dictionary value is either string or some iterable.
|
# linux_distribution deprecated in Python 3.7
|
||||||
#
|
try:
|
||||||
|
from platform import linux_distribution
|
||||||
|
except ImportError:
|
||||||
|
from distro import linux_distribution
|
||||||
|
|
||||||
# For the former we will just return the value, for an iterable
|
# For the former we will just return the value, for an iterable
|
||||||
# we will walk through the values and will return the first
|
# we will walk through the values and will return the first
|
||||||
# one that corresponds to the existing file.
|
# one that corresponds to the existing file.
|
||||||
__DEF_OS_LOCATIONS = {
|
__DEF_OS_LOCATIONS = {
|
||||||
'freebsd': '/usr/local/share/certs/ca-root-nss.crt',
|
'freebsd': ['/usr/local/share/certs/ca-root-nss.crt'],
|
||||||
'openbsd': '/etc/ssl/cert.pem',
|
'openbsd': ['/etc/ssl/cert.pem'],
|
||||||
'dragonfly': '/etc/ssl/cert.pem',
|
'dragonfly': ['/etc/ssl/cert.pem'],
|
||||||
'darwin': [
|
'darwin': [
|
||||||
# MacPorts, port curl-ca-bundle
|
# MacPorts, port curl-ca-bundle
|
||||||
'/opt/local/share/curl/curl-ca-bundle.crt',
|
'/opt/local/share/curl/curl-ca-bundle.crt',
|
||||||
# homebrew, package openssl
|
# homebrew, package openssl
|
||||||
'/usr/local/etc/openssl/cert.pem',
|
'/usr/local/etc/openssl/cert.pem',
|
||||||
],
|
],
|
||||||
'linux-ubuntu': '/etc/ssl/certs/ca-certificates.crt',
|
'linux-ubuntu': ['/etc/ssl/certs/ca-certificates.crt'],
|
||||||
'linux-debian': '/etc/ssl/certs/ca-certificates.crt',
|
'linux-debian': ['/etc/ssl/certs/ca-certificates.crt'],
|
||||||
'linux-gentoo': '/etc/ssl/certs/ca-certificates.crt',
|
'linux-gentoo': ['/etc/ssl/certs/ca-certificates.crt'],
|
||||||
'linux-fedora': '/etc/pki/tls/certs/ca-bundle.crt',
|
'linux-fedora': ['/etc/pki/tls/certs/ca-bundle.crt'],
|
||||||
'linux-redhat': '/etc/pki/tls/certs/ca-bundle.crt',
|
'linux-redhat': ['/etc/pki/tls/certs/ca-bundle.crt'],
|
||||||
'linux-suse': '/etc/ssl/ca-bundle.pem',
|
'linux-suse': ['/etc/ssl/ca-bundle.pem'],
|
||||||
'linux-opensuse': '/etc/ssl/ca-bundle.pem',
|
'linux-opensuse': ['/etc/ssl/ca-bundle.pem'],
|
||||||
'linux-arch': '/etc/ssl/certs/ca-certificates.crt',
|
'linux-arch': ['/etc/ssl/certs/ca-certificates.crt'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -42,16 +46,16 @@ def get_os_name():
|
|||||||
proper name capitalisation.
|
proper name capitalisation.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
OS = platform.system().lower()
|
os_name = platform.system().lower()
|
||||||
|
|
||||||
if OS.startswith('linux'):
|
if os_name.startswith('linux'):
|
||||||
DISTRO = platform.linux_distribution()[0]
|
distro_name = linux_distribution()[0]
|
||||||
if DISTRO:
|
if distro_name:
|
||||||
OS = OS + "-%s" % DISTRO.split()[0].lower()
|
os_name = os_name + "-%s" % distro_name.split()[0].lower()
|
||||||
if os.path.exists('/etc/arch-release'):
|
if os.path.exists('/etc/arch-release'):
|
||||||
OS = "linux-arch"
|
os_name = "linux-arch"
|
||||||
|
|
||||||
return OS
|
return os_name
|
||||||
|
|
||||||
|
|
||||||
def get_os_sslcertfile_searchpath():
|
def get_os_sslcertfile_searchpath():
|
||||||
@ -65,14 +69,13 @@ def get_os_sslcertfile_searchpath():
|
|||||||
at all.
|
at all.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
OS = get_os_name()
|
os_name = get_os_name()
|
||||||
|
|
||||||
l = None
|
location = None
|
||||||
if OS in __DEF_OS_LOCATIONS:
|
if os_name in __DEF_OS_LOCATIONS:
|
||||||
l = __DEF_OS_LOCATIONS[OS]
|
location = __DEF_OS_LOCATIONS[os_name]
|
||||||
if not hasattr(l, '__iter__'):
|
|
||||||
l = (l,)
|
return location
|
||||||
return l
|
|
||||||
|
|
||||||
|
|
||||||
def get_os_sslcertfile():
|
def get_os_sslcertfile():
|
||||||
@ -85,12 +88,12 @@ def get_os_sslcertfile():
|
|||||||
correspond to non-existing filesystem objects.
|
correspond to non-existing filesystem objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
l = get_os_sslcertfile_searchpath()
|
location = get_os_sslcertfile_searchpath()
|
||||||
if l is None:
|
if location is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for f in l:
|
for f in location:
|
||||||
assert (type(f) == type(""))
|
assert isinstance(f, str)
|
||||||
if os.path.exists(f) and (os.path.isfile(f) or os.path.islink(f)):
|
if os.path.exists(f) and (os.path.isfile(f) or os.path.islink(f)):
|
||||||
return f
|
return f
|
||||||
|
|
@ -2,3 +2,4 @@
|
|||||||
gssapi[kerberos]
|
gssapi[kerberos]
|
||||||
portalocker[cygwin]
|
portalocker[cygwin]
|
||||||
rfc6555
|
rfc6555
|
||||||
|
distro
|
||||||
|
35
setup.py
35
setup.py
@ -21,12 +21,12 @@
|
|||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
import os
|
|
||||||
from distutils.core import setup, Command
|
from distutils.core import setup, Command
|
||||||
import offlineimap
|
import offlineimap
|
||||||
import logging
|
import logging
|
||||||
from test.OLItest import TextTestRunner, TestLoader, OLITestLib
|
from test.OLItest import TextTestRunner, TestLoader, OLITestLib
|
||||||
|
|
||||||
|
|
||||||
class TestCommand(Command):
|
class TestCommand(Command):
|
||||||
"""runs the OLI testsuite"""
|
"""runs the OLI testsuite"""
|
||||||
description = """Runs the test suite. In order to execute only a single
|
description = """Runs the test suite. In order to execute only a single
|
||||||
@ -46,23 +46,20 @@ class TestCommand(Command):
|
|||||||
# set credentials and OfflineImap command to be executed:
|
# set credentials and OfflineImap command to be executed:
|
||||||
OLITestLib(cred_file='./test/credentials.conf', cmd='./offlineimap.py')
|
OLITestLib(cred_file='./test/credentials.conf', cmd='./offlineimap.py')
|
||||||
suite = TestLoader().discover('./test/tests')
|
suite = TestLoader().discover('./test/tests')
|
||||||
#TODO: failfast does not seem to exist in python2.6?
|
TextTestRunner(verbosity=2, failfast=True).run(suite)
|
||||||
TextTestRunner(verbosity=2,failfast=True).run(suite)
|
|
||||||
|
|
||||||
|
|
||||||
setup(name = "offlineimap",
|
setup(name="offlineimap",
|
||||||
version = offlineimap.__version__,
|
version=offlineimap.__version__,
|
||||||
description = offlineimap.__description__,
|
description=offlineimap.__description__,
|
||||||
long_description = offlineimap.__description__,
|
long_description=offlineimap.__description__,
|
||||||
author = offlineimap.__author__,
|
author=offlineimap.__author__,
|
||||||
author_email = offlineimap.__author_email__,
|
author_email=offlineimap.__author_email__,
|
||||||
url = offlineimap.__homepage__,
|
url=offlineimap.__homepage__,
|
||||||
packages = ['offlineimap', 'offlineimap.folder',
|
packages=['offlineimap', 'offlineimap.folder',
|
||||||
'offlineimap.repository', 'offlineimap.ui',
|
'offlineimap.repository', 'offlineimap.ui',
|
||||||
'offlineimap.utils'],
|
'offlineimap.utils'],
|
||||||
scripts = ['bin/offlineimap'],
|
scripts=['bin/offlineimap'],
|
||||||
license = offlineimap.__copyright__ + \
|
license=offlineimap.__copyright__ + ", Licensed under the GPL version 2",
|
||||||
", Licensed under the GPL version 2",
|
cmdclass={'test': TestCommand}
|
||||||
cmdclass = { 'test': TestCommand}
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import random
|
import random
|
||||||
import offlineimap.virtual_imaplib2 as imaplib
|
import imaplib2 as imaplib
|
||||||
from offlineimap.CustomConfig import CustomConfigParser
|
from offlineimap.CustomConfig import CustomConfigParser
|
||||||
from . import default_conf
|
from . import default_conf
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ class OLITestLib:
|
|||||||
continue
|
continue
|
||||||
if isinstance(d, tuple):
|
if isinstance(d, tuple):
|
||||||
# literal (unquoted)
|
# literal (unquoted)
|
||||||
folder = b'"%s"' % d[1].replace('"', '\\"')
|
folder = '"%s"' % d[1].replace('"', '\\"')
|
||||||
else:
|
else:
|
||||||
m = re.search(br'''
|
m = re.search(br'''
|
||||||
[ ] # space
|
[ ] # space
|
||||||
@ -156,13 +156,15 @@ class OLITestLib:
|
|||||||
([^"]|\\")* # a non-quote or a backslashded quote
|
([^"]|\\")* # a non-quote or a backslashded quote
|
||||||
(?P=quote))$ # ending quote
|
(?P=quote))$ # ending quote
|
||||||
''', d, flags=re.VERBOSE)
|
''', d, flags=re.VERBOSE)
|
||||||
folder = bytearray(m.group('dir'))
|
folder = m.group('dir').decode('utf-8')
|
||||||
if not m.group('quote'):
|
if not m.group('quote'):
|
||||||
folder = '"%s"' % folder
|
folder = '"%s"' % folder
|
||||||
# folder = folder.replace(br'\"', b'"') # remove quoting
|
# folder = folder.replace(br'\"', b'"') # remove quoting
|
||||||
dirs.append(folder)
|
dirs.append(folder)
|
||||||
# 2) filter out those not starting with INBOX.OLItest and del...
|
# 2) filter out those not starting with INBOX.OLItest and del...
|
||||||
dirs = [d for d in dirs if d.startswith(b'"INBOX.OLItest') or d.startswith(b'"INBOX/OLItest')]
|
dirs = [d for d in dirs
|
||||||
|
if d.startswith('"INBOX.OLItest')
|
||||||
|
or d.startswith('"INBOX/OLItest')]
|
||||||
for folder in dirs:
|
for folder in dirs:
|
||||||
res_t, data = imapobj.delete(folder)
|
res_t, data = imapobj.delete(folder)
|
||||||
assert res_t == 'OK', "Folder deletion of {0} failed with error" \
|
assert res_t == 'OK', "Folder deletion of {0} failed with error" \
|
||||||
|
@ -10,9 +10,9 @@ How to run the tests
|
|||||||
folder structure. So don't use a real used account here...
|
folder structure. So don't use a real used account here...
|
||||||
|
|
||||||
- go to the top level dir (one above this one) and execute:
|
- go to the top level dir (one above this one) and execute:
|
||||||
'python setup.py test'
|
'python3 setup.py test'
|
||||||
|
|
||||||
System requirements
|
System requirements
|
||||||
===================
|
===================
|
||||||
|
|
||||||
This test suite depend on python>=2.7 to run out of the box. If you want to run this with python 2.6 you will need to install the backport from http://pypi.python.org/pypi/unittest2 instead.
|
This test suite depend on python 3 to run out of the box.
|
||||||
|
@ -40,7 +40,7 @@ class TestOfflineimapGlobals(unittest.TestCase):
|
|||||||
|
|
||||||
def test_nonexistent_key(self):
|
def test_nonexistent_key(self):
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
pass
|
raise AttributeError
|
||||||
|
|
||||||
def test_double_init(self):
|
def test_double_init(self):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
|
@ -58,39 +58,39 @@ class TestInternalFunctions(unittest.TestCase):
|
|||||||
|
|
||||||
def test_01_imapsplit(self):
|
def test_01_imapsplit(self):
|
||||||
"""Test imaputil.imapsplit()"""
|
"""Test imaputil.imapsplit()"""
|
||||||
res = imaputil.imapsplit(b'(\\HasNoChildren) "." "INBOX.Sent"')
|
res = imaputil.imapsplit('(\\HasNoChildren) "." "INBOX.Sent"')
|
||||||
self.assertEqual(res, [b'(\\HasNoChildren)', b'"."', b'"INBOX.Sent"'])
|
self.assertEqual(res, ['(\\HasNoChildren)', '"."', '"INBOX.Sent"'])
|
||||||
|
|
||||||
res = imaputil.imapsplit(b'"mo\\" o" sdfsdf')
|
res = imaputil.imapsplit('"mo\\" o" sdfsdf')
|
||||||
self.assertEqual(res, [b'"mo\\" o"', b'sdfsdf'])
|
self.assertEqual(res, ['"mo\\" o"', 'sdfsdf'])
|
||||||
|
|
||||||
def test_02_flagsplit(self):
|
def test_02_flagsplit(self):
|
||||||
"""Test imaputil.flagsplit()"""
|
"""Test imaputil.flagsplit()"""
|
||||||
res = imaputil.flagsplit(b'(\\Draft \\Deleted)')
|
res = imaputil.flagsplit('(\\Draft \\Deleted)')
|
||||||
self.assertEqual(res, [b'\\Draft', b'\\Deleted'])
|
self.assertEqual(res, ['\\Draft', '\\Deleted'])
|
||||||
|
|
||||||
res = imaputil.flagsplit(b'(FLAGS (\\Seen Old) UID 4807)')
|
res = imaputil.flagsplit('(FLAGS (\\Seen Old) UID 4807)')
|
||||||
self.assertEqual(res, [b'FLAGS', b'(\\Seen Old)', b'UID', b'4807'])
|
self.assertEqual(res, ['FLAGS', '(\\Seen Old)', 'UID', '4807'])
|
||||||
|
|
||||||
def test_04_flags2hash(self):
|
def test_04_flags2hash(self):
|
||||||
"""Test imaputil.flags2hash()"""
|
"""Test imaputil.flags2hash()"""
|
||||||
res = imaputil.flags2hash(b'(FLAGS (\\Seen Old) UID 4807)')
|
res = imaputil.flags2hash('(FLAGS (\\Seen Old) UID 4807)')
|
||||||
self.assertEqual(res, {b'FLAGS': b'(\\Seen Old)', b'UID': b'4807'})
|
self.assertEqual(res, {'FLAGS': '(\\Seen Old)', 'UID': '4807'})
|
||||||
|
|
||||||
def test_05_flagsimap2maildir(self):
|
def test_05_flagsimap2maildir(self):
|
||||||
"""Test imaputil.flagsimap2maildir()"""
|
"""Test imaputil.flagsimap2maildir()"""
|
||||||
res = imaputil.flagsimap2maildir(b'(\\Draft \\Deleted)')
|
res = imaputil.flagsimap2maildir('(\\Draft \\Deleted)')
|
||||||
self.assertEqual(res, set(b'DT'))
|
self.assertEqual(res, set('DT'))
|
||||||
|
|
||||||
def test_06_flagsmaildir2imap(self):
|
def test_06_flagsmaildir2imap(self):
|
||||||
"""Test imaputil.flagsmaildir2imap()"""
|
"""Test imaputil.flagsmaildir2imap()"""
|
||||||
res = imaputil.flagsmaildir2imap(set(b'DR'))
|
res = imaputil.flagsmaildir2imap(set('DR'))
|
||||||
self.assertEqual(res, b'(\\Answered \\Draft)')
|
self.assertEqual(res, '(\\Answered \\Draft)')
|
||||||
# test all possible flags
|
# test all possible flags
|
||||||
res = imaputil.flagsmaildir2imap(set(b'SRFTD'))
|
res = imaputil.flagsmaildir2imap(set('SRFTD'))
|
||||||
self.assertEqual(res, b'(\\Answered \\Deleted \\Draft \\Flagged \\Seen)')
|
self.assertEqual(res, '(\\Answered \\Deleted \\Draft \\Flagged \\Seen)')
|
||||||
|
|
||||||
def test_07_uid_sequence(self):
|
def test_07_uid_sequence(self):
|
||||||
"""Test imaputil.uid_sequence()"""
|
"""Test imaputil.uid_sequence()"""
|
||||||
res = imaputil.uid_sequence([1, 2, 3, 4, 5, 10, 12, 13])
|
res = imaputil.uid_sequence([1, 2, 3, 4, 5, 10, 12, 13])
|
||||||
self.assertEqual(res, b'1:5,10,12:13')
|
self.assertEqual(res, '1:5,10,12:13')
|
||||||
|
@ -53,8 +53,7 @@ class TestBasicFunctions(unittest.TestCase):
|
|||||||
Cleans existing remote test folders. Then syncs all "OLItest*
|
Cleans existing remote test folders. Then syncs all "OLItest*
|
||||||
(specified in the default config) to our local Maildir. The
|
(specified in the default config) to our local Maildir. The
|
||||||
result should be 0 folders and 0 mails."""
|
result should be 0 folders and 0 mails."""
|
||||||
code, res = OLITestLib.run_OLI()
|
OLITestLib.run_OLI()
|
||||||
self.assertEqual(res, "")
|
|
||||||
boxes, mails = OLITestLib.count_maildir_mails('')
|
boxes, mails = OLITestLib.count_maildir_mails('')
|
||||||
self.assertTrue((boxes, mails) == (0, 0),
|
self.assertTrue((boxes, mails) == (0, 0),
|
||||||
msg="Expected 0 folders and 0 "
|
msg="Expected 0 folders and 0 "
|
||||||
@ -65,8 +64,7 @@ class TestBasicFunctions(unittest.TestCase):
|
|||||||
"""Create local 'OLItest 1', sync"""
|
"""Create local 'OLItest 1', sync"""
|
||||||
OLITestLib.delete_maildir('') # Delete all local maildir folders
|
OLITestLib.delete_maildir('') # Delete all local maildir folders
|
||||||
OLITestLib.create_maildir('INBOX.OLItest 1')
|
OLITestLib.create_maildir('INBOX.OLItest 1')
|
||||||
code, res = OLITestLib.run_OLI()
|
OLITestLib.run_OLI()
|
||||||
self.assertEqual(res, "")
|
|
||||||
boxes, mails = OLITestLib.count_maildir_mails('')
|
boxes, mails = OLITestLib.count_maildir_mails('')
|
||||||
self.assertTrue((boxes, mails) == (1, 0),
|
self.assertTrue((boxes, mails) == (1, 0),
|
||||||
msg="Expected 1 folders and 0 "
|
msg="Expected 1 folders and 0 "
|
||||||
@ -80,10 +78,9 @@ class TestBasicFunctions(unittest.TestCase):
|
|||||||
one is included here as a small challenge."""
|
one is included here as a small challenge."""
|
||||||
OLITestLib.delete_maildir('') # Delete all local maildir folders
|
OLITestLib.delete_maildir('') # Delete all local maildir folders
|
||||||
OLITestLib.create_maildir('INBOX.OLItest "1"')
|
OLITestLib.create_maildir('INBOX.OLItest "1"')
|
||||||
code, res = OLITestLib.run_OLI()
|
code, res = OLITestLib.run_OLI()
|
||||||
if 'unallowed folder' in res:
|
if 'unallowed folder' in res:
|
||||||
raise unittest.SkipTest("remote server doesn't handle quote")
|
raise unittest.SkipTest("remote server doesn't handle quote")
|
||||||
self.assertEqual(res, "")
|
|
||||||
boxes, mails = OLITestLib.count_maildir_mails('')
|
boxes, mails = OLITestLib.count_maildir_mails('')
|
||||||
self.assertTrue((boxes, mails) == (1, 0),
|
self.assertTrue((boxes, mails) == (1, 0),
|
||||||
msg="Expected 1 folders and 0 "
|
msg="Expected 1 folders and 0 "
|
||||||
@ -153,12 +150,9 @@ class TestBasicFunctions(unittest.TestCase):
|
|||||||
OLITestLib.delete_remote_testfolders()
|
OLITestLib.delete_remote_testfolders()
|
||||||
OLITestLib.delete_maildir('')
|
OLITestLib.delete_maildir('')
|
||||||
OLITestLib.create_maildir('INBOX.OLItest')
|
OLITestLib.create_maildir('INBOX.OLItest')
|
||||||
code, res = OLITestLib.run_OLI()
|
OLITestLib.run_OLI()
|
||||||
# logging.warn("%s %s "% (code, res))
|
|
||||||
self.assertEqual(res, "")
|
|
||||||
OLITestLib.delete_maildir('INBOX.OLItest')
|
OLITestLib.delete_maildir('INBOX.OLItest')
|
||||||
code, res = OLITestLib.run_OLI()
|
OLITestLib.run_OLI()
|
||||||
self.assertEqual(res, "")
|
|
||||||
boxes, mails = OLITestLib.count_maildir_mails('')
|
boxes, mails = OLITestLib.count_maildir_mails('')
|
||||||
self.assertTrue((boxes, mails) == (0, 0),
|
self.assertTrue((boxes, mails) == (0, 0),
|
||||||
msg="Expected 0 folders and 0 "
|
msg="Expected 0 folders and 0 "
|
||||||
|
Loading…
Reference in New Issue
Block a user