From f2e940b0da92dfc266c4f6bc06e46a0122bd28f8 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Sun, 26 Feb 2017 11:51:12 +0000 Subject: [PATCH 1/4] Add support for GitPython 1.x --- plugin.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugin.py b/plugin.py index 37dcf67..1032e47 100644 --- a/plugin.py +++ b/plugin.py @@ -40,6 +40,7 @@ import threading import time import traceback +from distutils.version import StrictVersion # 'import git' is performed during plugin initialization. # @@ -305,13 +306,10 @@ def init_git_python(self): import git except ImportError: raise Exception("GitPython is not installed.") - if not git.__version__.startswith('0.'): - raise Exception("Unsupported GitPython version.") - GIT_API_VERSION = int(git.__version__[2]) - if not GIT_API_VERSION in [1, 3]: - log_error('GitPython version %s unrecognized, using 0.3.x API.' - % git.__version__) + if StrictVersion(git.__version__) >= StrictVersion("0.3.0"): GIT_API_VERSION = 3 + else: + GIT_API_VERSION = 1 def die(self): self._stop_polling() From 1d6df75f919451a8c1ac7f2cb29766e98bf283d0 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Fri, 20 Jul 2018 11:43:37 +0100 Subject: [PATCH 2/4] Add support for GitPython 2.x --- plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin.py b/plugin.py index 1032e47..c028ae0 100644 --- a/plugin.py +++ b/plugin.py @@ -173,7 +173,8 @@ def get_new_commits(self): rev = "%s..%s" % (self.last_commit, self.branch) # Workaround for GitPython bug: # https://github.com/gitpython-developers/GitPython/issues/61 - self.repo.odb.update_cache() + if hasattr(self.repo.odb, 'update_cache'): + self.repo.odb.update_cache() result = self.repo.iter_commits(rev) else: raise Exception("Unsupported API version: %d" % GIT_API_VERSION) From c3274cb9799085d863cc7f880a7c399765075622 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 19 May 2020 15:05:19 +0100 Subject: [PATCH 3/4] Convert to python 3 --- __init__.py | 9 +++++---- plugin.py | 36 +++++++++++++++++------------------- test.py | 2 +- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/__init__.py b/__init__.py index c1106e7..436766b 100644 --- a/__init__.py +++ b/__init__.py @@ -34,6 +34,7 @@ import supybot import supybot.world as world +import importlib # Use this for the version of this plugin. You may wish to put a CVS keyword # in here if you're keeping the plugin in CVS or some similar system. @@ -49,14 +50,14 @@ # This is a url where the most recent plugin package can be downloaded. __url__ = 'http://github.com/mmueller/supybot-git' -import config -import plugin -reload(plugin) # In case we're being reloaded. +from . import config +from . import plugin +importlib.reload(plugin) # In case we're being reloaded. # Add more reloads here if you add third-party modules and want them to be # reloaded when this plugin is reloaded. Don't forget to import them as well! if world.testing: - import test + from . import test Class = plugin.Class configure = config.configure diff --git a/plugin.py b/plugin.py index c028ae0..4ff05fa 100644 --- a/plugin.py +++ b/plugin.py @@ -34,7 +34,7 @@ import supybot.log as log import supybot.world as world -import ConfigParser +import configparser from functools import wraps import os import threading @@ -105,7 +105,7 @@ def __init__(self, repo_dir, long_name, options): if name not in options: raise Exception('Section %s missing required value: %s' % (long_name, name)) - for name, value in options.items(): + for name, value in list(options.items()): if name not in required_values and name not in optional_values: raise Exception('Section %s contains unrecognized value: %s' % (long_name, name)) @@ -243,7 +243,7 @@ def format_message(self, commit, format_str=None): outline = '' for c in line: if mode == MODE_SUBST: - if c in subst.keys(): + if c in list(subst.keys()): outline += subst[c] mode = MODE_NORMAL elif c == '(': @@ -262,7 +262,7 @@ def format_message(self, commit, format_str=None): mode = MODE_SUBST else: outline += c - result.append(outline.encode('utf-8')) + result.append(outline) return result @synchronized('lock') @@ -293,7 +293,7 @@ def __init__(self, irc): self._stop_polling() try: self._read_config() - except Exception, e: + except Exception as e: if 'reply' in dir(irc): irc.reply('Warning: %s' % str(e)) else: @@ -322,7 +322,7 @@ def _log(self, irc, msg, args, channel, name, count): Display the last commits on the named repository. [count] defaults to 1 if unspecified. """ - matches = filter(lambda r: r.short_name == name, self.repository_list) + matches = [r for r in self.repository_list if r.short_name == name] if not matches: irc.reply('No configured repository named %s.' % name) return @@ -349,7 +349,7 @@ def rehash(self, irc, msg, args): n = len(self.repository_list) irc.reply('Git reinitialized with %d %s.' % (n, plural(n, 'repository'))) - except Exception, e: + except Exception as e: irc.reply('Warning: %s' % str(e)) def repositories(self, irc, msg, args, channel): @@ -357,8 +357,7 @@ def repositories(self, irc, msg, args, channel): Display the names of known repositories configured for this channel. """ - repositories = filter(lambda r: channel in r.channels, - self.repository_list) + repositories = [r for r in self.repository_list if channel in r.channels] if not repositories: irc.reply('No repositories configured for this channel.') return @@ -412,7 +411,7 @@ def _reply_commits(self, irc, channel, repository, commits): format_str = repository.commit_reply or repository.commit_message for commit in commits[-commits_at_once:]: lines = repository.format_message(commit, format_str) - map(irc.reply, lines) + list(map(irc.reply, lines)) def _poll(self): # Note that polling happens in two steps: @@ -447,7 +446,7 @@ def _poll(self): for irc, channel in targets: self._display_commits(irc, channel, repository, commits) - except Exception, e: + except Exception as e: log_error('Exception in _poll repository %s: %s' % (repository.short_name, str(e))) finally: @@ -456,7 +455,7 @@ def _poll(self): log.info('Postponing repository read: %s: Locked.' % repository.long_name) self._schedule_next_event() - except Exception, e: + except Exception as e: log_error('Exception in _poll(): %s' % str(e)) traceback.print_exc(e) @@ -466,7 +465,7 @@ def _read_config(self): config = self.registryValue('configFile') if not os.access(config, os.R_OK): raise Exception('Cannot access configuration file: %s' % config) - parser = ConfigParser.RawConfigParser() + parser = configparser.RawConfigParser() parser.read(config) for section in parser.sections(): options = dict(parser.items(section)) @@ -488,8 +487,7 @@ def _snarf(self, irc, msg, match): if self.registryValue('shaSnarfing'): sha = match.group('sha') channel = msg.args[0] - repositories = filter(lambda r: channel in r.channels, - self.repository_list) + repositories = [r for r in self.repository_list if channel in r.channels] for repository in repositories: commit = repository.get_commit(sha) if commit: @@ -502,14 +500,14 @@ def _stop_polling(self): try: self.fetcher.stop() self.fetcher.join() # This might take time, but it's safest. - except Exception, e: + except Exception as e: log_error('Stopping fetcher: %s' % str(e)) self.fetcher = None try: schedule.removeEvent(self.name()) except KeyError: pass - except Exception, e: + except Exception as e: log_error('Stopping scheduled task: %s' % str(e)) class GitFetcher(threading.Thread): @@ -553,14 +551,14 @@ def run(self): if repository.lock.acquire(blocking=False): try: repository.fetch() - except Exception, e: + except Exception as e: repository.record_error(e) finally: repository.lock.release() else: log_info('Postponing repository fetch: %s: Locked.' % repository.long_name) - except Exception, e: + except Exception as e: log_error('Exception checking repository %s: %s' % (repository.short_name, str(e))) # Wait for the next periodic check diff --git a/test.py b/test.py index 4d949e8..078ecaa 100644 --- a/test.py +++ b/test.py @@ -87,7 +87,7 @@ def _feedMsgLoop(self, query, timeout=None, **kwargs): def assertResponses(self, query, expectedResponses, **kwargs): "Run a command and assert that it returns the given list of replies." responses = self._feedMsgLoop(query, **kwargs) - responses = map(lambda m: m.args[1], responses) + responses = [m.args[1] for m in responses] self.assertEqual(responses, expectedResponses, '\nActual:\n%s\n\nExpected:\n%s' % ('\n'.join(responses), '\n'.join(expectedResponses))) From 28fab040f6aa5be18cf6f19b8116e5a20677d448 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 12 Jul 2022 00:14:31 +0100 Subject: [PATCH 4/4] Update for python 3.10 compatibility --- plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.py b/plugin.py index 4ff05fa..acce76a 100644 --- a/plugin.py +++ b/plugin.py @@ -474,7 +474,7 @@ def _read_config(self): def _schedule_next_event(self): period = self.registryValue('pollPeriod') if period > 0: - if not self.fetcher or not self.fetcher.isAlive(): + if not self.fetcher or not self.fetcher.is_alive(): self.fetcher = GitFetcher(self.repository_list, period) self.fetcher.start() schedule.addEvent(self._poll, time.time() + period,