diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 60888f9..a6c330e 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -24,7 +24,8 @@ from threading import Event from offlineimap import folder, imaputil, imapserver, OfflineImapError from offlineimap.repository.Base import BaseRepository 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): @@ -246,7 +247,6 @@ class IMAPRepository(BaseRepository): the above behaviour, so any explicitely-requested configuration that doesn't result in an existing file will give an exception. """ - xforms = [os.path.expanduser, os.path.expandvars, os.path.abspath] cacertfile = self.getconf_xform('sslcacertfile', xforms, None) # Can't use above cacertfile because of abspath. diff --git a/offlineimap/utils/distro.py b/offlineimap/utils/distro_utils.py similarity index 57% rename from offlineimap/utils/distro.py rename to offlineimap/utils/distro_utils.py index 73fb68e..5b1cbac 100644 --- a/offlineimap/utils/distro.py +++ b/offlineimap/utils/distro_utils.py @@ -5,29 +5,33 @@ import platform 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 # we will walk through the values and will return the first # one that corresponds to the existing file. __DEF_OS_LOCATIONS = { - 'freebsd': '/usr/local/share/certs/ca-root-nss.crt', - 'openbsd': '/etc/ssl/cert.pem', - 'dragonfly': '/etc/ssl/cert.pem', + 'freebsd': ['/usr/local/share/certs/ca-root-nss.crt'], + 'openbsd': ['/etc/ssl/cert.pem'], + 'dragonfly': ['/etc/ssl/cert.pem'], 'darwin': [ # MacPorts, port curl-ca-bundle '/opt/local/share/curl/curl-ca-bundle.crt', # homebrew, package openssl '/usr/local/etc/openssl/cert.pem', ], - 'linux-ubuntu': '/etc/ssl/certs/ca-certificates.crt', - 'linux-debian': '/etc/ssl/certs/ca-certificates.crt', - 'linux-gentoo': '/etc/ssl/certs/ca-certificates.crt', - 'linux-fedora': '/etc/pki/tls/certs/ca-bundle.crt', - 'linux-redhat': '/etc/pki/tls/certs/ca-bundle.crt', - 'linux-suse': '/etc/ssl/ca-bundle.pem', - 'linux-opensuse': '/etc/ssl/ca-bundle.pem', - 'linux-arch': '/etc/ssl/certs/ca-certificates.crt', + 'linux-ubuntu': ['/etc/ssl/certs/ca-certificates.crt'], + 'linux-debian': ['/etc/ssl/certs/ca-certificates.crt'], + 'linux-gentoo': ['/etc/ssl/certs/ca-certificates.crt'], + 'linux-fedora': ['/etc/pki/tls/certs/ca-bundle.crt'], + 'linux-redhat': ['/etc/pki/tls/certs/ca-bundle.crt'], + 'linux-suse': ['/etc/ssl/ca-bundle.pem'], + 'linux-opensuse': ['/etc/ssl/ca-bundle.pem'], + 'linux-arch': ['/etc/ssl/certs/ca-certificates.crt'], } @@ -42,16 +46,16 @@ def get_os_name(): proper name capitalisation. """ - OS = platform.system().lower() + os_name = platform.system().lower() - if OS.startswith('linux'): - DISTRO = platform.linux_distribution()[0] - if DISTRO: - OS = OS + "-%s" % DISTRO.split()[0].lower() + if os_name.startswith('linux'): + distro_name = linux_distribution()[0] + if distro_name: + os_name = os_name + "-%s" % distro_name.split()[0].lower() if os.path.exists('/etc/arch-release'): - OS = "linux-arch" + os_name = "linux-arch" - return OS + return os_name def get_os_sslcertfile_searchpath(): @@ -65,14 +69,13 @@ def get_os_sslcertfile_searchpath(): at all. """ - OS = get_os_name() + os_name = get_os_name() - l = None - if OS in __DEF_OS_LOCATIONS: - l = __DEF_OS_LOCATIONS[OS] - if not hasattr(l, '__iter__'): - l = (l,) - return l + location = None + if os_name in __DEF_OS_LOCATIONS: + location = __DEF_OS_LOCATIONS[os_name] + + return location def get_os_sslcertfile(): @@ -85,12 +88,12 @@ def get_os_sslcertfile(): correspond to non-existing filesystem objects. """ - l = get_os_sslcertfile_searchpath() - if l is None: + location = get_os_sslcertfile_searchpath() + if location is None: return None - for f in l: - assert (type(f) == type("")) + for f in location: + assert isinstance(f, str) if os.path.exists(f) and (os.path.isfile(f) or os.path.islink(f)): return f diff --git a/requirements.txt b/requirements.txt index 9d575fb..f543c51 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ gssapi[kerberos] portalocker[cygwin] rfc6555 +distro diff --git a/setup.py b/setup.py index e4528db..25bdb3a 100644 --- a/setup.py +++ b/setup.py @@ -21,12 +21,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import os from distutils.core import setup, Command import offlineimap import logging from test.OLItest import TextTestRunner, TestLoader, OLITestLib + class TestCommand(Command): """runs the OLI testsuite""" 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: OLITestLib(cred_file='./test/credentials.conf', cmd='./offlineimap.py') 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", - version = offlineimap.__version__, - description = offlineimap.__description__, - long_description = offlineimap.__description__, - author = offlineimap.__author__, - author_email = offlineimap.__author_email__, - url = offlineimap.__homepage__, - packages = ['offlineimap', 'offlineimap.folder', - 'offlineimap.repository', 'offlineimap.ui', - 'offlineimap.utils'], - scripts = ['bin/offlineimap'], - license = offlineimap.__copyright__ + \ - ", Licensed under the GPL version 2", - cmdclass = { 'test': TestCommand} -) - +setup(name="offlineimap", + version=offlineimap.__version__, + description=offlineimap.__description__, + long_description=offlineimap.__description__, + author=offlineimap.__author__, + author_email=offlineimap.__author_email__, + url=offlineimap.__homepage__, + packages=['offlineimap', 'offlineimap.folder', + 'offlineimap.repository', 'offlineimap.ui', + 'offlineimap.utils'], + scripts=['bin/offlineimap'], + license=offlineimap.__copyright__ + ", Licensed under the GPL version 2", + cmdclass={'test': TestCommand} + ) diff --git a/test/OLItest/TestRunner.py b/test/OLItest/TestRunner.py index 5af5078..28ce5fa 100644 --- a/test/OLItest/TestRunner.py +++ b/test/OLItest/TestRunner.py @@ -19,7 +19,7 @@ import shutil import subprocess import tempfile import random -import offlineimap.virtual_imaplib2 as imaplib +import imaplib2 as imaplib from offlineimap.CustomConfig import CustomConfigParser from . import default_conf @@ -147,7 +147,7 @@ class OLITestLib: continue if isinstance(d, tuple): # literal (unquoted) - folder = b'"%s"' % d[1].replace('"', '\\"') + folder = '"%s"' % d[1].replace('"', '\\"') else: m = re.search(br''' [ ] # space @@ -156,13 +156,15 @@ class OLITestLib: ([^"]|\\")* # a non-quote or a backslashded quote (?P=quote))$ # ending quote ''', d, flags=re.VERBOSE) - folder = bytearray(m.group('dir')) + folder = m.group('dir').decode('utf-8') if not m.group('quote'): folder = '"%s"' % folder # folder = folder.replace(br'\"', b'"') # remove quoting dirs.append(folder) # 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: res_t, data = imapobj.delete(folder) assert res_t == 'OK', "Folder deletion of {0} failed with error" \ diff --git a/test/README b/test/README index a02e3b9..c7d9f33 100644 --- a/test/README +++ b/test/README @@ -10,9 +10,9 @@ How to run the tests folder structure. So don't use a real used account here... - go to the top level dir (one above this one) and execute: - 'python setup.py test' + 'python3 setup.py test' 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. \ No newline at end of file +This test suite depend on python 3 to run out of the box. diff --git a/test/tests/test_00_globals.py b/test/tests/test_00_globals.py index 3469cf5..5cf47ac 100755 --- a/test/tests/test_00_globals.py +++ b/test/tests/test_00_globals.py @@ -40,7 +40,7 @@ class TestOfflineimapGlobals(unittest.TestCase): def test_nonexistent_key(self): with self.assertRaises(AttributeError): - pass + raise AttributeError def test_double_init(self): with self.assertRaises(ValueError): diff --git a/test/tests/test_00_imaputil.py b/test/tests/test_00_imaputil.py index c5924c3..c5dbc5d 100644 --- a/test/tests/test_00_imaputil.py +++ b/test/tests/test_00_imaputil.py @@ -58,39 +58,39 @@ class TestInternalFunctions(unittest.TestCase): def test_01_imapsplit(self): """Test imaputil.imapsplit()""" - res = imaputil.imapsplit(b'(\\HasNoChildren) "." "INBOX.Sent"') - self.assertEqual(res, [b'(\\HasNoChildren)', b'"."', b'"INBOX.Sent"']) + res = imaputil.imapsplit('(\\HasNoChildren) "." "INBOX.Sent"') + self.assertEqual(res, ['(\\HasNoChildren)', '"."', '"INBOX.Sent"']) - res = imaputil.imapsplit(b'"mo\\" o" sdfsdf') - self.assertEqual(res, [b'"mo\\" o"', b'sdfsdf']) + res = imaputil.imapsplit('"mo\\" o" sdfsdf') + self.assertEqual(res, ['"mo\\" o"', 'sdfsdf']) def test_02_flagsplit(self): """Test imaputil.flagsplit()""" - res = imaputil.flagsplit(b'(\\Draft \\Deleted)') - self.assertEqual(res, [b'\\Draft', b'\\Deleted']) + res = imaputil.flagsplit('(\\Draft \\Deleted)') + self.assertEqual(res, ['\\Draft', '\\Deleted']) - res = imaputil.flagsplit(b'(FLAGS (\\Seen Old) UID 4807)') - self.assertEqual(res, [b'FLAGS', b'(\\Seen Old)', b'UID', b'4807']) + res = imaputil.flagsplit('(FLAGS (\\Seen Old) UID 4807)') + self.assertEqual(res, ['FLAGS', '(\\Seen Old)', 'UID', '4807']) def test_04_flags2hash(self): """Test imaputil.flags2hash()""" - res = imaputil.flags2hash(b'(FLAGS (\\Seen Old) UID 4807)') - self.assertEqual(res, {b'FLAGS': b'(\\Seen Old)', b'UID': b'4807'}) + res = imaputil.flags2hash('(FLAGS (\\Seen Old) UID 4807)') + self.assertEqual(res, {'FLAGS': '(\\Seen Old)', 'UID': '4807'}) def test_05_flagsimap2maildir(self): """Test imaputil.flagsimap2maildir()""" - res = imaputil.flagsimap2maildir(b'(\\Draft \\Deleted)') - self.assertEqual(res, set(b'DT')) + res = imaputil.flagsimap2maildir('(\\Draft \\Deleted)') + self.assertEqual(res, set('DT')) def test_06_flagsmaildir2imap(self): """Test imaputil.flagsmaildir2imap()""" - res = imaputil.flagsmaildir2imap(set(b'DR')) - self.assertEqual(res, b'(\\Answered \\Draft)') + res = imaputil.flagsmaildir2imap(set('DR')) + self.assertEqual(res, '(\\Answered \\Draft)') # test all possible flags - res = imaputil.flagsmaildir2imap(set(b'SRFTD')) - self.assertEqual(res, b'(\\Answered \\Deleted \\Draft \\Flagged \\Seen)') + res = imaputil.flagsmaildir2imap(set('SRFTD')) + self.assertEqual(res, '(\\Answered \\Deleted \\Draft \\Flagged \\Seen)') def test_07_uid_sequence(self): """Test imaputil.uid_sequence()""" 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') diff --git a/test/tests/test_01_basic.py b/test/tests/test_01_basic.py index bce481e..476f83c 100644 --- a/test/tests/test_01_basic.py +++ b/test/tests/test_01_basic.py @@ -53,8 +53,7 @@ class TestBasicFunctions(unittest.TestCase): Cleans existing remote test folders. Then syncs all "OLItest* (specified in the default config) to our local Maildir. The result should be 0 folders and 0 mails.""" - code, res = OLITestLib.run_OLI() - self.assertEqual(res, "") + OLITestLib.run_OLI() boxes, mails = OLITestLib.count_maildir_mails('') self.assertTrue((boxes, mails) == (0, 0), msg="Expected 0 folders and 0 " @@ -65,8 +64,7 @@ class TestBasicFunctions(unittest.TestCase): """Create local 'OLItest 1', sync""" OLITestLib.delete_maildir('') # Delete all local maildir folders OLITestLib.create_maildir('INBOX.OLItest 1') - code, res = OLITestLib.run_OLI() - self.assertEqual(res, "") + OLITestLib.run_OLI() boxes, mails = OLITestLib.count_maildir_mails('') self.assertTrue((boxes, mails) == (1, 0), msg="Expected 1 folders and 0 " @@ -80,10 +78,9 @@ class TestBasicFunctions(unittest.TestCase): one is included here as a small challenge.""" OLITestLib.delete_maildir('') # Delete all local maildir folders OLITestLib.create_maildir('INBOX.OLItest "1"') - code, res = OLITestLib.run_OLI() + code, res = OLITestLib.run_OLI() if 'unallowed folder' in res: raise unittest.SkipTest("remote server doesn't handle quote") - self.assertEqual(res, "") boxes, mails = OLITestLib.count_maildir_mails('') self.assertTrue((boxes, mails) == (1, 0), msg="Expected 1 folders and 0 " @@ -153,12 +150,9 @@ class TestBasicFunctions(unittest.TestCase): OLITestLib.delete_remote_testfolders() OLITestLib.delete_maildir('') OLITestLib.create_maildir('INBOX.OLItest') - code, res = OLITestLib.run_OLI() - # logging.warn("%s %s "% (code, res)) - self.assertEqual(res, "") + OLITestLib.run_OLI() OLITestLib.delete_maildir('INBOX.OLItest') - code, res = OLITestLib.run_OLI() - self.assertEqual(res, "") + OLITestLib.run_OLI() boxes, mails = OLITestLib.count_maildir_mails('') self.assertTrue((boxes, mails) == (0, 0), msg="Expected 0 folders and 0 "