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 = [
# This linter should be first since bash_rules depends on it.
{'pattern': '\s+$',
{'pattern': r'\s+$',
'strip': '\n',
'description': 'Fix trailing whitespace'},
{'pattern': '\t',
@ -15,11 +15,11 @@ whitespace_rules = [
'description': 'Fix tab-based whitespace'},
] # 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.
# This rule finds one space trailing a non-space, three or more trailing spaces, and
# spaces on an empty line.
{'pattern': '((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)',
{'pattern': r'((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)',
'strip': '\n',
'description': 'Fix trailing whitespace'},
{'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(
langs=['py'],
rules=[
{'pattern': '".*"%\([a-z_].*\)?$',
{'pattern': r'".*"%\([a-z_].*\)?$',
'description': 'Missing space around "%"'},
{'pattern': "'.*'%\([a-z_].*\)?$",
{'pattern': r"'.*'%\([a-z_].*\)?$",
'description': 'Missing space around "%"'},
# This rule is constructed with + to avoid triggering on itself
{'pattern': " =" + '[^ =>~"]',
'description': 'Missing whitespace after "="'},
{'pattern': '":\w[^"]*$',
{'pattern': r'":\w[^"]*$',
'description': 'Missing whitespace after ":"'},
{'pattern': "':\w[^']*$",
{'pattern': r"':\w[^']*$",
'description': 'Missing whitespace after ":"'},
{'pattern': "^\s+[#]\w",
{'pattern': r"^\s+[#]\w",
'strip': '\n',
'description': 'Missing whitespace after "#"'},
{'pattern': "assertEquals[(]",
@ -67,26 +67,26 @@ python_rules = RuleList(
# 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
# this rule.
{'pattern': ' % [a-zA-Z0-9_.]*\)?$',
{'pattern': r' % [a-zA-Z0-9_.]*\)?$',
'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'},
{'pattern': '__future__',
'include_only': set(['zulip_bots/zulip_bots/bots/']),
'include_only': {'zulip_bots/zulip_bots/bots/'},
'description': 'Bots no longer need __future__ imports.'},
{'pattern': '#!/usr/bin/env python$',
'include_only': set(['zulip_bots/']),
'include_only': {'zulip_bots/'},
'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'
' 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',
'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):'],
'description': 'Bot test cases should directly inherit from BotTestCase *and* DefaultTests.'},
{'pattern': '\(DefaultTests, BotTestCase\)',
{'pattern': r'\(DefaultTests, BotTestCase\)',
'bad_lines': ['class TestSomeBot(DefaultTests, BotTestCase):'],
'good_lines': ['class TestSomeBot(BotTestCase, DefaultTests):'],
'description': 'Bot test cases should inherit from BotTestCase before DefaultTests.'},
@ -117,9 +117,9 @@ json_rules = RuleList(
)
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"},
{'pattern': '[^\/\-\.\"\'\_\=\>]([gG]ithub)[^\.\-\_\"\<]', # exclude usage in hrefs/divs
{'pattern': '[^\\/\\-\\.\"\'\\_\\=\\>]([gG]ithub)[^\\.\\-\\_\"\\<]', # exclude usage in hrefs/divs
'description': "github should be spelled GitHub"},
{'pattern': '[oO]rganisation', # exclude usage in hrefs/divs
'description': "Organization is spelled with a z"},
@ -136,7 +136,7 @@ markdown_docs_length_exclude = {
markdown_rules = RuleList(
langs=['md'],
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.'}
],
max_length=120,

View file

@ -201,7 +201,7 @@ def print_bots(bots: List[Any], pretty_print: bool) -> None:
print_bots_pretty(bots)
else:
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:
if len(bots) == 0:

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
@ -42,7 +41,7 @@ def create_pipe_event(to_client: zulip.Client, from_bot: Dict[str, Any],
"type": "stream",
"to": to_bot["stream"],
"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_image": msg.get("has_image", False),
"has_link": msg.get("has_link", False)

View file

@ -116,7 +116,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
"to": self.stream,
"subject": self.topic,
"content": content,
"content": "**{0}**: {1}".format(sender, content),
"content": "**{}**: {}".format(sender, content),
}))
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
# Note that this is the Codebase API Username, found in the Settings page
# for your account

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Zulip mirror of Codebase HQ activity
# The "zulip_codebase_mirror" script is run continuously, possibly on a work
@ -256,7 +255,7 @@ def run_mirror():
since = default_since()
else:
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)))
since = default_since()
@ -289,13 +288,13 @@ def check_permissions():
if config.LOG_FILE:
try:
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(str(e))
# check that the resume file can be written (this creates if it doesn't exist)
try:
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(str(e))

View file

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

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
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]]
if branch in ["master", "test-post-receive"]:
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

View file

@ -100,7 +100,7 @@ def get_credentials():
return credentials
except client.Error:
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.")

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 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(
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,
node=node[:12])

View file

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

View file

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

View file

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

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# https://github.com/python/mypy/issues/1141
from typing import Dict, Text, Optional
@ -25,7 +23,7 @@ def deployment_notice_destination(branch):
# type: (str) -> Optional[Dict[str, Text]]
if branch in ['master', 'test-post-receive']:
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

View file

@ -339,7 +339,7 @@ def setP4ExecBit(file, mode):
if not isModeExec(mode):
p4Type = getP4OpenedType(file)
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] == "+":
p4Type = p4Type[0:-1]
@ -349,7 +349,7 @@ def getP4OpenedType(file):
# Returns the perforce file type for the given file.
result = p4_read_pipe(["opened", wildcard_encode(file)])
match = re.match(".*\((.+)\)\r?$", result)
match = re.match(".*\\((.+)\\)\r?$", result)
if match:
return match.group(1)
else:
@ -378,7 +378,7 @@ def getGitTags():
def diffTreePattern():
# 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.
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:
yield pattern
@ -820,13 +820,13 @@ def wildcard_present(path):
m = re.search("[*#@%]", path)
return m is not None
class Command(object):
class Command:
def __init__(self):
self.usage = "usage: %prog [options]"
self.needsGit = True
self.verbose = False
class P4UserMap(object):
class P4UserMap:
def __init__(self):
self.userMapFromPerforceServer = False
self.myP4UserId = None
@ -883,7 +883,7 @@ class P4UserMap(object):
for line in lines:
entry = line.strip().split("\t")
self.users[entry[0]] = entry[1]
except IOError:
except OSError:
self.getUserMapFromPerforceServer()
class P4Debug(Command):
@ -1056,7 +1056,7 @@ class P4Submit(Command, P4UserMap):
(handle, outFileName) = tempfile.mkstemp(dir='.')
try:
outFile = os.fdopen(handle, "w+")
inFile = open(file, "r")
inFile = open(file)
regexp = re.compile(pattern, re.VERBOSE)
for line in inFile.readlines():
line = regexp.sub(r'$\1$', line)
@ -1391,7 +1391,7 @@ class P4Submit(Command, P4UserMap):
newdiff += "==== new file ====\n"
newdiff += "--- /dev/null\n"
newdiff += "+++ %s\n" % newFile
f = open(newFile, "r")
f = open(newFile)
for line in f.readlines():
newdiff += "+" + line
f.close()
@ -1773,7 +1773,7 @@ class P4Submit(Command, P4UserMap):
return True
class View(object):
class View:
"""Represent a p4 view ("p4 help views"), and map files in a
repo according to the view."""
@ -2377,7 +2377,7 @@ class P4Sync(Command, P4UserMap):
# find the corresponding git commit; take the oldest commit
changelist = int(change['change'])
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:
print("could not find git commit for changelist %d" % changelist)
else:
@ -2657,7 +2657,7 @@ class P4Sync(Command, P4UserMap):
self.initialParent)
# only needed once, to connect to the previous commit
self.initialParent = ""
except IOError:
except OSError:
print(self.gitError.read())
sys.exit(1)
@ -2712,7 +2712,7 @@ class P4Sync(Command, P4UserMap):
self.updateOptionDict(details)
try:
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(self.gitError.read())
@ -2878,7 +2878,7 @@ class P4Sync(Command, P4UserMap):
if len(self.changesFile) == 0:
revision = "#head"
p = re.sub ("\.\.\.$", "", p)
p = re.sub (r"\.\.\.$", "", p)
if not p.endswith("/"):
p += "/"

View file

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

View file

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

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# RSS integration for Zulip
#
@ -174,9 +173,9 @@ def send_zulip(entry, feed_name):
return client.send_message(message)
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]
except IOError:
except OSError:
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,
@ -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
try:
with open(feed_file, "r") as f:
old_feed_hashes = dict((line.strip(), True) for line in f.readlines()) # type: Dict[str, bool]
except IOError:
with open(feed_file) as f:
old_feed_hashes = {line.strip(): True for line in f.readlines()} # type: Dict[str, bool]
except OSError:
old_feed_hashes = {}
new_hashes = [] # type: List[str]

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Zulip notification post-commit hook.
#
@ -39,7 +38,7 @@ path, rev = sys.argv[1:] # type: Tuple[Text, Text]
path = "file://" + path
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'],
rev,
path.split('/')[-1],

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
from typing import Dict, Optional, Text
# Change these values to configure authentication for the plugin
@ -25,7 +23,7 @@ def commit_notice_destination(path, commit):
repo = path.split('/')[-1]
if repo not in ["evil-master-plan", "my-super-secret-repository"]:
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

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# Zulip trac plugin -- sends zulips when tickets change.
#
# 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
# Change these constants to configure the plugin:

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# An easy Trello integration for Zulip.
@ -39,7 +38,7 @@ def get_model_id(options):
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')
sys.exit(1)
@ -77,7 +76,7 @@ def get_webhook_id(options, id_model):
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)
sys.exit(1)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@
from typing import Any, List, Dict
import requests
class BaremetricsHandler(object):
class BaremetricsHandler:
def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('baremetrics')
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"
class BeeminderHandler(object):
class BeeminderHandler:
'''
This plugin allows users to easily add datapoints
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>.+)$')
RESIGN_REGEX = re.compile('resign$')
class ChessHandler(object):
class ChessHandler:
def usage(self) -> str:
return (
'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.
"""
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
class ConnectFourMessageHandler(object):
class ConnectFourMessageHandler:
tokens = [':blue_circle:', ':red_circle:']
def parse_board(self, board: Any) -> str:
@ -52,7 +52,7 @@ class ConnectFourBotHandler(GameAdapter):
gameMessageHandler = ConnectFourMessageHandler
rules = '''Try to get four pieces in row, Diagonals count too!'''
super(ConnectFourBotHandler, self).__init__(
super().__init__(
game_name,
bot_name,
move_help_message,

View file

@ -4,7 +4,7 @@ from functools import reduce
from zulip_bots.game_handler import BadMoveException
class ConnectFourModel(object):
class ConnectFourModel:
'''
Object that manages running the Connect
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:
return round(x, digits-int(floor(log10(abs(x)))))
class ConverterHandler(object):
class ConverterHandler:
'''
This plugin allows users to make conversions between various units,
e.g. Celsius to Fahrenheit, or kilobytes to gigabytes.

View file

@ -7,7 +7,7 @@ import string
from typing import Any, Dict
class DefineHandler(object):
class DefineHandler:
'''
This plugin define a word that the user inputs. It
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))
return 'Error. {}.'.format(str(e))
class DialogFlowHandler(object):
class DialogFlowHandler:
'''
This plugin allows users to easily add their own
DialogFlow bots to zulip

View file

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

View file

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

View file

@ -3,7 +3,7 @@ from typing import Any, Dict
import os
from pathlib import Path
class FileUploaderHandler(object):
class FileUploaderHandler:
def usage(self) -> str:
return (
'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)
return result
class FlockHandler(object):
class FlockHandler:
'''
This is flock bot. Now you can send messages to any of your
flock user without having to leave Zulip.

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@ import random
from typing import List, Any, Tuple, Dict
from zulip_bots.game_handler import GameAdapter, BadMoveException
class GameOfFifteenModel(object):
class GameOfFifteenModel:
final_board = [[0, 1, 2],
[3, 4, 5],
@ -84,7 +84,7 @@ class GameOfFifteenModel(object):
if m == moves - 1:
return board
class GameOfFifteenMessageHandler(object):
class GameOfFifteenMessageHandler:
tiles = {
'0': ':grey_question:',
@ -127,14 +127,14 @@ class GameOfFifteenBotHandler(GameAdapter):
bot_name = 'Game of Fifteen'
move_help_message = '* To make your move during a game, type\n' \
'```move <tile1> <tile2> ...```'
move_regex = 'move [\d{1}\s]+$'
move_regex = r'move [\d{1}\s]+$'
model = GameOfFifteenModel
gameMessageHandler = GameOfFifteenMessageHandler
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.
Final configuration will have :grey_question: in top left.'''
super(GameOfFifteenBotHandler, self).__init__(
super().__init__(
game_name,
bot_name,
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'
class GiphyHandler(object):
class GiphyHandler:
"""
This plugin posts a GIF in response to the keywords provided by the user.
Images are provided by Giphy, through the public API.

View file

@ -8,14 +8,14 @@ import requests
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
referenced in the chat.
'''
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:
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))
return 'Error: Search failed. {}.'.format(e)
class GoogleSearchHandler(object):
class GoogleSearchHandler:
'''
This plugin allows users to enter a search
term in Zulip and get the top URL sent back

View file

@ -4,7 +4,7 @@
import requests
from requests.exceptions import HTTPError, ConnectionError
class GoogleTranslateHandler(object):
class GoogleTranslateHandler:
'''
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

View file

@ -2,7 +2,7 @@
from typing import Any, Dict
class HelloWorldHandler(object):
class HelloWorldHandler:
def usage(self) -> str:
return '''
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.
from typing import Any, Dict
class HelpHandler(object):
class HelpHandler:
def usage(self) -> str:
return '''
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)
return "Great work :thumbs_up:. New entry `{}` created!".format(data['body_formatted'])
class IDoneThisHandler(object):
class IDoneThisHandler:
def initialize(self, bot_handler: Any) -> None:
global api_key, default_team
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)
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:
raise InvalidAnswerException()

View file

@ -2,7 +2,7 @@
from typing import Dict, Any
class IncrementorHandler(object):
class IncrementorHandler:
META = {
'name': 'Incrementor',
'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
'''
class JiraHandler(object):
class JiraHandler:
def usage(self) -> str:
return '''
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)
else:
response = (
'**Issue *[{0}]({1})*: {2}**\n\n'
' - Type: *{3}*\n'
'**Issue *[{}]({})*: {}**\n\n'
' - Type: *{}*\n'
' - Description:\n'
' > {4}\n'
' - Creator: *{5}*\n'
' - Project: *{6}*\n'
' - Priority: *{7}*\n'
' - Status: *{8}*\n'
' > {}\n'
' - Creator: *{}*\n'
' - Project: *{}*\n'
' - Priority: *{}*\n'
' - Status: *{}*\n'
).format(key, url, summary, type_name, description, creator_name, project_name,
priority_name, status_name)
elif create_match:

View file

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

View file

@ -4,7 +4,7 @@ import requests
from typing import Any, List, Dict
import logging
class MentionHandler(object):
class MentionHandler:
def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('mention')
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)
if win != "None":
merels.remove_game(topic_name)
return "{0} wins the game!".format(win)
return "{} wins the game!".format(win)
return ""

View file

@ -285,7 +285,7 @@ def create_room(topic_name, merels_storage):
return response
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)
@ -358,7 +358,7 @@ def move_man(topic_name, p1, p2, merels_storage):
merels.update_game(data.topic_name, data.turn, data.x_taken,
data.o_taken, data.board, data.hill_uid,
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)
else:
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,
data.o_taken, data.board, data.hill_uid,
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:
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,
data.o_taken, data.board, data.hill_uid,
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:
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
class Storage(object):
class Storage:
data = {}
def __init__(self, topic_name):
@ -19,7 +19,7 @@ class Storage(object):
def get(self, topic_name):
return self.data[topic_name]
class MerelsModel(object):
class MerelsModel:
def __init__(self, board: Any=None) -> None:
self.topic = "merels"
@ -54,7 +54,7 @@ class MerelsModel(object):
raise SamePlayerMove(same_player_move)
return self.current_board
class MerelsMessageHandler(object):
class MerelsMessageHandler:
tokens = [':o_button:', ':cross_mark_button:']
def parse_board(self, board: Any) -> str:
@ -90,7 +90,7 @@ class MerelsHandler(GameAdapter):
model = MerelsModel
rules = game.getInfo()
gameMessageHandler = MerelsMessageHandler
super(MerelsHandler, self).__init__(
super().__init__(
game_name,
bot_name,
move_help_message,

View file

@ -5,7 +5,7 @@ from zulip_bots.bots.monkeytestit.lib import parse
from zulip_bots.lib import NoBotConfigException
class MonkeyTestitBot(object):
class MonkeyTestitBot:
def __init__(self):
self.api_key = "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]
split_args = raw_arg.split(' -')
limit_num = 5
re_limit = re.compile('-limit \d+')
re_limit = re.compile(r'-limit \d+')
limit = re_limit.search(raw_arg)
if limit:
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.'
class SalesforceHandler(object):
class SalesforceHandler:
def usage(self) -> str:
return '''
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:
content = content.strip()
if content is '' or content == 'help':
if content == '' or content == 'help':
return get_help_text()
if content.startswith('http') and 'force' in content:
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.
class StackOverflowHandler(object):
class StackOverflowHandler:
'''
This plugin facilitates searching Stack Overflow for a
specific query and returns the top 3 questions from the

View file

@ -1,7 +1,7 @@
import requests
from typing import Dict, Any, Tuple, Union
class SusiHandler(object):
class SusiHandler:
'''
Susi AI Bot
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]]
class TicTacToeModel(object):
class TicTacToeModel:
smarter = True
# 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
class TicTacToeMessageHandler(object):
class TicTacToeMessageHandler:
tokens = [':x:', ':o:']
def parse_row(self, row: Tuple[int, int], row_num: int) -> str:
@ -259,11 +259,11 @@ class ticTacToeHandler(GameAdapter):
game_name = 'Tic Tac Toe'
bot_name = 'tictactoe'
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
gameMessageHandler = TicTacToeMessageHandler
rules = '''Try to get three in horizontal or vertical or diagonal row to win the game.'''
super(ticTacToeHandler, self).__init__(
super().__init__(
game_name,
bot_name,
move_help_message,

View file

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

View file

@ -3,7 +3,7 @@ import tweepy
from typing import Dict, Any, Union, List, Tuple, Optional
class TwitpostBot(object):
class TwitpostBot:
def usage(self) -> str:
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
class VirtualFsHandler(object):
class VirtualFsHandler:
META = {
'name': 'VirtualFs',
'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(
command='(cd|ls|mkdir|read|rmdir|rm|write|pwd)',
path='(\S+)',
optional_path='(\S*)',
path=r'(\S+)',
optional_path=r'(\S*)',
some_text='(.+)',
)

View file

@ -7,7 +7,7 @@ from typing import Any, Dict
api_url = 'http://api.openweathermap.org/data/2.5/weather'
class WeatherHandler(object):
class WeatherHandler:
def initialize(self, bot_handler: Any) -> None:
self.api_key = bot_handler.get_config_info('weather')['key']
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.
class WikipediaHandler(object):
class WikipediaHandler:
'''
This plugin facilitates searching Wikipedia for a
specific key term and returns the top 3 articles from the

View file

@ -5,7 +5,7 @@ import wit
import sys
import importlib.util
class WitaiHandler(object):
class WitaiHandler:
def usage(self) -> str:
return '''
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'
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
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)
bot_handler.send_reply(message, xkcd_bot_response)
class XkcdBotCommand(object):
class XkcdBotCommand:
LATEST = 0
RANDOM = 1
COMIC_ID = 2

View file

@ -28,7 +28,7 @@ class ServiceUnavailableError(Exception):
'''raise this when the service is unavailable.'''
class YodaSpeakHandler(object):
class YodaSpeakHandler:
'''
This bot will allow users to translate a sentence into 'Yoda speak'.
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')
class YoutubeHandler(object):
class YoutubeHandler:
def usage(self) -> str:
return '''

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