python: Replace list literal concatenation with * unpacking.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-09-01 21:59:07 -07:00 committed by Tim Abbott
parent a5dbab8fb0
commit 1ded51aa9d
45 changed files with 156 additions and 141 deletions

View File

@ -302,7 +302,7 @@ class TestGetChartData(ZulipTestCase):
data = result.json()
end_times = [ceiling_to_day(self.realm.date_created) + timedelta(days=i) for i in range(-1, 4)]
self.assertEqual(data['end_times'], [datetime_to_timestamp(dt) for dt in end_times])
self.assertEqual(data['everyone'], {'_1day': [0]+self.data(100), '_15day': [0]+self.data(100), 'all_time': [0]+self.data(100)})
self.assertEqual(data['everyone'], {'_1day': [0, *self.data(100)], '_15day': [0, *self.data(100)], 'all_time': [0, *self.data(100)]})
def test_non_existent_chart(self) -> None:
result = self.client_get('/json/analytics/chart_data',

View File

@ -20,9 +20,9 @@ vendor = distro_info['ID']
os_version = distro_info['VERSION_ID']
VENV_DEPENDENCIES = get_venv_dependencies(vendor, os_version)
if "debian" in os_families():
run(["apt-get", "-y", "install"] + VENV_DEPENDENCIES)
run(["apt-get", "-y", "install", *VENV_DEPENDENCIES])
elif "fedora" in os_families():
run(["yum", "-y", "install"] + VENV_DEPENDENCIES)
run(["yum", "-y", "install", *VENV_DEPENDENCIES])
else:
print("Unsupported platform: {}".format(distro_info['ID']))
sys.exit(1)

View File

@ -21,9 +21,9 @@ args = parser.parse_args()
# install dependencies for setting up the virtualenv
distro_info = parse_os_release()
if "debian" in os_families():
run(["apt-get", "-y", "install"] + THUMBOR_VENV_DEPENDENCIES)
run(["apt-get", "-y", "install", *THUMBOR_VENV_DEPENDENCIES])
elif "fedora" in os_families():
run(["yum", "-y", "install"] + YUM_THUMBOR_VENV_DEPENDENCIES)
run(["yum", "-y", "install", *YUM_THUMBOR_VENV_DEPENDENCIES])
else:
print("Unsupported platform: {}".format(distro_info['ID']))
sys.exit(1)

View File

@ -83,7 +83,7 @@ def do_yarn_install(
shutil.copytree("node_modules/", cached_node_modules, symlinks=True)
if os.environ.get('CUSTOM_CA_CERTIFICATES'):
run([YARN_BIN, "config", "set", "cafile", os.environ['CUSTOM_CA_CERTIFICATES']])
run([YARN_BIN, "install", "--non-interactive", "--frozen-lockfile"] + yarn_args,
run([YARN_BIN, "install", "--non-interactive", "--frozen-lockfile", *yarn_args],
cwd=target_path)
with open(success_stamp, 'w'):
pass

View File

@ -59,12 +59,14 @@ COMMON_YUM_VENV_DEPENDENCIES = [
"jq",
]
REDHAT_VENV_DEPENDENCIES = COMMON_YUM_VENV_DEPENDENCIES + [
REDHAT_VENV_DEPENDENCIES = [
*COMMON_YUM_VENV_DEPENDENCIES,
"python36-devel",
"python-virtualenv",
]
FEDORA_VENV_DEPENDENCIES = COMMON_YUM_VENV_DEPENDENCIES + [
FEDORA_VENV_DEPENDENCIES = [
*COMMON_YUM_VENV_DEPENDENCIES,
"python3-pip",
"virtualenv", # see https://unix.stackexchange.com/questions/27877/install-virtualenv-on-fedora-16
]

View File

@ -65,7 +65,7 @@ try:
# version is much better for fixing bugs in the upgrade process).
deploy_path = deploy_path.strip()
os.chdir(deploy_path)
subprocess.check_call([os.path.abspath("./scripts/lib/upgrade-zulip-stage-2"), deploy_path]
+ deploy_options)
subprocess.check_call([os.path.abspath("./scripts/lib/upgrade-zulip-stage-2"), deploy_path,
*deploy_options])
finally:
release_deployment_lock()

View File

@ -78,6 +78,6 @@ try:
overwrite_symlink(deploy_path, os.path.join(DEPLOYMENTS_DIR, "next"))
subprocess.check_call([os.path.join(deploy_path, "scripts", "lib", "upgrade-zulip-stage-2"),
deploy_path, "--from-git"] + deploy_options)
deploy_path, "--from-git", *deploy_options])
finally:
release_deployment_lock()

View File

@ -104,7 +104,7 @@ def shutdown_server() -> None:
core_server_services.append("zulip-thumbor")
logging.info("Stopping Zulip...")
subprocess.check_call(["supervisorctl", "stop"] + core_server_services + worker_services,
subprocess.check_call(["supervisorctl", "stop", *core_server_services, *worker_services],
preexec_fn=su_to_zulip)
IS_SERVER_UP = False

View File

@ -460,7 +460,7 @@ def is_root() -> bool:
def run_as_root(args: List[str], **kwargs: Any) -> None:
sudo_args = kwargs.pop('sudo_args', [])
if not is_root():
args = ['sudo'] + sudo_args + ['--'] + args
args = ['sudo', *sudo_args, '--', *args]
run(args, **kwargs)
def assert_not_running_as_root() -> None:

View File

@ -62,7 +62,7 @@ def main() -> None:
print("Cleaning orphaned/unused caches...")
# Call 'clean-unused-caches' script to clean any orphaned/unused caches.
subprocess.check_call([os.path.join(ZULIP_PATH, "scripts/lib/clean-unused-caches")] + sys.argv[1:])
subprocess.check_call([os.path.join(ZULIP_PATH, "scripts/lib/clean-unused-caches"), *sys.argv[1:]])
print("Done!")
if __name__ == "__main__":

View File

@ -75,10 +75,10 @@ else:
logging.info("Stopping workers")
subprocess.check_call(["supervisorctl", "stop", "zulip-workers:*"])
logging.info("Stopping server core")
subprocess.check_call(["supervisorctl", "stop"] + core_server_services)
subprocess.check_call(["supervisorctl", "stop", *core_server_services])
logging.info("Starting server core")
subprocess.check_call(["supervisorctl", "start"] + core_server_services)
subprocess.check_call(["supervisorctl", "start", *core_server_services])
logging.info("Starting workers")
subprocess.check_call(["supervisorctl", "start", "zulip-workers:*"])

View File

@ -75,7 +75,7 @@ def restore_backup(tarball_file: IO[bytes]) -> None:
os.mkdir(os.path.join(tmp, "zulip-backup"))
tarball_file.seek(0, 0)
run(["tar", "-C", tmp] + transform_args + ["-xPz"], stdin=tarball_file)
run(["tar", "-C", tmp, *transform_args, "-xPz"], stdin=tarball_file)
# Now, extract the the database backup, destroy the old
# database, and create a new, empty database.

View File

@ -50,7 +50,7 @@ if (distro_info['ID'], distro_info['VERSION_ID']) in [('ubuntu', '20.04')]:
puppet_env["RUBYOPT"] = "-W0"
if not args.noop and not args.force:
subprocess.check_call(puppet_cmd + ['--noop', '--show_diff'], env=puppet_env)
subprocess.check_call([*puppet_cmd, '--noop', '--show_diff'], env=puppet_env)
do_apply = None
while do_apply != 'y':
@ -60,7 +60,7 @@ if not args.noop and not args.force:
if do_apply == '' or do_apply == 'n':
sys.exit(0)
ret = subprocess.call(puppet_cmd + ['--detailed-exitcodes'], env=puppet_env)
ret = subprocess.call([*puppet_cmd, '--detailed-exitcodes'], env=puppet_env)
# ret = 0 => no changes, no errors
# ret = 2 => changes, no errors
# ret = 4 => no changes, yes errors

View File

@ -66,10 +66,11 @@ class TagInfo:
self.classes = classes
self.ids = ids
self.token = token
self.words = \
[self.tag] + \
['.' + s for s in classes] + \
['#' + s for s in ids]
self.words = [
self.tag,
*('.' + s for s in classes),
*('#' + s for s in ids),
]
def text(self) -> str:
s = self.tag

View File

@ -145,64 +145,68 @@ COMMON_DEPENDENCIES = [
# Puppeteer dependencies end here.
]
UBUNTU_COMMON_APT_DEPENDENCIES = COMMON_DEPENDENCIES + [
UBUNTU_COMMON_APT_DEPENDENCIES = [
*COMMON_DEPENDENCIES,
"redis-server",
"hunspell-en-us",
"puppet-lint",
"netcat", # Used for flushing memcached
"default-jre-headless", # Required by vnu-jar
] + THUMBOR_VENV_DEPENDENCIES
*THUMBOR_VENV_DEPENDENCIES,
]
COMMON_YUM_DEPENDENCIES = COMMON_DEPENDENCIES + [
COMMON_YUM_DEPENDENCIES = [
*COMMON_DEPENDENCIES,
"redis",
"hunspell-en-US",
"rubygem-puppet-lint",
"nmap-ncat",
] + YUM_THUMBOR_VENV_DEPENDENCIES
*YUM_THUMBOR_VENV_DEPENDENCIES,
]
BUILD_PGROONGA_FROM_SOURCE = False
if vendor == 'debian' and os_version in [] or vendor == 'ubuntu' and os_version in []:
# For platforms without a pgroonga release, we need to build it
# from source.
BUILD_PGROONGA_FROM_SOURCE = True
SYSTEM_DEPENDENCIES = UBUNTU_COMMON_APT_DEPENDENCIES + [
pkg.format(POSTGRES_VERSION) for pkg in [
"postgresql-{0}",
# Dependency for building pgroonga from source
"postgresql-server-dev-{0}",
"libgroonga-dev",
"libmsgpack-dev",
"clang-9",
"llvm-9-dev",
]
] + VENV_DEPENDENCIES
SYSTEM_DEPENDENCIES = [
*UBUNTU_COMMON_APT_DEPENDENCIES,
"postgresql-{0}".format(POSTGRES_VERSION),
# Dependency for building pgroonga from source
"postgresql-server-dev-{0}".format(POSTGRES_VERSION),
"libgroonga-dev",
"libmsgpack-dev",
"clang-9",
"llvm-9-dev",
*VENV_DEPENDENCIES,
]
elif "debian" in os_families():
SYSTEM_DEPENDENCIES = UBUNTU_COMMON_APT_DEPENDENCIES + [
pkg.format(POSTGRES_VERSION) for pkg in [
"postgresql-{0}",
"postgresql-{0}-pgroonga",
]
] + VENV_DEPENDENCIES
SYSTEM_DEPENDENCIES = [
*UBUNTU_COMMON_APT_DEPENDENCIES,
"postgresql-{0}".format(POSTGRES_VERSION),
"postgresql-{0}-pgroonga".format(POSTGRES_VERSION),
*VENV_DEPENDENCIES,
]
elif "rhel" in os_families():
SYSTEM_DEPENDENCIES = COMMON_YUM_DEPENDENCIES + [
pkg.format(POSTGRES_VERSION) for pkg in [
"postgresql{0}-server",
"postgresql{0}",
"postgresql{0}-devel",
"postgresql{0}-pgroonga",
]
] + VENV_DEPENDENCIES
SYSTEM_DEPENDENCIES = [
*COMMON_YUM_DEPENDENCIES,
"postgresql{0}-server".format(POSTGRES_VERSION),
"postgresql{0}".format(POSTGRES_VERSION),
"postgresql{0}-devel".format(POSTGRES_VERSION),
"postgresql{0}-pgroonga".format(POSTGRES_VERSION),
*VENV_DEPENDENCIES,
]
elif "fedora" in os_families():
SYSTEM_DEPENDENCIES = COMMON_YUM_DEPENDENCIES + [
pkg.format(POSTGRES_VERSION) for pkg in [
"postgresql{0}-server",
"postgresql{0}",
"postgresql{0}-devel",
# Needed to build pgroonga from source
"groonga-devel",
"msgpack-devel",
]
] + VENV_DEPENDENCIES
SYSTEM_DEPENDENCIES = [
*COMMON_YUM_DEPENDENCIES,
"postgresql{0}-server".format(POSTGRES_VERSION),
"postgresql{0}".format(POSTGRES_VERSION),
"postgresql{0}-devel".format(POSTGRES_VERSION),
# Needed to build pgroonga from source
"groonga-devel",
"msgpack-devel",
*VENV_DEPENDENCIES,
]
BUILD_PGROONGA_FROM_SOURCE = True
if "fedora" in os_families():
@ -247,9 +251,8 @@ def install_apt_deps(deps_to_install: List[str]) -> None:
run_as_root(
[
"env", "DEBIAN_FRONTEND=noninteractive",
"apt-get", "-y", "install", "--no-install-recommends",
"apt-get", "-y", "install", "--no-install-recommends", *deps_to_install,
]
+ deps_to_install,
)
def install_yum_deps(deps_to_install: List[str]) -> None:
@ -274,7 +277,7 @@ def install_yum_deps(deps_to_install: List[str]) -> None:
else:
print("Unrecognized output. `subscription-manager` might not be available")
run_as_root(["yum", "install", "-y"] + yum_extra_flags + deps_to_install)
run_as_root(["yum", "install", "-y", *yum_extra_flags, *deps_to_install])
if "rhel" in os_families():
# This is how a pip3 is installed to /usr/bin in CentOS/RHEL
# for python35 and later.
@ -363,7 +366,7 @@ def main(options: argparse.Namespace) -> "NoReturn":
"https_proxy=" + os.environ.get("https_proxy", ""),
"no_proxy=" + os.environ.get("no_proxy", ""),
]
run_as_root(proxy_env + ["scripts/lib/install-node"], sudo_args = ['-H'])
run_as_root([*proxy_env, "scripts/lib/install-node"], sudo_args = ['-H'])
if not os.access(NODE_MODULES_CACHE_PATH, os.W_OK):
run_as_root(["mkdir", "-p", NODE_MODULES_CACHE_PATH])

View File

@ -61,7 +61,7 @@ def run() -> None:
description="Runs the puppet parser validator, "
"checking for syntax errors.")
linter_config.external_linter('puppet-lint',
['puppet-lint', '--fail-on-warnings'] + PUPPET_CHECK_RULES_TO_EXCLUDE,
['puppet-lint', '--fail-on-warnings', *PUPPET_CHECK_RULES_TO_EXCLUDE],
['pp'],
fix_arg='--fix',
description="Standard puppet linter"

View File

@ -75,7 +75,8 @@ comma_whitespace_rule: List["Rule"] = [
'good_lines': ['foo(1, 2, 3)', 'foo = bar # some inline comment'],
'bad_lines': ['foo(1, 2, 3)', 'foo(1, 2, 3)']},
]
markdown_whitespace_rules = list([rule for rule in whitespace_rules if rule['pattern'] != r'\s+$']) + [
markdown_whitespace_rules: List["Rule"] = [
*(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.
@ -246,7 +247,7 @@ python_rules = RuleList(
'exclude': {'scripts/lib/setup_venv.py'},
'exclude_line': {
('scripts/lib/zulip_tools.py', 'sudo_args = kwargs.pop(\'sudo_args\', [])'),
('scripts/lib/zulip_tools.py', 'args = [\'sudo\'] + sudo_args + [\'--\'] + args'),
('scripts/lib/zulip_tools.py', 'args = [\'sudo\', *sudo_args, \'--\', *args]'),
},
'description': 'Most scripts are intended to run on systems without sudo.',
'good_lines': ['subprocess.check_call(["ls"])'],
@ -442,7 +443,9 @@ prose_style_rules: List["Rule"] = [
'description': "Use Botserver instead of botserver or bot server."},
*comma_whitespace_rule,
]
html_rules: List["Rule"] = whitespace_rules + prose_style_rules + [
html_rules: List["Rule"] = [
*whitespace_rules,
*prose_style_rules,
{'pattern': 'subject|SUBJECT',
'exclude': {'templates/zerver/email.html'},
'exclude_pattern': 'email subject',
@ -578,7 +581,8 @@ html_rules: List["Rule"] = whitespace_rules + prose_style_rules + [
handlebars_rules = RuleList(
langs=['hbs'],
rules=html_rules + [
rules=[
*html_rules,
{'pattern': "[<]script",
'description': "Do not use inline <script> tags here; put JavaScript in static/js instead."},
{'pattern': '{{ t ("|\')',
@ -600,7 +604,8 @@ handlebars_rules = RuleList(
jinja2_rules = RuleList(
langs=['html'],
rules=html_rules + [
rules=[
*html_rules,
{'pattern': r"{% endtrans %}[\.\?!]",
'description': "Period should be part of the translatable string."},
{'pattern': r"{{ _(.+) }}[\.\?!]",
@ -653,7 +658,9 @@ markdown_docs_length_exclude = {
markdown_rules = RuleList(
langs=['md'],
rules=markdown_whitespace_rules + prose_style_rules + [
rules=[
*markdown_whitespace_rules,
*prose_style_rules,
{'pattern': r'\[(?P<url>[^\]]+)\]\((?P=url)\)',
'description': 'Linkified Markdown URLs should use cleaner <http://example.com> syntax.'},
{'pattern': 'https://zulip.readthedocs.io/en/latest/[a-zA-Z0-9]',

View File

@ -135,10 +135,10 @@ with open(pid_file_path, 'w+') as f:
def server_processes() -> List[List[str]]:
main_cmds = [
['./manage.py', 'runserver'] +
manage_args + runserver_args + [f'127.0.0.1:{django_port}'],
['env', 'PYTHONUNBUFFERED=1', './manage.py', 'runtornado'] +
manage_args + [f'127.0.0.1:{tornado_port}'],
['./manage.py', 'runserver',
*manage_args, *runserver_args, f'127.0.0.1:{django_port}'],
['env', 'PYTHONUNBUFFERED=1', './manage.py', 'runtornado',
*manage_args, f'127.0.0.1:{tornado_port}'],
]
if options.streamlined:
@ -147,7 +147,7 @@ def server_processes() -> List[List[str]]:
return main_cmds
other_cmds = [
['./manage.py', 'process_queue', '--all'] + manage_args,
['./manage.py', 'process_queue', '--all', *manage_args],
['env', 'PGHOST=127.0.0.1', # Force password authentication using .pgpass
'./puppet/zulip/files/postgresql/process_fts_updates', '--quiet'],
['./manage.py', 'deliver_scheduled_messages'],

View File

@ -70,8 +70,8 @@ if not python_files and not pyi_files:
mypy_args: List[str] = []
if args.quiet:
mypy_args += ["--no-error-summary"]
mypy_args += ["--"] + python_files + pyi_files
rc = subprocess.call([mypy_command] + mypy_args)
mypy_args += ["--", *python_files, *pyi_files]
rc = subprocess.call([mypy_command, *mypy_args])
if rc != 0:
print("")

View File

@ -56,7 +56,7 @@ def check_valid_emoji_name(emoji_name: str) -> None:
def check_emoji_names(canonical_name: str, aliases: List[str]) -> None:
if canonical_name == 'X':
return
names_to_check = [canonical_name] + aliases
names_to_check = [canonical_name, *aliases]
for name in names_to_check:
check_valid_emoji_name(name)
check_uniqueness(name)

View File

@ -55,14 +55,14 @@ def vnu_servlet() -> Iterator[None]:
with vnu_servlet(), \
test_server_running(options.force, external_host, log_file=LOG_FILE,
dots=True, use_db=True):
ret_help_doc = subprocess.call(['scrapy', 'crawl_with_status'] + extra_args +
['help_documentation_crawler'],
ret_help_doc = subprocess.call(['scrapy', 'crawl_with_status', *extra_args,
'help_documentation_crawler'],
cwd='tools/documentation_crawler')
ret_api_doc = subprocess.call(['scrapy', 'crawl_with_status'] + extra_args +
['api_documentation_crawler'],
ret_api_doc = subprocess.call(['scrapy', 'crawl_with_status', *extra_args,
'api_documentation_crawler'],
cwd='tools/documentation_crawler')
ret_portico_doc = subprocess.call(['scrapy', 'crawl_with_status'] + extra_args +
['portico_documentation_crawler'],
ret_portico_doc = subprocess.call(['scrapy', 'crawl_with_status', *extra_args,
'portico_documentation_crawler'],
cwd='tools/documentation_crawler')
if ret_help_doc != 0 or ret_api_doc != 0 or ret_portico_doc != 0:

View File

@ -64,7 +64,7 @@ def run_tests(files: Iterable[str], external_host: str) -> None:
current_test_num = test_number
for test_file in test_files[test_number:]:
test_name = os.path.basename(test_file)
cmd = ["node"] + [test_file]
cmd = ["node", test_file]
print("\n\n===================== {}\nRunning {}\n\n".format(test_name, " ".join(map(shlex.quote, cmd))), flush=True)
ret = subprocess.call(cmd)
if ret != 0:

View File

@ -97,7 +97,7 @@ def main() -> None:
# Cache the hash so that we need not to run the `update_locked_requirements`
# tool again for checking this set of requirements.
valid_hash = get_requirements_hash(tmp_dir, use_test_lock_files=True)
update_cache([h for h in hash_list if h != valid_hash] + [valid_hash])
update_cache([*(h for h in hash_list if h != valid_hash), valid_hash])
if not requirements_are_consistent:
for test_locked_file in glob.glob(os.path.join(tmp_dir, "*.txt")):
fn = os.path.basename(test_locked_file)

View File

@ -80,7 +80,7 @@ def check_events_dict(
assert "type" in rkeys
assert "id" not in keys
return check_dict_only(
required_keys=list(required_keys) + [("id", check_int)],
required_keys=[*required_keys, ("id", check_int)],
optional_keys=optional_keys,
)

View File

@ -1466,7 +1466,7 @@ def do_write_stats_file_for_realm_export(output_dir: Path) -> None:
attachment_file = os.path.join(output_dir, 'attachment.json')
analytics_file = os.path.join(output_dir, 'analytics.json')
message_files = glob.glob(os.path.join(output_dir, 'messages-*.json'))
fns = sorted([analytics_file] + [attachment_file] + message_files + [realm_file])
fns = sorted([analytics_file, attachment_file, *message_files, realm_file])
logging.info('Writing stats file: %s\n', stats_file)
with open(stats_file, 'w') as f:

View File

@ -80,7 +80,7 @@ class APIArgumentsTablePreprocessor(Preprocessor):
line_split = REGEXP.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:

View File

@ -52,7 +52,7 @@ class APIReturnValuesTablePreprocessor(Preprocessor):
line_split = REGEXP.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:

View File

@ -95,7 +95,7 @@ class RelativeLinks(Preprocessor):
line_split = REGEXP.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:

View File

@ -91,7 +91,7 @@ class Setting(Preprocessor):
line_split = REGEXP.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:

View File

@ -103,7 +103,7 @@ class TabbedSectionsPreprocessor(Preprocessor):
start = tab_section['start_tabs_index']
end = tab_section['end_tabs_index'] + 1
lines = lines[:start] + [rendered_tabs] + lines[end:]
lines = [*lines[:start], rendered_tabs, *lines[end:]]
tab_section = self.parse_tabs(lines)
return lines

View File

@ -100,12 +100,12 @@ class Database:
'ZULIP_DB_NAME=' + self.database_name,
]
run(env_prelude + [
'./manage.py', 'migrate', '--no-input',
run([
*env_prelude, './manage.py', 'migrate', '--no-input',
])
run(env_prelude + [
'./manage.py', 'get_migration_status', '--output='+self.migration_status_file,
run([
*env_prelude, './manage.py', 'get_migration_status', '--output='+self.migration_status_file,
])
def what_to_do_with_migrations(self) -> str:

View File

@ -416,7 +416,7 @@ def write_instrumentation_reports(full_suite: bool, include_webhooks: bool) -> N
assert len(pattern_cnt) > 100
untested_patterns = {p.replace("\\", "") for p in pattern_cnt if pattern_cnt[p] == 0}
exempt_patterns = set([
exempt_patterns = {
# We exempt some patterns that are called via Tornado.
'api/v1/events',
'api/v1/events/internal',
@ -429,7 +429,8 @@ def write_instrumentation_reports(full_suite: bool, include_webhooks: bool) -> N
'docs/(?P<path>.+)',
'casper/(?P<path>.+)',
'static/(?P<path>.*)',
] + [webhook.url for webhook in WEBHOOK_INTEGRATIONS if not include_webhooks])
*(webhook.url for webhook in WEBHOOK_INTEGRATIONS if not include_webhooks),
}
untested_patterns -= exempt_patterns

View File

@ -103,7 +103,7 @@ def exclude_topic_mutes(conditions: List[Selectable],
return and_(stream_cond, topic_cond)
condition = not_(or_(*list(map(mute_cond, rows))))
return conditions + [condition]
return [*conditions, condition]
def build_topic_mute_checker(user_profile: UserProfile) -> Callable[[int, str], bool]:
rows = MutedTopic.objects.filter(

View File

@ -394,7 +394,7 @@ def user_profile_to_user_row(user_profile: UserProfile) -> Dict[str, Any]:
# changing realm_user_dict_fields to name the bot owner with
# the less readable `bot_owner` (instead of `bot_owner_id`).
user_row = model_to_dict(user_profile,
fields=realm_user_dict_fields + ['bot_owner'])
fields=[*realm_user_dict_fields, 'bot_owner'])
user_row['bot_owner_id'] = user_row['bot_owner']
del user_row['bot_owner']
return user_row

View File

@ -117,10 +117,10 @@ class Command(ZulipBaseCommand):
tarball_path = options["output"]
run(
["tar", "-C", tmp, "-cPzf", tarball_path]
+ transform_args
+ ["--"]
+ members,
["tar", "-C", tmp, "-cPzf", tarball_path,
*transform_args,
"--",
*members]
)
print(f"Backup tarball written to {tarball_path}")
except BaseException:

View File

@ -249,8 +249,8 @@ def generate_curl_example(endpoint: str, method: str,
format_dict[param["name"]] = example_value
example_endpoint = endpoint.format_map(format_dict)
curl_first_line_parts = ["curl"] + curl_method_arguments(example_endpoint, method,
api_url)
curl_first_line_parts = ["curl", *curl_method_arguments(example_endpoint, method,
api_url)]
lines.append(" ".join(curl_first_line_parts))
insecure_operations = ['/dev_fetch_api_key:post']
@ -386,7 +386,7 @@ class APICodeExamplesPreprocessor(Preprocessor):
line_split = MACRO_REGEXP.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:
@ -429,7 +429,7 @@ class APIDescriptionPreprocessor(Preprocessor):
line_split = MACRO_REGEXP_DESC.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:

View File

@ -124,11 +124,11 @@ def render_markdown_path(markdown_file_path: str,
#
# TODO: Convert this to something more efficient involving
# passing the API URL as a direct parameter.
extensions = extensions + [zerver.openapi.markdown_extension.makeExtension(
extensions = [*extensions, zerver.openapi.markdown_extension.makeExtension(
api_url=context["api_url"],
)]
if not any(doc in markdown_file_path for doc in docs_without_macros):
extensions = [md_macro_extension] + extensions
extensions = [md_macro_extension, *extensions]
md_engine = markdown.Markdown(extensions=extensions)
md_engine.reset()

View File

@ -4141,21 +4141,21 @@ class TestLDAP(ZulipLDAPTestCase):
common_attrs = ['cn', 'userPassword', 'phoneNumber', 'birthDate']
for key, value in ldap_dir.items():
self.assertTrue(regex.match(key))
self.assertCountEqual(list(value.keys()), common_attrs + ['uid', 'thumbnailPhoto', 'userAccountControl'])
self.assertCountEqual(list(value.keys()), [*common_attrs, 'uid', 'thumbnailPhoto', 'userAccountControl'])
ldap_dir = generate_dev_ldap_dir('b', 9)
self.assertEqual(len(ldap_dir), 9)
regex = re.compile(r'(uid\=)+[a-zA-Z0-9_.+-]+(\,ou\=users\,dc\=zulip\,dc\=com)')
for key, value in ldap_dir.items():
self.assertTrue(regex.match(key))
self.assertCountEqual(list(value.keys()), common_attrs + ['uid', 'jpegPhoto'])
self.assertCountEqual(list(value.keys()), [*common_attrs, 'uid', 'jpegPhoto'])
ldap_dir = generate_dev_ldap_dir('c', 8)
self.assertEqual(len(ldap_dir), 8)
regex = re.compile(r'(uid\=)+[a-zA-Z0-9_.+-]+(\,ou\=users\,dc\=zulip\,dc\=com)')
for key, value in ldap_dir.items():
self.assertTrue(regex.match(key))
self.assertCountEqual(list(value.keys()), common_attrs + ['uid', 'email'])
self.assertCountEqual(list(value.keys()), [*common_attrs, 'uid', 'email'])
@override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',))
def test_dev_ldap_fail_login(self) -> None:

View File

@ -719,7 +719,7 @@ class NormalActionsTest(BaseAction):
timezone_now(),
UserPresence.ACTIVE),
slim_presence=False)
schema_checker = check_events_dict(fields + [email_field])
schema_checker = check_events_dict([*fields, email_field])
schema_checker('events[0]', events[0])
events = self.verify_action(

View File

@ -1391,11 +1391,11 @@ class GetOldMessagesTest(ZulipTestCase):
def dr_emails(dr: DisplayRecipientT) -> str:
assert isinstance(dr, list)
return ','.join(sorted(set([r['email'] for r in dr] + [me.email])))
return ','.join(sorted({*(r['email'] for r in dr), me.email}))
def dr_ids(dr: DisplayRecipientT) -> List[int]:
assert isinstance(dr, list)
return list(sorted(set([r['id'] for r in dr] + [self.example_user('hamlet').id])))
return sorted({*(r['id'] for r in dr), self.example_user('hamlet').id})
self.send_personal_message(me, self.example_user("iago"))
@ -2449,7 +2449,7 @@ class GetOldMessagesTest(ZulipTestCase):
"""
self.login('hamlet')
other_params = [("narrow", {}), ("anchor", 0)]
other_params = {"narrow": {}, "anchor": 0}
int_params = ["num_before", "num_after"]
bad_types = (False, "", "-1", -1)
@ -2457,10 +2457,12 @@ class GetOldMessagesTest(ZulipTestCase):
for type in bad_types:
# Rotate through every bad type for every integer
# parameter, one at a time.
post_params = dict(other_params + [(param, type)] +
[(other_param, 0) for other_param in
int_params[:idx] + int_params[idx + 1:]],
)
post_params = {
**other_params,
param: type,
**{other_param: 0 for other_param in
int_params[:idx] + int_params[idx + 1:]},
}
result = self.client_get("/json/messages", post_params)
self.assert_json_error(result,
f"Bad value for '{param}': {type}")
@ -2471,14 +2473,14 @@ class GetOldMessagesTest(ZulipTestCase):
"""
self.login('hamlet')
other_params: List[Tuple[str, Union[int, str, bool]]] = [("anchor", 0), ("num_before", 0), ("num_after", 0)]
other_params = {"anchor": 0, "num_before": 0, "num_after": 0}
bad_types: Tuple[Union[int, str, bool], ...] = (
False, 0, '', '{malformed json,',
'{foo: 3}', '[1,2]', '[["x","y","z"]]',
)
for type in bad_types:
post_params = dict(other_params + [("narrow", type)])
post_params = {**other_params, "narrow": type}
result = self.client_get("/json/messages", post_params)
self.assert_json_error(result,
f"Bad value for 'narrow': {type}")
@ -2538,10 +2540,9 @@ class GetOldMessagesTest(ZulipTestCase):
def exercise_bad_narrow_operand(self, operator: str,
operands: Sequence[Any],
error_msg: str) -> None:
other_params: List[Tuple[str, Any]] = [("anchor", 0), ("num_before", 0), ("num_after", 0)]
other_params = {"anchor": "0", "num_before": "0", "num_after": "0"}
for operand in operands:
post_params = dict(other_params + [
("narrow", orjson.dumps([[operator, operand]]).decode())])
post_params = {**other_params, "narrow": orjson.dumps([[operator, operand]]).decode()}
result = self.client_get("/json/messages", post_params)
self.assert_json_error_contains(result, error_msg)

View File

@ -320,7 +320,7 @@ class TestArchiveMessagesGeneral(ArchiveMessagesTestingBase):
timezone_now() - timedelta(ZULIP_REALM_DAYS+1),
)
expired_msg_ids = expired_mit_msg_ids + expired_zulip_msg_ids + [expired_crossrealm_msg_id]
expired_msg_ids = [*expired_mit_msg_ids, *expired_zulip_msg_ids, expired_crossrealm_msg_id]
expired_usermsg_ids = self._get_usermessage_ids(expired_msg_ids)
archive_messages(chunk_size=2) # Specify low chunk_size to test batching.

View File

@ -147,7 +147,7 @@ class UserSoftDeactivationTests(ZulipTestCase):
self.example_user('iago'),
self.example_user('cordelia'),
]
all_users = users + [hamlet]
all_users = [*users, hamlet]
for user in all_users:
self.subscribe(user, stream)
@ -182,7 +182,7 @@ class UserSoftDeactivationTests(ZulipTestCase):
sender = self.example_user('hamlet')
realm = get_realm('zulip')
stream_name = 'announce'
for user in users + [sender]:
for user in [*users, sender]:
self.subscribe(user, stream_name)
client, _ = Client.objects.get_or_create(name='website')

View File

@ -2707,9 +2707,9 @@ class SubscriptionAPITest(ZulipTestCase):
"""
Subscribing to a stream name with non-ASCII characters succeeds.
"""
self.helper_check_subs_before_and_after_add(self.streams + ["hümbüǵ"], {},
self.helper_check_subs_before_and_after_add([*self.streams, "hümbüǵ"], {},
["hümbüǵ"], self.streams, self.test_email,
self.streams + ["hümbüǵ"], self.test_realm)
[*self.streams, "hümbüǵ"], self.test_realm)
def test_subscriptions_add_too_long(self) -> None:
"""

View File

@ -1367,7 +1367,7 @@ class SocialAuthMixin(ZulipAuthMixin, ExternalAuthMethod, BaseAuth):
# it should be False.
full_name_validated = False
standard_relay_params = settings.SOCIAL_AUTH_FIELDS_STORED_IN_SESSION + ['next']
standard_relay_params = [*settings.SOCIAL_AUTH_FIELDS_STORED_IN_SESSION, 'next']
def auth_complete(self, *args: Any, **kwargs: Any) -> Optional[HttpResponse]:
"""This is a small wrapper around the core `auth_complete` method of

View File

@ -695,10 +695,10 @@ else:
# This is disabled in a few tests.
LOGGING_ENABLED = True
DEFAULT_ZULIP_HANDLERS = (
(['zulip_admins'] if ERROR_REPORTING else []) +
['console', 'file', 'errors_file']
)
DEFAULT_ZULIP_HANDLERS = [
*(['zulip_admins'] if ERROR_REPORTING else []),
'console', 'file', 'errors_file',
]
LOGGING: Dict[str, Any] = {
'version': 1,
@ -892,7 +892,7 @@ LOGGING: Dict[str, Any] = {
},
'zulip.auth': {
'level': 'DEBUG',
'handlers': DEFAULT_ZULIP_HANDLERS + ['auth_file'],
'handlers': [*DEFAULT_ZULIP_HANDLERS, 'auth_file'],
'propagate': False,
},
'zulip.ldap': {