From 26efc62ba7cd04292f81406e815a8ff1c851cdec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 15:24:40 +0100 Subject: [PATCH 01/47] imapserver import style This patch removes the unused import socket line. (warning) Split the line with multiple imports in different lines. (warning) --- offlineimap/imapserver.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index e9816ac..b40e814 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -18,9 +18,10 @@ import datetime import hashlib import hmac -import socket import json -import urllib.request, urllib.parse, urllib.error +import urllib.request +import urllib.parse +import urllib.error import time import errno import socket From 78aeed20a91455fb23b2e65fe115d7295a279e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 15:29:24 +0100 Subject: [PATCH 02/47] imapserver call to OfflineImapError with right arguments Call to OfflineImapError has the arguments: - message - severity - error code The None argument ir wrong here, we can remove it and then we have three arguments not four. --- offlineimap/imapserver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index b40e814..e2916a4 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -332,7 +332,8 @@ class IMAPServer(): except imapobj.error as e: raise OfflineImapError("Failed to start " "TLS connection: %s" % str(e), - OfflineImapError.ERROR.REPO, None, exc_info()[2]) + OfflineImapError.ERROR.REPO, + exc_info()[2]) # All __authn_* procedures are helpers that do authentication. # They are class methods that take one parameter, IMAP object. From 352133dcc0c0ea00fc641a996bc6f806308be3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 15:35:54 +0100 Subject: [PATCH 03/47] call to setDaemon uses Bool argument The argument 1 should be True in these files. --- offlineimap/imapserver.py | 2 +- offlineimap/repository/IMAP.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index e2916a4..067d04d 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -778,7 +778,7 @@ class IdleThread: self.thread = Thread(target=self.noop) else: self.thread = Thread(target=self.__idle) - self.thread.setDaemon(1) + self.thread.setDaemon(True) def start(self): self.thread.start() diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 68f1800..679af68 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -60,7 +60,7 @@ class IMAPRepository(BaseRepository): self.kathread = ExitNotifyThread(target=self.imapserver.keepalive, name="Keep alive " + self.getname(), args=(keepalivetime, self.kaevent)) - self.kathread.setDaemon(1) + self.kathread.setDaemon(True) self.kathread.start() def stopkeepalive(self): From 0e90bcbf380bf7c48f86cc9675e2308387ace264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 15:37:50 +0100 Subject: [PATCH 04/47] IMAP.py too many arguments for string format We need only two arguments, not three. We can remove the self argument. --- offlineimap/repository/IMAP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 679af68..36348ab 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -459,7 +459,7 @@ class IMAPRepository(BaseRepository): if result != 'OK': raise OfflineImapError("Could not list the folders for" " repository %s. Server responded: %s" % - (self.name, self, str(listresult)), + (self.name, str(listresult)), OfflineImapError.ERROR.FOLDER) finally: self.imapserver.releaseconnection(imapobj) From cbbeebbf44e7984240f63a796273dc94d37719fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 15:39:28 +0100 Subject: [PATCH 05/47] imapserver.py removed extra parenthesis We can remove this parenthesis. --- offlineimap/imapserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index 067d04d..489ef2d 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -40,7 +40,7 @@ except ImportError: have_gss = False -class IMAPServer(): +class IMAPServer: """Initializes all variables from an IMAPRepository() instance Various functions, such as acquireconnection() return an IMAP4 From 5033340c2fd1145248d8526fcbaab8d625276d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 15:53:45 +0100 Subject: [PATCH 06/47] IMAP.py should use encoding to read the file This patch includes the word "encoding" to select the right argument in remotepassfile. --- offlineimap/repository/IMAP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 36348ab..61a0076 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -398,7 +398,7 @@ class IMAPRepository(BaseRepository): # 3. Read password from file specified in Repository 'remotepassfile'. passfile = self.getconf('remotepassfile', None) if passfile is not None: - fd = open(os.path.expanduser(passfile), 'r', 'utf-8') + fd = open(os.path.expanduser(passfile), 'r', encoding='utf-8') password = fd.readline().strip() fd.close() return password.encode('UTF-8') From 2f2f4ef918eb5d2336caf29f185a18e13a95d685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 16:09:34 +0100 Subject: [PATCH 07/47] IMAP.py long lines style This patch changes long lines (>80 chars) to lines <80 chars. The patch only changes the style. --- offlineimap/repository/IMAP.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 61a0076..4ca669d 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -107,9 +107,9 @@ class IMAPRepository(BaseRepository): This requires that self.imapserver has been initialized with an acquireconnection() or it will still be `None`""" - assert self.imapserver.delim is not None, "'%s' " \ - "repository called getsep() before the folder separator was " \ - "queried from the server" % self + assert self.imapserver.delim is not None, \ + "'%s' repository called getsep() before the folder separator was " \ + "queried from the server" % self return self.imapserver.delim def gethost(self): @@ -141,7 +141,8 @@ class IMAPRepository(BaseRepository): # No success. raise OfflineImapError("No remote host for repository " - "'%s' specified." % self, OfflineImapError.ERROR.REPO) + "'%s' specified." % self, + OfflineImapError.ERROR.REPO) def get_remote_identity(self): """Remote identity is used for certain SASL mechanisms @@ -167,8 +168,8 @@ class IMAPRepository(BaseRepository): for m in mechs: if m not in supported: raise OfflineImapError("Repository %s: " % self + - "unknown authentication mechanism '%s'" % m, - OfflineImapError.ERROR.REPO) + "unknown authentication mechanism '%s'" + % m, OfflineImapError.ERROR.REPO) self.ui.debug('imap', "Using authentication mechanisms %s" % mechs) return mechs @@ -486,7 +487,8 @@ class IMAPRepository(BaseRepository): try: for foldername in self.folderincludes: try: - imapobj.select(imaputil.utf8_IMAP(foldername), readonly=True) + imapobj.select(imaputil.utf8_IMAP(foldername), + readonly=True) except OfflineImapError as e: # couldn't select this folderinclude, so ignore folder. if e.severity > OfflineImapError.ERROR.FOLDER: @@ -514,7 +516,8 @@ class IMAPRepository(BaseRepository): self.obj = obj def __cmp__(self, other): - return mycmp(self.obj.getvisiblename(), other.obj.getvisiblename()) + return mycmp(self.obj.getvisiblename(), + other.obj.getvisiblename()) return K @@ -532,9 +535,9 @@ class IMAPRepository(BaseRepository): try: result = imapobj.delete(foldername) if result[0] != 'OK': - raise OfflineImapError("Folder '%s'[%s] could not be deleted. " - "Server responded: %s" % (foldername, self, str(result)), - OfflineImapError.ERROR.FOLDER) + msg = "Folder '%s'[%s] could not be deleted. "\ + "Server responded: %s" % (foldername, self, str(result)) + raise OfflineImapError(msg, OfflineImapError.ERROR.FOLDER) finally: self.imapserver.releaseconnection(imapobj) @@ -577,9 +580,9 @@ class IMAPRepository(BaseRepository): result = imapobj.create(foldername) if result[0] != 'OK': - raise OfflineImapError("Folder '%s'[%s] could not be created. " - "Server responded: %s" % (foldername, self, str(result)), - OfflineImapError.ERROR.FOLDER) + msg = "Folder '%s'[%s] could not be created. "\ + "Server responded: %s" % (foldername, self, str(result)) + raise OfflineImapError(msg, OfflineImapError.ERROR.FOLDER) finally: self.imapserver.releaseconnection(imapobj) From 1ce229ca9d08181912cce3276d0440b7bac5ccbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 16:12:02 +0100 Subject: [PATCH 08/47] IMAP.py comparison with None should use is Comparison with None should be "is" not "==" --- offlineimap/repository/IMAP.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 4ca669d..b6f33c1 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -255,8 +255,8 @@ class IMAPRepository(BaseRepository): # Can't use above cacertfile because of abspath. conf_sslacertfile = self.getconf('sslcacertfile', None) if conf_sslacertfile == "OS-DEFAULT" or \ - conf_sslacertfile == None or \ - conf_sslacertfile == '': + conf_sslacertfile is None or \ + conf_sslacertfile == '': cacertfile = get_os_sslcertfile() if cacertfile is None: searchpath = get_os_sslcertfile_searchpath() From 332a6d72400a51b7ed2cb0368d6887abbddc984f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 16:14:53 +0100 Subject: [PATCH 09/47] IMAP.py long lines style This patch changes long lines (>80 chars) to lines <80 chars. The patch only changes the style. --- offlineimap/repository/IMAP.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index b6f33c1..0612f9d 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -199,7 +199,8 @@ class IMAPRepository(BaseRepository): return netrcentry[0] try: - netrcentry = netrc.netrc('/etc/netrc').authenticators(self.gethost()) + netrcentry = netrc.netrc('/etc/netrc')\ + .authenticators(self.gethost()) except IOError as inst: if inst.errno not in (errno.ENOENT, errno.EACCES): raise @@ -293,7 +294,8 @@ class IMAPRepository(BaseRepository): comma-separated fingerprints in hex form.""" value = self.getconf('cert_fingerprint', "") - return [f.strip().lower().replace(":", "") for f in value.split(',') if f] + return [f.strip().lower().replace(":", "") + for f in value.split(',') if f] def setoauth2_request_url(self, url): self.oauth2_request_url = url @@ -416,7 +418,8 @@ class IMAPRepository(BaseRepository): return netrcentry[2] # 5. Read password from /etc/netrc. try: - netrcentry = netrc.netrc('/etc/netrc').authenticators(self.gethost()) + netrcentry = netrc.netrc('/etc/netrc')\ + .authenticators(self.gethost()) except IOError as inst: if inst.errno not in (errno.ENOENT, errno.EACCES): raise @@ -456,7 +459,8 @@ class IMAPRepository(BaseRepository): listfunction = imapobj.lsub try: - result, listresult = listfunction(directory=self.imapserver.reference, pattern='"*"') + result, listresult = \ + listfunction(directory=self.imapserver.reference, pattern='"*"') if result != 'OK': raise OfflineImapError("Could not list the folders for" " repository %s. Server responded: %s" % @@ -561,7 +565,8 @@ class IMAPRepository(BaseRepository): return parts = foldername.split(self.getsep()) - folder_paths = [self.getsep().join(parts[:n + 1]) for n in range(len(parts))] + folder_paths = [self.getsep().join(parts[:n + 1]) + for n in range(len(parts))] for folder_path in folder_paths: try: self.makefolder_single(folder_path) From 23f67019cc366a7358d44cabc9cc3d4865ca90c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 16:43:52 +0100 Subject: [PATCH 10/47] Base.py long lines style This patch changes long lines (>80 chars) to lines <80 chars. The patch only changes the style. --- offlineimap/repository/Base.py | 57 ++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index 7893708..483d743 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -34,7 +34,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): self.localeval = account.getlocaleval() self._accountname = self.account.getname() self._readonly = self.getconfboolean('readonly', False) - self.uiddir = os.path.join(self.config.getmetadatadir(), 'Repository-' + self.name) + self.uiddir = os.path.join(self.config.getmetadatadir(), + 'Repository-' + self.name) if not os.path.exists(self.uiddir): os.mkdir(self.uiddir, 0o700) self.mapdir = os.path.join(self.uiddir, 'UIDMapping') @@ -154,7 +155,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): It is disabled by either setting the whole repository 'readonly' or by using the 'createfolders' setting.""" - return (not self._readonly) and self.getconfboolean('createfolders', True) + return (not self._readonly) and self.getconfboolean('createfolders', + True) def makefolder(self, foldername): """Create a new folder.""" @@ -182,7 +184,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): Configuring nametrans on BOTH repositories could lead to infinite folder creation cycles.""" - if not self.should_create_folders() and not local_repo.should_create_folders(): + if not self.should_create_folders()\ + and not local_repo.should_create_folders(): # Quick exit if no folder creation is enabled on either side. return @@ -204,7 +207,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): # Apply remote nametrans and fix serparator. local_name = remote_folder.getvisiblename().replace( remote_repo.getsep(), local_repo.getsep()) - if remote_folder.sync_this and local_name not in list(local_hash.keys()): + if remote_folder.sync_this \ + and local_name not in list(local_hash.keys()): try: local_repo.makefolder(local_name) # Need to refresh list. @@ -226,13 +230,15 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): # Apply reverse nametrans and fix serparator. remote_name = local_folder.getvisiblename().replace( local_repo.getsep(), remote_repo.getsep()) - if local_folder.sync_this and remote_name not in list(remote_hash.keys()): + if local_folder.sync_this \ + and remote_name not in list(remote_hash.keys()): # Would the remote filter out the new folder name? In this case # don't create it. if not remote_repo.should_sync_folder(remote_name): - self.ui.debug('', "Not creating folder '%s' (repository '%s" - "') as it would be filtered out on that repository." % - (remote_name, self)) + msg = "Not creating folder '%s' (repository '%s') " \ + "as it would be filtered out on that repository." % \ + (remote_name, self) + self.ui.debug('', msg) continue # nametrans sanity check! Does remote nametrans lead to the @@ -247,23 +253,25 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): # Get IMAPFolder and see if the reverse nametrans works fine. # TODO: getfolder() works only because we succeed in getting # inexisting folders which I would like to change. Take care! - tmp_remotefolder = remote_repo.getfolder(remote_name, decode=False) + tmp_remotefolder = remote_repo.getfolder(remote_name, + decode=False) loop_name = tmp_remotefolder.getvisiblename().replace( remote_repo.getsep(), local_repo.getsep()) if local_name != loop_name: - raise OfflineImapError("INFINITE FOLDER CREATION DETECTED! " - "Folder '%s' (repository '%s') would be created as fold" - "er '%s' (repository '%s'). The latter becomes '%s' in " - "return, leading to infinite folder creation cycles.\n " - "SOLUTION: 1) Do set your nametrans rules on both repos" - "itories so they lead to identical names if applied bac" - "k and forth. 2) Use folderfilter settings on a reposit" - "ory to prevent some folders from being created on the " - "other side." % - (local_folder.getname(), local_repo, remote_name, - remote_repo, - loop_name), - OfflineImapError.ERROR.REPO) + msg = "INFINITE FOLDER CREATION DETECTED! "\ + "Folder '%s' (repository '%s') would be created as " \ + "folder '%s' (repository '%s'). The latter " \ + "becomes '%s' in return, leading to infinite " \ + "folder creation cycles.\n "\ + "SOLUTION: 1) Do set your nametrans rules on both " \ + "repositories so they lead to identical names if " \ + "applied back and forth. " \ + "2) Use folderfilter settings on a repository to " \ + "prevent some folders from being created on the " \ + "other side." % \ + (local_folder.getname(), local_repo, remote_name, + remote_repo, loop_name) + raise OfflineImapError(msg, OfflineImapError.ERROR.REPO) # End sanity check, actually create the folder. try: @@ -271,8 +279,9 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): # Need to refresh list. self.forgetfolders() except OfflineImapError as e: - self.ui.error(e, exc_info()[2], "Creating folder %s on " - "repository %s" % (remote_name, remote_repo)) + msg = "Creating folder %s on repository %s" % \ + (remote_name, remote_repo) + self.ui.error(e, exc_info()[2], msg) raise status_repo.makefolder(local_name.replace( local_repo.getsep(), status_repo.getsep())) From 8504cdc6b8000e2376957ea60e299b27ba34f5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 16:55:20 +0100 Subject: [PATCH 11/47] Base.py long lines style This patch changes long lines (>80 chars) to lines <80 chars. The patch only changes the style. --- offlineimap/folder/Base.py | 66 +++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/offlineimap/folder/Base.py b/offlineimap/folder/Base.py index 7445875..366570d 100644 --- a/offlineimap/folder/Base.py +++ b/offlineimap/folder/Base.py @@ -397,7 +397,8 @@ class BaseFolder: def get_min_uid_file(self): startuiddir = os.path.join(self.config.getmetadatadir(), - 'Repository-' + self.repository.name, 'StartUID') + 'Repository-' + self.repository.name, + 'StartUID') if not os.path.exists(startuiddir): os.mkdir(startuiddir, 0o700) return os.path.join(startuiddir, self.getfolderbasename()) @@ -594,8 +595,8 @@ class BaseFolder: def addmessageheader(self, content, linebreak, headername, headervalue): """Adds new header to the provided message. - WARNING: This function is a bit tricky, and modifying it in the wrong way, - may easily lead to data-loss. + WARNING: This function is a bit tricky, and modifying it in the wrong + way, may easily lead to data-loss. Arguments: - content: message content, headers and body as a single string @@ -605,8 +606,8 @@ class BaseFolder: .. note:: - The following documentation will not get displayed correctly after being - processed by Sphinx. View the source of this method to read it. + The following documentation will not get displayed correctly after + being processed by Sphinx. View the source of this method to read it. This has to deal with strange corner cases where the header is missing or empty. Here are illustrations for all the cases, @@ -659,7 +660,8 @@ class BaseFolder: self.ui.debug('', 'addmessageheader: headers were missing') else: self.ui.debug('', - 'addmessageheader: headers end at position %d' % insertionpoint) + 'addmessageheader: headers end at position %d' % + insertionpoint) mark = '==>EOH<==' contextstart = max(0, insertionpoint - 100) contextend = min(len(content), insertionpoint + 100) @@ -693,9 +695,11 @@ class BaseFolder: self.ui.debug('', 'addmessageheader: insertionpoint = %d' % insertionpoint) headers = content[0:insertionpoint] - self.ui.debug('', 'addmessageheader: headers = %s' % repr(headers)) + self.ui.debug('', + 'addmessageheader: headers = %s' % repr(headers)) new_header = prefix + ("%s: %s" % (headername, headervalue)) + suffix - self.ui.debug('', 'addmessageheader: new_header = %s' % repr(new_header)) + self.ui.debug('', + 'addmessageheader: new_header = %s' % repr(new_header)) return headers + new_header + content[insertionpoint:] def __find_eoh(self, content): @@ -746,7 +750,8 @@ class BaseFolder: - contents: message itself - name: name of the header to be searched - Returns: list of header values or empty list if no such header was found. + Returns: list of header values or empty list if no such header was + found. """ self.ui.debug('', 'getmessageheaderlist: called to get %s' % name) @@ -769,7 +774,8 @@ class BaseFolder: if type(header_list) != type([]): header_list = [header_list] - self.ui.debug('', 'deletemessageheaders: called to delete %s' % header_list) + self.ui.debug('', + 'deletemessageheaders: called to delete %s' % header_list) if not len(header_list): return content @@ -783,7 +789,8 @@ class BaseFolder: for h in headers.split('\n'): keep_it = True for trim_h in header_list: - if len(h) > len(trim_h) and h[0:len(trim_h) + 1] == (trim_h + ":"): + if len(h) > len(trim_h) \ + and h[0:len(trim_h) + 1] == (trim_h + ":"): keep_it = False break if keep_it: @@ -873,9 +880,10 @@ class BaseFolder: # IMAP servers ... self.deletemessage(uid) else: - raise OfflineImapError("Trying to save msg (uid %d) on folder " - "%s returned invalid uid %d" % (uid, dstfolder.getvisiblename(), - new_uid), OfflineImapError.ERROR.MESSAGE) + msg = "Trying to save msg (uid %d) on folder " \ + "%s returned invalid uid %d" % \ + (uid, dstfolder.getvisiblename(), new_uid) + raise OfflineImapError(msg, OfflineImapError.ERROR.MESSAGE) except KeyboardInterrupt: # Bubble up CTRL-C. raise except OfflineImapError as e: @@ -884,7 +892,8 @@ class BaseFolder: self.ui.error(e, exc_info()[2]) except Exception as e: self.ui.error(e, exc_info()[2], - msg="Copying message %s [acc: %s]" % (uid, self.accountname)) + msg="Copying message %s [acc: %s]" % + (uid, self.accountname)) raise # Raise on unknown errors, so we can fix those. def __syncmessagesto_copy(self, dstfolder, statusfolder): @@ -929,24 +938,28 @@ class BaseFolder: break if uid == 0: - self.ui.warn("Assertion that UID != 0 failed; ignoring message.") + msg = "Assertion that UID != 0 failed; ignoring message." + self.ui.warn(msg) continue if uid > 0 and dstfolder.uidexists(uid): - # dstfolder has message with that UID already, only update status. + # dstfolder has message with that UID already, + # only update status. flags = self.getmessageflags(uid) rtime = self.getmessagetime(uid) statusfolder.savemessage(uid, None, flags, rtime) continue - self.ui.copyingmessage(uid, num + 1, num_to_copy, self, dstfolder) + self.ui.copyingmessage(uid, num + 1, num_to_copy, self, + dstfolder) # Exceptions are caught in copymessageto(). if self.suggeststhreads(): self.waitforthread() thread = threadutil.InstanceLimitedThread( self.getinstancelimitnamespace(), target=self.copymessageto, - name="Copy message from %s:%s" % (self.repository, self), + name="Copy message from %s:%s" % (self.repository, + self), args=(uid, dstfolder, statusfolder) ) thread.start() @@ -1015,9 +1028,10 @@ class BaseFolder: # skip them. skipped_keywords = list(selfkeywords - knownkeywords) selfkeywords &= knownkeywords - self.ui.warn("Unknown keywords skipped: %s\n" - "You may want to change your configuration to include " - "those\n" % skipped_keywords) + msg = "Unknown keywords skipped: %s\n" \ + "You may want to change your configuration to include " \ + "those\n" % skipped_keywords + self.ui.warn(msg) keywordletterset = set([keywordmap[keyw] for keyw in selfkeywords]) @@ -1130,11 +1144,11 @@ class BaseFolder: except OfflineImapError as e: if e.severity > OfflineImapError.ERROR.FOLDER: raise - self.ui.error(e, exc_info()[2], "while syncing %s [account %s]" % - (self, self.accountname)) + msg = "while syncing %s [account %s]" % (self, self.accountname) + self.ui.error(e, exc_info()[2], msg) except Exception as e: - self.ui.error(e, exc_info()[2], "while syncing %s [account %s]" % - (self, self.accountname)) + msg = "while syncing %s [account %s]" % (self, self.accountname) + self.ui.error(e, exc_info()[2], msg) raise # Raise unknown Exceptions so we can fix them. def __eq__(self, other): From 9239c804e961ce73182055cb10a68fb985d26d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sat, 31 Oct 2020 16:55:58 +0100 Subject: [PATCH 12/47] Base.py remove redundant parenthesis Just remove these parenthesis --- offlineimap/folder/Base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offlineimap/folder/Base.py b/offlineimap/folder/Base.py index 366570d..a236966 100644 --- a/offlineimap/folder/Base.py +++ b/offlineimap/folder/Base.py @@ -1139,7 +1139,7 @@ class BaseFolder: break try: action(dstfolder, statusfolder) - except (KeyboardInterrupt): + except KeyboardInterrupt: raise except OfflineImapError as e: if e.severity > OfflineImapError.ERROR.FOLDER: From cbfcd38bca7701fa53713c70c98602bff6817f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:16:19 +0100 Subject: [PATCH 13/47] stacktrace.py added docstring Removed warning: C0114: Missing module docstring (missing-module-docstring) --- offlineimap/utils/stacktrace.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/offlineimap/utils/stacktrace.py b/offlineimap/utils/stacktrace.py index ba6bf4f..eacd5e8 100644 --- a/offlineimap/utils/stacktrace.py +++ b/offlineimap/utils/stacktrace.py @@ -1,6 +1,8 @@ -# Copyright 2013 Eygene A. Ryabinkin -# Functions to perform stack tracing (for multithreaded programs -# as well as for single-threaded ones). +""" +Copyright 2013 Eygene A. Ryabinkin +Functions to perform stack tracing (for multithreaded programs +as well as for single-threaded ones). +""" import sys import threading From 3be65bf5dd21754a8b8f596b96f5fa5df93af088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:21:24 +0100 Subject: [PATCH 14/47] pylint renamed variables This patch renames some variables to avoid pylint warning about Variable name "f" doesn't conform to snake_case naming style (invalid-name) f is now file th is now the_en n is now count --- offlineimap/utils/stacktrace.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/offlineimap/utils/stacktrace.py b/offlineimap/utils/stacktrace.py index eacd5e8..c9a4826 100644 --- a/offlineimap/utils/stacktrace.py +++ b/offlineimap/utils/stacktrace.py @@ -12,14 +12,15 @@ import traceback def dump(out): """ Dumps current stack trace into I/O object 'out' """ id2name = {} - for th in threading.enumerate(): - id2name[th.ident] = th.name - n = 0 + for th_en in threading.enumerate(): + id2name[th_en.ident] = th_en.name + + count = 0 for i, stack in list(sys._current_frames().items()): - out.write("\n# Thread #%d (id=%d), %s\n" % (n, i, id2name[i])) - n = n + 1 - for f, lno, name, line in traceback.extract_stack(stack): - out.write('File: "%s", line %d, in %s' % (f, lno, name)) + out.write("\n# Thread #%d (id=%d), %s\n" % (count, i, id2name[i])) + count = count + 1 + for file, lno, name, line in traceback.extract_stack(stack): + out.write('File: "%s", line %d, in %s' % (file, lno, name)) if line: out.write(" %s" % (line.strip())) out.write("\n") From 9f34b14f7221c70d2826beb963f3d40986e43dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:22:44 +0100 Subject: [PATCH 15/47] const.py added docstring Remove pylint warning about C0114: Missing module docstring (missing-module-docstring) --- offlineimap/utils/const.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/offlineimap/utils/const.py b/offlineimap/utils/const.py index b8300bb..56a6551 100644 --- a/offlineimap/utils/const.py +++ b/offlineimap/utils/const.py @@ -1,8 +1,9 @@ -# Copyright (C) 2013-2014 Eygene A. Ryabinkin and contributors -# -# Collection of classes that implement const-like behaviour -# for various objects. +""" +Copyright (C) 2013-2014 Eygene A. Ryabinkin and contributors +Collection of classes that implement const-like behaviour +for various objects. +""" import copy From 4e31762ec61b12e11f9cb2721b16131d8ee1d2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:23:28 +0100 Subject: [PATCH 16/47] distro_utils.py added docstring Remove pylint warning about C0114: Missing module docstring (missing-module-docstring) --- offlineimap/utils/distro_utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/offlineimap/utils/distro_utils.py b/offlineimap/utils/distro_utils.py index 5b1cbac..5aa62d5 100644 --- a/offlineimap/utils/distro_utils.py +++ b/offlineimap/utils/distro_utils.py @@ -1,7 +1,8 @@ -# Copyright 2006-2018 Eygene A. Ryabinkin & contributors. -# -# Module that supports distribution-specific functions. +""" +Copyright 2006-2018 Eygene A. Ryabinkin & contributors. +Module that supports distribution-specific functions. +""" import platform import os From b51fa3b9f661eed182e26a292ce7909c361d1be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:29:15 +0100 Subject: [PATCH 17/47] distro_utils.py get dictionary value using get This patch use get to get the value of os_name. Else, None is get. --- offlineimap/utils/distro_utils.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/offlineimap/utils/distro_utils.py b/offlineimap/utils/distro_utils.py index 5aa62d5..799f4e6 100644 --- a/offlineimap/utils/distro_utils.py +++ b/offlineimap/utils/distro_utils.py @@ -69,12 +69,8 @@ def get_os_sslcertfile_searchpath(): Returned value of None means that there is no search path at all. """ - os_name = get_os_name() - - location = None - if os_name in __DEF_OS_LOCATIONS: - location = __DEF_OS_LOCATIONS[os_name] + location = __DEF_OS_LOCATIONS.get(os_name, None) return location From e5f0f1033444478ccb99f05d9d71d5f1f315ee04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:31:47 +0100 Subject: [PATCH 18/47] distro_utils.py renamed variable f The variable f is renamed to l_file to avoid pylint warning: utils/distro_utils.py:95:8: C0103: Variable name "f" doesn't conform to snake_case naming style (invalid-name) --- offlineimap/utils/distro_utils.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/offlineimap/utils/distro_utils.py b/offlineimap/utils/distro_utils.py index 799f4e6..9183045 100644 --- a/offlineimap/utils/distro_utils.py +++ b/offlineimap/utils/distro_utils.py @@ -89,9 +89,10 @@ def get_os_sslcertfile(): if location is None: return None - 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 + for l_file in location: + assert isinstance(l_file, str) + if os.path.exists(l_file) and (os.path.isfile(l_file) or + os.path.islink(l_file)): + return l_file return None From d50a28a68fd5e9c8a31e9a292f431402120bc09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:43:16 +0100 Subject: [PATCH 19/47] repository add docstring to files This patch includes the docstrings for all files, removing the pylint warning --- offlineimap/repository/Base.py | 31 +++++++++++----------- offlineimap/repository/Gmail.py | 36 ++++++++++++++------------ offlineimap/repository/GmailMaildir.py | 36 ++++++++++++++------------ offlineimap/repository/IMAP.py | 33 +++++++++++------------ offlineimap/repository/LocalStatus.py | 33 +++++++++++------------ offlineimap/repository/Maildir.py | 34 ++++++++++++------------ offlineimap/repository/__init__.py | 31 +++++++++++----------- 7 files changed, 121 insertions(+), 113 deletions(-) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index 483d743..fdc3413 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -1,21 +1,20 @@ -""" Base repository support """ +""" Base repository support +Copyright (C) 2002-2017 John Goerzen & contributors -# Copyright (C) 2002-2017 John Goerzen & contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" import re import os.path from sys import exc_info diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index 4bb4f8b..ef9b2eb 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -1,20 +1,22 @@ -# Gmail IMAP repository support -# Copyright (C) 2008-2016 Riccardo Murri & -# contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Gmail IMAP repository support +Copyright (C) 2008-2016 Riccardo Murri & +contributors + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" from offlineimap.repository.IMAP import IMAPRepository from offlineimap import folder, OfflineImapError diff --git a/offlineimap/repository/GmailMaildir.py b/offlineimap/repository/GmailMaildir.py index 3ab8874..b393cb7 100644 --- a/offlineimap/repository/GmailMaildir.py +++ b/offlineimap/repository/GmailMaildir.py @@ -1,20 +1,22 @@ -# Maildir repository support -# Copyright (C) 2002-2015 John Goerzen & contributors -# -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Maildir repository support +Copyright (C) 2002-2015 John Goerzen & contributors + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" from offlineimap.repository.Maildir import MaildirRepository from offlineimap.folder.GmailMaildir import GmailMaildirFolder diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 0612f9d..66fa1c8 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -1,21 +1,22 @@ -""" IMAP repository support """ +""" +IMAP repository support -# Copyright (C) 2002-2019 John Goerzen & contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +Copyright (C) 2002-2019 John Goerzen & contributors + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + 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 import netrc import errno diff --git a/offlineimap/repository/LocalStatus.py b/offlineimap/repository/LocalStatus.py index d156498..1df8906 100644 --- a/offlineimap/repository/LocalStatus.py +++ b/offlineimap/repository/LocalStatus.py @@ -1,20 +1,21 @@ -# Local status cache repository support -# Copyright (C) 2002-2017 John Goerzen & contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Local status cache repository support +Copyright (C) 2002-2017 John Goerzen & contributors + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + 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 offlineimap.folder.LocalStatus import LocalStatusFolder diff --git a/offlineimap/repository/Maildir.py b/offlineimap/repository/Maildir.py index 9d9789e..39e14b5 100644 --- a/offlineimap/repository/Maildir.py +++ b/offlineimap/repository/Maildir.py @@ -1,20 +1,22 @@ -# Maildir repository support -# Copyright (C) 2002-2015 John Goerzen & contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Maildir repository support +Copyright (C) 2002-2015 John Goerzen & contributors + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + 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 offlineimap import folder from offlineimap.ui import getglobalui diff --git a/offlineimap/repository/__init__.py b/offlineimap/repository/__init__.py index 171f6aa..bda464d 100644 --- a/offlineimap/repository/__init__.py +++ b/offlineimap/repository/__init__.py @@ -1,19 +1,20 @@ -# Copyright (C) 2002-2016 John Goerzen & contributors. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Copyright (C) 2002-2016 John Goerzen & contributors. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" from sys import exc_info from configparser import NoSectionError from offlineimap.repository.IMAP import IMAPRepository, MappedIMAPRepository From 4198fa8201a009c93d6ffb3e0a2272084e2e375e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:51:03 +0100 Subject: [PATCH 20/47] Gmail.py else statement not needed We don't need speficify the else here. Always is else. --- offlineimap/repository/Gmail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index ef9b2eb..ed9b2d4 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -73,8 +73,8 @@ class GmailRepository(IMAPRepository): if port is None: return 993 - else: - return port + + return port def getssl(self): ssl = self.getconfboolean('ssl', None) From 0454e3e2f1a396119f3c64dda3007d9459a83e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:53:08 +0100 Subject: [PATCH 21/47] Gmail.py swap if block I swapped this if - else block, with the "is not". Code now is clear. --- offlineimap/repository/Gmail.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index ed9b2d4..b04a92f 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -71,10 +71,10 @@ class GmailRepository(IMAPRepository): port = super(GmailRepository, self).getport() - if port is None: - return 993 + if port is not None: + return port - return port + return 993 def getssl(self): ssl = self.getconfboolean('ssl', None) From fc2055de8caecba1d97dd6101471f8f58c81671c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:54:16 +0100 Subject: [PATCH 22/47] Gmail.py else statement not needed Always is else here. --- offlineimap/repository/Gmail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index b04a92f..1d8bd38 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -84,8 +84,8 @@ class GmailRepository(IMAPRepository): # GMail. Maybe this should look more similar to gethost & # we could just rely on the global "ssl = yes" default. return True - else: - return ssl + + return ssl def getpreauthtunnel(self): return None From 3f7e9fe1bd8610ca92c616cb8b27365983b7570a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 08:57:43 +0100 Subject: [PATCH 23/47] Gmail.py Changed comments to docstring This patch changes the comments in these functions to docstrings and remove pylint warnings. --- offlineimap/repository/Gmail.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index 1d8bd38..e9737e9 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -98,12 +98,16 @@ class GmailRepository(IMAPRepository): return folder.Gmail.GmailFolder def gettrashfolder(self): - # Where deleted mail should be moved + """ + Where deleted mail should be moved + """ return self.getconf('trashfolder', '[Gmail]/Trash') def getspamfolder(self): - # Depending on the IMAP settings (Settings -> Forwarding and - # POP/IMAP -> IMAP Access -> "When I mark a message in IMAP as - # deleted") GMail might also deletes messages upon EXPUNGE in - # the Spam folder. + """ + Depending on the IMAP settings (Settings -> Forwarding and + POP/IMAP -> IMAP Access -> "When I mark a message in IMAP as + deleted") GMail might also deletes messages upon EXPUNGE in + the Spam folder. + """ return self.getconf('spamfolder', '[Gmail]/Spam') From c2fce5de3854fa5a4d5eb3628e6b1f0520e9d3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:02:09 +0100 Subject: [PATCH 24/47] Gmail.py removed parent class in super calls In Python 3 we don't need specify the class for these calls, the MRO find it. --- offlineimap/repository/Gmail.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index e9737e9..d0b9435 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -40,7 +40,7 @@ class GmailRepository(IMAPRepository): We first check the usual IMAP settings, and then fall back to imap.gmail.com if nothing is specified.""" try: - return super(GmailRepository, self).gethost() + return super().gethost() except OfflineImapError: # Nothing was configured, cache and return hardcoded # one. See the parent class (IMAPRepository) for how this @@ -55,7 +55,7 @@ class GmailRepository(IMAPRepository): https://accounts.google.com/o/oauth2/token if nothing is specified.""" - url = super(GmailRepository, self).getoauth2_request_url() + url = super().getoauth2_request_url() if url is None: # Nothing was configured, cache and return hardcoded one. self.setoauth2_request_url("https://accounts.google.com/o/oauth2/token") @@ -69,7 +69,7 @@ class GmailRepository(IMAPRepository): This Gmail implementation first checks for the usual IMAP settings and falls back to 993 if nothing is specified.""" - port = super(GmailRepository, self).getport() + port = super().getport() if port is not None: return port From caea1b7baa710b483b5aa9d48bceaf185709a0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:03:37 +0100 Subject: [PATCH 25/47] GmailMaildir.py included class docstring Only added docstring for the class. --- offlineimap/repository/GmailMaildir.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/offlineimap/repository/GmailMaildir.py b/offlineimap/repository/GmailMaildir.py index b393cb7..d87fc1c 100644 --- a/offlineimap/repository/GmailMaildir.py +++ b/offlineimap/repository/GmailMaildir.py @@ -23,6 +23,9 @@ from offlineimap.folder.GmailMaildir import GmailMaildirFolder class GmailMaildirRepository(MaildirRepository): + """ + GMail Maildir Repository Class + """ def __init__(self, reposname, account): """Initialize a MaildirRepository object. Takes a path name to the directory holding all the Maildir directories.""" From 5f338454ee472e36cfbe81376741f8bd2f52e840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:06:35 +0100 Subject: [PATCH 26/47] GmailMaildir.py Removed parent class for super call The super() call in Python 3 does not need the parent class. The MRO get it. --- offlineimap/repository/GmailMaildir.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/offlineimap/repository/GmailMaildir.py b/offlineimap/repository/GmailMaildir.py index d87fc1c..a820696 100644 --- a/offlineimap/repository/GmailMaildir.py +++ b/offlineimap/repository/GmailMaildir.py @@ -29,8 +29,7 @@ class GmailMaildirRepository(MaildirRepository): def __init__(self, reposname, account): """Initialize a MaildirRepository object. Takes a path name to the directory holding all the Maildir directories.""" - - super(GmailMaildirRepository, self).__init__(reposname, account) + super().__init__(reposname, account) def getfoldertype(self): return GmailMaildirFolder From e12a70212806eef40d0056e9bbd111ecbff145a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:13:17 +0100 Subject: [PATCH 27/47] GmailMaildir.py Removed __init__ First, in Python 3 we don't need call the super().__init__ explicitly, because Python does it. So, we can remove the line: super().__init__(reposname, account) If we leafe the method __init__ empty, the parent __init__ method is not called, we need remove the __init__ and then Python uses the parent __init__ method. --- offlineimap/repository/GmailMaildir.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/offlineimap/repository/GmailMaildir.py b/offlineimap/repository/GmailMaildir.py index a820696..8522e21 100644 --- a/offlineimap/repository/GmailMaildir.py +++ b/offlineimap/repository/GmailMaildir.py @@ -26,10 +26,5 @@ class GmailMaildirRepository(MaildirRepository): """ GMail Maildir Repository Class """ - def __init__(self, reposname, account): - """Initialize a MaildirRepository object. Takes a path name - to the directory holding all the Maildir directories.""" - super().__init__(reposname, account) - def getfoldertype(self): return GmailMaildirFolder From 5c6e95103e72f1efca5973632cf9fe14e6dc2aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:21:08 +0100 Subject: [PATCH 28/47] Maildir.py added docstrings This patch adds the docstring for the class and for two methods. --- offlineimap/repository/Maildir.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/offlineimap/repository/Maildir.py b/offlineimap/repository/Maildir.py index 39e14b5..53699fc 100644 --- a/offlineimap/repository/Maildir.py +++ b/offlineimap/repository/Maildir.py @@ -25,6 +25,9 @@ from offlineimap.repository.Base import BaseRepository class MaildirRepository(BaseRepository): + """ + Maildir Repository Class + """ def __init__(self, reposname, account): """Initialize a MaildirRepository object. Takes a path name to the directory holding all the Maildir directories.""" @@ -77,6 +80,15 @@ class MaildirRepository(BaseRepository): return self.getconf_xform('localfolders', xforms) def debug(self, msg): + """ + Debug function for the message. It calls the ui.debug function and + prepends the string 'maildir'. + Args: + msg: Message to send to the debug + + Returns: None + + """ self.ui.debug('maildir', msg) def getsep(self): @@ -211,6 +223,12 @@ class MaildirRepository(BaseRepository): return self.folders def getfoldertype(self): + """ + Returns a folder MaildirFolder type. + + Returns: A MaildirFolder class + + """ return folder.Maildir.MaildirFolder def forgetfolders(self): From 646cb4354b95d7aa6f920001d332e2b2827360dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:26:42 +0100 Subject: [PATCH 29/47] Maildir.py renamed variable names This patch renames some variables to avoid these warnings: Variable name "e" doesn't conform to snake_case naming style (invalid-name) --- offlineimap/repository/Maildir.py | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/offlineimap/repository/Maildir.py b/offlineimap/repository/Maildir.py index 53699fc..89886ad 100644 --- a/offlineimap/repository/Maildir.py +++ b/offlineimap/repository/Maildir.py @@ -46,19 +46,19 @@ class MaildirRepository(BaseRepository): # Create the keyword->char mapping self.keyword2char = dict() - for c in 'abcdefghijklmnopqrstuvwxyz': - confkey = 'customflag_' + c + for char in 'abcdefghijklmnopqrstuvwxyz': + confkey = 'customflag_' + char keyword = self.getconf(confkey, None) if keyword is not None: - self.keyword2char[keyword] = c + self.keyword2char[keyword] = char def _append_folder_atimes(self, foldername): """Store the atimes of a folder's new|cur in self.folder_atimes""" - p = os.path.join(self.root, foldername) - new = os.path.join(p, 'new') - cur = os.path.join(p, 'cur') - atimes = (p, os.path.getatime(new), os.path.getatime(cur)) + path = os.path.join(self.root, foldername) + new = os.path.join(path, 'new') + cur = os.path.join(path, 'cur') + atimes = (path, os.path.getatime(new), os.path.getatime(cur)) self.folder_atimes.append(atimes) def restore_atime(self): @@ -129,16 +129,16 @@ class MaildirRepository(BaseRepository): self.debug("makefolder: calling makedirs '%s'" % full_path) try: os.makedirs(full_path, 0o700) - except OSError as e: - if e.errno == 17 and os.path.isdir(full_path): + except OSError as exc: + if exc.errno == 17 and os.path.isdir(full_path): self.debug("makefolder: '%s' already a directory" % foldername) else: raise for subdir in ['cur', 'new', 'tmp']: try: os.mkdir(os.path.join(full_path, subdir), 0o700) - except OSError as e: - if e.errno == 17 and os.path.isdir(full_path): + except OSError as exc: + if exc.errno == 17 and os.path.isdir(full_path): self.debug("makefolder: '%s' already has subdir %s" % (foldername, subdir)) else: @@ -156,9 +156,9 @@ class MaildirRepository(BaseRepository): # getfolders() will scan and cache the values *if* necessary folders = self.getfolders() - for f in folders: - if foldername == f.name: - return f + for foldr in folders: + if foldername == foldr.name: + return foldr raise OfflineImapError("getfolder() asked for a nonexisting " "folder '%s'." % foldername, OfflineImapError.ERROR.FOLDER) @@ -207,9 +207,9 @@ class MaildirRepository(BaseRepository): self.debug(" This is maildir folder '%s'." % foldername) if self.getconfboolean('restoreatime', False): self._append_folder_atimes(foldername) - fd = self.getfoldertype()(self.root, foldername, - self.getsep(), self) - retval.append(fd) + file_desc = self.getfoldertype()(self.root, foldername, + self.getsep(), self) + retval.append(file_desc) if self.getsep() == '/' and dirname != '': # Recursively check sub-directories for folders too. From 62bfead5e4fdbd6da94b501dc690835afbb59815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:29:31 +0100 Subject: [PATCH 30/47] Maildir.py split long lines This patch split long lines in less 80 chars. --- offlineimap/repository/Maildir.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/offlineimap/repository/Maildir.py b/offlineimap/repository/Maildir.py index 89886ad..b147384 100644 --- a/offlineimap/repository/Maildir.py +++ b/offlineimap/repository/Maildir.py @@ -37,7 +37,8 @@ class MaildirRepository(BaseRepository): self.root = self.getlocalroot() self.folders = None self.ui = getglobalui() - self.debug("MaildirRepository initialized, sep is %s" % repr(self.getsep())) + self.debug("MaildirRepository initialized, sep is %s" % + repr(self.getsep())) self.folder_atimes = [] # Create the top-level folder if it doesn't exist @@ -121,8 +122,10 @@ class MaildirRepository(BaseRepository): assert component not in ['new', 'cur', 'tmp'], \ "When using nested folders (/ as a Maildir separator), " \ "folder names may not contain 'new', 'cur', 'tmp'." - assert foldername.find('../') == -1, "Folder names may not contain ../" - assert not foldername.startswith('/'), "Folder names may not begin with /" + assert foldername.find('../') == -1, \ + "Folder names may not contain ../" + assert not foldername.startswith('/'), \ + "Folder names may not begin with /" # If we're using hierarchical folders, it's possible that # sub-folders may be created before higher-up ones. @@ -160,7 +163,8 @@ class MaildirRepository(BaseRepository): if foldername == foldr.name: return foldr raise OfflineImapError("getfolder() asked for a nonexisting " - "folder '%s'." % foldername, OfflineImapError.ERROR.FOLDER) + "folder '%s'." % foldername, + OfflineImapError.ERROR.FOLDER) def _getfolders_scandir(self, root, extension=None): """Recursively scan folder 'root'; return a list of MailDirFolder @@ -214,7 +218,8 @@ class MaildirRepository(BaseRepository): if self.getsep() == '/' and dirname != '': # Recursively check sub-directories for folders too. retval.extend(self._getfolders_scandir(root, foldername)) - self.debug("_GETFOLDERS_SCANDIR RETURNING %s" % repr([x.getname() for x in retval])) + self.debug("_GETFOLDERS_SCANDIR RETURNING %s" % + repr([x.getname() for x in retval])) return retval def getfolders(self): From 20e33237184c3a18d83805e3ab0110b9adf2f2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:47:17 +0100 Subject: [PATCH 31/47] Base.py added docstrings This patch adds multiple docstrings. --- offlineimap/repository/Base.py | 82 +++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index fdc3413..99d6e66 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -25,6 +25,9 @@ from offlineimap.error import OfflineImapError class BaseRepository(CustomConfig.ConfigHelperMixin): + """ + Base Class for Repository + """ def __init__(self, reposname, account): self.ui = getglobalui() self.account = account @@ -83,15 +86,39 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): pass def holdordropconnections(self): + """ + Hold the drop connections functions. + + Returns: None + + """ pass def dropconnections(self): + """ + Drop connections functions. + + Returns: None + + """ pass def getaccount(self): + """ + This patch returns the account + + Returns: The account + + """ return self.account def getname(self): + """ + Get the repository name + + Returns: String with the repository name + + """ return self.name def __str__(self): @@ -104,9 +131,21 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): return self._accountname def getuiddir(self): + """ + The FolderValidity directory + + Returns: The FolderValidity directory + + """ return self.uiddir def getmapdir(self): + """ + Get the map dir (UIDMapping) + + Returns: The UIDMapping directory + + """ return self.mapdir # Interface from CustomConfig.ConfigHelperMixin @@ -124,6 +163,12 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): return self._readonly def getlocaleval(self): + """ + Get the account local eval. + + Returns: LocalEval class for account. + + """ return self.account.getlocaleval() def getfolders(self): @@ -138,9 +183,25 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): pass def getsep(self): + """ + Get the separator. + + This function is not implemented. + + Returns: None + + """ raise NotImplementedError def getkeywordmap(self): + """ + Get the keyword map. + + This function is not implemented. + + Returns: None + + """ raise NotImplementedError def should_sync_folder(self, fname): @@ -158,11 +219,30 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): True) def makefolder(self, foldername): - """Create a new folder.""" + """ + Create a new folder. + This function is not implemented + Args: + foldername: Folder to create + + Returns: None + + """ raise NotImplementedError def deletefolder(self, foldername): + """ + Remove the selected folder. + + This function is not implemented + + Args: + foldername: Folder to delete + + Returns: None + + """ raise NotImplementedError def getfolder(self, foldername, decode=True): From e25bd7b48b60f4da94366f32dbb69b5ffcd6855c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:49:28 +0100 Subject: [PATCH 32/47] Base.py removed unused pass This patch removes these pass calls, because we have the docstrings and then we don't need include it. --- offlineimap/repository/Base.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index 99d6e66..459fa1b 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -73,8 +73,6 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): False), applies only to local Maildir mailboxes and does nothing on all other repository types.""" - pass - def connect(self): """Establish a connection to the remote, if necessary. This exists so that IMAP connections can all be established up front, gathering @@ -83,8 +81,6 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): trap in order to validate the password, and that's the point of this function.""" - pass - def holdordropconnections(self): """ Hold the drop connections functions. @@ -92,7 +88,6 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): Returns: None """ - pass def dropconnections(self): """ @@ -101,7 +96,6 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): Returns: None """ - pass def getaccount(self): """ @@ -180,8 +174,6 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): """Forgets the cached list of folders, if any. Useful to run after a sync run.""" - pass - def getsep(self): """ Get the separator. @@ -372,14 +364,10 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): def startkeepalive(self): """The default implementation will do nothing.""" - pass - def stopkeepalive(self): """Stop keep alive, but don't bother waiting for the threads to terminate.""" - pass - def getlocalroot(self): """ Local root folder for storing messages. Will not be set for remote repositories.""" From 1d93f90db516eb4c739e6efba661bcd7356b96d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 09:55:25 +0100 Subject: [PATCH 33/47] Base.py renamed exception variable e to exc This variable is renamed twice to avoid this warning: C0103: Attribute name "e" doesn't conform to snake_case naming style (invalid-name) --- offlineimap/repository/Base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index 459fa1b..1418d83 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -284,8 +284,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): local_repo.makefolder(local_name) # Need to refresh list. local_repo.forgetfolders() - except OfflineImapError as e: - self.ui.error(e, exc_info()[2], + except OfflineImapError as exc: + self.ui.error(exc, exc_info()[2], "Creating folder %s on repository %s" % (local_name, local_repo)) raise @@ -349,10 +349,10 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): remote_repo.makefolder(remote_name) # Need to refresh list. self.forgetfolders() - except OfflineImapError as e: + except OfflineImapError as exc: msg = "Creating folder %s on repository %s" % \ (remote_name, remote_repo) - self.ui.error(e, exc_info()[2], msg) + self.ui.error(exc, exc_info()[2], msg) raise status_repo.makefolder(local_name.replace( local_repo.getsep(), status_repo.getsep())) From b175f7a69852f1d4101629ec1915e7378bbabec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 10:00:02 +0100 Subject: [PATCH 34/47] Base.py sync_folder_structure returns always None The function sync_folder_structure is only used in the accounts.py file: kix@inle:~/src/offlineimap3/offlineimap$ rgrep sync_folder_structure * accounts.py: remoterepos.sync_folder_structure(localrepos, statusrepos) repository/Base.py: def sync_folder_structure(self, local_repo, status_repo): kix@inle:~/src/offlineimap3/offlineimap$ The returned value is not used. We have this warning: R1710: Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements) Because is not returning anything here, but is returning None at the function end. We can include this None here safely. --- offlineimap/repository/Base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index 1418d83..af35d49 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -258,7 +258,7 @@ class BaseRepository(CustomConfig.ConfigHelperMixin): if not self.should_create_folders()\ and not local_repo.should_create_folders(): # Quick exit if no folder creation is enabled on either side. - return + return None remote_repo = self remote_hash, local_hash = {}, {} From 6b9f37e31705712fd57186b5adb95595b39fab82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 10:04:18 +0100 Subject: [PATCH 35/47] Gmail.py use hardcoded url variable 1/2 This patch sets the url variable to the hardcoded value. Then call the self.setoauth2_request_url(url) function. --- offlineimap/repository/Gmail.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index d0b9435..6509701 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -58,7 +58,8 @@ class GmailRepository(IMAPRepository): url = super().getoauth2_request_url() if url is None: # Nothing was configured, cache and return hardcoded one. - self.setoauth2_request_url("https://accounts.google.com/o/oauth2/token") + url = "https://accounts.google.com/o/oauth2/token" + self.setoauth2_request_url(url) else: self.setoauth2_request_url(url) return self.oauth2_request_url From 852bc9acd9a24ba79731d8a34fb805ac16c5df6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 10:06:32 +0100 Subject: [PATCH 36/47] Gmail.py use hardcoded url variable 2/2 Because the call in the if and in the else blocks is the same, we can move it outside the conditional block. Code now is clear. --- offlineimap/repository/Gmail.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index 6509701..b94726b 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -57,11 +57,11 @@ class GmailRepository(IMAPRepository): url = super().getoauth2_request_url() if url is None: - # Nothing was configured, cache and return hardcoded one. + # Nothing was configured, use a hardcoded one. url = "https://accounts.google.com/o/oauth2/token" - self.setoauth2_request_url(url) - else: - self.setoauth2_request_url(url) + + self.setoauth2_request_url(url) + return self.oauth2_request_url def getport(self): From 316fcfbbee3dc5079a33e516853ea44dde1005c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:31:18 +0100 Subject: [PATCH 37/47] IMAP.py docstrings This patch includes the docstrings for IMAP.py file. --- offlineimap/repository/IMAP.py | 206 ++++++++++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 3 deletions(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 66fa1c8..d9f6c4a 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -30,6 +30,9 @@ from offlineimap.utils.distro_utils import get_os_sslcertfile, \ class IMAPRepository(BaseRepository): + """ + IMAP Repository Class, children of BaseRepository + """ def __init__(self, reposname, account): self.idlefolders = None BaseRepository.__init__(self, reposname, account) @@ -93,11 +96,25 @@ class IMAPRepository(BaseRepository): return self.copy_ignore_eval(foldername) def getholdconnectionopen(self): + """ + Value of holdconnectionopen or False if it is not set + + Returns: Value of holdconnectionopen or False if it is not set + + """ if self.getidlefolders(): return True return self.getconfboolean("holdconnectionopen", False) def getkeepalive(self): + """ + This function returns the keepalive value. If it is not set, then + check if the getidlefolders is set. If getidlefolders is set, then + returns 29 * 60 + + Returns: keepalive value + + """ num = self.getconfint("keepalive", 0) if num == 0 and self.getidlefolders(): return 29 * 60 @@ -156,6 +173,13 @@ class IMAPRepository(BaseRepository): return identity def get_auth_mechanisms(self): + """ + Get the AUTH mechanisms. We have (ranged from the strongest to weakest) + these methods: "GSSAPI", "XOAUTH2", "CRAM-MD5", "PLAIN", "LOGIN" + + Returns: The supported AUTH Methods + + """ supported = ["GSSAPI", "XOAUTH2", "CRAM-MD5", "PLAIN", "LOGIN"] # Mechanisms are ranged from the strongest to the # weakest ones. @@ -176,6 +200,12 @@ class IMAPRepository(BaseRepository): return mechs def getuser(self): + """ + Returns the remoteusereval or remoteuser or netrc user value. + + Returns: Returns the remoteusereval or remoteuser or netrc user value. + + """ localeval = self.localeval if self.config.has_option(self.getsection(), 'remoteusereval'): @@ -210,6 +240,12 @@ class IMAPRepository(BaseRepository): return netrcentry[0] def getport(self): + """ + Returns remoteporteval value or None if not found. + + Returns: Returns remoteporteval int value or None if not found. + + """ port = None if self.config.has_option(self.getsection(), 'remoteporteval'): @@ -220,16 +256,40 @@ class IMAPRepository(BaseRepository): return self.getconfint('remoteport', None) def getipv6(self): + """ + Returns if IPv6 is set. If not set, then return None + + Returns: Boolean flag if IPv6 is set. + + """ return self.getconfboolean('ipv6', None) def getssl(self): + """ + Get the boolean SSL value. Default is True, used if not found. + + Returns: Get the boolean SSL value. Default is True + + """ return self.getconfboolean('ssl', True) def getsslclientcert(self): + """ + Return the SSL client cert (sslclientcert) or None if not found + + Returns: SSL client key (sslclientcert) or None if not found + + """ xforms = [os.path.expanduser, os.path.expandvars, os.path.abspath] return self.getconf_xform('sslclientcert', xforms, None) def getsslclientkey(self): + """ + Return the SSL client key (sslclientkey) or None if not found + + Returns: SSL client key (sslclientkey) or None if not found + + """ xforms = [os.path.expanduser, os.path.expandvars, os.path.abspath] return self.getconf_xform('sslclientkey', xforms, None) @@ -280,12 +340,30 @@ class IMAPRepository(BaseRepository): return cacertfile def gettlslevel(self): + """ + Returns the TLS level (tls_level). If not set, returns 'tls_compat' + + Returns: TLS level (tls_level). If not set, returns 'tls_compat' + + """ return self.getconf('tls_level', 'tls_compat') def getsslversion(self): + """ + Returns the SSL version. If not set, returns None. + + Returns: SSL version. If not set, returns None. + + """ return self.getconf('ssl_version', None) def getstarttls(self): + """ + Get the value of starttls. If not set, returns True + + Returns: Value of starttls. If not set, returns True + + """ return self.getconfboolean('starttls', True) def get_ssl_fingerprint(self): @@ -299,9 +377,25 @@ class IMAPRepository(BaseRepository): for f in value.split(',') if f] def setoauth2_request_url(self, url): + """ + Set the OAUTH2 URL request. + + Args: + url: OAUTH2 URL request + + Returns: None + + """ self.oauth2_request_url = url def getoauth2_request_url(self): + """ + Returns the OAUTH2 URL request from configuration (oauth2_request_url). + If it is not found, then returns None + + Returns: OAUTH2 URL request (oauth2_request_url) + + """ if self.oauth2_request_url is not None: # Use cached value if possible. return self.oauth2_request_url @@ -309,6 +403,14 @@ class IMAPRepository(BaseRepository): return self.oauth2_request_url def getoauth2_refresh_token(self): + """ + Get the OAUTH2 refresh token from the configuration + (oauth2_refresh_token) + If the access token is not found, then returns None. + + Returns: OAUTH2 refresh token (oauth2_refresh_token) + + """ refresh_token = self.getconf('oauth2_refresh_token', None) if refresh_token is None: refresh_token = self.localeval.eval( @@ -319,6 +421,13 @@ class IMAPRepository(BaseRepository): return refresh_token def getoauth2_access_token(self): + """ + Get the OAUTH2 access token from the configuration (oauth2_access_token) + If the access token is not found, then returns None. + + Returns: OAUTH2 access token (oauth2_access_token) + + """ access_token = self.getconf('oauth2_access_token', None) if access_token is None: access_token = self.localeval.eval( @@ -329,6 +438,13 @@ class IMAPRepository(BaseRepository): return access_token def getoauth2_client_id(self): + """ + Get the OAUTH2 client id (oauth2_client_id) from the configuration. + If not found, returns None + + Returns: OAUTH2 client id (oauth2_client_id) + + """ client_id = self.getconf('oauth2_client_id', None) if client_id is None: client_id = self.localeval.eval( @@ -339,6 +455,13 @@ class IMAPRepository(BaseRepository): return client_id def getoauth2_client_secret(self): + """ + Get the OAUTH2 client secret (oauth2_client_secret) from the + configuration. If it is not found, then returns None. + + Returns: OAUTH2 client secret + + """ client_secret = self.getconf('oauth2_client_secret', None) if client_secret is None: client_secret = self.localeval.eval( @@ -349,18 +472,51 @@ class IMAPRepository(BaseRepository): return client_secret def getpreauthtunnel(self): + """ + Get the value of preauthtunnel. If not found, then returns None. + + Returns: Returns preauthtunnel value. If not found, returns None. + + """ return self.getconf('preauthtunnel', None) def gettransporttunnel(self): + """ + Get the value of transporttunnel. If not found, then returns None. + + Returns: Returns transporttunnel value. If not found, returns None. + + """ return self.getconf('transporttunnel', None) def getreference(self): + """ + Get the reference value in the configuration. If the value is not found + then returns a double quote ("") as string. + + Returns: The reference variable. If not set, then returns '""' + + """ return self.getconf('reference', '""') def getdecodefoldernames(self): + """ + Get the boolean value of decodefoldernames configuration variable, + if the value is not found, returns False. + + Returns: Boolean value of decodefoldernames, else False + + """ return self.getconfboolean('decodefoldernames', False) def getidlefolders(self): + """ + Get the list of idlefolders from configuration. If the value is not + found, returns an empty list. + + Returns: A list of idle folders + + """ if self.idlefolders is None: self.idlefolders = self.localeval.eval( self.getconf('idlefolders', '[]') @@ -368,11 +524,25 @@ class IMAPRepository(BaseRepository): return self.idlefolders def getmaxconnections(self): + """ + Get the maxconnections configuration value from configuration. + If the value is not set, returns 1 connection + + Returns: Integer value of maxconnections configuration variable, else 1 + + """ num1 = len(self.getidlefolders()) num2 = self.getconfint('maxconnections', 1) return max(num1, num2) def getexpunge(self): + """ + Get the expunge configuration value from configuration. + If the value is not set in the configuration, then returns True + + Returns: Boolean value of expunge configuration variable + + """ return self.getconfboolean('expunge', True) def getpassword(self): @@ -438,6 +608,13 @@ class IMAPRepository(BaseRepository): return self.getfoldertype()(self.imapserver, foldername, self, decode) def getfoldertype(self): + """ + This function returns the folder type, in this case + folder.IMAP.IMAPFolder + + Returns: folder.IMAP.IMAPFolder + + """ return folder.IMAP.IMAPFolder def connect(self): @@ -511,12 +688,16 @@ class IMAPRepository(BaseRepository): retval.sort(key=lambda x: str.lower(x.getvisiblename())) else: # do foldersort in a python3-compatible way - # http://bytes.com/topic/python/answers/844614-python-3-sorting-comparison-function + # http://bytes.com/topic/python/answers/ \ + # 844614-python-3-sorting-comparison-function def cmp2key(mycmp): """Converts a cmp= function into a key= function We need to keep cmp functions for backward compatibility""" class K: + """ + Class to compare getvisiblename() between two objects. + """ def __init__(self, obj, *args): self.obj = obj @@ -547,14 +728,19 @@ class IMAPRepository(BaseRepository): self.imapserver.releaseconnection(imapobj) def makefolder(self, foldername): - """Create a folder on the IMAP server + """ + Create a folder on the IMAP server This will not update the list cached in :meth:`getfolders`. You will need to invoke :meth:`forgetfolders` to force new caching when you are done creating folders yourself. - :param foldername: Full path of the folder to be created.""" + Args: + foldername: Full path of the folder to be created + Returns: None + + """ if foldername == '': return @@ -576,6 +762,15 @@ class IMAPRepository(BaseRepository): raise def makefolder_single(self, foldername): + """ + Create a IMAP folder. + + Args: + foldername: Folder's name to create + + Returns: None + + """ self.ui.makefolder(self, foldername) if self.account.dryrun: return @@ -594,5 +789,10 @@ class IMAPRepository(BaseRepository): class MappedIMAPRepository(IMAPRepository): + """ + This subclass of IMAPRepository includes only the method + getfoldertype modified that returns folder.UIDMaps.MappedIMAPFolder + instead of folder.IMAP.IMAPFolder + """ def getfoldertype(self): return folder.UIDMaps.MappedIMAPFolder From f8a5b0b2957857723ac3c946cc41ec22344deba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:40:48 +0100 Subject: [PATCH 38/47] IMAP.py renamed variables This patch renames some variables to avoid warnings like: 'e' doesn't conform to snake_case naming style (invalid-name) --- offlineimap/repository/IMAP.py | 35 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index d9f6c4a..d2f577a 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -142,10 +142,10 @@ class IMAPRepository(BaseRepository): host = self.getconf('remotehosteval') try: host = self.localeval.eval(host) - except Exception as e: + except Exception as exc: raise OfflineImapError( "remotehosteval option for repository " - "'%s' failed:\n%s" % (self, e), + "'%s' failed:\n%s" % (self, exc), OfflineImapError.ERROR.REPO, exc_info()[2]) if host: @@ -190,11 +190,11 @@ class IMAPRepository(BaseRepository): mechs = self.getconflist('auth_mechanisms', r',\s*', default) - for m in mechs: - if m not in supported: + for mech in mechs: + if mech not in supported: raise OfflineImapError("Repository %s: " % self + "unknown authentication mechanism '%s'" - % m, OfflineImapError.ERROR.REPO) + % mech, OfflineImapError.ERROR.REPO) self.ui.debug('imap', "Using authentication mechanisms %s" % mechs) return mechs @@ -572,9 +572,10 @@ class IMAPRepository(BaseRepository): # 3. Read password from file specified in Repository 'remotepassfile'. passfile = self.getconf('remotepassfile', None) if passfile is not None: - fd = open(os.path.expanduser(passfile), 'r', encoding='utf-8') - password = fd.readline().strip() - fd.close() + file_desc = open(os.path.expanduser(passfile), 'r', + encoding='utf-8') + password = file_desc.readline().strip() + file_desc.close() return password.encode('UTF-8') # 4. Read password from ~/.netrc. try: @@ -647,16 +648,16 @@ class IMAPRepository(BaseRepository): finally: self.imapserver.releaseconnection(imapobj) - for s in listresult: - if s is None or (isinstance(s, str) and s == ''): + for fldr in listresult: + if fldr is None or (isinstance(fldr, str) and fldr == ''): # Bug in imaplib: empty strings in results from # literals. TODO: still relevant? continue try: - flags, delim, name = imaputil.imapsplit(s) + flags, delim, name = imaputil.imapsplit(fldr) except ValueError: self.ui.error( - "could not correctly parse server response; got: %s" % s) + "could not correctly parse server response; got: %s" % fldr) raise flaglist = [x.lower() for x in imaputil.flagsplit(flags)] if '\\noselect' in flaglist: @@ -671,11 +672,11 @@ class IMAPRepository(BaseRepository): try: imapobj.select(imaputil.utf8_IMAP(foldername), readonly=True) - except OfflineImapError as e: + except OfflineImapError as exc: # couldn't select this folderinclude, so ignore folder. - if e.severity > OfflineImapError.ERROR.FOLDER: + if exc.severity > OfflineImapError.ERROR.FOLDER: raise - self.ui.error(e, exc_info()[2], + self.ui.error(exc, exc_info()[2], 'Invalid folderinclude:') continue retval.append(self.getfoldertype()( @@ -757,8 +758,8 @@ class IMAPRepository(BaseRepository): for folder_path in folder_paths: try: self.makefolder_single(folder_path) - except OfflineImapError as e: - if '[ALREADYEXISTS]' not in e.reason: + except OfflineImapError as exc: + if '[ALREADYEXISTS]' not in exc.reason: raise def makefolder_single(self, foldername): From 2409fe8f490fbc939fa944786a5ff3260a4eb8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:45:48 +0100 Subject: [PATCH 39/47] IMAP.py removed warning about explicitly re-raising This patch removes this warning: repository/IMAP.py:146:16: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from) --- offlineimap/repository/IMAP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index d2f577a..f09fd28 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -147,7 +147,7 @@ class IMAPRepository(BaseRepository): "remotehosteval option for repository " "'%s' failed:\n%s" % (self, exc), OfflineImapError.ERROR.REPO, - exc_info()[2]) + exc_info()[2]) from exc if host: self._host = host return self._host From 14020a670f026f0f342a9538a2674b9209a70355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:52:51 +0100 Subject: [PATCH 40/47] LocalStatus.py added docstrings This patch adds some docstrings. --- offlineimap/repository/LocalStatus.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/offlineimap/repository/LocalStatus.py b/offlineimap/repository/LocalStatus.py index 1df8906..59554b9 100644 --- a/offlineimap/repository/LocalStatus.py +++ b/offlineimap/repository/LocalStatus.py @@ -25,6 +25,9 @@ from offlineimap.error import OfflineImapError class LocalStatusRepository(BaseRepository): + """ + Local Status Repository Class, child of Base Repository Class + """ def __init__(self, reposname, account): BaseRepository.__init__(self, reposname, account) @@ -58,12 +61,30 @@ class LocalStatusRepository(BaseRepository): return self.LocalStatusFolderClass(foldername, self) # Instantiate. def setup_backend(self, backend): + """ + Setup the backend. + + Args: + backend: backend to use + + Returns: None + + """ if backend in list(self.backends.keys()): self._backend = backend self.root = self.backends[backend]['root'] self.LocalStatusFolderClass = self.backends[backend]['class'] def import_other_backend(self, folder): + """ + Import other backend + + Args: + folder: folder + + Returns: None + + """ for bk, dic in list(self.backends.items()): # Skip folder's own type. if dic['class'] == type(folder): From 3e5832e828fffd2d60d4a172b83b5f3fed8755be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:53:34 +0100 Subject: [PATCH 41/47] LocalStatus.py removed unused pass We don't need this pass because we have the docstring. --- offlineimap/repository/LocalStatus.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/offlineimap/repository/LocalStatus.py b/offlineimap/repository/LocalStatus.py index 59554b9..cb0ecdf 100644 --- a/offlineimap/repository/LocalStatus.py +++ b/offlineimap/repository/LocalStatus.py @@ -152,8 +152,6 @@ class LocalStatusRepository(BaseRepository): the file names that we have available. TODO: need to store a list of folder names somehow?""" - pass - def forgetfolders(self): """Forgets the cached list of folders, if any. Useful to run after a sync run.""" From 8c6de099f973a46d49017f9704a2e7b1fcc6885e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:54:59 +0100 Subject: [PATCH 42/47] LocalStatus.py Renamed variable Variable bk is renamed to bkend to avoid this pylint warning: repository/LocalStatus.py:88:12: C0103: Variable name "bk" doesn't conform to snake_case naming style (invalid-name) --- offlineimap/repository/LocalStatus.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/offlineimap/repository/LocalStatus.py b/offlineimap/repository/LocalStatus.py index cb0ecdf..40d076a 100644 --- a/offlineimap/repository/LocalStatus.py +++ b/offlineimap/repository/LocalStatus.py @@ -85,20 +85,20 @@ class LocalStatusRepository(BaseRepository): Returns: None """ - for bk, dic in list(self.backends.items()): + for bkend, dic in list(self.backends.items()): # Skip folder's own type. if dic['class'] == type(folder): continue repobk = LocalStatusRepository(self.name, self.account) - repobk.setup_backend(bk) # Fake the backend. + repobk.setup_backend(bkend) # Fake the backend. folderbk = dic['class'](folder.name, repobk) # If backend contains data, import it to folder. if not folderbk.isnewfolder(): self.ui._msg("Migrating LocalStatus cache from %s to %s " "status folder for %s:%s" % - (bk, self._backend, self.name, folder.name)) + (bkend, self._backend, self.name, folder.name)) folderbk.cachemessagelist() folder.messagelist = folderbk.messagelist From 0f19b6e63ac777e74db743b1d5aa3e1541f811ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:56:57 +0100 Subject: [PATCH 43/47] __init__.py removed pass This pass is not needed, because we have docstring. --- offlineimap/repository/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/offlineimap/repository/__init__.py b/offlineimap/repository/__init__.py index bda464d..dd36d18 100644 --- a/offlineimap/repository/__init__.py +++ b/offlineimap/repository/__init__.py @@ -84,4 +84,3 @@ class Repository: :param account: :class:`Account` :param reqtype: 'remote', 'local', or 'status' """ - pass From 60104378852dab72503088bb14820099a1822b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 12:58:39 +0100 Subject: [PATCH 44/47] __init__.py added explicit from in raise exceptions Remove the warnings: repository/__init__.py:66:12: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from) repository/__init__.py:74:12: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from) --- offlineimap/repository/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/offlineimap/repository/__init__.py b/offlineimap/repository/__init__.py index dd36d18..e0c387e 100644 --- a/offlineimap/repository/__init__.py +++ b/offlineimap/repository/__init__.py @@ -60,19 +60,19 @@ class Repository: config = account.getconfig() try: repostype = config.get('Repository ' + name, 'type').strip() - except NoSectionError: + except NoSectionError as exc: errstr = ("Could not find section '%s' in configuration. Required " "for account '%s'." % ('Repository %s' % name, account)) raise OfflineImapError(errstr, OfflineImapError.ERROR.REPO, - exc_info()[2]) + exc_info()[2]) from exc try: repo = typemap[repostype] - except KeyError: + except KeyError as exc: errstr = "'%s' repository not supported for '%s' repositories." % \ (repostype, reqtype) raise OfflineImapError(errstr, OfflineImapError.ERROR.REPO, - exc_info()[2]) + exc_info()[2]) from exc return repo(name, account) From f53bee733527eadd003254817da01c422435b558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 13:11:52 +0100 Subject: [PATCH 45/47] Base.py added docstrings Just added docstrings. --- offlineimap/folder/Base.py | 77 ++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/offlineimap/folder/Base.py b/offlineimap/folder/Base.py index a236966..8b98555 100644 --- a/offlineimap/folder/Base.py +++ b/offlineimap/folder/Base.py @@ -1,19 +1,21 @@ -# Base folder support -# Copyright (C) 2002-2016 John Goerzen & contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" +Base folder support +Copyright (C) 2002-2016 John Goerzen & contributors + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + 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.path import re @@ -27,6 +29,9 @@ import offlineimap.accounts class BaseFolder: + """ + Base Folder Class + """ __hash__ = None def __init__(self, name, repository): @@ -130,6 +135,12 @@ class BaseFolder: return self.repository.should_sync_folder(self.ffilter_name) def dofsync(self): + """ + Call and returns _dofsync() + + Returns: Call and returns _dofsync() + + """ return self._dofsync def suggeststhreads(self): @@ -196,6 +207,13 @@ class BaseFolder: return self.sep def getfullname(self): + """ + Returns the folder full name, using the getname(). If getroot() is set + their value is concatenated to getname() using the separator + + Returns: The folder full name + + """ if self.getroot(): return self.getroot() + self.getsep() + self.getname() else: @@ -371,6 +389,12 @@ class BaseFolder: OfflineImapError.ERROR.MESSAGE) def getmaxsize(self): + """ + Get the maxsize for account name. If not found, returns None. + + Returns: A string with the maxise of the account name + + """ return self.config.getdefaultint("Account %s" % self.accountname, "maxsize", None) @@ -396,6 +420,12 @@ class BaseFolder: OfflineImapError.ERROR.MESSAGE) def get_min_uid_file(self): + """ + Get the min UID file name. Create it if not found. + + Returns: Min UID file name. + + """ startuiddir = os.path.join(self.config.getmetadatadir(), 'Repository-' + self.repository.name, 'StartUID') @@ -404,12 +434,27 @@ class BaseFolder: return os.path.join(startuiddir, self.getfolderbasename()) def save_min_uid(self, min_uid): + """ + Save the min UID in the min uid file + + Args: + min_uid: min_uid to save + + Returns: None + + """ uidfile = self.get_min_uid_file() fd = open(uidfile, 'wt') fd.write(str(min_uid) + "\n") fd.close() def retrieve_min_uid(self): + """ + Retrieve the min UID file + + Returns: min UID of file + + """ uidfile = self.get_min_uid_file() if not os.path.exists(uidfile): return None From f7534c70ce97a9698c5347c5ee13093f91eace05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Sun, 1 Nov 2020 13:12:03 +0100 Subject: [PATCH 46/47] __init__.py added docstrings Just added docstrings. --- offlineimap/folder/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/offlineimap/folder/__init__.py b/offlineimap/folder/__init__.py index bae2689..3553030 100644 --- a/offlineimap/folder/__init__.py +++ b/offlineimap/folder/__init__.py @@ -1 +1,4 @@ +""" +Folder Module of offlineimap +""" from . import Base, Gmail, IMAP, Maildir, LocalStatus, UIDMaps From 7a4285370f338a6653e8bb1a8fb99e3703683b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolfo=20Garc=C3=ADa=20Pe=C3=B1as=20=28kix=29?= Date: Wed, 4 Nov 2020 22:17:32 +0100 Subject: [PATCH 47/47] BUG: Right format for password using remotepasseval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reading the password using remotepasseval returns a bytes objects instead an utf-8 string. This patch includes support strings and bytes objects. Closes #21 Signed-off-by: Rodolfo García Peñas (kix) --- offlineimap/repository/IMAP.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index f09fd28..699f0c9 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -562,7 +562,21 @@ class IMAPRepository(BaseRepository): # 1. Evaluate Repository 'remotepasseval'. passwd = self.getconf('remotepasseval', None) if passwd is not None: - return self.localeval.eval(passwd).encode('utf-8') + l_pass = self.localeval.eval(passwd) + + # We need a str password + if isinstance(l_pass, bytes): + return l_pass.decode(encoding='utf-8') + elif isinstance(l_pass, str): + return l_pass + + # If is not bytes or str, we have a problem + raise OfflineImapError("Could not get a right password format for" + " repository %s. Type found: %s. " + "Please, open a bug." % + (self.name, type(l_pass)), + OfflineImapError.ERROR.FOLDER) + # 2. Read password from Repository 'remotepass'. password = self.getconf('remotepass', None) if password is not None: