Modernize legacy Python 2 syntax with pyupgrade.

Generated by `pyupgrade --py3-plus --keep-percent-format` followed by
manual indentation fixes.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This commit is contained in:
Anders Kaseorg 2020-04-09 17:14:01 -07:00 committed by Tim Abbott
parent 543eb396b9
commit e30b3b094b
107 changed files with 192 additions and 244 deletions

View file

@ -7,7 +7,7 @@ if MYPY:
whitespace_rules = [ whitespace_rules = [
# This linter should be first since bash_rules depends on it. # This linter should be first since bash_rules depends on it.
{'pattern': '\s+$', {'pattern': r'\s+$',
'strip': '\n', 'strip': '\n',
'description': 'Fix trailing whitespace'}, 'description': 'Fix trailing whitespace'},
{'pattern': '\t', {'pattern': '\t',
@ -15,11 +15,11 @@ whitespace_rules = [
'description': 'Fix tab-based whitespace'}, 'description': 'Fix tab-based whitespace'},
] # type: Rule ] # type: Rule
markdown_whitespace_rules = list([rule for rule in whitespace_rules if rule['pattern'] != '\s+$']) + [ markdown_whitespace_rules = list([rule for rule in whitespace_rules if rule['pattern'] != r'\s+$']) + [
# Two spaces trailing a line with other content is okay--it's a markdown line break. # Two spaces trailing a line with other content is okay--it's a markdown line break.
# This rule finds one space trailing a non-space, three or more trailing spaces, and # This rule finds one space trailing a non-space, three or more trailing spaces, and
# spaces on an empty line. # spaces on an empty line.
{'pattern': '((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)', {'pattern': r'((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)',
'strip': '\n', 'strip': '\n',
'description': 'Fix trailing whitespace'}, 'description': 'Fix trailing whitespace'},
{'pattern': '^#+[A-Za-z0-9]', {'pattern': '^#+[A-Za-z0-9]',
@ -30,18 +30,18 @@ markdown_whitespace_rules = list([rule for rule in whitespace_rules if rule['pat
python_rules = RuleList( python_rules = RuleList(
langs=['py'], langs=['py'],
rules=[ rules=[
{'pattern': '".*"%\([a-z_].*\)?$', {'pattern': r'".*"%\([a-z_].*\)?$',
'description': 'Missing space around "%"'}, 'description': 'Missing space around "%"'},
{'pattern': "'.*'%\([a-z_].*\)?$", {'pattern': r"'.*'%\([a-z_].*\)?$",
'description': 'Missing space around "%"'}, 'description': 'Missing space around "%"'},
# This rule is constructed with + to avoid triggering on itself # This rule is constructed with + to avoid triggering on itself
{'pattern': " =" + '[^ =>~"]', {'pattern': " =" + '[^ =>~"]',
'description': 'Missing whitespace after "="'}, 'description': 'Missing whitespace after "="'},
{'pattern': '":\w[^"]*$', {'pattern': r'":\w[^"]*$',
'description': 'Missing whitespace after ":"'}, 'description': 'Missing whitespace after ":"'},
{'pattern': "':\w[^']*$", {'pattern': r"':\w[^']*$",
'description': 'Missing whitespace after ":"'}, 'description': 'Missing whitespace after ":"'},
{'pattern': "^\s+[#]\w", {'pattern': r"^\s+[#]\w",
'strip': '\n', 'strip': '\n',
'description': 'Missing whitespace after "#"'}, 'description': 'Missing whitespace after "#"'},
{'pattern': "assertEquals[(]", {'pattern': "assertEquals[(]",
@ -67,26 +67,26 @@ python_rules = RuleList(
# This next check could have false positives, but it seems pretty # This next check could have false positives, but it seems pretty
# rare; if we find any, they can be added to the exclude list for # rare; if we find any, they can be added to the exclude list for
# this rule. # this rule.
{'pattern': ' % [a-zA-Z0-9_.]*\)?$', {'pattern': r' % [a-zA-Z0-9_.]*\)?$',
'description': 'Used % comprehension without a tuple'}, 'description': 'Used % comprehension without a tuple'},
{'pattern': '.*%s.* % \([a-zA-Z0-9_.]*\)$', {'pattern': r'.*%s.* % \([a-zA-Z0-9_.]*\)$',
'description': 'Used % comprehension without a tuple'}, 'description': 'Used % comprehension without a tuple'},
{'pattern': '__future__', {'pattern': '__future__',
'include_only': set(['zulip_bots/zulip_bots/bots/']), 'include_only': {'zulip_bots/zulip_bots/bots/'},
'description': 'Bots no longer need __future__ imports.'}, 'description': 'Bots no longer need __future__ imports.'},
{'pattern': '#!/usr/bin/env python$', {'pattern': '#!/usr/bin/env python$',
'include_only': set(['zulip_bots/']), 'include_only': {'zulip_bots/'},
'description': 'Python shebangs must be python3'}, 'description': 'Python shebangs must be python3'},
{'pattern': '(^|\s)open\s*\(', {'pattern': r'(^|\s)open\s*\(',
'description': 'open() should not be used in Zulip\'s bots. Use functions' 'description': 'open() should not be used in Zulip\'s bots. Use functions'
' provided by the bots framework to access the filesystem.', ' provided by the bots framework to access the filesystem.',
'include_only': set(['zulip_bots/zulip_bots/bots/'])}, 'include_only': {'zulip_bots/zulip_bots/bots/'}},
{'pattern': 'pprint', {'pattern': 'pprint',
'description': 'Used pprint, which is most likely a debugging leftover. For user output, use print().'}, 'description': 'Used pprint, which is most likely a debugging leftover. For user output, use print().'},
{'pattern': '\(BotTestCase\)', {'pattern': r'\(BotTestCase\)',
'bad_lines': ['class TestSomeBot(BotTestCase):'], 'bad_lines': ['class TestSomeBot(BotTestCase):'],
'description': 'Bot test cases should directly inherit from BotTestCase *and* DefaultTests.'}, 'description': 'Bot test cases should directly inherit from BotTestCase *and* DefaultTests.'},
{'pattern': '\(DefaultTests, BotTestCase\)', {'pattern': r'\(DefaultTests, BotTestCase\)',
'bad_lines': ['class TestSomeBot(DefaultTests, BotTestCase):'], 'bad_lines': ['class TestSomeBot(DefaultTests, BotTestCase):'],
'good_lines': ['class TestSomeBot(BotTestCase, DefaultTests):'], 'good_lines': ['class TestSomeBot(BotTestCase, DefaultTests):'],
'description': 'Bot test cases should inherit from BotTestCase before DefaultTests.'}, 'description': 'Bot test cases should inherit from BotTestCase before DefaultTests.'},
@ -117,9 +117,9 @@ json_rules = RuleList(
) )
prose_style_rules = [ prose_style_rules = [
{'pattern': '[^\/\#\-\"]([jJ]avascript)', # exclude usage in hrefs/divs {'pattern': '[^\\/\\#\\-\"]([jJ]avascript)', # exclude usage in hrefs/divs
'description': "javascript should be spelled JavaScript"}, 'description': "javascript should be spelled JavaScript"},
{'pattern': '[^\/\-\.\"\'\_\=\>]([gG]ithub)[^\.\-\_\"\<]', # exclude usage in hrefs/divs {'pattern': '[^\\/\\-\\.\"\'\\_\\=\\>]([gG]ithub)[^\\.\\-\\_\"\\<]', # exclude usage in hrefs/divs
'description': "github should be spelled GitHub"}, 'description': "github should be spelled GitHub"},
{'pattern': '[oO]rganisation', # exclude usage in hrefs/divs {'pattern': '[oO]rganisation', # exclude usage in hrefs/divs
'description': "Organization is spelled with a z"}, 'description': "Organization is spelled with a z"},
@ -136,7 +136,7 @@ markdown_docs_length_exclude = {
markdown_rules = RuleList( markdown_rules = RuleList(
langs=['md'], langs=['md'],
rules=markdown_whitespace_rules + prose_style_rules + [ rules=markdown_whitespace_rules + prose_style_rules + [
{'pattern': '\[(?P<url>[^\]]+)\]\((?P=url)\)', {'pattern': r'\[(?P<url>[^\]]+)\]\((?P=url)\)',
'description': 'Linkified markdown URLs should use cleaner <http://example.com> syntax.'} 'description': 'Linkified markdown URLs should use cleaner <http://example.com> syntax.'}
], ],
max_length=120, max_length=120,

View file

@ -201,7 +201,7 @@ def print_bots(bots: List[Any], pretty_print: bool) -> None:
print_bots_pretty(bots) print_bots_pretty(bots)
else: else:
for bot in bots: for bot in bots:
print('{0}\t{1}\t{2}\t{3}'.format(bot['name'], bot['status'], bot['email'], bot['site'])) print('{}\t{}\t{}\t{}'.format(bot['name'], bot['status'], bot['email'], bot['site']))
def print_bots_pretty(bots: List[Any]) -> None: def print_bots_pretty(bots: List[Any]) -> None:
if len(bots) == 0: if len(bots) == 0:

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys import sys
import os import os
@ -42,7 +41,7 @@ def create_pipe_event(to_client: zulip.Client, from_bot: Dict[str, Any],
"type": "stream", "type": "stream",
"to": to_bot["stream"], "to": to_bot["stream"],
"subject": subject, "subject": subject,
"content": "**{0}**: {1}".format(msg["sender_full_name"], msg["content"]), "content": "**{}**: {}".format(msg["sender_full_name"], msg["content"]),
"has_attachment": msg.get("has_attachment", False), "has_attachment": msg.get("has_attachment", False),
"has_image": msg.get("has_image", False), "has_image": msg.get("has_image", False),
"has_link": msg.get("has_link", False) "has_link": msg.get("has_link", False)

View file

@ -116,7 +116,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
"to": self.stream, "to": self.stream,
"subject": self.topic, "subject": self.topic,
"content": content, "content": content,
"content": "**{0}**: {1}".format(sender, content), "content": "**{}**: {}".format(sender, content),
})) }))
def on_dccmsg(self, c, e): def on_dccmsg(self, c, e):

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# Change these values to configure authentication for your codebase account # Change these values to configure authentication for your codebase account
# Note that this is the Codebase API Username, found in the Settings page # Note that this is the Codebase API Username, found in the Settings page
# for your account # for your account

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Zulip mirror of Codebase HQ activity # Zulip mirror of Codebase HQ activity
# The "zulip_codebase_mirror" script is run continuously, possibly on a work # The "zulip_codebase_mirror" script is run continuously, possibly on a work
@ -256,7 +255,7 @@ def run_mirror():
since = default_since() since = default_since()
else: else:
since = datetime.fromtimestamp(float(timestamp), tz=pytz.utc) since = datetime.fromtimestamp(float(timestamp), tz=pytz.utc)
except (ValueError, IOError) as e: except (ValueError, OSError) as e:
logging.warn("Could not open resume file: %s" % (str(e))) logging.warn("Could not open resume file: %s" % (str(e)))
since = default_since() since = default_since()
@ -289,13 +288,13 @@ def check_permissions():
if config.LOG_FILE: if config.LOG_FILE:
try: try:
open(config.LOG_FILE, "w") open(config.LOG_FILE, "w")
except IOError as e: except OSError as e:
sys.stderr.write("Could not open up log for writing:") sys.stderr.write("Could not open up log for writing:")
sys.stderr.write(str(e)) sys.stderr.write(str(e))
# check that the resume file can be written (this creates if it doesn't exist) # check that the resume file can be written (this creates if it doesn't exist)
try: try:
open(config.RESUME_FILE, "a+") open(config.RESUME_FILE, "a+")
except IOError as e: except OSError as e:
sys.stderr.write("Could not open up the file %s for reading and writing" % (config.RESUME_FILE,)) sys.stderr.write("Could not open up the file %s for reading and writing" % (config.RESUME_FILE,))
sys.stderr.write(str(e)) sys.stderr.write(str(e))

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Zulip notification post-receive hook. # Zulip notification post-receive hook.
# #

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# #
from typing import Dict, Text, Optional from typing import Dict, Text, Optional
@ -28,7 +27,7 @@ def commit_notice_destination(repo, branch, commit):
# type: (Text, Text, Text) -> Optional[Dict[Text, Text]] # type: (Text, Text, Text) -> Optional[Dict[Text, Text]]
if branch in ["master", "test-post-receive"]: if branch in ["master", "test-post-receive"]:
return dict(stream = STREAM_NAME, return dict(stream = STREAM_NAME,
subject = u"%s" % (branch,)) subject = "%s" % (branch,))
# Return None for cases where you don't want a notice sent # Return None for cases where you don't want a notice sent
return None return None

View file

@ -100,7 +100,7 @@ def get_credentials():
return credentials return credentials
except client.Error: except client.Error:
logging.exception('Error while trying to open the `google-credentials.json` file.') logging.exception('Error while trying to open the `google-credentials.json` file.')
except IOError: except OSError:
logging.error("Run the get-google-credentials script from this directory first.") logging.error("Run the get-google-credentials script from this directory first.")

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Zulip hook for Mercurial changeset pushes. # Zulip hook for Mercurial changeset pushes.
# #
@ -35,7 +34,7 @@ def format_summary_line(web_url, user, base, tip, branch, node):
formatted_commit_count = "{revcount} commit{s}".format( formatted_commit_count = "{revcount} commit{s}".format(
revcount=revcount, s=plural) revcount=revcount, s=plural)
return u"**{user}** pushed {commits} to **{branch}** (`{tip}:{node}`):\n\n".format( return "**{user}** pushed {commits} to **{branch}** (`{tip}:{node}`):\n\n".format(
user=user, commits=formatted_commit_count, branch=branch, tip=tip, user=user, commits=formatted_commit_count, branch=branch, tip=tip,
node=node[:12]) node=node[:12])

View file

@ -161,7 +161,7 @@ class JabberToZulipBot(ClientXMPP):
def private(self, msg): def private(self, msg):
# type: (JabberMessage) -> None # type: (JabberMessage) -> None
if options.mode == 'public' or msg['thread'] == u'\u1FFFE': if options.mode == 'public' or msg['thread'] == '\u1FFFE':
return return
sender = jid_to_zulip(msg["from"]) sender = jid_to_zulip(msg["from"])
recipient = jid_to_zulip(msg["to"]) recipient = jid_to_zulip(msg["to"])
@ -178,7 +178,7 @@ class JabberToZulipBot(ClientXMPP):
def group(self, msg): def group(self, msg):
# type: (JabberMessage) -> None # type: (JabberMessage) -> None
if options.mode == 'personal' or msg["thread"] == u'\u1FFFE': if options.mode == 'personal' or msg["thread"] == '\u1FFFE':
return return
subject = msg["subject"] subject = msg["subject"]
@ -212,7 +212,7 @@ class JabberToZulipBot(ClientXMPP):
else: else:
return jid return jid
class ZulipToJabberBot(object): class ZulipToJabberBot:
def __init__(self, zulip_client): def __init__(self, zulip_client):
# type: (Client) -> None # type: (Client) -> None
self.client = zulip_client self.client = zulip_client
@ -254,7 +254,7 @@ class ZulipToJabberBot(object):
mto = jabber_recipient, mto = jabber_recipient,
mbody = msg['content'], mbody = msg['content'],
mtype = 'groupchat') mtype = 'groupchat')
outgoing['thread'] = u'\u1FFFE' outgoing['thread'] = '\u1FFFE'
outgoing.send() outgoing.send()
def private_message(self, msg): def private_message(self, msg):
@ -271,7 +271,7 @@ class ZulipToJabberBot(object):
mto = jabber_recipient, mto = jabber_recipient,
mbody = msg['content'], mbody = msg['content'],
mtype = 'chat') mtype = 'chat')
outgoing['thread'] = u'\u1FFFE' outgoing['thread'] = '\u1FFFE'
outgoing.send() outgoing.send()
def process_subscription(self, event): def process_subscription(self, event):
@ -415,9 +415,9 @@ option does not affect login credentials.'''.replace("\n", " "))
config = SafeConfigParser() config = SafeConfigParser()
try: try:
with open(config_file, 'r') as f: with open(config_file) as f:
config.readfp(f, config_file) config.readfp(f, config_file)
except IOError: except OSError:
pass pass
for option in ("jid", "jabber_password", "conference_domain", "mode", "zulip_email_suffix", for option in ("jid", "jabber_password", "conference_domain", "mode", "zulip_email_suffix",
"jabber_server_address", "jabber_server_port"): "jabber_server_address", "jabber_server_port"):

View file

@ -112,8 +112,8 @@ if __name__ == "__main__":
open(lock_path, "w").write("1") open(lock_path, "w").write("1")
zulip_client = zulip.init_from_options(args) zulip_client = zulip.init_from_options(args)
try: try:
log_files = json.loads(open(args.control_path, "r").read()) log_files = json.loads(open(args.control_path).read())
except (json.JSONDecodeError, IOError): # type: ignore # error: Cannot determine type of 'IOError' except (json.JSONDecodeError, OSError): # type: ignore # error: Cannot determine type of 'IOError'
print("Could not load control data from %s" % (args.control_path,)) print("Could not load control data from %s" % (args.control_path,))
traceback.print_exc() traceback.print_exc()
sys.exit(1) sys.exit(1)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# #
# Zulip notification post-receive hook. # Zulip notification post-receive hook.

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# https://github.com/python/mypy/issues/1141 # https://github.com/python/mypy/issues/1141
from typing import Dict, Text, Optional from typing import Dict, Text, Optional
@ -25,7 +23,7 @@ def deployment_notice_destination(branch):
# type: (str) -> Optional[Dict[str, Text]] # type: (str) -> Optional[Dict[str, Text]]
if branch in ['master', 'test-post-receive']: if branch in ['master', 'test-post-receive']:
return dict(stream = 'deployments', return dict(stream = 'deployments',
subject = u'%s' % (branch,)) subject = '%s' % (branch,))
# Return None for cases where you don't want a notice sent # Return None for cases where you don't want a notice sent
return None return None

View file

@ -339,7 +339,7 @@ def setP4ExecBit(file, mode):
if not isModeExec(mode): if not isModeExec(mode):
p4Type = getP4OpenedType(file) p4Type = getP4OpenedType(file)
p4Type = re.sub('^([cku]?)x(.*)', '\\1\\2', p4Type) p4Type = re.sub('^([cku]?)x(.*)', '\\1\\2', p4Type)
p4Type = re.sub('(.*?\+.*?)x(.*?)', '\\1\\2', p4Type) p4Type = re.sub(r'(.*?\+.*?)x(.*?)', '\\1\\2', p4Type)
if p4Type[-1] == "+": if p4Type[-1] == "+":
p4Type = p4Type[0:-1] p4Type = p4Type[0:-1]
@ -349,7 +349,7 @@ def getP4OpenedType(file):
# Returns the perforce file type for the given file. # Returns the perforce file type for the given file.
result = p4_read_pipe(["opened", wildcard_encode(file)]) result = p4_read_pipe(["opened", wildcard_encode(file)])
match = re.match(".*\((.+)\)\r?$", result) match = re.match(".*\\((.+)\\)\r?$", result)
if match: if match:
return match.group(1) return match.group(1)
else: else:
@ -378,7 +378,7 @@ def getGitTags():
def diffTreePattern(): def diffTreePattern():
# This is a simple generator for the diff tree regex pattern. This could be # This is a simple generator for the diff tree regex pattern. This could be
# a class variable if this and parseDiffTreeEntry were a part of a class. # a class variable if this and parseDiffTreeEntry were a part of a class.
pattern = re.compile(':(\d+) (\d+) (\w+) (\w+) ([A-Z])(\d+)?\t(.*?)((\t(.*))|$)') pattern = re.compile(':(\\d+) (\\d+) (\\w+) (\\w+) ([A-Z])(\\d+)?\t(.*?)((\t(.*))|$)')
while True: while True:
yield pattern yield pattern
@ -820,13 +820,13 @@ def wildcard_present(path):
m = re.search("[*#@%]", path) m = re.search("[*#@%]", path)
return m is not None return m is not None
class Command(object): class Command:
def __init__(self): def __init__(self):
self.usage = "usage: %prog [options]" self.usage = "usage: %prog [options]"
self.needsGit = True self.needsGit = True
self.verbose = False self.verbose = False
class P4UserMap(object): class P4UserMap:
def __init__(self): def __init__(self):
self.userMapFromPerforceServer = False self.userMapFromPerforceServer = False
self.myP4UserId = None self.myP4UserId = None
@ -883,7 +883,7 @@ class P4UserMap(object):
for line in lines: for line in lines:
entry = line.strip().split("\t") entry = line.strip().split("\t")
self.users[entry[0]] = entry[1] self.users[entry[0]] = entry[1]
except IOError: except OSError:
self.getUserMapFromPerforceServer() self.getUserMapFromPerforceServer()
class P4Debug(Command): class P4Debug(Command):
@ -1056,7 +1056,7 @@ class P4Submit(Command, P4UserMap):
(handle, outFileName) = tempfile.mkstemp(dir='.') (handle, outFileName) = tempfile.mkstemp(dir='.')
try: try:
outFile = os.fdopen(handle, "w+") outFile = os.fdopen(handle, "w+")
inFile = open(file, "r") inFile = open(file)
regexp = re.compile(pattern, re.VERBOSE) regexp = re.compile(pattern, re.VERBOSE)
for line in inFile.readlines(): for line in inFile.readlines():
line = regexp.sub(r'$\1$', line) line = regexp.sub(r'$\1$', line)
@ -1391,7 +1391,7 @@ class P4Submit(Command, P4UserMap):
newdiff += "==== new file ====\n" newdiff += "==== new file ====\n"
newdiff += "--- /dev/null\n" newdiff += "--- /dev/null\n"
newdiff += "+++ %s\n" % newFile newdiff += "+++ %s\n" % newFile
f = open(newFile, "r") f = open(newFile)
for line in f.readlines(): for line in f.readlines():
newdiff += "+" + line newdiff += "+" + line
f.close() f.close()
@ -1773,7 +1773,7 @@ class P4Submit(Command, P4UserMap):
return True return True
class View(object): class View:
"""Represent a p4 view ("p4 help views"), and map files in a """Represent a p4 view ("p4 help views"), and map files in a
repo according to the view.""" repo according to the view."""
@ -2377,7 +2377,7 @@ class P4Sync(Command, P4UserMap):
# find the corresponding git commit; take the oldest commit # find the corresponding git commit; take the oldest commit
changelist = int(change['change']) changelist = int(change['change'])
gitCommit = read_pipe(["git", "rev-list", "--max-count=1", gitCommit = read_pipe(["git", "rev-list", "--max-count=1",
"--reverse", ":/\[git-p4:.*change = %d\]" % changelist]) "--reverse", r":/\[git-p4:.*change = %d\]" % changelist])
if len(gitCommit) == 0: if len(gitCommit) == 0:
print("could not find git commit for changelist %d" % changelist) print("could not find git commit for changelist %d" % changelist)
else: else:
@ -2657,7 +2657,7 @@ class P4Sync(Command, P4UserMap):
self.initialParent) self.initialParent)
# only needed once, to connect to the previous commit # only needed once, to connect to the previous commit
self.initialParent = "" self.initialParent = ""
except IOError: except OSError:
print(self.gitError.read()) print(self.gitError.read())
sys.exit(1) sys.exit(1)
@ -2712,7 +2712,7 @@ class P4Sync(Command, P4UserMap):
self.updateOptionDict(details) self.updateOptionDict(details)
try: try:
self.commit(details, self.extractFilesFromCommit(details), self.branch) self.commit(details, self.extractFilesFromCommit(details), self.branch)
except IOError: except OSError:
print("IO error with git fast-import. Is your git version recent enough?") print("IO error with git fast-import. Is your git version recent enough?")
print(self.gitError.read()) print(self.gitError.read())
@ -2878,7 +2878,7 @@ class P4Sync(Command, P4UserMap):
if len(self.changesFile) == 0: if len(self.changesFile) == 0:
revision = "#head" revision = "#head"
p = re.sub ("\.\.\.$", "", p) p = re.sub (r"\.\.\.$", "", p)
if not p.endswith("/"): if not p.endswith("/"):
p += "/" p += "/"

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''Zulip notification change-commit hook. '''Zulip notification change-commit hook.

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
from typing import Dict, Optional, Text from typing import Dict, Optional, Text
# Change these values to configure authentication for the plugin # Change these values to configure authentication for the plugin

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# #
# RSS integration for Zulip # RSS integration for Zulip
# #
@ -174,9 +173,9 @@ def send_zulip(entry, feed_name):
return client.send_message(message) return client.send_message(message)
try: try:
with open(opts.feed_file, "r") as f: with open(opts.feed_file) as f:
feed_urls = [feed.strip() for feed in f.readlines()] # type: List[str] feed_urls = [feed.strip() for feed in f.readlines()] # type: List[str]
except IOError: except OSError:
log_error_and_exit("Unable to read feed file at %s." % (opts.feed_file,)) log_error_and_exit("Unable to read feed file at %s." % (opts.feed_file,))
client = zulip.Client(email=opts.zulip_email, api_key=opts.zulip_api_key, client = zulip.Client(email=opts.zulip_email, api_key=opts.zulip_api_key,
@ -189,9 +188,9 @@ for feed_url in feed_urls:
feed_file = os.path.join(opts.data_dir, urllib.parse.urlparse(feed_url).netloc) # Type: str feed_file = os.path.join(opts.data_dir, urllib.parse.urlparse(feed_url).netloc) # Type: str
try: try:
with open(feed_file, "r") as f: with open(feed_file) as f:
old_feed_hashes = dict((line.strip(), True) for line in f.readlines()) # type: Dict[str, bool] old_feed_hashes = {line.strip(): True for line in f.readlines()} # type: Dict[str, bool]
except IOError: except OSError:
old_feed_hashes = {} old_feed_hashes = {}
new_hashes = [] # type: List[str] new_hashes = [] # type: List[str]

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# #
# Zulip notification post-commit hook. # Zulip notification post-commit hook.
# #
@ -39,7 +38,7 @@ path, rev = sys.argv[1:] # type: Tuple[Text, Text]
path = "file://" + path path = "file://" + path
entry = svn.log(path, revision_end=pysvn.Revision(pysvn.opt_revision_kind.number, rev))[0] # type: Dict[Text, Any] entry = svn.log(path, revision_end=pysvn.Revision(pysvn.opt_revision_kind.number, rev))[0] # type: Dict[Text, Any]
message = "**{0}** committed revision r{1} to `{2}`.\n\n> {3}".format( message = "**{}** committed revision r{} to `{}`.\n\n> {}".format(
entry['author'], entry['author'],
rev, rev,
path.split('/')[-1], path.split('/')[-1],

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
from typing import Dict, Optional, Text from typing import Dict, Optional, Text
# Change these values to configure authentication for the plugin # Change these values to configure authentication for the plugin
@ -25,7 +23,7 @@ def commit_notice_destination(path, commit):
repo = path.split('/')[-1] repo = path.split('/')[-1]
if repo not in ["evil-master-plan", "my-super-secret-repository"]: if repo not in ["evil-master-plan", "my-super-secret-repository"]:
return dict(stream = "commits", return dict(stream = "commits",
subject = u"%s" % (repo,)) subject = "%s" % (repo,))
# Return None for cases where you don't want a notice sent # Return None for cases where you don't want a notice sent
return None return None

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# Zulip trac plugin -- sends zulips when tickets change. # Zulip trac plugin -- sends zulips when tickets change.
# #
# Install by copying this file and zulip_trac_config.py to the trac # Install by copying this file and zulip_trac_config.py to the trac

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# See zulip_trac.py for installation and configuration instructions # See zulip_trac.py for installation and configuration instructions
# Change these constants to configure the plugin: # Change these constants to configure the plugin:

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# #
# An easy Trello integration for Zulip. # An easy Trello integration for Zulip.
@ -39,7 +38,7 @@ def get_model_id(options):
params=params params=params
) )
if trello_response.status_code is not 200: if trello_response.status_code != 200:
print('Error: Can\'t get the idModel. Please check the configuration') print('Error: Can\'t get the idModel. Please check the configuration')
sys.exit(1) sys.exit(1)
@ -77,7 +76,7 @@ def get_webhook_id(options, id_model):
data=data data=data
) )
if trello_response.status_code is not 200: if trello_response.status_code != 200:
print('Error: Can\'t create the Webhook:', trello_response.text) print('Error: Can\'t create the Webhook:', trello_response.text)
sys.exit(1) sys.exit(1)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Twitter integration for Zulip # Twitter integration for Zulip

View file

@ -155,7 +155,7 @@ for tries in range(10):
if missing == 0: if missing == 0:
actually_subscribed = True actually_subscribed = True
break break
except IOError as e: except OSError as e:
if "SERVNAK received" in e: # type: ignore # https://github.com/python/mypy/issues/2118 if "SERVNAK received" in e: # type: ignore # https://github.com/python/mypy/issues/2118
logger.error("SERVNAK repeatedly received, punting rest of test") logger.error("SERVNAK repeatedly received, punting rest of test")
else: else:
@ -283,8 +283,8 @@ def process_keys(content_list):
key_counts[key] = 0 key_counts[key] = 0
for key in content_keys: for key in content_keys:
key_counts[key] += 1 key_counts[key] += 1
z_missing = set(key for key in zhkeys.keys() if key_counts[key] == 0) z_missing = {key for key in zhkeys.keys() if key_counts[key] == 0}
h_missing = set(key for key in hzkeys.keys() if key_counts[key] == 0) h_missing = {key for key in hzkeys.keys() if key_counts[key] == 0}
duplicates = any(val > 1 for val in key_counts.values()) duplicates = any(val > 1 for val in key_counts.values())
success = all(val == 1 for val in key_counts.values()) success = all(val == 1 for val in key_counts.values())
return key_counts, z_missing, h_missing, duplicates, success return key_counts, z_missing, h_missing, duplicates, success

View file

@ -26,7 +26,7 @@ session_path = "/home/zulip/zephyr_sessions/%s" % (program_name,)
# Preserve mail zephyrs forwarding setting across rewriting the config file # Preserve mail zephyrs forwarding setting across rewriting the config file
try: try:
if "--forward-mail-zephyrs" in open(supervisor_path, "r").read(): if "--forward-mail-zephyrs" in open(supervisor_path).read():
template_data = template_data.replace("--use-sessions", "--use-sessions --forward-mail-zephyrs") template_data = template_data.replace("--use-sessions", "--use-sessions --forward-mail-zephyrs")
except Exception: except Exception:
pass pass

View file

@ -20,7 +20,7 @@ import select
DEFAULT_SITE = "https://api.zulip.com" DEFAULT_SITE = "https://api.zulip.com"
class States(object): class States:
Startup, ZulipToZephyr, ZephyrToZulip, ChildSending = list(range(4)) Startup, ZulipToZephyr, ZephyrToZulip, ChildSending = list(range(4))
CURRENT_STATE = States.Startup CURRENT_STATE = States.Startup
@ -142,7 +142,7 @@ def zephyr_bulk_subscribe(subs):
# type: (List[Tuple[str, str, str]]) -> None # type: (List[Tuple[str, str, str]]) -> None
try: try:
zephyr._z.subAll(subs) zephyr._z.subAll(subs)
except IOError: except OSError:
# Since we haven't added the subscription to # Since we haven't added the subscription to
# current_zephyr_subs yet, we can just return (so that we'll # current_zephyr_subs yet, we can just return (so that we'll
# continue processing normal messages) and we'll end up # continue processing normal messages) and we'll end up
@ -153,7 +153,7 @@ def zephyr_bulk_subscribe(subs):
return return
try: try:
actual_zephyr_subs = [cls for (cls, _, _) in zephyr._z.getSubscriptions()] actual_zephyr_subs = [cls for (cls, _, _) in zephyr._z.getSubscriptions()]
except IOError: except OSError:
logger.exception("Error getting current Zephyr subscriptions") logger.exception("Error getting current Zephyr subscriptions")
# Don't add anything to current_zephyr_subs so that we'll # Don't add anything to current_zephyr_subs so that we'll
# retry the next time we check for streams to subscribe to # retry the next time we check for streams to subscribe to
@ -169,7 +169,7 @@ def zephyr_bulk_subscribe(subs):
# missing 15 seconds of messages on the affected # missing 15 seconds of messages on the affected
# classes # classes
zephyr._z.sub(cls, instance, recipient) zephyr._z.sub(cls, instance, recipient)
except IOError: except OSError:
pass pass
else: else:
current_zephyr_subs.add(cls) current_zephyr_subs.add(cls)
@ -177,7 +177,7 @@ def zephyr_bulk_subscribe(subs):
def update_subscriptions(): def update_subscriptions():
# type: () -> None # type: () -> None
try: try:
f = open(options.stream_file_path, "r") f = open(options.stream_file_path)
public_streams = json.loads(f.read()) public_streams = json.loads(f.read())
f.close() f.close()
except Exception: except Exception:
@ -217,7 +217,7 @@ def maybe_restart_mirroring_script():
maybe_kill_child() maybe_kill_child()
try: try:
zephyr._z.cancelSubs() zephyr._z.cancelSubs()
except IOError: except OSError:
# We don't care whether we failed to cancel subs properly, but we should log it # We don't care whether we failed to cancel subs properly, but we should log it
logger.exception("") logger.exception("")
while True: while True:
@ -288,14 +288,14 @@ def parse_crypt_table(zephyr_class, instance):
# type: (Text, str) -> Optional[str] # type: (Text, str) -> Optional[str]
try: try:
crypt_table = open(os.path.join(os.environ["HOME"], ".crypt-table")) crypt_table = open(os.path.join(os.environ["HOME"], ".crypt-table"))
except IOError: except OSError:
return None return None
for line in crypt_table.readlines(): for line in crypt_table.readlines():
if line.strip() == "": if line.strip() == "":
# Ignore blank lines # Ignore blank lines
continue continue
match = re.match("^crypt-(?P<class>\S+):\s+((?P<algorithm>(AES|DES)):\s+)?(?P<keypath>\S+)$", line) match = re.match(r"^crypt-(?P<class>\S+):\s+((?P<algorithm>(AES|DES)):\s+)?(?P<keypath>\S+)$", line)
if match is None: if match is None:
# Malformed crypt_table line # Malformed crypt_table line
logger.debug("Invalid crypt_table line!") logger.debug("Invalid crypt_table line!")
@ -464,7 +464,7 @@ def zephyr_init_autoretry():
zephyr.init() zephyr.init()
backoff.succeed() backoff.succeed()
return return
except IOError: except OSError:
logger.exception("Error initializing Zephyr library (retrying). Traceback:") logger.exception("Error initializing Zephyr library (retrying). Traceback:")
backoff.fail() backoff.fail()
@ -475,12 +475,12 @@ def zephyr_load_session_autoretry(session_path):
backoff = zulip.RandomExponentialBackoff() backoff = zulip.RandomExponentialBackoff()
while backoff.keep_going(): while backoff.keep_going():
try: try:
session = open(session_path, "r").read() session = open(session_path).read()
zephyr._z.initialize() zephyr._z.initialize()
zephyr._z.load_session(session) zephyr._z.load_session(session)
zephyr.__inited = True zephyr.__inited = True
return return
except IOError: except OSError:
logger.exception("Error loading saved Zephyr session (retrying). Traceback:") logger.exception("Error loading saved Zephyr session (retrying). Traceback:")
backoff.fail() backoff.fail()
@ -494,7 +494,7 @@ def zephyr_subscribe_autoretry(sub):
zephyr.Subscriptions().add(sub) zephyr.Subscriptions().add(sub)
backoff.succeed() backoff.succeed()
return return
except IOError: except OSError:
# Probably a SERVNAK from the zephyr server, but log the # Probably a SERVNAK from the zephyr server, but log the
# traceback just in case it's something else # traceback just in case it's something else
logger.exception("Error subscribing to personals (retrying). Traceback:") logger.exception("Error subscribing to personals (retrying). Traceback:")
@ -522,7 +522,7 @@ def zephyr_to_zulip(options):
open(options.session_path, "w").write(zephyr._z.dump_session()) open(options.session_path, "w").write(zephyr._z.dump_session())
if options.logs_to_resend is not None: if options.logs_to_resend is not None:
with open(options.logs_to_resend, 'r') as log: with open(options.logs_to_resend) as log:
for ln in log: for ln in log:
try: try:
zeph = json.loads(ln) zeph = json.loads(ln)
@ -884,7 +884,7 @@ def parse_zephyr_subs(verbose=False):
logger.error("Couldn't find ~/.zephyr.subs!") logger.error("Couldn't find ~/.zephyr.subs!")
return zephyr_subscriptions return zephyr_subscriptions
for line in open(subs_file, "r").readlines(): for line in open(subs_file).readlines():
line = line.strip() line = line.strip()
if len(line) == 0: if len(line) == 0:
continue continue
@ -1039,7 +1039,7 @@ def die_gracefully(signal, frame):
try: try:
# zephyr=>zulip processes may have added subs, so run cancelSubs # zephyr=>zulip processes may have added subs, so run cancelSubs
zephyr._z.cancelSubs() zephyr._z.cancelSubs()
except IOError: except OSError:
# We don't care whether we failed to cancel subs properly, but we should log it # We don't care whether we failed to cancel subs properly, but we should log it
logger.exception("") logger.exception("")

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
if False: if False:
from typing import Any, Dict, Generator, List, Tuple from typing import Any, Dict, Generator, List, Tuple
@ -9,7 +8,7 @@ import sys
import itertools import itertools
with open("README.md", "r") as fh: with open("README.md") as fh:
long_description = fh.read() long_description = fh.read()
def version(): def version():

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import json import json
import requests import requests
import time import time
@ -34,7 +32,7 @@ requests_json_is_function = callable(requests.Response.json)
API_VERSTRING = "v1/" API_VERSTRING = "v1/"
class CountingBackoff(object): class CountingBackoff:
def __init__(self, maximum_retries=10, timeout_success_equivalent=None, delay_cap=90.0): def __init__(self, maximum_retries=10, timeout_success_equivalent=None, delay_cap=90.0):
# type: (int, Optional[float], float) -> None # type: (int, Optional[float], float) -> None
self.number_of_retries = 0 self.number_of_retries = 0
@ -70,7 +68,7 @@ class CountingBackoff(object):
class RandomExponentialBackoff(CountingBackoff): class RandomExponentialBackoff(CountingBackoff):
def fail(self): def fail(self):
# type: () -> None # type: () -> None
super(RandomExponentialBackoff, self).fail() super().fail()
# Exponential growth with ratio sqrt(2); compute random delay # Exponential growth with ratio sqrt(2); compute random delay
# between x and 2x where x is growing exponentially # between x and 2x where x is growing exponentially
delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1 delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1
@ -278,7 +276,7 @@ class MissingURLError(ZulipError):
class UnrecoverableNetworkError(ZulipError): class UnrecoverableNetworkError(ZulipError):
pass pass
class Client(object): class Client:
def __init__(self, email=None, api_key=None, config_file=None, def __init__(self, email=None, api_key=None, config_file=None,
verbose=False, retry_on_errors=True, verbose=False, retry_on_errors=True,
site=None, client=None, site=None, client=None,
@ -324,7 +322,7 @@ class Client(object):
if config_file is not None and os.path.exists(config_file): if config_file is not None and os.path.exists(config_file):
config = SafeConfigParser() config = SafeConfigParser()
with open(config_file, 'r') as f: with open(config_file) as f:
config.readfp(f, config_file) config.readfp(f, config_file)
if api_key is None: if api_key is None:
api_key = config.get("api", "key") api_key = config.get("api", "key")
@ -438,7 +436,7 @@ class Client(object):
try: try:
vendor = platform.system() vendor = platform.system()
vendor_version = platform.release() vendor_version = platform.release()
except IOError: except OSError:
# If the calling process is handling SIGCHLD, platform.system() can # If the calling process is handling SIGCHLD, platform.system() can
# fail with an IOError. See http://bugs.python.org/issue9127 # fail with an IOError. See http://bugs.python.org/issue9127
pass pass
@ -1475,7 +1473,7 @@ class Client(object):
request=request request=request
) )
class ZulipStream(object): class ZulipStream:
""" """
A Zulip stream-like object A Zulip stream-like object
""" """

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys import sys
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys import sys
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse import argparse

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# zulip-send -- Sends a message to the specified recipients. # zulip-send -- Sends a message to the specified recipients.
import sys import sys

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os import os
import sys import sys
@ -23,7 +22,7 @@ if not IS_PYPA_PACKAGE:
package_data[''].append('fixtures/*.json') package_data[''].append('fixtures/*.json')
package_data[''].append('logo.*') package_data[''].append('logo.*')
with open("README.md", "r") as fh: with open("README.md") as fh:
long_description = fh.read() long_description = fh.read()
# We should be installable with either setuptools or distutils. # We should be installable with either setuptools or distutils.

View file

@ -3,7 +3,7 @@
from typing import Any, List, Dict from typing import Any, List, Dict
import requests import requests
class BaremetricsHandler(object): class BaremetricsHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('baremetrics') self.config_info = bot_handler.get_config_info('baremetrics')
self.api_key = self.config_info['api_key'] self.api_key = self.config_info['api_key']

View file

@ -74,7 +74,7 @@ at syntax by: @mention-botname help"
right now.\nPlease try again later" right now.\nPlease try again later"
class BeeminderHandler(object): class BeeminderHandler:
''' '''
This plugin allows users to easily add datapoints This plugin allows users to easily add datapoints
towards their beeminder goals via zulip towards their beeminder goals via zulip

View file

@ -11,7 +11,7 @@ START_COMPUTER_REGEX = re.compile(
MOVE_REGEX = re.compile('do (?P<move_san>.+)$') MOVE_REGEX = re.compile('do (?P<move_san>.+)$')
RESIGN_REGEX = re.compile('resign$') RESIGN_REGEX = re.compile('resign$')
class ChessHandler(object): class ChessHandler:
def usage(self) -> str: def usage(self) -> str:
return ( return (
'Chess Bot is a bot that allows you to play chess against either ' 'Chess Bot is a bot that allows you to play chess against either '
@ -742,4 +742,4 @@ def trim_whitespace_before_newline(str_to_trim: str) -> str:
Returns: The trimmed string. Returns: The trimmed string.
""" """
return re.sub('\s+$', '', str_to_trim, flags=re.M) return re.sub(r'\s+$', '', str_to_trim, flags=re.M)

View file

@ -3,7 +3,7 @@ from zulip_bots.bots.connect_four.controller import ConnectFourModel
from typing import Any from typing import Any
class ConnectFourMessageHandler(object): class ConnectFourMessageHandler:
tokens = [':blue_circle:', ':red_circle:'] tokens = [':blue_circle:', ':red_circle:']
def parse_board(self, board: Any) -> str: def parse_board(self, board: Any) -> str:
@ -52,7 +52,7 @@ class ConnectFourBotHandler(GameAdapter):
gameMessageHandler = ConnectFourMessageHandler gameMessageHandler = ConnectFourMessageHandler
rules = '''Try to get four pieces in row, Diagonals count too!''' rules = '''Try to get four pieces in row, Diagonals count too!'''
super(ConnectFourBotHandler, self).__init__( super().__init__(
game_name, game_name,
bot_name, bot_name,
move_help_message, move_help_message,

View file

@ -4,7 +4,7 @@ from functools import reduce
from zulip_bots.game_handler import BadMoveException from zulip_bots.game_handler import BadMoveException
class ConnectFourModel(object): class ConnectFourModel:
''' '''
Object that manages running the Connect Object that manages running the Connect
Four logic for the Connect Four Bot Four logic for the Connect Four Bot

View file

@ -25,7 +25,7 @@ def is_float(value: Any) -> bool:
def round_to(x: float, digits: int) -> float: def round_to(x: float, digits: int) -> float:
return round(x, digits-int(floor(log10(abs(x))))) return round(x, digits-int(floor(log10(abs(x)))))
class ConverterHandler(object): class ConverterHandler:
''' '''
This plugin allows users to make conversions between various units, This plugin allows users to make conversions between various units,
e.g. Celsius to Fahrenheit, or kilobytes to gigabytes. e.g. Celsius to Fahrenheit, or kilobytes to gigabytes.

View file

@ -7,7 +7,7 @@ import string
from typing import Any, Dict from typing import Any, Dict
class DefineHandler(object): class DefineHandler:
''' '''
This plugin define a word that the user inputs. It This plugin define a word that the user inputs. It
looks for messages starting with '@mention-bot'. looks for messages starting with '@mention-bot'.

View file

@ -35,7 +35,7 @@ def get_bot_result(message_content: str, config: Dict[str, str], sender_id: str)
logging.exception(str(e)) logging.exception(str(e))
return 'Error. {}.'.format(str(e)) return 'Error. {}.'.format(str(e))
class DialogFlowHandler(object): class DialogFlowHandler:
''' '''
This plugin allows users to easily add their own This plugin allows users to easily add their own
DialogFlow bots to zulip DialogFlow bots to zulip

View file

@ -4,7 +4,7 @@ import re
URL = "[{name}](https://www.dropbox.com/home{path})" URL = "[{name}](https://www.dropbox.com/home{path})"
class DropboxHandler(object): class DropboxHandler:
''' '''
This bot allows you to easily share, search and upload files This bot allows you to easily share, search and upload files
between zulip and your dropbox account. between zulip and your dropbox account.
@ -60,11 +60,11 @@ def get_usage_examples() -> str:
REGEXES = dict( REGEXES = dict(
command='(ls|mkdir|read|rm|write|search|usage|help)', command='(ls|mkdir|read|rm|write|search|usage|help)',
path='(\S+)', path=r'(\S+)',
optional_path='(\S*)', optional_path=r'(\S*)',
some_text='(.+?)', some_text='(.+?)',
folder='?(?:--fd (\S+))?', folder=r'?(?:--fd (\S+))?',
max_results='?(?:--mr (\d+))?' max_results=r'?(?:--mr (\d+))?'
) )
def get_commands() -> Dict[str, Tuple[Any, List[str]]]: def get_commands() -> Dict[str, Tuple[Any, List[str]]]:
@ -137,7 +137,7 @@ def dbx_ls(client: Any, fn: str) -> str:
files_list += [" - " + URL.format(name=meta.name, path=meta.path_lower)] files_list += [" - " + URL.format(name=meta.name, path=meta.path_lower)]
msg = '\n'.join(files_list) msg = '\n'.join(files_list)
if msg is '': if msg == '':
msg = '`No files available`' msg = '`No files available`'
except Exception: except Exception:

View file

@ -17,7 +17,7 @@ def encrypt(text: str) -> str:
return newtext return newtext
class EncryptHandler(object): class EncryptHandler:
''' '''
This bot allows users to quickly encrypt messages using ROT13 encryption. This bot allows users to quickly encrypt messages using ROT13 encryption.
It encrypts/decrypts messages starting with @mention-bot. It encrypts/decrypts messages starting with @mention-bot.

View file

@ -3,7 +3,7 @@ from typing import Any, Dict
import os import os
from pathlib import Path from pathlib import Path
class FileUploaderHandler(object): class FileUploaderHandler:
def usage(self) -> str: def usage(self) -> str:
return ( return (
'This interactive bot is used to upload files (such as images) to the Zulip server:' 'This interactive bot is used to upload files (such as images) to the Zulip server:'

View file

@ -86,7 +86,7 @@ def get_flock_bot_response(content: str, config: Dict[str, str]) -> None:
result = get_flock_response(content, config) result = get_flock_response(content, config)
return result return result
class FlockHandler(object): class FlockHandler:
''' '''
This is flock bot. Now you can send messages to any of your This is flock bot. Now you can send messages to any of your
flock user without having to leave Zulip. flock user without having to leave Zulip.

View file

@ -1,7 +1,7 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Dict, Any from typing import Dict, Any
class FollowupHandler(object): class FollowupHandler:
''' '''
This plugin facilitates creating follow-up tasks when This plugin facilitates creating follow-up tasks when
you are using Zulip to conduct a virtual meeting. It you are using Zulip to conduct a virtual meeting. It

View file

@ -2,7 +2,7 @@ import requests
import re import re
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
class FrontHandler(object): class FrontHandler:
FRONT_API = "https://api2.frontapp.com/conversations/{}" FRONT_API = "https://api2.frontapp.com/conversations/{}"
COMMANDS = [ COMMANDS = [
('archive', "Archive a conversation."), ('archive', "Archive a conversation."),

View file

@ -2,7 +2,7 @@ from zulip_bots.game_handler import GameAdapter, BadMoveException
from typing import List, Any from typing import List, Any
class GameHandlerBotMessageHandler(object): class GameHandlerBotMessageHandler:
tokens = [':blue_circle:', ':red_circle:'] tokens = [':blue_circle:', ':red_circle:']
def parse_board(self, board: Any) -> str: def parse_board(self, board: Any) -> str:
@ -21,7 +21,7 @@ The first player to get 4 in a row wins!\n \
Good Luck!' Good Luck!'
class MockModel(object): class MockModel:
def __init__(self) -> None: def __init__(self) -> None:
self.current_board = 'mock board' self.current_board = 'mock board'
@ -53,12 +53,12 @@ class GameHandlerBotHandler(GameAdapter):
bot_name = 'game_handler_bot' bot_name = 'game_handler_bot'
move_help_message = '* To make your move during a game, type\n' \ move_help_message = '* To make your move during a game, type\n' \
'```move <column-number>```' '```move <column-number>```'
move_regex = 'move (\d)$' move_regex = r'move (\d)$'
model = MockModel model = MockModel
gameMessageHandler = GameHandlerBotMessageHandler gameMessageHandler = GameHandlerBotMessageHandler
rules = '' rules = ''
super(GameHandlerBotHandler, self).__init__( super().__init__(
game_name, game_name,
bot_name, bot_name,
move_help_message, move_help_message,

View file

@ -4,7 +4,7 @@ import random
from typing import List, Any, Tuple, Dict from typing import List, Any, Tuple, Dict
from zulip_bots.game_handler import GameAdapter, BadMoveException from zulip_bots.game_handler import GameAdapter, BadMoveException
class GameOfFifteenModel(object): class GameOfFifteenModel:
final_board = [[0, 1, 2], final_board = [[0, 1, 2],
[3, 4, 5], [3, 4, 5],
@ -84,7 +84,7 @@ class GameOfFifteenModel(object):
if m == moves - 1: if m == moves - 1:
return board return board
class GameOfFifteenMessageHandler(object): class GameOfFifteenMessageHandler:
tiles = { tiles = {
'0': ':grey_question:', '0': ':grey_question:',
@ -127,14 +127,14 @@ class GameOfFifteenBotHandler(GameAdapter):
bot_name = 'Game of Fifteen' bot_name = 'Game of Fifteen'
move_help_message = '* To make your move during a game, type\n' \ move_help_message = '* To make your move during a game, type\n' \
'```move <tile1> <tile2> ...```' '```move <tile1> <tile2> ...```'
move_regex = 'move [\d{1}\s]+$' move_regex = r'move [\d{1}\s]+$'
model = GameOfFifteenModel model = GameOfFifteenModel
gameMessageHandler = GameOfFifteenMessageHandler gameMessageHandler = GameOfFifteenMessageHandler
rules = '''Arrange the boards tiles from smallest to largest, left to right, rules = '''Arrange the boards tiles from smallest to largest, left to right,
top to bottom, and tiles adjacent to :grey_question: can only be moved. top to bottom, and tiles adjacent to :grey_question: can only be moved.
Final configuration will have :grey_question: in top left.''' Final configuration will have :grey_question: in top left.'''
super(GameOfFifteenBotHandler, self).__init__( super().__init__(
game_name, game_name,
bot_name, bot_name,
move_help_message, move_help_message,

View file

@ -9,7 +9,7 @@ GIPHY_TRANSLATE_API = 'http://api.giphy.com/v1/gifs/translate'
GIPHY_RANDOM_API = 'http://api.giphy.com/v1/gifs/random' GIPHY_RANDOM_API = 'http://api.giphy.com/v1/gifs/random'
class GiphyHandler(object): class GiphyHandler:
""" """
This plugin posts a GIF in response to the keywords provided by the user. This plugin posts a GIF in response to the keywords provided by the user.
Images are provided by Giphy, through the public API. Images are provided by Giphy, through the public API.

View file

@ -8,14 +8,14 @@ import requests
from typing import Dict, Any, Tuple, Union from typing import Dict, Any, Tuple, Union
class GithubHandler(object): class GithubHandler:
''' '''
This bot provides details on github issues and pull requests when they're This bot provides details on github issues and pull requests when they're
referenced in the chat. referenced in the chat.
''' '''
GITHUB_ISSUE_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/issues/{id}' GITHUB_ISSUE_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/issues/{id}'
HANDLE_MESSAGE_REGEX = re.compile("(?:([\w-]+)\/)?([\w-]+)?#(\d+)") HANDLE_MESSAGE_REGEX = re.compile(r"(?:([\w-]+)\/)?([\w-]+)?#(\d+)")
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('github_detail', optional=True) self.config_info = bot_handler.get_config_info('github_detail', optional=True)

View file

@ -63,7 +63,7 @@ def get_google_result(search_keywords: str) -> str:
logging.exception(str(e)) logging.exception(str(e))
return 'Error: Search failed. {}.'.format(e) return 'Error: Search failed. {}.'.format(e)
class GoogleSearchHandler(object): class GoogleSearchHandler:
''' '''
This plugin allows users to enter a search This plugin allows users to enter a search
term in Zulip and get the top URL sent back term in Zulip and get the top URL sent back

View file

@ -4,7 +4,7 @@
import requests import requests
from requests.exceptions import HTTPError, ConnectionError from requests.exceptions import HTTPError, ConnectionError
class GoogleTranslateHandler(object): class GoogleTranslateHandler:
''' '''
This bot will translate any messages sent to it using google translate. This bot will translate any messages sent to it using google translate.
Before using it, make sure you set up google api keys, and enable google Before using it, make sure you set up google api keys, and enable google

View file

@ -2,7 +2,7 @@
from typing import Any, Dict from typing import Any, Dict
class HelloWorldHandler(object): class HelloWorldHandler:
def usage(self) -> str: def usage(self) -> str:
return ''' return '''
This is a boilerplate bot that responds to a user query with This is a boilerplate bot that responds to a user query with

View file

@ -1,7 +1,7 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Any, Dict from typing import Any, Dict
class HelpHandler(object): class HelpHandler:
def usage(self) -> str: def usage(self) -> str:
return ''' return '''
This plugin will give info about Zulip to This plugin will give info about Zulip to

View file

@ -128,7 +128,7 @@ More information in my help""")
data = api_create_entry(new_message, team_id) data = api_create_entry(new_message, team_id)
return "Great work :thumbs_up:. New entry `{}` created!".format(data['body_formatted']) return "Great work :thumbs_up:. New entry `{}` created!".format(data['body_formatted'])
class IDoneThisHandler(object): class IDoneThisHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: Any) -> None:
global api_key, default_team global api_key, default_team
self.config_info = bot_handler.get_config_info('idonethis') self.config_info = bot_handler.get_config_info('idonethis')

View file

@ -59,7 +59,7 @@ def start_new_incident(query: str, message: Dict[str, Any], bot_handler: Any) ->
bot_handler.send_reply(message, bot_response, widget_content) bot_handler.send_reply(message, bot_response, widget_content)
def parse_answer(query: str) -> Tuple[str, str]: def parse_answer(query: str) -> Tuple[str, str]:
m = re.match('answer\s+(TICKET....)\s+(.)', query) m = re.match(r'answer\s+(TICKET....)\s+(.)', query)
if not m: if not m:
raise InvalidAnswerException() raise InvalidAnswerException()

View file

@ -2,7 +2,7 @@
from typing import Dict, Any from typing import Dict, Any
class IncrementorHandler(object): class IncrementorHandler:
META = { META = {
'name': 'Incrementor', 'name': 'Incrementor',
'description': 'Example bot to test the update_message() function.', 'description': 'Example bot to test the update_message() function.',

View file

@ -106,7 +106,7 @@ Jira Bot:
> Issue *BOTS-16* was edited! https://example.atlassian.net/browse/BOTS-16 > Issue *BOTS-16* was edited! https://example.atlassian.net/browse/BOTS-16
''' '''
class JiraHandler(object): class JiraHandler:
def usage(self) -> str: def usage(self) -> str:
return ''' return '''
Jira Bot uses the Jira REST API to interact with Jira. In order to use Jira Bot uses the Jira REST API to interact with Jira. In order to use
@ -164,14 +164,14 @@ class JiraHandler(object):
response = 'Oh no! Jira raised an error:\n > ' + ', '.join(errors) response = 'Oh no! Jira raised an error:\n > ' + ', '.join(errors)
else: else:
response = ( response = (
'**Issue *[{0}]({1})*: {2}**\n\n' '**Issue *[{}]({})*: {}**\n\n'
' - Type: *{3}*\n' ' - Type: *{}*\n'
' - Description:\n' ' - Description:\n'
' > {4}\n' ' > {}\n'
' - Creator: *{5}*\n' ' - Creator: *{}*\n'
' - Project: *{6}*\n' ' - Project: *{}*\n'
' - Priority: *{7}*\n' ' - Priority: *{}*\n'
' - Status: *{8}*\n' ' - Status: *{}*\n'
).format(key, url, summary, type_name, description, creator_name, project_name, ).format(key, url, summary, type_name, description, creator_name, project_name,
priority_name, status_name) priority_name, status_name)
elif create_match: elif create_match:

View file

@ -4,7 +4,7 @@ import logging
from typing import Any, Dict from typing import Any, Dict
class LinkShortenerHandler(object): class LinkShortenerHandler:
'''A Zulip bot that will shorten URLs ("links") in a conversation using the '''A Zulip bot that will shorten URLs ("links") in a conversation using the
goo.gl URL shortener. goo.gl URL shortener.
''' '''
@ -33,9 +33,9 @@ class LinkShortenerHandler(object):
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
REGEX_STR = ( REGEX_STR = (
'(' '('
'(?:http|https):\/\/' # This allows for the HTTP or HTTPS r'(?:http|https):\/\/' # This allows for the HTTP or HTTPS
# protocol. # protocol.
'[^"<>\{\}|\\^~[\]` ]+' # This allows for any character except '[^"<>\\{\\}|\\^~[\\]` ]+' # This allows for any character except
# for certain non-URL-safe ones. # for certain non-URL-safe ones.
')' ')'
) )

View file

@ -4,7 +4,7 @@ import requests
from typing import Any, List, Dict from typing import Any, List, Dict
import logging import logging
class MentionHandler(object): class MentionHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('mention') self.config_info = bot_handler.get_config_info('mention')
self.access_token = self.config_info['access_token'] self.access_token = self.config_info['access_token']

View file

@ -199,5 +199,5 @@ def check_win(topic_name, merels_storage):
win = mechanics.who_won(topic_name, merels_storage) win = mechanics.who_won(topic_name, merels_storage)
if win != "None": if win != "None":
merels.remove_game(topic_name) merels.remove_game(topic_name)
return "{0} wins the game!".format(win) return "{} wins the game!".format(win)
return "" return ""

View file

@ -285,7 +285,7 @@ def create_room(topic_name, merels_storage):
return response return response
else: else:
return "Failed: Cannot create an already existing game in {0}. " \ return "Failed: Cannot create an already existing game in {}. " \
"Please finish the game first.".format(topic_name) "Please finish the game first.".format(topic_name)
@ -358,7 +358,7 @@ def move_man(topic_name, p1, p2, merels_storage):
merels.update_game(data.topic_name, data.turn, data.x_taken, merels.update_game(data.topic_name, data.turn, data.x_taken,
data.o_taken, data.board, data.hill_uid, data.o_taken, data.board, data.hill_uid,
data.take_mode) data.take_mode)
return "Moved a man from ({0}, {1}) -> ({2}, {3}) for {4}.".format( return "Moved a man from ({}, {}) -> ({}, {}) for {}.".format(
p1[0], p1[1], p2[0], p2[1], data.turn) p1[0], p1[1], p2[0], p2[1], data.turn)
else: else:
raise BadMoveException("Failed: That's not a legal move. Please try again.") raise BadMoveException("Failed: That's not a legal move. Please try again.")
@ -390,7 +390,7 @@ def put_man(topic_name, v, h, merels_storage):
merels.update_game(data.topic_name, data.turn, data.x_taken, merels.update_game(data.topic_name, data.turn, data.x_taken,
data.o_taken, data.board, data.hill_uid, data.o_taken, data.board, data.hill_uid,
data.take_mode) data.take_mode)
return "Put a man to ({0}, {1}) for {2}.".format(v, h, data.turn) return "Put a man to ({}, {}) for {}.".format(v, h, data.turn)
else: else:
raise BadMoveException("Failed: That's not a legal put. Please try again.") raise BadMoveException("Failed: That's not a legal put. Please try again.")
@ -428,7 +428,7 @@ def take_man(topic_name, v, h, merels_storage):
merels.update_game(data.topic_name, data.turn, data.x_taken, merels.update_game(data.topic_name, data.turn, data.x_taken,
data.o_taken, data.board, data.hill_uid, data.o_taken, data.board, data.hill_uid,
data.take_mode) data.take_mode)
return "Taken a man from ({0}, {1}) for {2}.".format(v, h, data.turn) return "Taken a man from ({}, {}) for {}.".format(v, h, data.turn)
else: else:
raise BadMoveException("Failed: That's not a legal take. Please try again.") raise BadMoveException("Failed: That's not a legal take. Please try again.")

View file

@ -7,7 +7,7 @@ from zulip_bots.bots.merels.libraries import (
) )
from zulip_bots.game_handler import GameAdapter, SamePlayerMove, GameInstance from zulip_bots.game_handler import GameAdapter, SamePlayerMove, GameInstance
class Storage(object): class Storage:
data = {} data = {}
def __init__(self, topic_name): def __init__(self, topic_name):
@ -19,7 +19,7 @@ class Storage(object):
def get(self, topic_name): def get(self, topic_name):
return self.data[topic_name] return self.data[topic_name]
class MerelsModel(object): class MerelsModel:
def __init__(self, board: Any=None) -> None: def __init__(self, board: Any=None) -> None:
self.topic = "merels" self.topic = "merels"
@ -54,7 +54,7 @@ class MerelsModel(object):
raise SamePlayerMove(same_player_move) raise SamePlayerMove(same_player_move)
return self.current_board return self.current_board
class MerelsMessageHandler(object): class MerelsMessageHandler:
tokens = [':o_button:', ':cross_mark_button:'] tokens = [':o_button:', ':cross_mark_button:']
def parse_board(self, board: Any) -> str: def parse_board(self, board: Any) -> str:
@ -90,7 +90,7 @@ class MerelsHandler(GameAdapter):
model = MerelsModel model = MerelsModel
rules = game.getInfo() rules = game.getInfo()
gameMessageHandler = MerelsMessageHandler gameMessageHandler = MerelsMessageHandler
super(MerelsHandler, self).__init__( super().__init__(
game_name, game_name,
bot_name, bot_name,
move_help_message, move_help_message,

View file

@ -5,7 +5,7 @@ from zulip_bots.bots.monkeytestit.lib import parse
from zulip_bots.lib import NoBotConfigException from zulip_bots.lib import NoBotConfigException
class MonkeyTestitBot(object): class MonkeyTestitBot:
def __init__(self): def __init__(self):
self.api_key = "None" self.api_key = "None"
self.config = None self.config = None

View file

@ -82,7 +82,7 @@ def query_salesforce(arg: str, salesforce: simple_salesforce.Salesforce, command
raw_arg = ' -' + arg.split(' -', 1)[1] raw_arg = ' -' + arg.split(' -', 1)[1]
split_args = raw_arg.split(' -') split_args = raw_arg.split(' -')
limit_num = 5 limit_num = 5
re_limit = re.compile('-limit \d+') re_limit = re.compile(r'-limit \d+')
limit = re_limit.search(raw_arg) limit = re_limit.search(raw_arg)
if limit: if limit:
limit_num = int(limit.group().rsplit(' ', 1)[1]) limit_num = int(limit.group().rsplit(' ', 1)[1])
@ -122,7 +122,7 @@ def get_salesforce_link_details(link: str, sf: Any) -> str:
return 'No object found. Make sure it is of the supported types. Type `help` for more info.' return 'No object found. Make sure it is of the supported types. Type `help` for more info.'
class SalesforceHandler(object): class SalesforceHandler:
def usage(self) -> str: def usage(self) -> str:
return ''' return '''
This is a Salesforce bot, which can search for Contacts, This is a Salesforce bot, which can search for Contacts,
@ -136,7 +136,7 @@ class SalesforceHandler(object):
def get_salesforce_response(self, content: str) -> str: def get_salesforce_response(self, content: str) -> str:
content = content.strip() content = content.strip()
if content is '' or content == 'help': if content == '' or content == 'help':
return get_help_text() return get_help_text()
if content.startswith('http') and 'force' in content: if content.startswith('http') and 'force' in content:
return get_salesforce_link_details(content, self.sf) return get_salesforce_link_details(content, self.sf)

View file

@ -7,7 +7,7 @@ from typing import Optional, Any, Dict
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
class StackOverflowHandler(object): class StackOverflowHandler:
''' '''
This plugin facilitates searching Stack Overflow for a This plugin facilitates searching Stack Overflow for a
specific query and returns the top 3 questions from the specific query and returns the top 3 questions from the

View file

@ -1,7 +1,7 @@
import requests import requests
from typing import Dict, Any, Tuple, Union from typing import Dict, Any, Tuple, Union
class SusiHandler(object): class SusiHandler:
''' '''
Susi AI Bot Susi AI Bot
To create and know more of SUSI skills go to `https://skills.susi.ai/` To create and know more of SUSI skills go to `https://skills.susi.ai/`

View file

@ -9,7 +9,7 @@ from zulip_bots.game_handler import GameAdapter, BadMoveException
State = List[List[str]] State = List[List[str]]
class TicTacToeModel(object): class TicTacToeModel:
smarter = True smarter = True
# If smarter is True, the computer will do some extra thinking - it'll be harder for the user. # If smarter is True, the computer will do some extra thinking - it'll be harder for the user.
@ -208,7 +208,7 @@ class TicTacToeModel(object):
return board return board
class TicTacToeMessageHandler(object): class TicTacToeMessageHandler:
tokens = [':x:', ':o:'] tokens = [':x:', ':o:']
def parse_row(self, row: Tuple[int, int], row_num: int) -> str: def parse_row(self, row: Tuple[int, int], row_num: int) -> str:
@ -259,11 +259,11 @@ class ticTacToeHandler(GameAdapter):
game_name = 'Tic Tac Toe' game_name = 'Tic Tac Toe'
bot_name = 'tictactoe' bot_name = 'tictactoe'
move_help_message = '* To move during a game, type\n`move <number>` or `<number>`' move_help_message = '* To move during a game, type\n`move <number>` or `<number>`'
move_regex = '(move (\d)$)|((\d)$)' move_regex = r'(move (\d)$)|((\d)$)'
model = TicTacToeModel model = TicTacToeModel
gameMessageHandler = TicTacToeMessageHandler gameMessageHandler = TicTacToeMessageHandler
rules = '''Try to get three in horizontal or vertical or diagonal row to win the game.''' rules = '''Try to get three in horizontal or vertical or diagonal row to win the game.'''
super(ticTacToeHandler, self).__init__( super().__init__(
game_name, game_name,
bot_name, bot_name,
move_help_message, move_help_message,

View file

@ -14,7 +14,7 @@ supported_commands = [
INVALID_ARGUMENTS_ERROR_MESSAGE = 'Invalid Arguments.' INVALID_ARGUMENTS_ERROR_MESSAGE = 'Invalid Arguments.'
RESPONSE_ERROR_MESSAGE = 'Invalid Response. Please check configuration and parameters.' RESPONSE_ERROR_MESSAGE = 'Invalid Response. Please check configuration and parameters.'
class TrelloHandler(object): class TrelloHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('trello') self.config_info = bot_handler.get_config_info('trello')
self.api_key = self.config_info['api_key'] self.api_key = self.config_info['api_key']

View file

@ -65,7 +65,7 @@ def start_new_quiz(message: Dict[str, Any], bot_handler: Any) -> None:
bot_handler.send_reply(message, bot_response, widget_content) bot_handler.send_reply(message, bot_response, widget_content)
def parse_answer(query: str) -> Tuple[str, str]: def parse_answer(query: str) -> Tuple[str, str]:
m = re.match('answer\s+(Q...)\s+(.)', query) m = re.match(r'answer\s+(Q...)\s+(.)', query)
if not m: if not m:
raise InvalidAnswerException() raise InvalidAnswerException()

View file

@ -3,7 +3,7 @@ import tweepy
from typing import Dict, Any, Union, List, Tuple, Optional from typing import Dict, Any, Union, List, Tuple, Optional
class TwitpostBot(object): class TwitpostBot:
def usage(self) -> str: def usage(self) -> str:
return ''' This bot posts on twitter from zulip chat itself. return ''' This bot posts on twitter from zulip chat itself.

View file

@ -5,7 +5,7 @@ import os
from typing import Any, Dict, List, Tuple, Callable, Set, Union from typing import Any, Dict, List, Tuple, Callable, Set, Union
class VirtualFsHandler(object): class VirtualFsHandler:
META = { META = {
'name': 'VirtualFs', 'name': 'VirtualFs',
'description': 'Provides a simple, permanent file system to store and retrieve strings.', 'description': 'Provides a simple, permanent file system to store and retrieve strings.',
@ -112,8 +112,8 @@ def sample_conversation() -> List[Tuple[str, str]]:
REGEXES = dict( REGEXES = dict(
command='(cd|ls|mkdir|read|rmdir|rm|write|pwd)', command='(cd|ls|mkdir|read|rmdir|rm|write|pwd)',
path='(\S+)', path=r'(\S+)',
optional_path='(\S*)', optional_path=r'(\S*)',
some_text='(.+)', some_text='(.+)',
) )

View file

@ -7,7 +7,7 @@ from typing import Any, Dict
api_url = 'http://api.openweathermap.org/data/2.5/weather' api_url = 'http://api.openweathermap.org/data/2.5/weather'
class WeatherHandler(object): class WeatherHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: Any) -> None:
self.api_key = bot_handler.get_config_info('weather')['key'] self.api_key = bot_handler.get_config_info('weather')['key']
self.response_pattern = 'Weather in {}, {}:\n{:.2f} F / {:.2f} C\n{}' self.response_pattern = 'Weather in {}, {}:\n{:.2f} F / {:.2f} C\n{}'

View file

@ -8,7 +8,7 @@ from typing import Optional, Any, Dict
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
class WikipediaHandler(object): class WikipediaHandler:
''' '''
This plugin facilitates searching Wikipedia for a This plugin facilitates searching Wikipedia for a
specific key term and returns the top 3 articles from the specific key term and returns the top 3 articles from the

View file

@ -5,7 +5,7 @@ import wit
import sys import sys
import importlib.util import importlib.util
class WitaiHandler(object): class WitaiHandler:
def usage(self) -> str: def usage(self) -> str:
return ''' return '''
Wit.ai bot uses pywit API to interact with Wit.ai. In order to use Wit.ai bot uses pywit API to interact with Wit.ai. In order to use

View file

@ -8,7 +8,7 @@ from typing import Any, Dict, Optional
XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json' XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json'
LATEST_XKCD_URL = 'https://xkcd.com/info.0.json' LATEST_XKCD_URL = 'https://xkcd.com/info.0.json'
class XkcdHandler(object): class XkcdHandler:
''' '''
This plugin provides several commands that can be used for fetch a comic This plugin provides several commands that can be used for fetch a comic
strip from https://xkcd.com. The bot looks for messages starting with strip from https://xkcd.com. The bot looks for messages starting with
@ -39,7 +39,7 @@ class XkcdHandler(object):
xkcd_bot_response = get_xkcd_bot_response(message, quoted_name) xkcd_bot_response = get_xkcd_bot_response(message, quoted_name)
bot_handler.send_reply(message, xkcd_bot_response) bot_handler.send_reply(message, xkcd_bot_response)
class XkcdBotCommand(object): class XkcdBotCommand:
LATEST = 0 LATEST = 0
RANDOM = 1 RANDOM = 1
COMIC_ID = 2 COMIC_ID = 2

View file

@ -28,7 +28,7 @@ class ServiceUnavailableError(Exception):
'''raise this when the service is unavailable.''' '''raise this when the service is unavailable.'''
class YodaSpeakHandler(object): class YodaSpeakHandler:
''' '''
This bot will allow users to translate a sentence into 'Yoda speak'. This bot will allow users to translate a sentence into 'Yoda speak'.
It looks for messages starting with '@mention-bot'. It looks for messages starting with '@mention-bot'.

View file

@ -7,7 +7,7 @@ from typing import Dict, Any, Union, List, Tuple, Optional
commands_list = ('list', 'top', 'help') commands_list = ('list', 'top', 'help')
class YoutubeHandler(object): class YoutubeHandler:
def usage(self) -> str: def usage(self) -> str:
return ''' return '''

Some files were not shown because too many files have changed in this diff Show more