python: Convert "".format to Python 3.6 f-strings.

Generated by pyupgrade --py36-plus --keep-percent-format, but with the
NamedTuple changes reverted (see commit
ba7906a3c6, #15132).

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-06-08 15:25:09 -07:00
parent 8c15081069
commit 8dd83228e7
146 changed files with 596 additions and 596 deletions

View File

@ -432,7 +432,7 @@ class TestSupportEndpoint(ZulipTestCase):
def check_preregistration_user_query_result(result: HttpResponse, email: str, invite: Optional[bool]=False) -> None:
self.assert_in_success_response(['<span class="label">preregistration user</span>\n',
'<b>Email</b>: {}'.format(email),
f'<b>Email</b>: {email}',
], result)
if invite:
self.assert_in_success_response(['<span class="label">invite</span>'], result)

View File

@ -1103,23 +1103,23 @@ def support(request: HttpRequest) -> HttpResponse:
new_discount = Decimal(new_discount)
current_discount = get_discount_for_realm(realm)
attach_discount_to_realm(realm, new_discount)
msg = "Discount of {} changed to {} from {} ".format(realm.name, new_discount, current_discount)
msg = f"Discount of {realm.name} changed to {new_discount} from {current_discount} "
context["message"] = msg
status = request.POST.get("status", None)
if status is not None:
if status == "active":
do_send_realm_reactivation_email(realm)
context["message"] = "Realm reactivation email sent to admins of {}.".format(realm.name)
context["message"] = f"Realm reactivation email sent to admins of {realm.name}."
elif status == "deactivated":
do_deactivate_realm(realm, request.user)
context["message"] = "{} deactivated.".format(realm.name)
context["message"] = f"{realm.name} deactivated."
scrub_realm = request.POST.get("scrub_realm", None)
if scrub_realm is not None:
if scrub_realm == "scrub_realm":
do_scrub_realm(realm)
context["message"] = "{} scrubbed.".format(realm.name)
context["message"] = f"{realm.name} scrubbed."
query = request.GET.get("q", None)
if query:
@ -1135,7 +1135,7 @@ def support(request: HttpRequest) -> HttpResponse:
hostname = parse_result.hostname
assert hostname is not None
if parse_result.port:
hostname = "{}:{}".format(hostname, parse_result.port)
hostname = f"{hostname}:{parse_result.port}"
subdomain = get_subdomain_from_hostname(hostname)
try:
realms.add(get_realm(subdomain))
@ -1295,13 +1295,13 @@ def realm_activity_link(realm_str: str) -> mark_safe:
def realm_stats_link(realm_str: str) -> mark_safe:
url_name = 'analytics.views.stats_for_realm'
url = reverse(url_name, kwargs=dict(realm_str=realm_str))
stats_link = '<a href="{}"><i class="fa fa-pie-chart"></i>{}</a>'.format(url, realm_str)
stats_link = f'<a href="{url}"><i class="fa fa-pie-chart"></i>{realm_str}</a>'
return mark_safe(stats_link)
def remote_installation_stats_link(server_id: int, hostname: str) -> mark_safe:
url_name = 'analytics.views.stats_for_remote_installation'
url = reverse(url_name, kwargs=dict(remote_server_id=server_id))
stats_link = '<a href="{}"><i class="fa fa-pie-chart"></i>{}</a>'.format(url, hostname)
stats_link = f'<a href="{url}"><i class="fa fa-pie-chart"></i>{hostname}</a>'
return mark_safe(stats_link)
def realm_client_table(user_summaries: Dict[str, Dict[str, Dict[str, Any]]]) -> str:

View File

@ -283,7 +283,7 @@ def compute_plan_parameters(
price_per_license = 800
period_end = add_months(billing_cycle_anchor, 1)
else:
raise AssertionError('Unknown billing_schedule: {}'.format(billing_schedule))
raise AssertionError(f'Unknown billing_schedule: {billing_schedule}')
if discount is not None:
# There are no fractional cents in Stripe, so round down to nearest integer.
price_per_license = int(float(price_per_license * (1 - discount / 100)) + .00001)
@ -326,12 +326,12 @@ def process_initial_upgrade(user: UserProfile, licenses: int, automanage_license
amount=price_per_license * licenses,
currency='usd',
customer=customer.stripe_customer_id,
description="Upgrade to Zulip Standard, ${} x {}".format(price_per_license/100, licenses),
description=f"Upgrade to Zulip Standard, ${price_per_license/100} x {licenses}",
receipt_email=user.delivery_email,
statement_descriptor='Zulip Standard')
# Not setting a period start and end, but maybe we should? Unclear what will make things
# most similar to the renewal case from an accounting perspective.
description = "Payment (Card ending in {})".format(cast(stripe.Card, stripe_charge.source).last4)
description = f"Payment (Card ending in {cast(stripe.Card, stripe_charge.source).last4})"
stripe.InvoiceItem.create(
amount=price_per_license * licenses * -1,
currency='usd',
@ -454,7 +454,7 @@ def invoice_plan(plan: CustomerPlan, event_time: datetime) -> None:
plan.invoiced_through = ledger_entry
plan.invoicing_status = CustomerPlan.STARTED
plan.save(update_fields=['invoicing_status', 'invoiced_through'])
idempotency_key: Optional[str] = 'ledger_entry:{}'.format(ledger_entry.id)
idempotency_key: Optional[str] = f'ledger_entry:{ledger_entry.id}'
if settings.TEST_SUITE:
idempotency_key = None
stripe.InvoiceItem.create(

View File

@ -71,7 +71,7 @@ def fixture_files_for_function(decorated_function: CallableT) -> List[str]: # n
decorated_function_name = decorated_function.__name__
if decorated_function_name[:5] == 'test_':
decorated_function_name = decorated_function_name[5:]
return sorted(['{}/{}'.format(STRIPE_FIXTURES_DIR, f) for f in os.listdir(STRIPE_FIXTURES_DIR)
return sorted([f'{STRIPE_FIXTURES_DIR}/{f}' for f in os.listdir(STRIPE_FIXTURES_DIR)
if f.startswith(decorated_function_name + '--')])
def generate_and_save_stripe_fixture(decorated_function_name: str, mocked_function_name: str,
@ -174,7 +174,7 @@ def normalize_fixture_data(decorated_function: CallableT,
with open(fixture_file, "w") as f:
f.write(file_content)
MOCKED_STRIPE_FUNCTION_NAMES = ["stripe.{}".format(name) for name in [
MOCKED_STRIPE_FUNCTION_NAMES = [f"stripe.{name}" for name in [
"Charge.create", "Charge.list",
"Coupon.create",
"Customer.create", "Customer.retrieve", "Customer.save",
@ -392,7 +392,7 @@ class StripeTest(StripeTestCase):
self.assertEqual(stripe_charges[0].amount, 8000 * self.seat_count)
# TODO: fix Decimal
self.assertEqual(stripe_charges[0].description,
"Upgrade to Zulip Standard, $80.0 x {}".format(self.seat_count))
f"Upgrade to Zulip Standard, $80.0 x {self.seat_count}")
self.assertEqual(stripe_charges[0].receipt_email, user.email)
self.assertEqual(stripe_charges[0].statement_descriptor, "Zulip Standard")
# Check Invoices in Stripe
@ -775,7 +775,7 @@ class StripeTest(StripeTestCase):
'Zulip Standard', 'Free Trial', str(self.seat_count),
'You are using', '%s of %s licenses' % (self.seat_count, 123),
'Your plan will be upgraded to', 'March 2, 2012',
'{:,.2f}'.format(80 * 123), 'Billed by invoice'
f'{80 * 123:,.2f}', 'Billed by invoice'
]:
self.assert_in_response(substring, response)
@ -983,13 +983,13 @@ class StripeTest(StripeTestCase):
upgrade_params['licenses'] = licenses
response = self.upgrade(invoice=invoice, talk_to_stripe=False,
del_args=del_args, **upgrade_params)
self.assert_json_error_contains(response, "at least {} users".format(min_licenses_in_response))
self.assert_json_error_contains(response, f"at least {min_licenses_in_response} users")
self.assertEqual(ujson.loads(response.content)['error_description'], 'not enough licenses')
def check_max_licenses_error(licenses: int) -> None:
response = self.upgrade(invoice=True, talk_to_stripe=False,
licenses=licenses)
self.assert_json_error_contains(response, "with more than {} licenses".format(MAX_INVOICED_LICENSES))
self.assert_json_error_contains(response, f"with more than {MAX_INVOICED_LICENSES} licenses")
self.assertEqual(ujson.loads(response.content)['error_description'], 'too many licenses')
def check_success(invoice: bool, licenses: Optional[int], upgrade_params: Dict[str, Any]={}) -> None:
@ -1108,7 +1108,7 @@ class StripeTest(StripeTestCase):
realm = Realm.objects.create(string_id='second', name='second')
UserProfile.objects.create(realm=realm, email='member@second.com', pointer=-1)
for i in range(5):
UserProfile.objects.create(realm=realm, email='guest{}@second.com'.format(i),
UserProfile.objects.create(realm=realm, email=f'guest{i}@second.com',
pointer=-1, role=UserProfile.ROLE_GUEST)
self.assertEqual(get_latest_seat_count(realm), 1)
# Test 1 member and 6 guests

View File

@ -131,7 +131,7 @@ def initial_upgrade(request: HttpRequest) -> HttpResponse:
if customer is not None and get_current_plan_by_customer(customer) is not None:
billing_page_url = reverse('corporate.views.billing_home')
if request.GET.get("onboarding") is not None:
billing_page_url = "{}?onboarding=true".format(billing_page_url)
billing_page_url = f"{billing_page_url}?onboarding=true"
return HttpResponseRedirect(billing_page_url)
percent_off = Decimal(0)
@ -210,7 +210,7 @@ def billing_home(request: HttpRequest) -> HttpResponse:
'licenses': licenses,
'licenses_used': licenses_used,
'renewal_date': renewal_date,
'renewal_amount': '{:,.2f}'.format(renewal_cents / 100.),
'renewal_amount': f'{renewal_cents / 100.:,.2f}',
'payment_method': payment_method,
'charge_automatically': charge_automatically,
'publishable_key': STRIPE_PUBLISHABLE_KEY,

View File

@ -99,7 +99,7 @@ def run_tests(files: Iterable[str], external_host: str) -> None:
print('\n\nWe will use loop mode for these tests:\n')
for test_file in test_files:
print(' ' + os.path.basename(test_file))
print('\nnumber of loops: {}\n'.format(loop_cnt))
print(f'\nnumber of loops: {loop_cnt}\n')
print()
else:
loop_cnt = None
@ -130,12 +130,12 @@ def run_tests(files: Iterable[str], external_host: str) -> None:
def run_loops(loop_cnt: int) -> None:
while True:
for trial in range(1, loop_cnt + 1):
print('\n\n\nSTARTING TRIAL {} / {}\n'.format(trial, loop_cnt))
print(f'\n\n\nSTARTING TRIAL {trial} / {loop_cnt}\n')
ret = run_tests()
if ret == 0:
print('`\n\nSUCCESS! trial #{}\n\n'.format(trial))
print(f'`\n\nSUCCESS! trial #{trial}\n\n')
else:
print('\n\nFAIL! trial #{}\n'.format(trial))
print(f'\n\nFAIL! trial #{trial}\n')
break
while True:

View File

@ -47,7 +47,7 @@ with open('/etc/zulip/nginx_sharding.conf.tmp', 'w') as nginx_sharding_conf_f, \
if '.' in shard:
host = shard
else:
host = "{}.{}".format(shard, external_host)
host = f"{shard}.{external_host}"
assert host not in shard_map, "host %s duplicated" % (host,)
shard_map[host] = int(port)
write_realm_nginx_config_line(nginx_sharding_conf_f, host, port)

View File

@ -14,7 +14,7 @@ if __name__ == "__main__":
dockerfile_settings = yaml.safe_load(f)
for distro in dockerfile_settings:
dockerfile_path = "images/{}/Dockerfile".format(distro)
dockerfile_path = f"images/{distro}/Dockerfile"
os.makedirs(os.path.dirname(dockerfile_path), exist_ok=True)
with open(dockerfile_path, "w") as f:
f.write("""\

View File

@ -25,7 +25,7 @@ class UnusedImagesLinterSpider(BaseDocumentationSpider):
def _is_external_url(self, url: str) -> bool:
is_external = url.startswith('http') and self.start_urls[0] not in url
if self._has_extension(url) and 'localhost:9981/{}'.format(self.images_path) in url:
if self._has_extension(url) and f'localhost:9981/{self.images_path}' in url:
self.static_images.add(basename(urlparse(url).path))
return is_external or self._has_extension(url)

View File

@ -32,7 +32,7 @@ append_key = """\
"""
def get_mentor_keys(username: str) -> List[str]:
url = 'https://api.github.com/users/{}/keys'.format(username)
url = f'https://api.github.com/users/{username}/keys'
r = requests.get(url)
if r.status_code != 200:
@ -41,7 +41,7 @@ def get_mentor_keys(username: str) -> List[str]:
keys = r.json()
if not keys:
print('Mentor "{}" has no public key.'.format(username))
print(f'Mentor "{username}" has no public key.')
sys.exit(1)
return [key['key'] for key in keys]
@ -62,7 +62,7 @@ if __name__ == '__main__':
f.write(new_content)
f.truncate()
print('Successfully removed {}\' SSH key!'.format(args.username))
print(f'Successfully removed {args.username}\' SSH key!')
else:
keys = get_mentor_keys(args.username)
@ -70,6 +70,6 @@ if __name__ == '__main__':
for key in keys:
f.write(append_key.format(username=args.username, key=key))
print('Successfully added {}\'s SSH key!'.format(args.username))
print(f'Successfully added {args.username}\'s SSH key!')
print('Can you let your mentor know that they can connect to this machine with:\n')
print(' $ ssh zulipdev@{}\n'.format(socket.gethostname()))
print(f' $ ssh zulipdev@{socket.gethostname()}\n')

View File

@ -39,8 +39,8 @@ def get_config() -> configparser.ConfigParser:
return config
def user_exists(username: str) -> bool:
print("Checking to see if GitHub user {} exists...".format(username))
user_api_url = "https://api.github.com/users/{}".format(username)
print(f"Checking to see if GitHub user {username} exists...")
user_api_url = f"https://api.github.com/users/{username}"
try:
response = urllib.request.urlopen(user_api_url)
json.load(response)
@ -48,28 +48,28 @@ def user_exists(username: str) -> bool:
return True
except urllib.error.HTTPError as err:
print(err)
print("Does the github user {} exist?".format(username))
print(f"Does the github user {username} exist?")
sys.exit(1)
def get_keys(username: str) -> List[Dict[str, Any]]:
print("Checking to see that GitHub user has available public keys...")
apiurl_keys = "https://api.github.com/users/{}/keys".format(username)
apiurl_keys = f"https://api.github.com/users/{username}/keys"
try:
response = urllib.request.urlopen(apiurl_keys)
userkeys = json.load(response)
if not userkeys:
print("No keys found. Has user {} added ssh keys to their github account?".format(username))
print(f"No keys found. Has user {username} added ssh keys to their github account?")
sys.exit(1)
print("...public keys found!")
return userkeys
except urllib.error.HTTPError as err:
print(err)
print("Has user {} added ssh keys to their github account?".format(username))
print(f"Has user {username} added ssh keys to their github account?")
sys.exit(1)
def fork_exists(username: str) -> bool:
print("Checking to see GitHub user has forked zulip/zulip...")
apiurl_fork = "https://api.github.com/repos/{}/zulip".format(username)
apiurl_fork = f"https://api.github.com/repos/{username}/zulip"
try:
response = urllib.request.urlopen(apiurl_fork)
json.load(response)
@ -77,21 +77,21 @@ def fork_exists(username: str) -> bool:
return True
except urllib.error.HTTPError as err:
print(err)
print("Has user {} forked zulip/zulip?".format(username))
print(f"Has user {username} forked zulip/zulip?")
sys.exit(1)
def exit_if_droplet_exists(my_token: str, username: str, recreate: bool) -> None:
print("Checking to see if droplet for {} already exists...".format(username))
print(f"Checking to see if droplet for {username} already exists...")
manager = digitalocean.Manager(token=my_token)
my_droplets = manager.get_all_droplets()
for droplet in my_droplets:
if droplet.name.lower() == "{}.zulipdev.org".format(username):
if droplet.name.lower() == f"{username}.zulipdev.org":
if not recreate:
print("Droplet for user {} already exists. Pass --recreate if you "
"need to recreate the droplet.".format(username))
sys.exit(1)
else:
print("Deleting existing droplet for {}.".format(username))
print(f"Deleting existing droplet for {username}.")
droplet.destroy()
return
print("...No droplet found...proceeding.")
@ -101,13 +101,13 @@ def set_user_data(username: str, userkey_dicts: List[Dict[str, Any]]) -> str:
userkeys = [userkey_dict["key"] for userkey_dict in userkey_dicts]
ssh_keys = "\n".join(userkeys)
setup_root_ssh_keys = "printf '{keys}' > /root/.ssh/authorized_keys".format(keys=ssh_keys)
setup_zulipdev_ssh_keys = "printf '{keys}' > /home/zulipdev/.ssh/authorized_keys".format(keys=ssh_keys)
setup_root_ssh_keys = f"printf '{ssh_keys}' > /root/.ssh/authorized_keys"
setup_zulipdev_ssh_keys = f"printf '{ssh_keys}' > /home/zulipdev/.ssh/authorized_keys"
# We pass the hostname as username.zulipdev.org to the DigitalOcean API.
# But some droplets (eg on 18.04) are created with with hostname set to just username.
# So we fix the hostname using cloud-init.
hostname_setup = "hostnamectl set-hostname {username}.zulipdev.org".format(username=username)
hostname_setup = f"hostnamectl set-hostname {username}.zulipdev.org"
setup_repo = (
"cd /home/zulipdev/{1} && "
@ -141,7 +141,7 @@ su -c 'git config --global pull.rebase true' zulipdev
def create_droplet(my_token: str, template_id: str, username: str, tags: List[str], user_data: str) -> str:
droplet = digitalocean.Droplet(
token=my_token,
name='{}.zulipdev.org'.format(username),
name=f'{username}.zulipdev.org',
region='nyc3',
image=template_id,
size_slug='s-1vcpu-2gb',
@ -157,7 +157,7 @@ def create_droplet(my_token: str, template_id: str, username: str, tags: List[st
actions = droplet.get_actions()
for action in actions:
action.load()
print("...[{}]: {}".format(action.type, action.status))
print(f"...[{action.type}]: {action.status}")
if action.type == 'create' and action.status == 'completed':
incomplete = False
break
@ -165,7 +165,7 @@ def create_droplet(my_token: str, template_id: str, username: str, tags: List[st
time.sleep(15)
print("...droplet created!")
droplet.load()
print("...ip address for new droplet is: {}.".format(droplet.ip_address))
print(f"...ip address for new droplet is: {droplet.ip_address}.")
return droplet.ip_address
def delete_existing_records(records: List[digitalocean.Record], record_name: str) -> None:
@ -175,7 +175,7 @@ def delete_existing_records(records: List[digitalocean.Record], record_name: str
record.destroy()
count = count + 1
if count:
print("Deleted {} existing A records for {}.zulipdev.org.".format(count, record_name))
print(f"Deleted {count} existing A records for {record_name}.zulipdev.org.")
def create_dns_record(my_token: str, username: str, ip_address: str) -> None:
domain = digitalocean.Domain(token=my_token, name='zulipdev.org')
@ -186,9 +186,9 @@ def create_dns_record(my_token: str, username: str, ip_address: str) -> None:
wildcard_name = "*." + username
delete_existing_records(records, wildcard_name)
print("Creating new A record for {}.zulipdev.org that points to {}.".format(username, ip_address))
print(f"Creating new A record for {username}.zulipdev.org that points to {ip_address}.")
domain.create_new_domain_record(type='A', name=username, data=ip_address)
print("Creating new A record for *.{}.zulipdev.org that points to {}.".format(username, ip_address))
print(f"Creating new A record for *.{username}.zulipdev.org that points to {ip_address}.")
domain.create_new_domain_record(type='A', name=wildcard_name, data=ip_address)
def print_completion(username: str) -> None:
@ -230,7 +230,7 @@ if __name__ == '__main__':
# get command line arguments
args = parser.parse_args()
username = args.username.lower()
print("Creating Zulip developer environment for GitHub user {}...".format(username))
print(f"Creating Zulip developer environment for GitHub user {username}...")
# get config details
config = get_config()

View File

@ -49,7 +49,7 @@ def fetch_contributors(repo_link: str) -> Optional[List[Dict[str, Dict[str, Any]
def write_to_disk(json_data: ContributorsJSON, out_file: str) -> None:
with open(out_file, 'w') as f:
try:
f.write("{}\n".format(json.dumps(json_data, indent=2, sort_keys=True)))
f.write(f"{json.dumps(json_data, indent=2, sort_keys=True)}\n")
except OSError as e:
logger.warning(e)
sys.exit(1)

View File

@ -47,9 +47,9 @@ from zerver.lib.storage import static_path
def create_integration_bot(integration: WebhookIntegration, bot_name: Optional[str]=None) -> UserProfile:
realm = get_realm('zulip')
owner = get_user_by_delivery_email("iago@zulip.com", realm)
bot_email = "{}-bot@example.com".format(integration.name)
bot_email = f"{integration.name}-bot@example.com"
if bot_name is None:
bot_name = "{} Bot".format(integration.name.capitalize())
bot_name = f"{integration.name.capitalize()} Bot"
try:
bot = UserProfile.objects.get(email=bot_email)
except UserProfile.DoesNotExist:
@ -123,13 +123,13 @@ def send_bot_payload_message(bot: UserProfile, integration: WebhookIntegration,
if config.custom_headers:
headers.update(config.custom_headers)
if config.use_basic_auth:
credentials = base64.b64encode('{}:{}'.format(bot.email, bot.api_key).encode('utf8')).decode('utf8')
auth = 'basic {}'.format(credentials)
credentials = base64.b64encode(f'{bot.email}:{bot.api_key}'.encode('utf8')).decode('utf8')
auth = f'basic {credentials}'
headers.update(dict(Authorization=auth))
assert isinstance(bot.bot_owner, UserProfile)
stream = integration.stream_name or 'devel'
url = "{}/{}".format(bot.bot_owner.realm.uri, integration.url)
url = f"{bot.bot_owner.realm.uri}/{integration.url}"
params = {'api_key': bot.api_key, 'stream': stream}
if config.extra_params:
params.update(config.extra_params)
@ -148,7 +148,7 @@ def send_bot_payload_message(bot: UserProfile, integration: WebhookIntegration,
else:
extra_args = {'json': data}
url = '{}?{}'.format(url, urlencode(params))
url = f'{url}?{urlencode(params)}'
try:
response = requests.post(url=url, headers=headers, **extra_args)
@ -161,13 +161,13 @@ def send_bot_payload_message(bot: UserProfile, integration: WebhookIntegration,
print('Failed to trigger webhook')
return False
else:
print('Triggered {} webhook'.format(integration.name))
print(f'Triggered {integration.name} webhook')
return True
def capture_last_message_screenshot(bot: UserProfile, image_path: str) -> None:
message = Message.objects.filter(sender=bot).last()
if message is None:
print('No message found for {}'.format(bot.full_name))
print(f'No message found for {bot.full_name}')
return
message_id = str(message.id)
screenshot_script = os.path.join(TOOLS_DIR, 'message-screenshot.js')

View File

@ -6,7 +6,7 @@ from subprocess import check_output
from typing import Dict, List
def get_json_filename(locale: str) -> str:
return "locale/{}/mobile.json".format(locale)
return f"locale/{locale}/mobile.json"
def get_locales() -> List[str]:
output = check_output(['git', 'ls-files', 'locale'])

View File

@ -167,7 +167,7 @@ COMPILED_IGNORED_PHRASES = [
]
SPLIT_BOUNDARY = '?.!' # Used to split string into sentences.
SPLIT_BOUNDARY_REGEX = re.compile(r'[{}]'.format(SPLIT_BOUNDARY))
SPLIT_BOUNDARY_REGEX = re.compile(fr'[{SPLIT_BOUNDARY}]')
# Regexes which check capitalization in sentences.
DISALLOWED_REGEXES = [re.compile(regex) for regex in [

View File

@ -98,7 +98,7 @@ def head_binary_search(key: Text, words: List[str]) -> str:
while True:
if lower > upper:
# Should not happen
raise Exception("Cannot find imperative mood of {}".format(key))
raise Exception(f"Cannot find imperative mood of {key}")
mid = (lower + upper) // 2
imperative_form = words[mid]
@ -156,7 +156,7 @@ class TitleMatchRegexAllowException(LineRule):
regex = self.options['regex'].value
pattern = re.compile(regex, re.UNICODE)
if not pattern.search(title) and not title.startswith("Revert \""):
violation_msg = "Title does not match regex ({})".format(regex)
violation_msg = f"Title does not match regex ({regex})"
return [RuleViolation(self.id, violation_msg, title)]
return []

View File

@ -11,15 +11,15 @@ from zulint.custom_rules import Rule, RuleList
# 'include_only': 'set([<path>, ...])' - includes only those files where <path> is a substring of the filepath.
PYDELIMS = r'''"'()\[\]{}#\\'''
PYREG = r"[^{}]".format(PYDELIMS)
PYREG = fr"[^{PYDELIMS}]"
PYSQ = r'"(?:[^"\\]|\\.)*"'
PYDQ = r"'(?:[^'\\]|\\.)*'"
PYLEFT = r"[(\[{]"
PYRIGHT = r"[)\]}]"
PYCODE = PYREG
for depth in range(5):
PYGROUP = r"""(?:{}|{}|{}{}*{})""".format(PYSQ, PYDQ, PYLEFT, PYCODE, PYRIGHT)
PYCODE = r"""(?:{}|{})""".format(PYREG, PYGROUP)
PYGROUP = fr"""(?:{PYSQ}|{PYDQ}|{PYLEFT}{PYCODE}*{PYRIGHT})"""
PYCODE = fr"""(?:{PYREG}|{PYGROUP})"""
FILES_WITH_LEGACY_SUBJECT = {
# This basically requires a big DB migration:
@ -305,7 +305,7 @@ python_rules = RuleList(
{'pattern': r'''\WJsonableError\(["'].+\)''',
'exclude': {'zerver/tests', 'zerver/views/development/'},
'description': 'Argument to JsonableError should be a literal string enclosed by _()'},
{'pattern': r"""\b_\((?:\s|{}|{})*[^\s'")]""".format(PYSQ, PYDQ),
{'pattern': fr"""\b_\((?:\s|{PYSQ}|{PYDQ})*[^\s'")]""",
'description': 'Called _() on a computed string',
'exclude_line': {('zerver/lib/i18n.py', 'result = _(string)')},
'good_lines': ["return json_error(_('No presence data for %s') % (target.email,))"],

View File

@ -91,7 +91,7 @@ def main() -> None:
with open(success_stamp, 'w') as f:
f.close()
print("build_emoji: Using cached emojis from {}".format(source_emoji_dump))
print(f"build_emoji: Using cached emojis from {source_emoji_dump}")
if os.path.lexists(TARGET_EMOJI_DUMP):
os.remove(TARGET_EMOJI_DUMP)
os.symlink(source_emoji_dump, TARGET_EMOJI_DUMP)
@ -300,13 +300,13 @@ def setup_old_emoji_farm(cache_path: str,
for name, codepoint in emoji_map.items():
mapped_codepoint = REMAPPED_EMOJIS.get(codepoint, codepoint)
image_file_path = os.path.join(google_emoji_cache_path, '{}.png'.format(mapped_codepoint))
symlink_path = os.path.join(emoji_cache_path, '{}.png'.format(name))
image_file_path = os.path.join(google_emoji_cache_path, f'{mapped_codepoint}.png')
symlink_path = os.path.join(emoji_cache_path, f'{name}.png')
os.symlink(image_file_path, symlink_path)
try:
# `emoji_map` contains duplicate entries for the same codepoint with different
# names. So creation of symlink for <codepoint>.png may throw `FileExistsError`.
unicode_symlink_path = os.path.join(unicode_emoji_cache_path, '{}.png'.format(codepoint))
unicode_symlink_path = os.path.join(unicode_emoji_cache_path, f'{codepoint}.png')
os.symlink(image_file_path, unicode_symlink_path)
except FileExistsError:
pass

View File

@ -169,7 +169,7 @@ class ZulipInternetBlockedError(Exception):
"More details and advice are available here:"
"https://zulip.readthedocs.io/en/latest/testing/testing.html#internet-access-inside-test-suites"
)
msg = "{}\nResponses library error message: {}".format(zulip_msg, original_msg)
msg = f"{zulip_msg}\nResponses library error message: {original_msg}"
super().__init__(msg)
def main() -> None:
@ -405,7 +405,7 @@ def main() -> None:
missed_count = len(templates_not_rendered)
print("\nError: %s templates have no tests!" % (missed_count,))
for template in templates_not_rendered:
print(' {}'.format(template))
print(f' {template}')
print("See zerver/tests/test_templates.py for the exclude list.")
failures = True
@ -452,11 +452,11 @@ def main() -> None:
prof.disable()
with tempfile.NamedTemporaryFile(prefix='profile.data.', delete=False) as stats_file:
prof.dump_stats(stats_file.name)
print("Profile data saved to {}".format(stats_file.name))
print("You can visualize it using e.g. `snakeviz {}`".format(shlex.quote(stats_file.name)))
print(f"Profile data saved to {stats_file.name}")
print(f"You can visualize it using e.g. `snakeviz {shlex.quote(stats_file.name)}`")
print("Note: If you are using vagrant for development environment you will need to do:")
print("1.) `vagrant ssh -- -L 8080:127.0.0.1:8080`")
print("2.) `snakeviz -s {}`".format(shlex.quote(stats_file.name)))
print(f"2.) `snakeviz -s {shlex.quote(stats_file.name)}`")
if options.report_slow_tests:
from zerver.lib.test_runner import report_slow_tests

View File

@ -310,7 +310,7 @@ def enforce_proper_coverage(coverage_json: Any) -> bool:
line_mapping = coverage_json[path]['statementMap']
if check_line_coverage(relative_path, line_coverage, line_mapping, log=False):
coverage_not_enforced = True
print_error("{} unexpectedly has 100% line coverage.".format(relative_path))
print_error(f"{relative_path} unexpectedly has 100% line coverage.")
if coverage_not_enforced:
print()
@ -332,7 +332,7 @@ if options.coverage and ret == 0:
print()
if ret == 0:
if options.coverage:
reports_location = 'http://{}/node-coverage/index.html'.format(get_dev_host())
reports_location = f'http://{get_dev_host()}/node-coverage/index.html'
print('View coverage reports at ' + CYAN + reports_location + ENDC)
print(GREEN + "Test(s) passed. SUCCESS!" + ENDC)

View File

@ -56,7 +56,7 @@ def check_worker_launch(run_dev: "subprocess.Popen[str]") -> bool:
if __name__ == '__main__':
print('\nStarting Development Server')
args = ["{}/run-dev.py".format(TOOLS_DIR)]
args = [f"{TOOLS_DIR}/run-dev.py"]
run_dev = subprocess.Popen(
args,
bufsize=1, # line buffered

View File

@ -19,7 +19,7 @@ def start_server(logfile_name: str) -> Tuple[bool, str]:
with open(logfile_name, 'rb', buffering=0) as logfile:
for i in range(200):
time.sleep(0.5)
print("{}. Polling run-dev...".format(i))
print(f"{i}. Polling run-dev...")
new_data = logfile.read().decode()
if new_data:
datalog.append(new_data)

View File

@ -23,18 +23,18 @@ class TestRuleList(TestCase):
for path in rule.get('exclude', {}):
abs_path = os.path.abspath(os.path.join(ROOT_DIR, path))
self.assertTrue(os.path.exists(abs_path),
"'{}' is neither an existing file, nor a directory. {}".format(path, CHECK_MESSAGE))
f"'{path}' is neither an existing file, nor a directory. {CHECK_MESSAGE}")
for line_tuple in rule.get('exclude_line', {}):
path = line_tuple[0]
abs_path = os.path.abspath(os.path.join(ROOT_DIR, path))
self.assertTrue(os.path.isfile(abs_path),
"The file '{}' doesn't exist. {}".format(path, CHECK_MESSAGE))
f"The file '{path}' doesn't exist. {CHECK_MESSAGE}")
for path in rule.get('include_only', {}):
if not os.path.splitext(path)[1]:
self.assertTrue(path.endswith('/'),
"The path '{}' should end with '/'. {}".format(path, CHECK_MESSAGE))
f"The path '{path}' should end with '/'. {CHECK_MESSAGE}")
def test_rule_patterns(self) -> None:
"""Verifies that the search regex specified in a custom rule actually matches
@ -45,7 +45,7 @@ class TestRuleList(TestCase):
# create=True is superfluous when mocking built-ins in Python >= 3.5
with patch('builtins.open', return_value=StringIO(line + '\n\n'), create=True, autospec=True):
self.assertFalse(RuleList([], [rule]).custom_check_file('foo.bar', 'baz', ''),
"The pattern '{}' matched the line '{}' while it shouldn't.".format(pattern, line))
f"The pattern '{pattern}' matched the line '{line}' while it shouldn't.")
for line in rule.get('bad_lines', []):
# create=True is superfluous when mocking built-ins in Python >= 3.5
@ -53,4 +53,4 @@ class TestRuleList(TestCase):
return_value=StringIO(line + '\n\n'), create=True, autospec=True), patch('builtins.print'):
filename = list(rule.get('include_only', {'foo.bar'}))[0]
self.assertTrue(RuleList([], [rule]).custom_check_file(filename, 'baz', ''),
"The pattern '{}' didn't match the line '{}' while it should.".format(pattern, line))
f"The pattern '{pattern}' didn't match the line '{line}' while it should.")

View File

@ -72,4 +72,4 @@ for zuliprc_path in zuliprc_paths_list:
else:
result = 'SUCCESS'
reason = 'API key for user %s is already consistent' % (email,)
print('{}: {}: {}'.format(zuliprc_path, result, reason))
print(f'{zuliprc_path}: {result}: {reason}')

View File

@ -119,12 +119,12 @@ def convert_user_data(user_handler: UserHandler,
if role == UserProfile.ROLE_GUEST:
# Hipchat guest users don't have emails, so
# we just fake them.
email = 'guest-{id}@example.com'.format(id=id)
email = f'guest-{id}@example.com'
delivery_email = email
else:
# Hipchat sometimes doesn't export an email for deactivated users.
assert not is_active
email = delivery_email = "deactivated-{id}@example.com".format(id=id)
email = delivery_email = f"deactivated-{id}@example.com"
# unmapped fields:
# title - Developer, Project Manager, etc.

View File

@ -45,7 +45,7 @@ class UserHandler:
user_id = self._new_mirror_user_id()
short_name = name
full_name = name
email = 'mirror-{user_id}@example.com'.format(user_id=user_id)
email = f'mirror-{user_id}@example.com'
delivery_email = email
avatar_source = 'G'
date_joined = int(timezone_now().timestamp())

View File

@ -1112,7 +1112,7 @@ def log_token_warning(token: str) -> None:
def get_slack_api_data(slack_api_url: str, get_param: str, **kwargs: Any) -> Any:
if not kwargs.get("token"):
raise AssertionError("Slack token missing in kwargs")
data = requests.get("{}?{}".format(slack_api_url, urlencode(kwargs)))
data = requests.get(f"{slack_api_url}?{urlencode(kwargs)}")
if data.status_code == requests.codes.ok:
result = data.json()

View File

@ -305,7 +305,7 @@ body:
def full_webhook_client_name(raw_client_name: Optional[str]=None) -> Optional[str]:
if raw_client_name is None:
return None
return "Zulip{}Webhook".format(raw_client_name)
return f"Zulip{raw_client_name}Webhook"
# Use this for webhook views that don't get an email passed in.
def api_key_only_webhook_view(

View File

@ -228,7 +228,7 @@ def generate_password_reset_url(user_profile: UserProfile,
uid = urlsafe_base64_encode(force_bytes(user_profile.id))
endpoint = reverse('django.contrib.auth.views.password_reset_confirm',
kwargs=dict(uidb64=uid, token=token))
return "{}{}".format(user_profile.realm.uri, endpoint)
return f"{user_profile.realm.uri}{endpoint}"
class ZulipPasswordResetForm(PasswordResetForm):
def save(self,
@ -319,7 +319,7 @@ class RateLimitedPasswordResetByEmail(RateLimitedObject):
super().__init__()
def key(self) -> str:
return "{}:{}".format(type(self).__name__, self.email)
return f"{type(self).__name__}:{self.email}"
def rules(self) -> List[Tuple[int, int]]:
return settings.RATE_LIMITING_RULES['password_reset_form_by_email']

View File

@ -754,8 +754,8 @@ def do_scrub_realm(realm: Realm) -> None:
for user in users:
do_delete_messages_by_sender(user)
do_delete_avatar_image(user)
user.full_name = "Scrubbed {}".format(generate_key()[:15])
scrubbed_email = "scrubbed-{}@{}".format(generate_key()[:15], realm.host)
user.full_name = f"Scrubbed {generate_key()[:15]}"
scrubbed_email = f"scrubbed-{generate_key()[:15]}@{realm.host}"
user.email = scrubbed_email
user.delivery_email = scrubbed_email
user.save(update_fields=["full_name", "email", "delivery_email"])

View File

@ -59,10 +59,10 @@ def set_bot_config(bot_profile: UserProfile, key: str, value: str) -> None:
obj.save()
def load_bot_config_template(bot: str) -> Dict[str, str]:
bot_module_name = 'zulip_bots.bots.{}'.format(bot)
bot_module_name = f'zulip_bots.bots.{bot}'
bot_module = importlib.import_module(bot_module_name)
bot_module_path = os.path.dirname(bot_module.__file__)
config_path = os.path.join(bot_module_path, '{}.conf'.format(bot))
config_path = os.path.join(bot_module_path, f'{bot}.conf')
if os.path.isfile(config_path):
config = configparser.ConfigParser()
with open(config_path) as conf:

View File

@ -31,9 +31,9 @@ def set_bot_storage(bot_profile: UserProfile, entries: List[Tuple[str, str]]) ->
storage_size_difference = 0
for key, value in entries:
if not isinstance(key, str):
raise StateError("Key type is {}, but should be str.".format(type(key)))
raise StateError(f"Key type is {type(key)}, but should be str.")
if not isinstance(value, str):
raise StateError("Value type is {}, but should be str.".format(type(value)))
raise StateError(f"Value type is {type(value)}, but should be str.")
storage_size_difference += (len(key) + len(value)) - get_bot_storage_size(bot_profile, key)
new_storage_size = get_bot_storage_size(bot_profile) + storage_size_difference
if new_storage_size > storage_size_limit:

View File

@ -769,7 +769,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
def youtube_title(self, extracted_data: Dict[str, Any]) -> Optional[str]:
title = extracted_data.get("title")
if title is not None:
return "YouTube - {}".format(title)
return f"YouTube - {title}"
return None
def youtube_image(self, url: str) -> Optional[str]:
@ -796,7 +796,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
def vimeo_title(self, extracted_data: Dict[str, Any]) -> Optional[str]:
title = extracted_data.get("title")
if title is not None:
return "Vimeo - {}".format(title)
return f"Vimeo - {title}"
return None
def twitter_text(self, text: str,
@ -1201,7 +1201,7 @@ class Avatar(markdown.inlinepatterns.Pattern):
profile_id = user_dict['id']
img.set('class', 'message_body_gravatar')
img.set('src', '/avatar/{}?s=30'.format(profile_id or email))
img.set('src', f'/avatar/{profile_id or email}?s=30')
img.set('title', email)
img.set('alt', email)
return img
@ -1637,7 +1637,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
el.set('class', 'user-mention silent')
else:
el.set('class', 'user-mention')
text = "@{}".format(text)
text = f"@{text}"
el.text = markdown.util.AtomicString(text)
return el
return None
@ -1691,8 +1691,8 @@ class StreamPattern(CompiledPattern):
# provide more clarity to API clients.
# Also do the same for StreamTopicPattern.
stream_url = encode_stream(stream['id'], name)
el.set('href', '/#narrow/stream/{stream_url}'.format(stream_url=stream_url))
text = '#{stream_name}'.format(stream_name=name)
el.set('href', f'/#narrow/stream/{stream_url}')
text = f'#{name}'
el.text = markdown.util.AtomicString(text)
return el
return None
@ -1721,7 +1721,7 @@ class StreamTopicPattern(CompiledPattern):
link = '/#narrow/stream/{stream_url}/topic/{topic_url}'.format(stream_url=stream_url,
topic_url=topic_url)
el.set('href', link)
text = '#{stream_name} > {topic_name}'.format(stream_name=stream_name, topic_name=topic_name)
text = f'#{stream_name} > {topic_name}'
el.text = markdown.util.AtomicString(text)
return el
return None

View File

@ -113,7 +113,7 @@ class APIArgumentsTablePreprocessor(Preprocessor):
default = argument.get('schema', {}).get('default')
if default is not None:
description += '\nDefaults to `{}`.'.format(json.dumps(default))
description += f'\nDefaults to `{json.dumps(default)}`.'
# TODO: OpenAPI allows indicating where the argument goes
# (path, querystring, form data...). We should document this detail.

View File

@ -45,7 +45,7 @@ class IncludeCustomPreprocessor(IncludePreprocessor):
with open(filename, encoding=self.encoding) as r:
text = r.readlines()
except Exception as e:
print('Warning: could not find file {}. Error: {}'.format(filename, e))
print(f'Warning: could not find file {filename}. Error: {e}')
lines[loc] = INC_SYNTAX.sub('', line)
raise InvalidMarkdownIncludeStatement(m.group(0).strip())

View File

@ -124,7 +124,7 @@ class TabbedSectionsPreprocessor(Preprocessor):
# Wrapping the content in two newlines is necessary here.
# If we don't do this, the inner Markdown does not get
# rendered properly.
content='\n{}\n'.format(content))
content=f'\n{content}\n')
tab_content_blocks.append(tab_content_block)
return '\n'.join(tab_content_blocks)

View File

@ -216,7 +216,7 @@ def validate_cache_key(key: str) -> None:
if not bool(re.fullmatch(r"([!-~])+", key)):
raise InvalidCacheKeyException("Invalid characters in the cache key: " + key)
if len(key) > MEMCACHED_MAX_KEY_LENGTH:
raise InvalidCacheKeyException("Cache key too long: {} Length: {}".format(key, len(key)))
raise InvalidCacheKeyException(f"Cache key too long: {key} Length: {len(key)}")
def cache_set(key: str, val: Any, cache_name: Optional[str]=None, timeout: Optional[int]=None) -> None:
final_key = KEY_PREFIX + key

View File

@ -52,7 +52,7 @@ def tracemalloc_dump() -> None:
gc.collect()
tracemalloc.take_snapshot().dump(path)
with open('/proc/{}/stat'.format(os.getpid()), 'rb') as f:
with open(f'/proc/{os.getpid()}/stat', 'rb') as f:
procstat = f.read().split()
rss_pages = int(procstat[23])
logger.info("tracemalloc dump: tracing %s MiB (%s MiB peak), using %s MiB; rss %s MiB; dumped %s",
@ -79,7 +79,7 @@ def tracemalloc_listen() -> None:
listener_pid = os.getpid()
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
path = "/tmp/tracemalloc.{}".format(os.getpid())
path = f"/tmp/tracemalloc.{os.getpid()}"
sock.bind(path)
thread = threading.Thread(target=lambda: tracemalloc_listen_sock(sock),
daemon=True)

View File

@ -43,15 +43,15 @@ def redact_email_address(error_message: str) -> str:
# Annotate basic info about the address before scrubbing:
if is_missed_message_address(email_address):
redacted_message = error_message.replace(email_address,
"{} <Missed message address>".format(email_address))
f"{email_address} <Missed message address>")
else:
try:
target_stream_id = decode_stream_email_address(email_address)[0].id
annotated_address = "{} <Address to stream id: {}>".format(email_address, target_stream_id)
annotated_address = f"{email_address} <Address to stream id: {target_stream_id}>"
redacted_message = error_message.replace(email_address, annotated_address)
except ZulipEmailForwardError:
redacted_message = error_message.replace(email_address,
"{} <Invalid address>".format(email_address))
f"{email_address} <Invalid address>")
# Scrub the address from the message, to the form XXXXX@example.com:
string_to_scrub = address_match.groups()[0]
@ -429,7 +429,7 @@ def mirror_email_message(data: Dict[str, str]) -> Dict[str, str]:
except ZulipEmailForwardError as e:
return {
"status": "error",
"msg": "5.1.1 Bad destination mailbox address: {}".format(e)
"msg": f"5.1.1 Bad destination mailbox address: {e}"
}
queue_json_publish(
@ -449,7 +449,7 @@ class RateLimitedRealmMirror(RateLimitedObject):
super().__init__()
def key(self) -> str:
return "{}:{}".format(type(self).__name__, self.realm.string_id)
return f"{type(self).__name__}:{self.realm.string_id}"
def rules(self) -> List[Tuple[int, int]]:
return settings.RATE_LIMITING_MIRROR_REALM_RULES

View File

@ -141,9 +141,9 @@ def build_message_list(user_profile: UserProfile, messages: List[Message]) -> Li
return re.sub(r"\[(\S*)\]\((\S*)\)", r"\2", content)
def append_sender_to_message(message_plain: str, message_html: str, sender: str) -> Tuple[str, str]:
message_plain = "{}: {}".format(sender, message_plain)
message_plain = f"{sender}: {message_plain}"
message_soup = BeautifulSoup(message_html, "html.parser")
sender_name_soup = BeautifulSoup("<b>{}</b>: ".format(sender), "html.parser")
sender_name_soup = BeautifulSoup(f"<b>{sender}</b>: ", "html.parser")
first_tag = message_soup.find()
if first_tag.name == "p":
first_tag.insert(0, sender_name_soup)

View File

@ -30,9 +30,9 @@ EMOTICON_CONVERSIONS = emoji_codes["emoticon_conversions"]
possible_emoticons = EMOTICON_CONVERSIONS.keys()
possible_emoticon_regexes = (re.escape(emoticon) for emoticon in possible_emoticons)
terminal_symbols = ',.;?!()\\[\\] "\'\\n\\t' # from composebox_typeahead.js
emoticon_regex = ('(?<![^{}])(?P<emoticon>('.format(terminal_symbols)
emoticon_regex = (f'(?<![^{terminal_symbols}])(?P<emoticon>('
+ ')|('.join(possible_emoticon_regexes)
+ '))(?![^{}])'.format(terminal_symbols))
+ f'))(?![^{terminal_symbols}])')
# Translates emoticons to their colon syntax, e.g. `:smiley:`.
def translate_emoticons(text: str) -> str:

View File

@ -92,5 +92,5 @@ def get_language_translation_data(language: str) -> Dict[str, str]:
with open(path) as reader:
return ujson.load(reader)
except FileNotFoundError:
print('Translation for {} not found at {}'.format(language, path))
print(f'Translation for {language} not found at {path}')
return {}

View File

@ -333,7 +333,7 @@ def idseq(model_class: Any) -> str:
return 'zerver_botuserstatedata_id_seq'
elif model_class == BotConfigData:
return 'zerver_botuserconfigdata_id_seq'
return '{}_id_seq'.format(model_class._meta.db_table)
return f'{model_class._meta.db_table}_id_seq'
def allocate_ids(model_class: Any, count: int) -> List[int]:
"""

View File

@ -139,9 +139,9 @@ class BotIntegration(Integration):
self.logo_url = staticfiles_storage.url(logo)
if display_name is None:
display_name = "{} Bot".format(name.title()) # nocoverage
display_name = f"{name.title()} Bot" # nocoverage
else:
display_name = "{} Bot".format(display_name)
display_name = f"{display_name} Bot"
self.display_name = display_name
if doc is None:
@ -235,7 +235,7 @@ class HubotIntegration(Integration):
logo_alt: Optional[str]=None, git_url: Optional[str]=None,
legacy: bool=False) -> None:
if logo_alt is None:
logo_alt = "{} logo".format(name.title())
logo_alt = f"{name.title()} logo"
self.logo_alt = logo_alt
if git_url is None:

View File

@ -170,7 +170,7 @@ def find_log_origin(record: logging.LogRecord) -> str:
# responsible for the request in the logs.
from zerver.tornado.ioloop_logging import logging_data
shard = logging_data.get('port', 'unknown')
logger_name = "{}:{}".format(logger_name, shard)
logger_name = f"{logger_name}:{shard}"
return logger_name

View File

@ -116,7 +116,7 @@ class RateLimitedUser(RateLimitedObject):
super().__init__(backend=backend)
def key(self) -> str:
return "{}:{}:{}".format(type(self).__name__, self.user.id, self.domain)
return f"{type(self).__name__}:{self.user.id}:{self.domain}"
def rules(self) -> List[Tuple[int, int]]:
# user.rate_limits are general limits, applicable to the domain 'api_by_user'
@ -294,7 +294,7 @@ class TornadoInMemoryRateLimiterBackend(RateLimiterBackend):
class RedisRateLimiterBackend(RateLimiterBackend):
@classmethod
def get_keys(cls, entity_key: str) -> List[str]:
return ["{}ratelimit:{}:{}".format(KEY_PREFIX, entity_key, keytype)
return [f"{KEY_PREFIX}ratelimit:{entity_key}:{keytype}"
for keytype in ['list', 'zset', 'block']]
@classmethod

View File

@ -60,7 +60,7 @@ def send_to_push_bouncer(method: str,
except (requests.exceptions.Timeout, requests.exceptions.SSLError,
requests.exceptions.ConnectionError) as e:
raise PushNotificationBouncerRetryLaterError(
"{} while trying to connect to push notification bouncer".format(e.__class__.__name__))
f"{e.__class__.__name__} while trying to connect to push notification bouncer")
if res.status_code >= 500:
# 500s should be resolved by the people who run the push

View File

@ -329,7 +329,7 @@ class ZulipTestCase(TestCase):
return None
else:
self.assert_json_success(result)
bot_email = '{}-bot@zulip.testserver'.format(short_name)
bot_email = f'{short_name}-bot@zulip.testserver'
bot_profile = get_user(bot_email, user_profile.realm)
return bot_profile
@ -865,7 +865,7 @@ class ZulipTestCase(TestCase):
the attribute only for the specific test function that calls this method,
and is isolated from other tests.
"""
dn = "uid={username},ou=users,dc=zulip,dc=com".format(username=username)
dn = f"uid={username},ou=users,dc=zulip,dc=com"
if binary:
with open(attr_value, "rb") as f:
# attr_value should be a path to the file with the binary data
@ -884,7 +884,7 @@ class ZulipTestCase(TestCase):
return self.example_user_ldap_username_map[username]
def ldap_password(self, uid: str) -> str:
return "{}_ldap_password".format(uid)
return f"{uid}_ldap_password"
class WebhookTestCase(ZulipTestCase):
"""
@ -955,15 +955,15 @@ class WebhookTestCase(ZulipTestCase):
has_arguments = kwargs or args
if has_arguments and url.find('?') == -1:
url = "{}?".format(url) # nocoverage
url = f"{url}?" # nocoverage
else:
url = "{}&".format(url)
url = f"{url}&"
for key, value in kwargs.items():
url = "{}{}={}&".format(url, key, value)
url = f"{url}{key}={value}&"
for arg in args:
url = "{}{}&".format(url, arg)
url = f"{url}{arg}&"
return url[:-1] if has_arguments else url
@ -995,7 +995,7 @@ class MigrationsTestCase(ZulipTestCase): # nocoverage
def setUp(self) -> None:
assert self.migrate_from and self.migrate_to, \
"TestCase '{}' must define migrate_from and migrate_to properties".format(type(self).__name__)
f"TestCase '{type(self).__name__}' must define migrate_from and migrate_to properties"
migrate_from: List[Tuple[str, str]] = [(self.app, self.migrate_from)]
migrate_to: List[Tuple[str, str]] = [(self.app, self.migrate_to)]
executor = MigrationExecutor(connection)

View File

@ -345,7 +345,7 @@ def destroy_leaked_test_databases(expiry_time: int = 60 * 60) -> int:
if round(time.time()) - os.path.getmtime(file) < expiry_time:
with open(file) as f:
for line in f:
databases_in_use.add('zulip_test_template_{}'.format(line).rstrip())
databases_in_use.add(f'zulip_test_template_{line}'.rstrip())
else:
# Any test-backend run older than expiry_time can be
# cleaned up, both the database and the file listing its

View File

@ -43,12 +43,12 @@ random_id_range_start = str(random.randint(1, 10000000))
def get_database_id(worker_id: Optional[int]=None) -> str:
if worker_id:
return "{}_{}".format(random_id_range_start, worker_id)
return f"{random_id_range_start}_{worker_id}"
return random_id_range_start
# The root directory for this run of the test suite.
TEST_RUN_DIR = get_or_create_dev_uuid_var_path(
os.path.join('test-backend', 'run_{}'.format(get_database_id())))
os.path.join('test-backend', f'run_{get_database_id()}'))
_worker_id = 0 # Used to identify the worker process.
@ -165,7 +165,7 @@ class TextTestResult(runner.TextTestResult):
def startTest(self, test: TestCase) -> None:
TestResult.startTest(self, test)
self.stream.writeln("Running {}".format(full_test_name(test))) # type: ignore[attr-defined] # https://github.com/python/typeshed/issues/3139
self.stream.writeln(f"Running {full_test_name(test)}") # type: ignore[attr-defined] # https://github.com/python/typeshed/issues/3139
self.stream.flush() # type: ignore[attr-defined] # https://github.com/python/typeshed/issues/3139
def addSuccess(self, *args: Any, **kwargs: Any) -> None:
@ -382,7 +382,7 @@ def check_import_error(test_name: str) -> None:
def initialize_worker_path(worker_id: int) -> None:
# Allow each test worker process to write to a unique directory
# within `TEST_RUN_DIR`.
worker_path = os.path.join(TEST_RUN_DIR, 'worker_{}'.format(_worker_id))
worker_path = os.path.join(TEST_RUN_DIR, f'worker_{_worker_id}')
os.makedirs(worker_path, exist_ok=True)
settings.TEST_WORKER_DIR = worker_path

View File

@ -247,7 +247,7 @@ def validate_user_custom_profile_field(realm_id: int, field: CustomProfileField,
value: Union[int, str, List[int]]) -> Optional[str]:
validators = CustomProfileField.FIELD_VALIDATORS
field_type = field.field_type
var_name = '{}'.format(field.name)
var_name = f'{field.name}'
if field_type in validators:
validator = validators[field_type]
result = validator(var_name, value)

View File

@ -91,7 +91,7 @@ def get_push_commits_event_message(user_name: str, compare_url: Optional[str],
committers_details = "{} ({})".format(*committers_items[0])
for name, number_of_commits in committers_items[1:-1]:
committers_details = "{}, {} ({})".format(committers_details, name, number_of_commits)
committers_details = f"{committers_details}, {name} ({number_of_commits})"
if len(committers_items) > 1:
committers_details = "{} and {} ({})".format(committers_details, *committers_items[-1])
@ -140,7 +140,7 @@ def get_pull_request_event_message(user_name: str, action: str, url: str, number
'action': action,
'type': type,
'url': url,
'id': ' #{}'.format(number) if number is not None else '',
'id': f' #{number}' if number is not None else '',
'title': title,
}
@ -162,19 +162,19 @@ def get_pull_request_event_message(user_name: str, action: str, url: str, number
assignee_info = PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE.format(
assignee=assignees_string)
main_message = "{} {}".format(main_message, assignee_info)
main_message = f"{main_message} {assignee_info}"
elif assignee:
assignee_info = PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE.format(
assignee=assignee)
main_message = "{} {}".format(main_message, assignee_info)
main_message = f"{main_message} {assignee_info}"
if target_branch and base_branch:
branch_info = PULL_REQUEST_BRANCH_INFO_TEMPLATE.format(
target=target_branch,
base=base_branch
)
main_message = "{} {}".format(main_message, branch_info)
main_message = f"{main_message} {branch_info}"
punctuation = ':' if message else '.'
if (assignees or assignee or (target_branch and base_branch) or (title is None)):
@ -195,7 +195,7 @@ def get_setup_webhook_message(integration: str, user_name: Optional[str]=None) -
content = SETUP_MESSAGE_TEMPLATE.format(integration=integration)
if user_name:
content += SETUP_MESSAGE_USER_PART.format(user_name=user_name)
content = "{}.".format(content)
content = f"{content}."
return content
def get_issue_event_message(user_name: str,
@ -234,7 +234,7 @@ def get_push_tag_event_message(user_name: str,
)
if tag_name[-1] not in string.punctuation:
message = '{}.'.format(message)
message = f'{message}.'
return message
@ -250,7 +250,7 @@ def get_commits_comment_action_message(user_name: str,
url=commit_url
)
punctuation = ':' if message else '.'
content = '{}{}'.format(content, punctuation)
content = f'{content}{punctuation}'
if message:
content += CONTENT_MESSAGE_TEMPLATE.format(
message=message

View File

@ -57,7 +57,7 @@ class Command(compilemessages.Command):
return po_template.format(locale_path, locale)
def get_json_filename(self, locale_path: str, locale: str) -> str:
return "{}/{}/translations.json".format(locale_path, locale)
return f"{locale_path}/{locale}/translations.json"
def get_name_from_po_file(self, po_filename: str, locale: str) -> str:
lang_name_re = re.compile(r'"Language-Team: (.*?) \(')
@ -67,7 +67,7 @@ class Command(compilemessages.Command):
try:
return result.group(1)
except Exception:
print("Problem in parsing {}".format(po_filename))
print(f"Problem in parsing {po_filename}")
raise
else:
raise Exception("Unknown language %s" % (locale,))
@ -85,8 +85,8 @@ class Command(compilemessages.Command):
return locales
def extract_language_options(self) -> None:
locale_path = "{}/locale".format(settings.DEPLOY_ROOT)
output_path = "{}/language_options.json".format(locale_path)
locale_path = f"{settings.DEPLOY_ROOT}/locale"
output_path = f"{locale_path}/language_options.json"
data: Dict[str, List[Dict[str, Any]]] = {'languages': []}

View File

@ -164,9 +164,9 @@ class Command(ZulipBaseCommand):
if reaction.user_profile.realm != realm:
raise CommandError("Users from a different realm reacted to message. Aborting...")
print("\n\033[94mMessage content:\033[0m\n{}\n".format(message.content))
print(f"\n\033[94mMessage content:\033[0m\n{message.content}\n")
print("\033[94mNumber of users that reacted outbox:\033[0m {}\n".format(len(reactions)))
print(f"\033[94mNumber of users that reacted outbox:\033[0m {len(reactions)}\n")
# Allows us to trigger exports separately from command line argument parsing
export_realm_wrapper(realm=realm, output_dir=output_dir,

View File

@ -71,7 +71,7 @@ class Command(makemessages.Command):
xgettext_options = makemessages.Command.xgettext_options
for func, tag in tags:
xgettext_options += ['--keyword={}:1,"{}"'.format(func, tag)]
xgettext_options += [f'--keyword={func}:1,"{tag}"']
def add_arguments(self, parser: ArgumentParser) -> None:
super().add_arguments(parser)
@ -241,7 +241,7 @@ class Command(makemessages.Command):
def write_translation_strings(self, translation_strings: List[str]) -> None:
for locale, output_path in zip(self.get_locales(), self.get_output_paths()):
self.stdout.write("[frontend] processing locale {}".format(locale))
self.stdout.write(f"[frontend] processing locale {locale}")
try:
with open(output_path) as reader:
old_strings = json.load(reader)

View File

@ -89,7 +89,7 @@ Example:
def _parse_email_fixture(self, fixture_path: str) -> Message:
if not self._does_fixture_path_exist(fixture_path):
raise CommandError('Fixture {} does not exist'.format(fixture_path))
raise CommandError(f'Fixture {fixture_path} does not exist')
if fixture_path.endswith('.json'):
message = self._parse_email_json_fixture(fixture_path)

View File

@ -153,7 +153,7 @@ def render_javascript_code_example(function: str, admin_config: Optional[bool]=F
for line in snippet:
result = re.search('const result.*=(.*);', line)
if result:
line = " return{};".format(result.group(1))
line = f" return{result.group(1)};"
# Strip newlines
code_example.append(line.rstrip())
code_example.append("}).then(console.log).catch(console.err);")
@ -167,7 +167,7 @@ def curl_method_arguments(endpoint: str, method: str,
api_url: str) -> List[str]:
# We also include the -sS verbosity arguments here.
method = method.upper()
url = "{}/v1{}".format(api_url, endpoint)
url = f"{api_url}/v1{endpoint}"
valid_methods = ["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS"]
if method == "GET":
# Then we need to make sure that each -d option translates to becoming
@ -206,7 +206,7 @@ cURL example.""".format(endpoint, method, param_name)
raise ValueError(msg)
ordered_ex_val_str = json.dumps(example_value, sort_keys=True)
if curl_argument:
return " --data-urlencode {}='{}'".format(param_name, ordered_ex_val_str)
return f" --data-urlencode {param_name}='{ordered_ex_val_str}'"
return ordered_ex_val_str # nocoverage
else:
example_value = param.get("example", DEFAULT_EXAMPLE[param_type])
@ -215,7 +215,7 @@ cURL example.""".format(endpoint, method, param_name)
if jsonify:
example_value = json.dumps(example_value)
if curl_argument:
return " -d '{}={}'".format(param_name, example_value)
return f" -d '{param_name}={example_value}'"
return example_value
def generate_curl_example(endpoint: str, method: str,

View File

@ -185,7 +185,7 @@ def validate_object(content: Dict[str, Any], schema: Dict[str, Any]) -> None:
# If the object is not opaque then continue statements
# will be executed above and this will be skipped
if expected_type is dict:
raise SchemaError('Opaque object "{}"'.format(key))
raise SchemaError(f'Opaque object "{key}"')
# Check that at least all the required keys are present
if 'required' in schema:
for req_key in schema['required']:

View File

@ -97,7 +97,7 @@ def test_authorization_errors_fatal(client: Client, nonadmin_client: Client) ->
stream_id = client.get_stream_id('private_stream')['stream_id']
client.call_endpoint(
'streams/{}'.format(stream_id),
f'streams/{stream_id}',
method='PATCH',
request={'is_private': True}
)
@ -945,7 +945,7 @@ def upload_custom_emoji(client: Client) -> None:
with open(emoji_path, 'rb') as fp:
emoji_name = 'my_custom_emoji'
result = client.call_endpoint(
'realm/emoji/{}'.format(emoji_name),
f'realm/emoji/{emoji_name}',
method='POST',
files=[fp]
)
@ -1064,8 +1064,8 @@ def test_against_fixture(result: Dict[str, Any], fixture: Dict[str, Any], check_
def assertEqual(key: str, result: Dict[str, Any], fixture: Dict[str, Any]) -> None:
if result[key] != fixture[key]:
first = "{key} = {value}".format(key=key, value=result[key])
second = "{key} = {value}".format(key=key, value=fixture[key])
first = f"{key} = {result[key]}"
second = f"{key} = {fixture[key]}"
raise AssertionError("Actual and expected outputs do not match; showing diff:\n" +
mdiff.diff_strings(first, second))
else:
@ -1083,7 +1083,7 @@ def assertLength(result: Dict[str, Any], fixture: Dict[str, Any]) -> None:
def assertIn(key: str, result: Dict[str, Any]) -> None:
if key not in result.keys():
raise AssertionError(
"The actual output does not contain the the key `{key}`.".format(key=key)
f"The actual output does not contain the the key `{key}`."
)
else:
assert key in result

View File

@ -11,7 +11,7 @@ from zerver.models import get_realm
from zerver.openapi.curl_param_value_generators import REGISTERED_GENERATOR_FUNCTIONS, CALLED_GENERATOR_FUNCTIONS
def test_generated_curl_examples_for_success(client: Client) -> None:
authentication_line = "{}:{}".format(client.email, client.api_key)
authentication_line = f"{client.email}:{client.api_key}"
# A limited markdown engine that just processes the code example syntax.
realm = get_realm("zulip")
md_engine = markdown.Markdown(extensions=[markdown_extension.makeExtension(

View File

@ -87,7 +87,7 @@ def email_on_new_login(sender: Any, user: UserProfile, request: Any, **kwargs: A
hhmm_string = local_time.strftime('%H:%M')
else:
hhmm_string = local_time.strftime('%I:%M%p')
context['login_time'] = local_time.strftime('%A, %B %d, %Y at {} %Z'.format(hhmm_string))
context['login_time'] = local_time.strftime(f'%A, %B %d, %Y at {hhmm_string} %Z')
context['device_ip'] = request.META.get('REMOTE_ADDR') or _("Unknown IP address")
context['device_os'] = get_device_os(user_agent) or _("an unknown operating system")
context['device_browser'] = get_device_browser(user_agent) or _("An unknown browser")

View File

@ -26,14 +26,14 @@ class AttachmentsTests(ZulipTestCase):
user_profile = self.example_user('cordelia')
self.login_user(user_profile)
with mock.patch('zerver.lib.attachments.delete_message_image', side_effect=Exception()):
result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id))
result = self.client_delete(f'/json/attachments/{self.attachment.id}')
self.assert_json_error(result, "An error occurred while deleting the attachment. Please try again later.")
@mock.patch('zerver.lib.attachments.delete_message_image')
def test_remove_attachment(self, ignored: Any) -> None:
user_profile = self.example_user('cordelia')
self.login_user(user_profile)
result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id))
result = self.client_delete(f'/json/attachments/{self.attachment.id}')
self.assert_json_success(result)
attachments = user_attachments(user_profile)
self.assertEqual(attachments, [])
@ -48,7 +48,7 @@ class AttachmentsTests(ZulipTestCase):
def test_remove_another_user(self) -> None:
user_profile = self.example_user('iago')
self.login_user(user_profile)
result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id))
result = self.client_delete(f'/json/attachments/{self.attachment.id}')
self.assert_json_error(result, 'Invalid attachment')
user_profile_to_remove = self.example_user('cordelia')
attachments = user_attachments(user_profile_to_remove)
@ -59,5 +59,5 @@ class AttachmentsTests(ZulipTestCase):
self.assert_json_error(result, 'Not logged in: API authentication or user session required', status_code=401)
def test_delete_unauthenticated(self) -> None:
result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id))
result = self.client_delete(f'/json/attachments/{self.attachment.id}')
self.assert_json_error(result, 'Not logged in: API authentication or user session required', status_code=401)

View File

@ -491,7 +491,7 @@ class RateLimitAuthenticationTests(ZulipTestCase):
salt = generate_random_token(32)
def _mock_key(self: RateLimitedAuthenticationByUsername) -> str:
return "{}:{}".format(salt, original_key_method(self))
return f"{salt}:{original_key_method(self)}"
def attempt_authentication(username: str, password: str) -> Optional[UserProfile]:
request = HttpRequest()
@ -1291,7 +1291,7 @@ class SocialAuthBase(DesktopFlowTestingLib, ZulipTestCase):
ldap_user_attr_map = {'full_name': 'cn'}
account_data_dict = self.get_account_data_dict(email=email, name=name)
backend_path = 'zproject.backends.{}'.format(self.BACKEND_CLASS.__name__)
backend_path = f'zproject.backends.{self.BACKEND_CLASS.__name__}'
with self.settings(
POPULATE_PROFILE_VIA_LDAP=True,
LDAP_APPEND_DOMAIN='zulip.com',
@ -1333,7 +1333,7 @@ class SocialAuthBase(DesktopFlowTestingLib, ZulipTestCase):
ldap_user_attr_map = {'full_name': 'cn'}
account_data_dict = self.get_account_data_dict(email=email, name=name)
backend_path = 'zproject.backends.{}'.format(self.BACKEND_CLASS.__name__)
backend_path = f'zproject.backends.{self.BACKEND_CLASS.__name__}'
with self.settings(
POPULATE_PROFILE_VIA_LDAP=True,
LDAP_EMAIL_ATTR='mail',
@ -1503,7 +1503,7 @@ class SAMLAuthBackendTest(SocialAuthBase):
self.assertTrue(saml_auth_enabled())
result = self.client_get("/saml/metadata.xml")
self.assert_in_success_response(
['entityID="{}"'.format(settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID)], result
[f'entityID="{settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID}"'], result
)
def test_social_auth_complete(self) -> None:
@ -1737,17 +1737,17 @@ class SAMLAuthBackendTest(SocialAuthBase):
def test_social_auth_saml_login_bad_idp_arg(self) -> None:
for action in ['login', 'register']:
result = self.client_get('/accounts/{}/social/saml'.format(action))
result = self.client_get(f'/accounts/{action}/social/saml')
# Missing idp argument.
self.assertEqual(result.status_code, 302)
self.assertEqual(result.url, '/config-error/saml')
result = self.client_get('/accounts/{}/social/saml/nonexistent_idp'.format(action))
result = self.client_get(f'/accounts/{action}/social/saml/nonexistent_idp')
# No such IdP is configured.
self.assertEqual(result.status_code, 302)
self.assertEqual(result.url, '/config-error/saml')
result = self.client_get('/accounts/{}/social/saml/'.format(action))
result = self.client_get(f'/accounts/{action}/social/saml/')
# No matching url pattern.
self.assertEqual(result.status_code, 404)
@ -4327,7 +4327,7 @@ class TestMaybeSendToRegistration(ZulipTestCase):
result = self.client_get(result.url)
self.assert_in_response('action="/accounts/register/"', result)
self.assert_in_response('value="{}" name="key"'.format(confirmation_key), result)
self.assert_in_response(f'value="{confirmation_key}" name="key"', result)
def test_sso_only_when_preregistration_user_exists(self) -> None:
rf = RequestFactory()

View File

@ -70,7 +70,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
def deactivate_bot(self) -> None:
email = 'hambot-bot@zulip.testserver'
result = self.client_delete("/json/bots/{}".format(self.get_bot_user(email).id))
result = self.client_delete(f"/json/bots/{self.get_bot_user(email).id}")
self.assert_json_success(result)
def test_add_bot_with_bad_username(self) -> None:
@ -541,7 +541,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.create_bot()
self.assert_num_bots_equal(1)
invalid_user_id = 1000
result = self.client_delete("/json/bots/{}".format(invalid_user_id))
result = self.client_delete(f"/json/bots/{invalid_user_id}")
self.assert_json_error(result, 'No such bot')
self.assert_num_bots_equal(1)
@ -591,7 +591,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
bot_email = result.json()['bots'][0]['username']
bot = get_user(bot_email, user.realm)
self.login('iago')
result = self.client_delete("/json/bots/{}".format(bot.id))
result = self.client_delete(f"/json/bots/{bot.id}")
self.assert_json_error(result, 'No such bot')
def test_bot_deactivation_attacks(self) -> None:
@ -610,7 +610,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.assert_json_error(result, 'No such bot')
email = 'hambot-bot@zulip.testserver'
result = self.client_delete("/json/bots/{}".format(self.get_bot_user(email).id))
result = self.client_delete(f"/json/bots/{self.get_bot_user(email).id}")
self.assert_json_error(result, 'Insufficient permission')
# But we don't actually deactivate the other person's bot.
@ -618,7 +618,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.assert_num_bots_equal(1)
# Cannot deactivate a bot as a user
result = self.client_delete("/json/users/{}".format(self.get_bot_user(email).id))
result = self.client_delete(f"/json/users/{self.get_bot_user(email).id}")
self.assert_json_error(result, 'No such user')
self.assert_num_bots_equal(1)
@ -632,13 +632,13 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.login('othello')
email = 'hambot-bot@zulip.testserver'
result = self.client_post("/json/bots/{}/api_key/regenerate".format(self.get_bot_user(email).id))
result = self.client_post(f"/json/bots/{self.get_bot_user(email).id}/api_key/regenerate")
self.assert_json_error(result, 'Insufficient permission')
bot_info = {
'full_name': 'Fred',
}
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, 'Insufficient permission')
def get_bot(self) -> Dict[str, Any]:
@ -652,7 +652,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
bot = self.get_bot()
old_api_key = bot['api_key']
email = 'hambot-bot@zulip.testserver'
result = self.client_post('/json/bots/{}/api_key/regenerate'.format(self.get_bot_user(email).id))
result = self.client_post(f'/json/bots/{self.get_bot_user(email).id}/api_key/regenerate')
self.assert_json_success(result)
new_api_key = result.json()['api_key']
self.assertNotEqual(old_api_key, new_api_key)
@ -662,7 +662,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
def test_update_api_key_for_invalid_user(self) -> None:
self.login('hamlet')
invalid_user_id = 1000
result = self.client_post('/json/bots/{}/api_key/regenerate'.format(invalid_user_id))
result = self.client_post(f'/json/bots/{invalid_user_id}/api_key/regenerate')
self.assert_json_error(result, 'No such bot')
def test_add_bot_with_bot_type_default(self) -> None:
@ -810,7 +810,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'full_name': 'Fred',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual('Fred', result.json()['full_name'])
@ -832,7 +832,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
bot_email = 'hambot-bot@zulip.testserver'
bot = self.get_bot_user(bot_email)
url = "/json/bots/{}".format(bot.id)
url = f"/json/bots/{bot.id}"
# It doesn't matter whether a name is taken by a human
# or a bot, we can't use it.
@ -890,7 +890,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'bot_owner_id': othello.id,
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
# Test bot's owner has been changed successfully.
@ -912,7 +912,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
bot_info = {
'bot_owner_id': bad_bot_owner_id,
}
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Failed to change owner, no such user")
profile = get_user('hambot-bot@zulip.testserver', get_realm('zulip'))
self.assertEqual(profile.bot_owner, self.example_user("hamlet"))
@ -931,7 +931,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Failed to change owner, user is deactivated")
profile = self.get_bot_user(email)
self.assertEqual(profile.bot_owner, self.example_user("hamlet"))
@ -946,7 +946,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Failed to change owner, no such user")
profile = self.get_bot_user(email)
self.assertEqual(profile.bot_owner, self.example_user("hamlet"))
@ -961,7 +961,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
# Check that we're still the owner
self.assert_json_success(result)
@ -984,7 +984,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'bot_owner_id': self.get_bot_user('hamelbot-bot@zulip.testserver').id,
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Failed to change owner, bots can't own other bots")
profile = get_user(email, get_realm('zulip'))
self.assertEqual(profile.bot_owner, self.example_user("hamlet"))
@ -1008,7 +1008,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
with get_test_image_file('img.png') as fp1, \
get_test_image_file('img.gif') as fp2:
result = self.client_patch_multipart(
'/json/bots/{}'.format(self.get_bot_user(email).id),
f'/json/bots/{self.get_bot_user(email).id}',
dict(file1=fp1, file2=fp2))
self.assert_json_error(result, 'You may only upload one file at a time')
@ -1018,7 +1018,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
# HAPPY PATH
with get_test_image_file('img.png') as fp:
result = self.client_patch_multipart(
'/json/bots/{}'.format(self.get_bot_user(email).id),
f'/json/bots/{self.get_bot_user(email).id}',
dict(file=fp))
profile = get_user(bot_email, bot_realm)
self.assertEqual(profile.avatar_version, 2)
@ -1043,7 +1043,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_sending_stream': 'Denmark',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual('Denmark', result.json()['default_sending_stream'])
@ -1063,7 +1063,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_sending_stream': 'Rome',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual('Rome', result.json()['default_sending_stream'])
@ -1083,7 +1083,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_sending_stream': '',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
bot_email = "hambot-bot@zulip.testserver"
@ -1111,7 +1111,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_sending_stream': 'Denmark',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual('Denmark', result.json()['default_sending_stream'])
@ -1137,7 +1137,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_sending_stream': 'Denmark',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Invalid stream name 'Denmark'")
def test_patch_bot_to_stream_not_found(self) -> None:
@ -1152,7 +1152,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_sending_stream': 'missing',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Invalid stream name 'missing'")
def test_patch_bot_events_register_stream(self) -> None:
@ -1167,7 +1167,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
email = 'hambot-bot@zulip.testserver'
bot_user = self.get_bot_user(email)
url = "/json/bots/{}".format(bot_user.id)
url = f"/json/bots/{bot_user.id}"
# Successfully give the bot a default stream.
stream_name = 'Denmark'
@ -1197,7 +1197,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.assert_json_success(result)
# Make sure the bot cannot create their own default stream.
url = "/api/v1/bots/{}".format(bot_user.id)
url = f"/api/v1/bots/{bot_user.id}"
result = self.api_patch(bot_user, url, bot_info)
self.assert_json_error_contains(result, 'endpoint does not accept')
@ -1217,7 +1217,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_events_register_stream': 'Denmark',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual('Denmark', result.json()['default_events_register_stream'])
@ -1242,7 +1242,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_events_register_stream': 'Denmark',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Invalid stream name 'Denmark'")
def test_patch_bot_events_register_stream_none(self) -> None:
@ -1257,7 +1257,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_events_register_stream': '',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
bot_email = "hambot-bot@zulip.testserver"
@ -1280,7 +1280,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_events_register_stream': 'missing',
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_error(result, "Invalid stream name 'missing'")
def test_patch_bot_default_all_public_streams_true(self) -> None:
@ -1295,7 +1295,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_all_public_streams': ujson.dumps(True),
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual(result.json()['default_all_public_streams'], True)
@ -1315,7 +1315,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'default_all_public_streams': ujson.dumps(False),
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
self.assertEqual(result.json()['default_all_public_streams'], False)
@ -1337,7 +1337,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
}
email = 'hambot-bot@zulip.testserver'
# Important: We intentionally use the wrong method, post, here.
result = self.client_post("/json/bots/{}".format(self.get_bot_user(email).id),
result = self.client_post(f"/json/bots/{self.get_bot_user(email).id}",
bot_info)
self.assert_json_success(result)
@ -1354,7 +1354,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'full_name': 'Fred',
}
invalid_user_id = 1000
result = self.client_patch("/json/bots/{}".format(invalid_user_id), bot_info)
result = self.client_patch(f"/json/bots/{invalid_user_id}", bot_info)
self.assert_json_error(result, 'No such bot')
self.assert_num_bots_equal(1)
@ -1374,7 +1374,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
'service_interface': Service.SLACK,
}
email = 'hambot-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
service_interface = ujson.loads(result.content)['service_interface']
@ -1392,7 +1392,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
config_data=ujson.dumps({'key': '12345678'}))
bot_info = {'config_data': ujson.dumps({'key': '87654321'})}
email = 'test-bot@zulip.testserver'
result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info)
result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info)
self.assert_json_success(result)
config_data = ujson.loads(result.content)['config_data']
self.assertEqual(config_data, ujson.loads(bot_info['config_data']))

View File

@ -1580,7 +1580,7 @@ class BugdownTest(ZulipTestCase):
cordelia = self.example_user('cordelia')
msg = Message(sender=sender_user_profile, sending_client=get_client("test"))
content = "@**Mark Twin|{}**, @**Mark Twin|{}** and @**Cordelia Lear**, hi.".format(twin1.id, twin2.id)
content = f"@**Mark Twin|{twin1.id}**, @**Mark Twin|{twin2.id}** and @**Cordelia Lear**, hi."
self.assertEqual(render_markdown(msg, content),
'<p>'
@ -1918,7 +1918,7 @@ class BugdownTest(ZulipTestCase):
stream = Stream.objects.create(name='Stream #1234', realm=realm)
msg = Message(sender=sender_user_profile, sending_client=get_client("test"))
content = "#**Stream #1234**"
href = '/#narrow/stream/{stream_id}-Stream-.231234'.format(stream_id=stream.id)
href = f'/#narrow/stream/{stream.id}-Stream-.231234'
self.assertEqual(
render_markdown(msg, content),
'<p><a class="stream" data-stream-id="{s.id}" href="{href}">#{s.name}</a></p>'.format(
@ -2159,7 +2159,7 @@ class BugdownAvatarTestCase(ZulipTestCase):
message = Message(sender=sender_user_profile, sending_client=get_client("test"))
user_profile = self.example_user('hamlet')
msg = '!avatar({})'.format(user_profile.email)
msg = f'!avatar({user_profile.email})'
converted = bugdown.convert(msg, message=message)
values = {'email': user_profile.email, 'id': user_profile.id}
self.assertEqual(
@ -2171,7 +2171,7 @@ class BugdownAvatarTestCase(ZulipTestCase):
message = Message(sender=sender_user_profile, sending_client=get_client("test"))
email = 'fakeuser@example.com'
msg = '!avatar({})'.format(email)
msg = f'!avatar({email})'
converted = bugdown.convert(msg, message=message)
self.assertEqual(
converted,

View File

@ -62,7 +62,7 @@ class CacheKeyValidationTest(ZulipTestCase):
class CacheWithKeyDecoratorTest(ZulipTestCase):
def test_cache_with_key_invalid_character(self) -> None:
def invalid_characters_cache_key_function(user_id: int) -> str:
return 'CacheWithKeyDecoratorTest:invalid_character:ą:{}'.format(user_id)
return f'CacheWithKeyDecoratorTest:invalid_character:ą:{user_id}'
@cache_with_key(invalid_characters_cache_key_function, timeout=1000)
def get_user_function_with_bad_cache_keys(user_id: int) -> UserProfile:
@ -101,7 +101,7 @@ class CacheWithKeyDecoratorTest(ZulipTestCase):
def test_cache_with_key_good_key(self) -> None:
def good_cache_key_function(user_id: int) -> str:
return 'CacheWithKeyDecoratorTest:good_cache_key:{}'.format(user_id)
return f'CacheWithKeyDecoratorTest:good_cache_key:{user_id}'
@cache_with_key(good_cache_key_function, timeout=1000)
def get_user_function_with_good_cache_keys(user_id: int) -> UserProfile:
@ -125,7 +125,7 @@ class CacheWithKeyDecoratorTest(ZulipTestCase):
def test_cache_with_key_none_values(self) -> None:
def cache_key_function(user_id: int) -> str:
return 'CacheWithKeyDecoratorTest:test_cache_with_key_none_values:{}'.format(user_id)
return f'CacheWithKeyDecoratorTest:test_cache_with_key_none_values:{user_id}'
@cache_with_key(cache_key_function, timeout=1000)
def get_user_function_can_return_none(user_id: int) -> Optional[UserProfile]:
@ -155,7 +155,7 @@ class GetCacheWithKeyDecoratorTest(ZulipTestCase):
# we got the result from calling the function (None)
def good_cache_key_function(user_id: int) -> str:
return 'CacheWithKeyDecoratorTest:good_cache_key:{}'.format(user_id)
return f'CacheWithKeyDecoratorTest:good_cache_key:{user_id}'
@get_cache_with_key(good_cache_key_function)
def get_user_function_with_good_cache_keys(user_id: int) -> Any: # nocoverage
@ -173,7 +173,7 @@ class GetCacheWithKeyDecoratorTest(ZulipTestCase):
def test_get_cache_with_bad_key(self) -> None:
def bad_cache_key_function(user_id: int) -> str:
return 'CacheWithKeyDecoratorTest:invalid_character:ą:{}'.format(user_id)
return f'CacheWithKeyDecoratorTest:invalid_character:ą:{user_id}'
@get_cache_with_key(bad_cache_key_function)
def get_user_function_with_bad_cache_keys(user_id: int) -> Any: # nocoverage

View File

@ -29,7 +29,7 @@ class VersionTest(ZulipTestCase):
def test_version_lt(self) -> None:
for ver1, cmp, ver2 in self.data:
msg = 'expected {} {} {}'.format(ver1, cmp, ver2)
msg = f'expected {ver1} {cmp} {ver2}'
if cmp == '<':
self.assertTrue(version_lt(ver1, ver2), msg=msg)
self.assertFalse(version_lt(ver2, ver1), msg=msg)

View File

@ -150,7 +150,7 @@ class CreateCustomProfileFieldTest(CustomProfileFieldTestCase):
self.assertEqual(field.name, DEFAULT_EXTERNAL_ACCOUNTS['twitter']['name'])
self.assertEqual(field.hint, DEFAULT_EXTERNAL_ACCOUNTS['twitter']['hint'])
result = self.client_delete("/json/realm/profile_fields/{}".format(field.id))
result = self.client_delete(f"/json/realm/profile_fields/{field.id}")
self.assert_json_success(result)
# Should also work without name or hint and only external field type and subtype data
@ -161,13 +161,13 @@ class CreateCustomProfileFieldTest(CustomProfileFieldTestCase):
# Default external account field data cannot be updated
field = CustomProfileField.objects.get(name="Twitter", realm=realm)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'Twitter username',
'field_type': CustomProfileField.EXTERNAL_ACCOUNT}
)
self.assert_json_error(result, 'Default custom field cannot be updated.')
result = self.client_delete("/json/realm/profile_fields/{}".format(field.id))
result = self.client_delete(f"/json/realm/profile_fields/{field.id}")
self.assert_json_success(result)
def test_create_external_account_field(self) -> None:
@ -292,7 +292,7 @@ class DeleteCustomProfileFieldTest(CustomProfileFieldTestCase):
self.assertTrue(self.custom_field_exists_in_realm(field.id))
result = self.client_delete(
"/json/realm/profile_fields/{}".format(field.id))
f"/json/realm/profile_fields/{field.id}")
self.assert_json_success(result)
self.assertFalse(self.custom_field_exists_in_realm(field.id))
@ -359,7 +359,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
field = CustomProfileField.objects.get(name="Phone number", realm=realm)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': '',
'field_type': CustomProfileField.SHORT_TEXT}
)
@ -367,7 +367,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
self.assertEqual(CustomProfileField.objects.count(), self.original_count)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'New phone number',
'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_success(result)
@ -378,14 +378,14 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
self.assertEqual(field.field_type, CustomProfileField.SHORT_TEXT)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': '*' * 41,
'field_type': CustomProfileField.SHORT_TEXT})
msg = "name is too long (limit: 40 characters)"
self.assert_json_error(result, msg)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'New phone number',
'hint': '*' * 81,
'field_type': CustomProfileField.SHORT_TEXT})
@ -393,7 +393,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
self.assert_json_error(result, msg)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'New phone number',
'hint': 'New contact number',
'field_type': CustomProfileField.SHORT_TEXT})
@ -407,7 +407,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
field = CustomProfileField.objects.get(name="Favorite editor", realm=realm)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'Favorite editor',
'field_data': 'invalid'})
self.assert_json_error(result, "Bad value for 'field_data': invalid")
@ -417,7 +417,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
'emacs': {'order': '2', 'text': 'Emacs'},
})
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'Favorite editor',
'field_data': field_data})
self.assert_json_error(result, "field_data is not a dict")
@ -428,7 +428,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
'notepad': {'order': '3', 'text': 'Notepad'},
})
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
f"/json/realm/profile_fields/{field.id}",
info={'name': 'Favorite editor',
'field_data': field_data})
self.assert_json_success(result)
@ -445,7 +445,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
self.assertTrue(self.custom_field_exists_in_realm(field_1.id))
self.assertTrue(self.custom_field_exists_in_realm(field_2.id))
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field_2.id),
f"/json/realm/profile_fields/{field_2.id}",
info={'name': 'Phone', 'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_error(
result, 'A field with that label already exists.')
@ -472,19 +472,19 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
def test_update_invalid_short_text(self) -> None:
field_name = "Phone number"
self.assert_error_update_invalid_value(field_name, 't' * 201,
"{} is too long (limit: 50 characters)".format(field_name))
f"{field_name} is too long (limit: 50 characters)")
def test_update_invalid_date(self) -> None:
field_name = "Birthday"
self.assert_error_update_invalid_value(field_name, "a-b-c",
"{} is not a date".format(field_name))
f"{field_name} is not a date")
self.assert_error_update_invalid_value(field_name, 123,
"{} is not a string".format(field_name))
f"{field_name} is not a string")
def test_update_invalid_url(self) -> None:
field_name = "Favorite website"
self.assert_error_update_invalid_value(field_name, "not URL",
"{} is not a URL".format(field_name))
f"{field_name} is not a URL")
def test_update_invalid_user_field(self) -> None:
field_name = "Mentor"
@ -554,7 +554,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase):
def test_update_invalid_choice_field(self) -> None:
field_name = "Favorite editor"
self.assert_error_update_invalid_value(field_name, "foobar",
"'foobar' is not a valid choice for '{}'.".format(field_name))
f"'foobar' is not a valid choice for '{field_name}'.")
def test_update_choice_field_successfully(self) -> None:
self.login('iago')

View File

@ -262,7 +262,7 @@ class TestDigestEmailMessages(ZulipTestCase):
cordelia = self.example_user('cordelia')
stream_id = create_stream_if_needed(cordelia.realm, 'New stream')[0].id
new_stream = gather_new_streams(cordelia, cutoff)[1]
expected_html = "<a href='http://zulip.testserver/#narrow/stream/{stream_id}-New-stream'>New stream</a>".format(stream_id=stream_id)
expected_html = f"<a href='http://zulip.testserver/#narrow/stream/{stream_id}-New-stream'>New stream</a>"
self.assertIn(expected_html, new_stream['html'])
def simulate_stream_conversation(self, stream: str, senders: List[str]) -> List[int]:
@ -271,7 +271,7 @@ class TestDigestEmailMessages(ZulipTestCase):
message_ids = [] # List[int]
for sender_name in senders:
sender = self.example_user(sender_name)
content = 'some content for {} from {}'.format(stream, sender_name)
content = f'some content for {stream} from {sender_name}'
message_id = self.send_stream_message(sender, stream, content)
message_ids.append(message_id)
Message.objects.filter(id__in=message_ids).update(sending_client=sending_client)

View File

@ -103,7 +103,7 @@ class DocPageTest(ZulipTestCase):
files = list(filter(_filter_func, files))
for f in files:
endpoint = '/api/{}'.format(os.path.splitext(f)[0])
endpoint = f'/api/{os.path.splitext(f)[0]}'
self._test(endpoint, '', doc_html_str=True)
@slow("Tests dozens of endpoints, including generating lots of emails")
@ -181,7 +181,7 @@ class DocPageTest(ZulipTestCase):
])
for integration in INTEGRATIONS.keys():
url = '/integrations/doc-html/{}'.format(integration)
url = f'/integrations/doc-html/{integration}'
self._test(url, '', doc_html_str=True)
def test_integration_pages_open_graph_metadata(self) -> None:
@ -209,13 +209,13 @@ class DocPageTest(ZulipTestCase):
# We don't need to test all the pages for 404
for integration in list(INTEGRATIONS.keys())[5]:
with self.settings(ROOT_DOMAIN_LANDING_PAGE=True):
url = '/en/integrations/doc-html/{}'.format(integration)
url = f'/en/integrations/doc-html/{integration}'
result = self.client_get(url, subdomain="", follow=True)
self.assertEqual(result.status_code, 404)
result = self.client_get(url, subdomain="zephyr", follow=True)
self.assertEqual(result.status_code, 404)
url = '/en/integrations/doc-html/{}'.format(integration)
url = f'/en/integrations/doc-html/{integration}'
result = self.client_get(url, subdomain="", follow=True)
self.assertEqual(result.status_code, 404)
result = self.client_get(url, subdomain="zephyr", follow=True)

View File

@ -211,7 +211,7 @@ class EmailChangeTestCase(ZulipTestCase):
response)
user_profile = get_user_profile_by_id(user_profile.id)
self.assertEqual(user_profile.delivery_email, new_email)
self.assertEqual(user_profile.email, "user{}@zulip.testserver".format(user_profile.id))
self.assertEqual(user_profile.email, f"user{user_profile.id}@zulip.testserver")
obj.refresh_from_db()
self.assertEqual(obj.status, 1)
with self.assertRaises(UserProfile.DoesNotExist):

View File

@ -73,11 +73,11 @@ class TestEncodeDecode(ZulipTestCase):
stream_name = 'dev. help'
stream = ensure_stream(realm, stream_name)
email_address = encode_email_address(stream)
self.assertEqual(email_address, "dev-help.{}@testserver".format(stream.email_token))
self.assertEqual(email_address, f"dev-help.{stream.email_token}@testserver")
# The default form of the email address (with an option - "include-footer"):
token, options = decode_email_address(
"dev-help.{}.include-footer@testserver".format(stream.email_token)
f"dev-help.{stream.email_token}.include-footer@testserver"
)
self._assert_options(options, include_footer=True)
self.assertEqual(token, stream.email_token)
@ -85,7 +85,7 @@ class TestEncodeDecode(ZulipTestCase):
# Using + instead of . as the separator is also supported for backwards compatibility,
# since that was the original form of addresses that we used:
token, options = decode_email_address(
"dev-help+{}+include-footer@testserver".format(stream.email_token)
f"dev-help+{stream.email_token}+include-footer@testserver"
)
self._assert_options(options, include_footer=True)
self.assertEqual(token, stream.email_token)
@ -164,8 +164,8 @@ class TestEncodeDecode(ZulipTestCase):
def test_decode_prefer_text_options(self) -> None:
stream = get_stream("Denmark", get_realm("zulip"))
address_prefer_text = "Denmark.{}.prefer-text@testserver".format(stream.email_token)
address_prefer_html = "Denmark.{}.prefer-html@testserver".format(stream.email_token)
address_prefer_text = f"Denmark.{stream.email_token}.prefer-text@testserver"
address_prefer_html = f"Denmark.{stream.email_token}.prefer-html@testserver"
token, options = decode_email_address(address_prefer_text)
self._assert_options(options, prefer_text=True)
@ -301,7 +301,7 @@ class TestStreamEmailMessagesSuccess(ZulipTestCase):
# stream address is angle-addr within multiple addresses
stream_to_addresses = ["A.N. Other <another@example.org>",
"Denmark <{}>".format(encode_email_address(stream))]
f"Denmark <{encode_email_address(stream)}>"]
incoming_valid_message = MIMEText('TestStreamEmailMessages Body')
@ -566,8 +566,8 @@ class TestEmailMirrorMessagesWithAttachments(ZulipTestCase):
self.login_user(user_profile)
self.subscribe(user_profile, "Denmark")
stream = get_stream("Denmark", user_profile.realm)
stream_address = "Denmark.{}@testserver".format(stream.email_token)
stream_address_prefer_html = "Denmark.{}.prefer-html@testserver".format(stream.email_token)
stream_address = f"Denmark.{stream.email_token}@testserver"
stream_address_prefer_html = f"Denmark.{stream.email_token}.prefer-html@testserver"
text = "Test message"
html = "<html><body><b>Test html message</b></body></html>"
@ -601,7 +601,7 @@ class TestEmailMirrorMessagesWithAttachments(ZulipTestCase):
self.login_user(user_profile)
self.subscribe(user_profile, "Denmark")
stream = get_stream("Denmark", user_profile.realm)
stream_address_prefer_html = "Denmark.{}.prefer-html@testserver".format(stream.email_token)
stream_address_prefer_html = f"Denmark.{stream.email_token}.prefer-html@testserver"
text = "Test message"
# This should be correctly identified as empty html body:

View File

@ -700,8 +700,8 @@ class TestMissedMessages(ZulipTestCase):
self.example_user('othello'), self.example_user('hamlet'),
'Come and join us in #**Verona**.')
stream_id = get_stream('Verona', get_realm('zulip')).id
href = "http://zulip.testserver/#narrow/stream/{stream_id}-Verona".format(stream_id=stream_id)
verify_body_include = ['<a class="stream" data-stream-id="5" href="{href}">#Verona</a'.format(href=href)]
href = f"http://zulip.testserver/#narrow/stream/{stream_id}-Verona"
verify_body_include = [f'<a class="stream" data-stream-id="5" href="{href}">#Verona</a']
email_subject = 'PMs with Othello, the Moor of Venice'
self._test_cases(msg_id, verify_body_include, email_subject, send_as_user=False, verify_html_body=True)

View File

@ -36,7 +36,7 @@ class TestEmbeddedBotMessaging(ZulipTestCase):
def test_stream_message_to_embedded_bot(self) -> None:
assert self.bot_profile is not None
self.send_stream_message(self.user_profile, "Denmark",
content="@**{}** foo".format(self.bot_profile.full_name),
content=f"@**{self.bot_profile.full_name}** foo",
topic_name="bar")
last_message = self.get_last_message()
self.assertEqual(last_message.content, "beep boop")
@ -56,7 +56,7 @@ class TestEmbeddedBotMessaging(ZulipTestCase):
with patch('zulip_bots.bots.helloworld.helloworld.HelloWorldHandler.initialize',
create=True) as mock_initialize:
self.send_stream_message(self.user_profile, "Denmark",
content="@**{}** foo".format(self.bot_profile.full_name),
content=f"@**{self.bot_profile.full_name}** foo",
topic_name="bar")
mock_initialize.assert_called_once()
@ -66,7 +66,7 @@ class TestEmbeddedBotMessaging(ZulipTestCase):
side_effect=EmbeddedBotQuitException("I'm quitting!")):
with patch('logging.warning') as mock_logging:
self.send_stream_message(self.user_profile, "Denmark",
content="@**{}** foo".format(self.bot_profile.full_name),
content=f"@**{self.bot_profile.full_name}** foo",
topic_name="bar")
mock_logging.assert_called_once_with("I'm quitting!")
@ -83,7 +83,7 @@ class TestEmbeddedBotFailures(ZulipTestCase):
service_profile.save()
with patch('logging.error') as logging_error_mock:
self.send_stream_message(user_profile, "Denmark",
content="@**{}** foo".format(bot_profile.full_name),
content=f"@**{bot_profile.full_name}** foo",
topic_name="bar")
logging_error_mock.assert_called_once_with(
"Error: User %s has bot with invalid embedded bot service %s",

View File

@ -2803,7 +2803,7 @@ class EventsRegisterTest(ZulipTestCase):
hamlet = self.example_user("hamlet")
self.subscribe(hamlet, "Denmark")
body = "First message ...[zulip.txt](http://{}".format(hamlet.realm.host) + data['uri'] + ")"
body = f"First message ...[zulip.txt](http://{hamlet.realm.host}" + data['uri'] + ")"
events = self.do_test(
lambda: self.send_stream_message(self.example_user("hamlet"), "Denmark", body, "test"),
num_events=2)
@ -2888,7 +2888,7 @@ class EventsRegisterTest(ZulipTestCase):
audit_log_entry = RealmAuditLog.objects.filter(
event_type=RealmAuditLog.REALM_EXPORTED).first()
events = self.do_test(
lambda: self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id)),
lambda: self.client_delete(f'/json/export/realm/{audit_log_entry.id}'),
state_change_expected=False, num_events=1)
error = deletion_schema_checker('events[0]', events[0])
self.assert_on_error(error)

View File

@ -105,7 +105,7 @@ class TranslationTestCase(ZulipTestCase):
]
for lang, word in languages:
response = self.fetch('get', '/{}/integrations/'.format(lang), 200)
response = self.fetch('get', f'/{lang}/integrations/', 200)
self.assert_in_response(word, response)

View File

@ -946,7 +946,7 @@ class ImportExportTest(ZulipTestCase):
def get_user_mention(r: Realm) -> Set[Any]:
mentioned_user = UserProfile.objects.get(delivery_email=self.example_email("hamlet"), realm=r)
data_user_id = 'data-user-id="{}"'.format(mentioned_user.id)
data_user_id = f'data-user-id="{mentioned_user.id}"'
mention_message = get_stream_messages(r).get(rendered_content__contains=data_user_id)
return mention_message.content
@ -954,7 +954,7 @@ class ImportExportTest(ZulipTestCase):
def get_stream_mention(r: Realm) -> Set[Any]:
mentioned_stream = get_stream('Denmark', r)
data_stream_id = 'data-stream-id="{}"'.format(mentioned_stream.id)
data_stream_id = f'data-stream-id="{mentioned_stream.id}"'
mention_message = get_stream_messages(r).get(rendered_content__contains=data_stream_id)
return mention_message.content
@ -962,7 +962,7 @@ class ImportExportTest(ZulipTestCase):
def get_user_group_mention(r: Realm) -> Set[Any]:
user_group = UserGroup.objects.get(realm=r, name='hamletcharacters')
data_usergroup_id = 'data-user-group-id="{}"'.format(user_group.id)
data_usergroup_id = f'data-user-group-id="{user_group.id}"'
mention_message = get_stream_messages(r).get(rendered_content__contains=data_usergroup_id)
return mention_message.content

View File

@ -9,7 +9,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_check_send_webhook_fixture_message_for_error(self) -> None:
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/airbrake?api_key={key}".format(key=bot.api_key)
url = f"/api/v1/external/airbrake?api_key={bot.api_key}"
target_url = "/devtools/integrations/check_send_webhook_fixture_message"
body = "{}" # This empty body should generate a KeyError on the webhook code side.
@ -28,7 +28,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_check_send_webhook_fixture_message_for_success_without_headers(self) -> None:
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/airbrake?api_key={key}&stream=Denmark&topic=Airbrake Notifications".format(key=bot.api_key)
url = f"/api/v1/external/airbrake?api_key={bot.api_key}&stream=Denmark&topic=Airbrake Notifications"
target_url = "/devtools/integrations/check_send_webhook_fixture_message"
with open("zerver/webhooks/airbrake/fixtures/error_message.json") as f:
body = f.read()
@ -55,7 +55,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_check_send_webhook_fixture_message_for_success_with_headers(self) -> None:
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/github?api_key={key}&stream=Denmark&topic=GitHub Notifications".format(key=bot.api_key)
url = f"/api/v1/external/github?api_key={bot.api_key}&stream=Denmark&topic=GitHub Notifications"
target_url = "/devtools/integrations/check_send_webhook_fixture_message"
with open("zerver/webhooks/github/fixtures/ping__organization.json") as f:
body = f.read()
@ -78,7 +78,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_check_send_webhook_fixture_message_for_success_with_headers_and_non_json_fixtures(self) -> None:
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/wordpress?api_key={key}&stream=Denmark&topic=Wordpress Notifications".format(key=bot.api_key)
url = f"/api/v1/external/wordpress?api_key={bot.api_key}&stream=Denmark&topic=Wordpress Notifications"
target_url = "/devtools/integrations/check_send_webhook_fixture_message"
with open("zerver/webhooks/wordpress/fixtures/publish_post_no_data_provided.txt") as f:
body = f.read()
@ -129,7 +129,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_send_all_webhook_fixture_messages_for_success(self) -> None:
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/appfollow?api_key={key}&stream=Denmark&topic=Appfollow Bulk Notifications".format(key=bot.api_key)
url = f"/api/v1/external/appfollow?api_key={bot.api_key}&stream=Denmark&topic=Appfollow Bulk Notifications"
target_url = "/devtools/integrations/send_all_webhook_fixture_messages"
data = {
@ -173,7 +173,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_send_all_webhook_fixture_messages_for_success_with_non_json_fixtures(self) -> None:
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/wordpress?api_key={key}&stream=Denmark&topic=Wordpress Bulk Notifications".format(key=bot.api_key)
url = f"/api/v1/external/wordpress?api_key={bot.api_key}&stream=Denmark&topic=Wordpress Bulk Notifications"
target_url = "/devtools/integrations/send_all_webhook_fixture_messages"
data = {
@ -243,7 +243,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
def test_send_all_webhook_fixture_messages_for_missing_fixtures(self, os_path_exists_mock: MagicMock) -> None:
os_path_exists_mock.return_value = False
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
url = "/api/v1/external/appfollow?api_key={key}&stream=Denmark&topic=Appfollow Bulk Notifications".format(key=bot.api_key)
url = f"/api/v1/external/appfollow?api_key={bot.api_key}&stream=Denmark&topic=Appfollow Bulk Notifications"
data = {
"url": url,
"custom_headers": "{}",

View File

@ -131,7 +131,7 @@ class OembedTestCase(ZulipTestCase):
def test_autodiscovered_oembed_xml_format_html(self) -> None:
iframe_content = '<iframe src="https://w.soundcloud.com/player"></iframe>'
html = '<![CDATA[{}]]>'.format(iframe_content)
html = f'<![CDATA[{iframe_content}]]>'
stripped_html = strip_cdata(html)
self.assertEqual(iframe_content, stripped_html)
@ -299,7 +299,7 @@ class PreviewTestCase(ZulipTestCase):
with mock.patch('requests.get', mocked_response):
FetchLinksEmbedData().consume(event)
embedded_link = '<a href="{}" title="The Rock">The Rock</a>'.format(url)
embedded_link = f'<a href="{url}" title="The Rock">The Rock</a>'
msg = Message.objects.select_related("sender").get(id=msg_id)
self.assertIn(embedded_link, msg.rendered_content)
@ -327,7 +327,7 @@ class PreviewTestCase(ZulipTestCase):
# Verify the initial message doesn't have the embedded links rendered
msg = Message.objects.select_related("sender").get(id=msg_id)
self.assertNotIn(
'<a href="{}" title="The Rock">The Rock</a>'.format(url),
f'<a href="{url}" title="The Rock">The Rock</a>',
msg.rendered_content)
# Mock the network request result so the test can be fast without Internet
@ -367,7 +367,7 @@ class PreviewTestCase(ZulipTestCase):
msg = Message.objects.select_related("sender").get(id=msg_id)
# The content of the message has changed since the event for original_url has been created,
# it should not be rendered. Another, up-to-date event will have been sent (edited_url).
self.assertNotIn('<a href="{}" title="The Rock">The Rock</a>'.format(original_url),
self.assertNotIn(f'<a href="{original_url}" title="The Rock">The Rock</a>',
msg.rendered_content)
mocked_response_edited.assert_not_called()
@ -377,7 +377,7 @@ class PreviewTestCase(ZulipTestCase):
# up-to-date event for edited_url.
queue_json_publish(*args, **kwargs)
msg = Message.objects.select_related("sender").get(id=msg_id)
self.assertIn('<a href="{}" title="The Rock">The Rock</a>'.format(edited_url),
self.assertIn(f'<a href="{edited_url}" title="The Rock">The Rock</a>',
msg.rendered_content)
with mock.patch('zerver.views.messages.queue_json_publish', wraps=wrapped_queue_json_publish) as patched:
@ -388,7 +388,7 @@ class PreviewTestCase(ZulipTestCase):
def test_get_link_embed_data(self) -> None:
url = 'http://test.org/'
embedded_link = '<a href="{}" title="The Rock">The Rock</a>'.format(url)
embedded_link = f'<a href="{url}" title="The Rock">The Rock</a>'
# When humans send, we should get embedded content.
msg = self._send_message_with_test_org_url(sender=self.example_user('hamlet'))
@ -659,8 +659,8 @@ class PreviewTestCase(ZulipTestCase):
'message_realm_id': msg.sender.realm_id,
'message_content': url}
mocked_data = {'html': '<iframe src="{}"></iframe>'.format(url),
'oembed': True, 'type': 'video', 'image': '{}/image.png'.format(url)}
mocked_data = {'html': f'<iframe src="{url}"></iframe>',
'oembed': True, 'type': 'video', 'image': f'{url}/image.png'}
mocked_response = mock.Mock(side_effect=self.create_mock_response(url))
with self.settings(TEST_SUITE=False, CACHES=TEST_CACHES):
with mock.patch('requests.get', mocked_response):

View File

@ -283,7 +283,7 @@ class TestGenerateRealmCreationLink(ZulipTestCase):
result = self.client_post(generated_link, {'email': email})
self.assertEqual(result.status_code, 302)
self.assertTrue(re.search('/accounts/new/send_confirm/{}$'.format(email),
self.assertTrue(re.search(f'/accounts/new/send_confirm/{email}$',
result["Location"]))
result = self.client_get(result["Location"])
self.assert_in_response("Check your email so we can get started", result)
@ -354,7 +354,7 @@ class TestSendToEmailMirror(ZulipTestCase):
self.login_user(user_profile)
self.subscribe(user_profile, "Denmark")
call_command(self.COMMAND_NAME, "--fixture={}".format(fixture_path))
call_command(self.COMMAND_NAME, f"--fixture={fixture_path}")
message = most_recent_message(user_profile)
# last message should be equal to the body of the email in 1.txt
@ -366,7 +366,7 @@ class TestSendToEmailMirror(ZulipTestCase):
self.login_user(user_profile)
self.subscribe(user_profile, "Denmark")
call_command(self.COMMAND_NAME, "--fixture={}".format(fixture_path))
call_command(self.COMMAND_NAME, f"--fixture={fixture_path}")
message = most_recent_message(user_profile)
# last message should be equal to the body of the email in 1.json
@ -378,7 +378,7 @@ class TestSendToEmailMirror(ZulipTestCase):
self.login_user(user_profile)
self.subscribe(user_profile, "Denmark2")
call_command(self.COMMAND_NAME, "--fixture={}".format(fixture_path), "--stream=Denmark2")
call_command(self.COMMAND_NAME, f"--fixture={fixture_path}", "--stream=Denmark2")
message = most_recent_message(user_profile)
# last message should be equal to the body of the email in 1.txt
@ -395,7 +395,7 @@ class TestConvertMattermostData(ZulipTestCase):
with patch('zerver.management.commands.convert_mattermost_data.do_convert_data') as m:
mm_fixtures = self.fixture_file_name("", "mattermost_fixtures")
output_dir = self.make_import_output_dir("mattermost")
call_command(self.COMMAND_NAME, mm_fixtures, "--output={}".format(output_dir))
call_command(self.COMMAND_NAME, mm_fixtures, f"--output={output_dir}")
m.assert_called_with(
masking_content=False,
@ -425,7 +425,7 @@ class TestExport(ZulipTestCase):
do_add_reaction(self.example_user("hamlet"), message, "outbox", "1f4e4", Reaction.UNICODE_EMOJI)
with patch("zerver.management.commands.export.export_realm_wrapper") as m:
call_command(self.COMMAND_NAME, "-r=zulip", "--consent-message-id={}".format(message.id))
call_command(self.COMMAND_NAME, "-r=zulip", f"--consent-message-id={message.id}")
m.assert_called_once_with(realm=realm, public_only=False, consent_message_id=message.id,
delete_after_upload=False, threads=mock.ANY, output_dir=mock.ANY,
upload=False)
@ -436,10 +436,10 @@ class TestExport(ZulipTestCase):
message.last_edit_time = timezone_now()
message.save()
with self.assertRaisesRegex(CommandError, "Message was edited. Aborting..."):
call_command(self.COMMAND_NAME, "-r=zulip", "--consent-message-id={}".format(message.id))
call_command(self.COMMAND_NAME, "-r=zulip", f"--consent-message-id={message.id}")
message.last_edit_time = None
message.save()
do_add_reaction(self.mit_user("sipbtest"), message, "outbox", "1f4e4", Reaction.UNICODE_EMOJI)
with self.assertRaisesRegex(CommandError, "Users from a different realm reacted to message. Aborting..."):
call_command(self.COMMAND_NAME, "-r=zulip", "--consent-message-id={}".format(message.id))
call_command(self.COMMAND_NAME, "-r=zulip", f"--consent-message-id={message.id}")

View File

@ -796,7 +796,7 @@ class PersonalMessagesTest(ZulipTestCase):
user_message = most_recent_usermessage(user_profile)
self.assertEqual(
str(user_message),
'<UserMessage: recip / {} ([])>'.format(user_profile.email)
f'<UserMessage: recip / {user_profile.email} ([])>'
)
@slow("checks several profiles")
@ -1409,7 +1409,7 @@ class MessageDictTest(ZulipTestCase):
# extract messages. Note that we increased this from 1ms to
# 1.5ms to handle tests running in parallel being a bit
# slower.
error_msg = "Number of ids: {}. Time delay: {}".format(num_ids, delay)
error_msg = f"Number of ids: {num_ids}. Time delay: {delay}"
self.assertTrue(delay < 0.0015 * num_ids, error_msg)
self.assert_length(queries, 7)
self.assertEqual(len(rows), num_ids)
@ -1959,14 +1959,14 @@ class MessagePOSTTest(ZulipTestCase):
"content": "Test message",
"client": "test suite",
"to": ujson.dumps([othello.id])})
self.assert_json_error(result, "'{}' is no longer using Zulip.".format(othello.email))
self.assert_json_error(result, f"'{othello.email}' is no longer using Zulip.")
result = self.client_post("/json/messages", {
"type": "private",
"content": "Test message",
"client": "test suite",
"to": ujson.dumps([othello.id, cordelia.id])})
self.assert_json_error(result, "'{}' is no longer using Zulip.".format(othello.email))
self.assert_json_error(result, f"'{othello.email}' is no longer using Zulip.")
def test_invalid_type(self) -> None:
"""
@ -2960,7 +2960,7 @@ class EditMessageTest(ZulipTestCase):
topic_name='editing',
content='This message has not been edited.')
result = self.client_get('/json/messages/{}/history'.format(msg_id))
result = self.client_get(f'/json/messages/{msg_id}/history')
self.assert_json_success(result)
@ -4158,7 +4158,7 @@ class MessageHasKeywordsTest(ZulipTestCase):
def test_claim_attachment(self) -> None:
user_profile = self.example_user('hamlet')
dummy_path_ids = self.setup_dummy_attachments(user_profile)
dummy_urls = ["http://zulip.testserver/user_uploads/{}".format(x) for x in dummy_path_ids]
dummy_urls = [f"http://zulip.testserver/user_uploads/{x}" for x in dummy_path_ids]
# Send message referring the attachment
self.subscribe(user_profile, "Denmark")
@ -4178,17 +4178,17 @@ class MessageHasKeywordsTest(ZulipTestCase):
# This message tries to claim the third attachment but fails because
# Bugdown would not set has_attachments = True here.
body = "Link in code: `{}`".format(dummy_urls[2])
body = f"Link in code: `{dummy_urls[2]}`"
self.send_stream_message(user_profile, "Denmark", body, "test")
assert_attachment_claimed(dummy_path_ids[2], False)
# Another scenario where we wouldn't parse the link.
body = "Link to not parse: .{}.`".format(dummy_urls[2])
body = f"Link to not parse: .{dummy_urls[2]}.`"
self.send_stream_message(user_profile, "Denmark", body, "test")
assert_attachment_claimed(dummy_path_ids[2], False)
# Finally, claim attachment 3.
body = "Link: {}".format(dummy_urls[2])
body = f"Link: {dummy_urls[2]}"
self.send_stream_message(user_profile, "Denmark", body, "test")
assert_attachment_claimed(dummy_path_ids[2], True)
assert_attachment_claimed(dummy_path_ids[1], False)
@ -4255,7 +4255,7 @@ class MessageHasKeywordsTest(ZulipTestCase):
def test_has_attachment(self) -> None:
hamlet = self.example_user('hamlet')
dummy_path_ids = self.setup_dummy_attachments(hamlet)
dummy_urls = ["http://zulip.testserver/user_uploads/{}".format(x) for x in dummy_path_ids]
dummy_urls = [f"http://zulip.testserver/user_uploads/{x}" for x in dummy_path_ids]
self.subscribe(hamlet, "Denmark")
body = ("Files ...[zulip.txt]({}) {} {}").format(dummy_urls[0], dummy_urls[1], dummy_urls[2])
@ -4267,24 +4267,24 @@ class MessageHasKeywordsTest(ZulipTestCase):
self.assertFalse(msg.has_attachment)
self.update_message(msg, body)
self.assertTrue(msg.has_attachment)
self.update_message(msg, 'Link in code: `{}`'.format(dummy_urls[1]))
self.update_message(msg, f'Link in code: `{dummy_urls[1]}`')
self.assertFalse(msg.has_attachment)
# Test blockquotes
self.update_message(msg, '> {}'.format(dummy_urls[1]))
self.update_message(msg, f'> {dummy_urls[1]}')
self.assertTrue(msg.has_attachment)
# Additional test to check has_attachment is being set is due to the correct attachment.
self.update_message(msg, 'Outside: {}. In code: `{}`.'.format(dummy_urls[0], dummy_urls[1]))
self.update_message(msg, f'Outside: {dummy_urls[0]}. In code: `{dummy_urls[1]}`.')
self.assertTrue(msg.has_attachment)
self.assertTrue(msg.attachment_set.filter(path_id=dummy_path_ids[0]))
self.assertEqual(msg.attachment_set.count(), 1)
self.update_message(msg, 'Outside: {}. In code: `{}`.'.format(dummy_urls[1], dummy_urls[0]))
self.update_message(msg, f'Outside: {dummy_urls[1]}. In code: `{dummy_urls[0]}`.')
self.assertTrue(msg.has_attachment)
self.assertTrue(msg.attachment_set.filter(path_id=dummy_path_ids[1]))
self.assertEqual(msg.attachment_set.count(), 1)
self.update_message(msg, 'Both in code: `{} {}`.'.format(dummy_urls[1], dummy_urls[0]))
self.update_message(msg, f'Both in code: `{dummy_urls[1]} {dummy_urls[0]}`.')
self.assertFalse(msg.has_attachment)
self.assertEqual(msg.attachment_set.count(), 0)
@ -4304,16 +4304,16 @@ class MessageHasKeywordsTest(ZulipTestCase):
self.assertTrue(m.called)
m.reset_mock()
self.update_message(msg, '[link](/user_uploads/{})'.format(dummy_path_ids[1]))
self.update_message(msg, f'[link](/user_uploads/{dummy_path_ids[1]})')
self.assertTrue(m.called)
m.reset_mock()
self.update_message(msg, '[new text link](/user_uploads/{})'.format(dummy_path_ids[1]))
self.update_message(msg, f'[new text link](/user_uploads/{dummy_path_ids[1]})')
self.assertFalse(m.called)
m.reset_mock()
# It's not clear this is correct behavior
self.update_message(msg, '[link](user_uploads/{})'.format(dummy_path_ids[2]))
self.update_message(msg, f'[link](user_uploads/{dummy_path_ids[2]})')
self.assertFalse(m.called)
m.reset_mock()
@ -4486,10 +4486,10 @@ class DeleteMessageTest(ZulipTestCase):
self.login('iago')
hamlet = self.example_user('hamlet')
msg_id = self.send_stream_message(hamlet, "Scotland")
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id + 1),
result = self.client_delete(f'/json/messages/{msg_id + 1}',
{'message_id': msg_id})
self.assert_json_error(result, "Invalid message(s)")
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
result = self.client_delete(f'/json/messages/{msg_id}')
self.assert_json_success(result)
def test_delete_message_by_user(self) -> None:
@ -4504,17 +4504,17 @@ class DeleteMessageTest(ZulipTestCase):
def test_delete_message_by_admin(msg_id: int) -> HttpResponse:
self.login('iago')
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
result = self.client_delete(f'/json/messages/{msg_id}')
return result
def test_delete_message_by_owner(msg_id: int) -> HttpResponse:
self.login('hamlet')
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
result = self.client_delete(f'/json/messages/{msg_id}')
return result
def test_delete_message_by_other_user(msg_id: int) -> HttpResponse:
self.login('cordelia')
result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id))
result = self.client_delete(f'/json/messages/{msg_id}')
return result
# Test if message deleting is not allowed(default).

View File

@ -1143,7 +1143,7 @@ class GetOldMessagesTest(ZulipTestCase):
'emoji_name': reaction_name
}
url = '/json/messages/{}/reactions'.format(message_id)
url = f'/json/messages/{message_id}/reactions'
payload = self.client_post(url, reaction_info)
self.assert_json_success(payload)
@ -2667,7 +2667,7 @@ class GetOldMessagesTest(ZulipTestCase):
stream = get_stream('Scotland', realm)
recipient_id = stream.recipient.id
cond = "AND NOT (recipient_id = {scotland} AND upper(subject) = upper('golf'))".format(scotland=recipient_id)
cond = f"AND NOT (recipient_id = {recipient_id} AND upper(subject) = upper('golf'))"
self.assertIn(cond, queries[0]['sql'])
# Next, verify the use_first_unread_anchor setting invokes

View File

@ -332,7 +332,7 @@ so maybe we shouldn't mark it as intentionally undocumented in the urls.
except AssertionError: # nocoverage
msg = "The following endpoints have been documented but can't be found in urls.py:"
for undocumented_path in undocumented_paths:
msg += "\n + {}".format(undocumented_path)
msg += f"\n + {undocumented_path}"
raise AssertionError(msg)
def get_type_by_priority(self, types: Sequence[Union[type, Tuple[type, object]]]) -> Union[type, Tuple[type, object]]:
@ -417,7 +417,7 @@ do not match the types declared in the implementation of {}.\n""".format(functio
if element[0] == vname:
fdvtype = element[1]
break
msg += "{:<10s}{:^30s}{:>10s}\n".format(vname, str(opvtype), str(fdvtype))
msg += f"{vname:<10s}{str(opvtype):^30s}{str(fdvtype):>10s}\n"
raise AssertionError(msg)
def check_argument_types(self, function: Callable[..., HttpResponse],

View File

@ -241,7 +241,7 @@ class TestOutgoingWebhookMessaging(ZulipTestCase):
bot = self.create_outgoing_bot(bot_owner)
self.send_stream_message(bot_owner, "Denmark",
content="@**{}** foo".format(bot.full_name),
content=f"@**{bot.full_name}** foo",
topic_name="bar")
last_message = self.get_last_message()
self.assertEqual(last_message.content, "Hidley ho, I'm a webhook responding!")

View File

@ -498,7 +498,7 @@ class UserPresenceAggregationTests(ZulipTestCase):
}
)
result = self.client_get("/json/users/{}/presence".format(user.email))
result = self.client_get(f"/json/users/{user.email}/presence")
return result.json()
def test_aggregated_info(self) -> None:

View File

@ -559,8 +559,8 @@ class AnalyticsBouncerTest(BouncerTestCase):
check_for_unwanted_data.first_call = False # type: ignore[attr-defined]
else:
# Test that we're respecting SYNCED_BILLING_EVENTS
self.assertIn('"event_type":{}'.format(RealmAuditLog.USER_REACTIVATED), str(args))
self.assertNotIn('"event_type":{}'.format(RealmAuditLog.REALM_LOGO_CHANGED), str(args))
self.assertIn(f'"event_type":{RealmAuditLog.USER_REACTIVATED}', str(args))
self.assertNotIn(f'"event_type":{RealmAuditLog.REALM_LOGO_CHANGED}', str(args))
# Test that we're respecting REALMAUDITLOG_PUSHED_FIELDS
self.assertIn('backfilled', str(args))
self.assertNotIn('modified_user', str(args))
@ -1774,7 +1774,7 @@ class TestClearOnRead(ZulipTestCase):
message_ids = [self.send_stream_message(self.example_user("iago"),
stream.name,
"yo {}".format(i))
f"yo {i}")
for i in range(n_msgs)]
UserMessage.objects.filter(
user_profile_id=hamlet.id,

View File

@ -78,7 +78,7 @@ class RealmExportTest(ZulipTestCase):
event_type=RealmAuditLog.REALM_EXPORTED).count())
# Finally, delete the file.
result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id))
result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}')
self.assert_json_success(result)
with self.assertRaises(botocore.exceptions.ClientError):
bucket.Object(path_id).load()
@ -87,7 +87,7 @@ class RealmExportTest(ZulipTestCase):
audit_log_entry.refresh_from_db()
export_data = ujson.loads(audit_log_entry.extra_data)
self.assertIn('deleted_timestamp', export_data)
result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id))
result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}')
self.assert_json_error(result, "Export already deleted")
# Now try to delete a non-existent export.
@ -137,7 +137,7 @@ class RealmExportTest(ZulipTestCase):
event_type=RealmAuditLog.REALM_EXPORTED).count())
# Finally, delete the file.
result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id))
result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}')
self.assert_json_success(result)
response = self.client_get(path_id)
self.assertEqual(response.status_code, 404)
@ -146,7 +146,7 @@ class RealmExportTest(ZulipTestCase):
audit_log_entry.refresh_from_db()
export_data = ujson.loads(audit_log_entry.extra_data)
self.assertIn('deleted_timestamp', export_data)
result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id))
result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}')
self.assert_json_error(result, "Export already deleted")
# Now try to delete a non-existent export.

View File

@ -107,9 +107,9 @@ class RealmFilterTest(ZulipTestCase):
"#(?P<id>[123])",
"https://realm.com/my_realm_filter/%(id)s")
filters_count = RealmFilter.objects.count()
result = self.client_delete("/json/realm/filters/{}".format(filter_id + 1))
result = self.client_delete(f"/json/realm/filters/{filter_id + 1}")
self.assert_json_error(result, 'Filter not found')
result = self.client_delete("/json/realm/filters/{}".format(filter_id))
result = self.client_delete(f"/json/realm/filters/{filter_id}")
self.assert_json_success(result)
self.assertEqual(RealmFilter.objects.count(), filters_count - 1)

View File

@ -257,7 +257,7 @@ class PasswordResetTest(ZulipTestCase):
email, url_pattern=settings.EXTERNAL_HOST + r"(\S\S+)")
result = self.client_get(password_reset_url)
self.assertEqual(result.status_code, 302)
self.assertTrue(result.url.endswith('/{}/'.format(INTERNAL_RESET_URL_TOKEN)))
self.assertTrue(result.url.endswith(f'/{INTERNAL_RESET_URL_TOKEN}/'))
final_reset_url = result.url
result = self.client_get(final_reset_url)
@ -593,7 +593,7 @@ class LoginTest(ZulipTestCase):
reset_emails_in_zulip_realm()
realm = get_realm("zulip")
stream_names = ["stream_{}".format(i) for i in range(40)]
stream_names = [f"stream_{i}" for i in range(40)]
for stream_name in stream_names:
stream = self.make_stream(stream_name, realm=realm)
DefaultStream.objects.create(stream=stream, realm=realm)
@ -1007,7 +1007,7 @@ class InviteUserTest(InviteUserBase):
"""
self.login('hamlet')
email = "alice-test@zulip.com"
invitee = "Alice Test <{}>".format(email)
invitee = f"Alice Test <{email}>"
self.assert_json_success(self.invite(invitee, ["Denmark"]))
self.assertTrue(find_key_by_email(email))
self.check_sent_emails([email], custom_from_name="Hamlet")
@ -1020,7 +1020,7 @@ class InviteUserTest(InviteUserBase):
self.login('hamlet')
email = "alice-test@zulip.com"
email2 = "bob-test@zulip.com"
invitee = "Alice Test <{}>, {}".format(email, email2)
invitee = f"Alice Test <{email}>, {email2}"
self.assert_json_success(self.invite(invitee, ["Denmark"]))
self.assertTrue(find_key_by_email(email))
self.assertTrue(find_key_by_email(email2))
@ -1037,7 +1037,7 @@ class InviteUserTest(InviteUserBase):
self.login('hamlet')
email = "alice-test@zulip.com"
email2 = "bob-test@zulip.com"
invitee = "Alice Test <{}>, {}".format(email, email2)
invitee = f"Alice Test <{email}>, {email2}"
self.assert_json_error(self.invite(invitee, ["Denmark"]),
"Must be an organization administrator")
@ -1090,7 +1090,7 @@ class InviteUserTest(InviteUserBase):
second_msg = last_3_messages[1]
self.assertEqual(second_msg.sender.email, "notification-bot@zulip.com")
self.assertTrue(second_msg.content.startswith(
"alice_zulip.com <`{}`> accepted your".format(invitee_profile.email)
f"alice_zulip.com <`{invitee_profile.email}`> accepted your"
))
# The second, from welcome-bot to the user who was invited.
@ -1175,7 +1175,7 @@ earl-test@zulip.com""", ["Denmark"]))
"""
self.login('hamlet')
self.assert_json_error(self.invite("iago-test@zulip.com", ["NotARealStream"]),
"Stream does not exist with id: {}. No invites were sent.".format(self.INVALID_STREAM_ID))
f"Stream does not exist with id: {self.INVALID_STREAM_ID}. No invites were sent.")
self.check_sent_emails([])
def test_invite_existing_user(self) -> None:
@ -1878,22 +1878,22 @@ class InviteeEmailsParserTests(TestCase):
self.email3 = "email3@zulip.com"
def test_if_emails_separated_by_commas_are_parsed_and_striped_correctly(self) -> None:
emails_raw = "{} ,{}, {}".format(self.email1, self.email2, self.email3)
emails_raw = f"{self.email1} ,{self.email2}, {self.email3}"
expected_set = {self.email1, self.email2, self.email3}
self.assertEqual(get_invitee_emails_set(emails_raw), expected_set)
def test_if_emails_separated_by_newlines_are_parsed_and_striped_correctly(self) -> None:
emails_raw = "{}\n {}\n {} ".format(self.email1, self.email2, self.email3)
emails_raw = f"{self.email1}\n {self.email2}\n {self.email3} "
expected_set = {self.email1, self.email2, self.email3}
self.assertEqual(get_invitee_emails_set(emails_raw), expected_set)
def test_if_emails_from_email_client_separated_by_newlines_are_parsed_correctly(self) -> None:
emails_raw = "Email One <{}>\nEmailTwo<{}>\nEmail Three<{}>".format(self.email1, self.email2, self.email3)
emails_raw = f"Email One <{self.email1}>\nEmailTwo<{self.email2}>\nEmail Three<{self.email3}>"
expected_set = {self.email1, self.email2, self.email3}
self.assertEqual(get_invitee_emails_set(emails_raw), expected_set)
def test_if_emails_in_mixed_style_are_parsed_correctly(self) -> None:
emails_raw = "Email One <{}>,EmailTwo<{}>\n{}".format(self.email1, self.email2, self.email3)
emails_raw = f"Email One <{self.email1}>,EmailTwo<{self.email2}>\n{self.email3}"
expected_set = {self.email1, self.email2, self.email3}
self.assertEqual(get_invitee_emails_set(emails_raw), expected_set)
@ -3018,7 +3018,7 @@ class UserSignUpTest(InviteUserBase):
request.session = {} # type: ignore[attr-defined]
email = 'user@acme.com'
form = HomepageForm({'email': email}, realm=realm)
self.assertIn("Your email address, {}, is not in one of the domains".format(email),
self.assertIn(f"Your email address, {email}, is not in one of the domains",
form.errors['email'][0])
def test_failed_signup_due_to_disposable_email(self) -> None:
@ -3052,7 +3052,7 @@ class UserSignUpTest(InviteUserBase):
request.session = {} # type: ignore[attr-defined]
email = 'user@zulip.com'
form = HomepageForm({'email': email}, realm=realm)
self.assertIn("Please request an invite for {} from".format(email),
self.assertIn(f"Please request an invite for {email} from",
form.errors['email'][0])
def test_failed_signup_due_to_nonexistent_realm(self) -> None:
@ -3856,10 +3856,10 @@ class UserSignUpTest(InviteUserBase):
result = self.client_post('/devtools/register_realm/')
self.assertEqual(result.status_code, 302)
self.assertTrue(result["Location"].startswith(
'http://{}.testserver/accounts/login/subdomain'.format(string_id)))
f'http://{string_id}.testserver/accounts/login/subdomain'))
result = self.client_get(result["Location"], subdomain=string_id)
self.assertEqual(result.status_code, 302)
self.assertEqual(result["Location"], 'http://{}.testserver'.format(string_id))
self.assertEqual(result["Location"], f'http://{string_id}.testserver')
user_profile = UserProfile.objects.all().order_by("id").last()
self.assert_logged_in_user_id(user_profile.id)
@ -4041,7 +4041,7 @@ class TestFindMyTeam(ZulipTestCase):
self.assertEqual(len(outbox), 0)
def test_find_team_more_than_ten_emails(self) -> None:
data = {'emails': ','.join(['hamlet-{}@zulip.com'.format(i) for i in range(11)])}
data = {'emails': ','.join([f'hamlet-{i}@zulip.com' for i in range(11)])}
result = self.client_post('/accounts/find/', data)
self.assertEqual(result.status_code, 200)
self.assertIn("Please enter at most 10", result.content.decode('utf8'))

View File

@ -831,7 +831,7 @@ class SlackImporter(ZulipTestCase):
image_path = zerver_attachment[0]['path_id']
self.assertIn('/SlackImportAttachment/', image_path)
expected_content = '[Apple](/user_uploads/{image_path})\n[banana](example.com/banana.zip)'.format(image_path=image_path)
expected_content = f'[Apple](/user_uploads/{image_path})\n[banana](example.com/banana.zip)'
self.assertEqual(info['content'], expected_content)
self.assertTrue(info['has_link'])

View File

@ -702,7 +702,7 @@ class StreamAdminTest(ZulipTestCase):
# Inspect the notification message sent
message = self.get_last_message()
actual_stream = Stream.objects.get(id=message.recipient.type_id)
message_content = '@_**King Hamlet|{}** renamed stream **stream_name1** to **stream_name2**.'.format(user_profile.id)
message_content = f'@_**King Hamlet|{user_profile.id}** renamed stream **stream_name1** to **stream_name2**.'
self.assertEqual(actual_stream.name, 'stream_name2')
self.assertEqual(actual_stream.realm_id, user_profile.realm_id)
self.assertEqual(message.recipient.type, Recipient.STREAM)
@ -1458,11 +1458,11 @@ class DefaultStreamGroupTest(ZulipTestCase):
new_streams.append(new_stream)
streams.append(new_stream)
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result, "Missing 'op' argument")
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "invalid", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result, 'Invalid value for "op". Specify one of "add" or "remove".')
@ -1470,16 +1470,16 @@ class DefaultStreamGroupTest(ZulipTestCase):
{"op": "add", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result, "Default stream group with id '12345' does not exist.")
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), {"op": "add"})
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "add"})
self.assert_json_error(result, "Missing 'stream_names' argument")
do_add_default_stream(new_streams[0])
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "add", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result, "'stream4' is a default stream and cannot be added to 'group1'")
do_remove_default_stream(new_streams[0])
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "add", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_success(result)
default_stream_groups = get_default_stream_groups(realm)
@ -1487,7 +1487,7 @@ class DefaultStreamGroupTest(ZulipTestCase):
self.assertEqual(default_stream_groups[0].name, group_name)
self.assertEqual(list(default_stream_groups[0].streams.all().order_by('name')), streams)
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "add", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result,
"Stream 'stream4' is already present in default stream group 'group1'")
@ -1497,12 +1497,12 @@ class DefaultStreamGroupTest(ZulipTestCase):
{"op": "remove", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result, "Default stream group with id '12345' does not exist.")
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "remove", "stream_names": ujson.dumps(["random stream name"])})
self.assert_json_error(result, "Invalid stream name 'random stream name'")
streams.remove(new_streams[0])
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "remove", "stream_names": ujson.dumps([new_stream_names[0]])})
self.assert_json_success(result)
default_stream_groups = get_default_stream_groups(realm)
@ -1510,14 +1510,14 @@ class DefaultStreamGroupTest(ZulipTestCase):
self.assertEqual(default_stream_groups[0].name, group_name)
self.assertEqual(list(default_stream_groups[0].streams.all().order_by('name')), streams)
result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams",
{"op": "remove", "stream_names": ujson.dumps(new_stream_names)})
self.assert_json_error(result, "Stream 'stream4' is not present in default stream group 'group1'")
# Test changing description of default stream group
new_description = "new group1 description"
result = self.client_patch("/json/default_stream_groups/{}".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}",
{"group_name": group_name, "op": "change"})
self.assert_json_error(result, 'You must pass "new_description" or "new_group_name".')
@ -1525,7 +1525,7 @@ class DefaultStreamGroupTest(ZulipTestCase):
{"op": "change", "new_description": ujson.dumps(new_description)})
self.assert_json_error(result, "Default stream group with id '12345' does not exist.")
result = self.client_patch("/json/default_stream_groups/{}".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}",
{"group_name": group_name,
"op": "change",
"new_description": ujson.dumps(new_description)})
@ -1538,17 +1538,17 @@ class DefaultStreamGroupTest(ZulipTestCase):
# Test changing name of default stream group
new_group_name = "new group1"
do_create_default_stream_group(realm, "group2", "", [])
result = self.client_patch("/json/default_stream_groups/{}".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}",
{"op": "change", "new_group_name": ujson.dumps("group2")})
self.assert_json_error(result, "Default stream group 'group2' already exists")
new_group = lookup_default_stream_groups(["group2"], realm)[0]
do_remove_default_stream_group(realm, new_group)
result = self.client_patch("/json/default_stream_groups/{}".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}",
{"op": "change", "new_group_name": ujson.dumps(group_name)})
self.assert_json_error(result, "This default stream group is already named 'group1'")
result = self.client_patch("/json/default_stream_groups/{}".format(group_id),
result = self.client_patch(f"/json/default_stream_groups/{group_id}",
{"op": "change", "new_group_name": ujson.dumps(new_group_name)})
self.assert_json_success(result)
default_stream_groups = get_default_stream_groups(realm)
@ -1557,13 +1557,13 @@ class DefaultStreamGroupTest(ZulipTestCase):
self.assertEqual(default_stream_groups[0].description, new_description)
# Test deleting a default stream group
result = self.client_delete('/json/default_stream_groups/{}'.format(group_id))
result = self.client_delete(f'/json/default_stream_groups/{group_id}')
self.assert_json_success(result)
default_stream_groups = get_default_stream_groups(realm)
self.assert_length(default_stream_groups, 0)
result = self.client_delete('/json/default_stream_groups/{}'.format(group_id))
self.assert_json_error(result, "Default stream group with id '{}' does not exist.".format(group_id))
result = self.client_delete(f'/json/default_stream_groups/{group_id}')
self.assert_json_error(result, f"Default stream group with id '{group_id}' does not exist.")
def test_invalid_default_stream_group_name(self) -> None:
self.login('iago')
@ -2900,7 +2900,7 @@ class SubscriptionAPITest(ZulipTestCase):
result = self.common_subscribe_to_streams(self.test_user, "Denmark", post_data)
self.assert_json_error(
result,
"User not authorized to execute queries on behalf of '{}'".format(target_profile.id),
f"User not authorized to execute queries on behalf of '{target_profile.id}'",
status_code=403)
def test_subscriptions_add_for_principal_invite_only(self) -> None:

View File

@ -66,7 +66,7 @@ class TornadoWebTestCase(AsyncHTTPTestCase, ZulipTestCase):
session_cookie = settings.SESSION_COOKIE_NAME
session_key = self.client.session.session_key
self.session_cookie = {
"Cookie": "{}={}".format(session_cookie, session_key)
"Cookie": f"{session_cookie}={session_key}"
}
def get_session_cookie(self) -> Dict[str, str]:
@ -102,7 +102,7 @@ class EventsTestCase(TornadoWebTestCase):
'last_event_id': -1,
}
path = '/json/events?{}'.format(urllib.parse.urlencode(data))
path = f'/json/events?{urllib.parse.urlencode(data)}'
self.client_get_async(path)
def process_events() -> None:

View File

@ -353,9 +353,9 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
self.subscribe(self.example_user("hamlet"), "Denmark")
host = self.example_user('hamlet').realm.host
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")"
body = f"First message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")"
self.send_stream_message(self.example_user("hamlet"), "Denmark", body, "test")
body = "Second message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")"
body = f"Second message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")"
self.send_stream_message(self.example_user("hamlet"), "Denmark", body, "test")
self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 2)
@ -374,25 +374,25 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
self.subscribe(self.example_user("hamlet"), "private_stream")
# First, send the message to the new private stream.
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")"
body = f"First message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")"
self.send_stream_message(self.example_user("hamlet"), "private_stream", body, "test")
self.assertFalse(Attachment.objects.get(path_id=d1_path_id).is_realm_public)
self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 1)
# Then, try having a user who didn't receive the message try to publish it, and fail
body = "Illegal message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")"
body = f"Illegal message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")"
self.send_stream_message(self.example_user("cordelia"), "Denmark", body, "test")
self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 1)
self.assertFalse(Attachment.objects.get(path_id=d1_path_id).is_realm_public)
# Then, have the owner PM it to another user, giving that other user access.
body = "Second message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")"
body = f"Second message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")"
self.send_personal_message(self.example_user("hamlet"), self.example_user("othello"), body)
self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 2)
self.assertFalse(Attachment.objects.get(path_id=d1_path_id).is_realm_public)
# Then, have that new recipient user publish it.
body = "Third message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")"
body = f"Third message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")"
self.send_stream_message(self.example_user("othello"), "Denmark", body, "test")
self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 3)
self.assertTrue(Attachment.objects.get(path_id=d1_path_id).is_realm_public)
@ -415,14 +415,14 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
f2_path_id = re.sub('/user_uploads/', '', result.json()['uri'])
self.subscribe(hamlet, "test")
body = ("[f1.txt](http://{}/user_uploads/".format(host) + f1_path_id + ") "
body = (f"[f1.txt](http://{host}/user_uploads/" + f1_path_id + ") "
"[f2.txt](http://{}/user_uploads/".format(host) + f2_path_id + ")")
msg_id = self.send_stream_message(hamlet, "test", body, "test")
result = self.client_post("/json/user_uploads", {'file': f3})
f3_path_id = re.sub('/user_uploads/', '', result.json()['uri'])
new_body = ("[f3.txt](http://{}/user_uploads/".format(host) + f3_path_id + ") "
new_body = (f"[f3.txt](http://{host}/user_uploads/" + f3_path_id + ") "
"[f2.txt](http://{}/user_uploads/".format(host) + f2_path_id + ")")
result = self.client_patch("/json/messages/" + str(msg_id), {
'message_id': msg_id,
@ -535,7 +535,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
result = self.client_post("/json/user_uploads", {'file': fp})
uri = result.json()['uri']
fp_path_id = re.sub('/user_uploads/', '', uri)
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(host) + fp_path_id + ")"
body = f"First message ...[zulip.txt](http://{host}/user_uploads/" + fp_path_id + ")"
with self.settings(CROSS_REALM_BOT_EMAILS = {user_2.email, user_3.email}):
internal_send_private_message(
realm=r1,
@ -575,7 +575,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
result = self.client_post("/json/user_uploads", {'file': fp})
uri = result.json()['uri']
fp_path_id = re.sub('/user_uploads/', '', uri)
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(realm.host) + fp_path_id + ")"
body = f"First message ...[zulip.txt](http://{realm.host}/user_uploads/" + fp_path_id + ")"
self.send_stream_message(hamlet, stream_name, body, "test")
self.logout()
@ -629,7 +629,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
result = self.client_post("/json/user_uploads", {'file': fp})
uri = result.json()['uri']
fp_path_id = re.sub('/user_uploads/', '', uri)
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(user.realm.host) + fp_path_id + ")"
body = f"First message ...[zulip.txt](http://{user.realm.host}/user_uploads/" + fp_path_id + ")"
self.send_stream_message(user, stream_name, body, "test")
self.logout()
@ -697,7 +697,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
uri = result.json()['uri']
fp_path_id = re.sub('/user_uploads/', '', uri)
for i in range(20):
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(hamlet.realm.host) + fp_path_id + ")"
body = f"First message ...[zulip.txt](http://{hamlet.realm.host}/user_uploads/" + fp_path_id + ")"
self.send_stream_message(self.example_user("hamlet"), "test-subscribe %s" % (i % 5,), body, "test")
self.logout()
@ -739,7 +739,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
result = self.client_post("/json/user_uploads", {'file': fp})
uri = result.json()['uri']
fp_path_id = re.sub('/user_uploads/', '', uri)
body = "First message ...[zulip.txt](http://{}/user_uploads/".format(realm.host) + fp_path_id + ")"
body = f"First message ...[zulip.txt](http://{realm.host}/user_uploads/" + fp_path_id + ")"
self.send_stream_message(self.example_user("hamlet"), "test-subscribe", body, "test")
self.logout()
@ -1530,7 +1530,7 @@ class LocalStorageTest(UploadSerializeMixin, ZulipTestCase):
realm_id=user_profile.realm_id,
emoji_file_name=file_name,
)
expected_url = "/user_avatars/{emoji_path}".format(emoji_path=emoji_path)
expected_url = f"/user_avatars/{emoji_path}"
self.assertEqual(expected_url, url)
def test_tarball_upload_and_deletion_local(self) -> None:
@ -1843,7 +1843,7 @@ class S3Test(ZulipTestCase):
url = zerver.lib.upload.upload_backend.get_emoji_url('emoji.png', realm_id)
expected_url = "https://{bucket}.s3.amazonaws.com/{path}".format(bucket=bucket, path=path)
expected_url = f"https://{bucket}.s3.amazonaws.com/{path}"
self.assertEqual(expected_url, url)
@use_s3_backend

View File

@ -150,11 +150,11 @@ class UserGroupAPITestCase(ZulipTestCase):
'name': 'help',
'description': 'Troubleshooting team',
}
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params)
self.assert_json_success(result)
# Test when new data is not supplied.
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info={})
result = self.client_patch(f'/json/user_groups/{user_group.id}', info={})
self.assert_json_error(result, "No new data supplied")
# Test when invalid user group is supplied
@ -170,7 +170,7 @@ class UserGroupAPITestCase(ZulipTestCase):
'name': 'help',
'description': 'Troubleshooting',
}
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params)
self.assert_json_error(result, "Only group members and organization administrators can administer this group.")
self.logout()
@ -181,7 +181,7 @@ class UserGroupAPITestCase(ZulipTestCase):
'name': 'help',
'description': 'Troubleshooting',
}
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params)
self.assert_json_success(result)
def test_user_group_update_by_guest_user(self) -> None:
@ -203,7 +203,7 @@ class UserGroupAPITestCase(ZulipTestCase):
'name': 'help',
'description': 'Troubleshooting team',
}
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params)
self.assert_json_error(result, "Not allowed for guest users")
def test_user_group_update_to_already_existing_name(self) -> None:
@ -216,9 +216,9 @@ class UserGroupAPITestCase(ZulipTestCase):
params = {
'name': marketing_user_group.name,
}
result = self.client_patch('/json/user_groups/{}'.format(support_user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{support_user_group.id}', info=params)
self.assert_json_error(
result, "User group '{}' already exists.".format(marketing_user_group.name))
result, f"User group '{marketing_user_group.name}' already exists.")
def test_user_group_delete(self) -> None:
hamlet = self.example_user('hamlet')
@ -233,7 +233,7 @@ class UserGroupAPITestCase(ZulipTestCase):
# Test success
self.assertEqual(UserGroup.objects.count(), 2)
self.assertEqual(UserGroupMembership.objects.count(), 3)
result = self.client_delete('/json/user_groups/{}'.format(user_group.id))
result = self.client_delete(f'/json/user_groups/{user_group.id}')
self.assert_json_success(result)
self.assertEqual(UserGroup.objects.count(), 1)
self.assertEqual(UserGroupMembership.objects.count(), 2)
@ -255,7 +255,7 @@ class UserGroupAPITestCase(ZulipTestCase):
cordelia = self.example_user('cordelia')
self.login_user(cordelia)
result = self.client_delete('/json/user_groups/{}'.format(user_group.id))
result = self.client_delete(f'/json/user_groups/{user_group.id}')
self.assert_json_error(result, "Only group members and organization administrators can administer this group.")
self.assertEqual(UserGroup.objects.count(), 2)
@ -264,7 +264,7 @@ class UserGroupAPITestCase(ZulipTestCase):
iago = self.example_user('iago')
self.login_user(iago)
result = self.client_delete('/json/user_groups/{}'.format(user_group.id))
result = self.client_delete(f'/json/user_groups/{user_group.id}')
self.assert_json_success(result)
self.assertEqual(UserGroup.objects.count(), 1)
self.assertEqual(UserGroupMembership.objects.count(), 2)
@ -284,7 +284,7 @@ class UserGroupAPITestCase(ZulipTestCase):
# Guest users can't delete any user group(not even those of which they are a member)
self.login_user(guest_user)
result = self.client_delete('/json/user_groups/{}'.format(user_group.id))
result = self.client_delete(f'/json/user_groups/{user_group.id}')
self.assert_json_error(result, "Not allowed for guest users")
def test_update_members_of_user_group(self) -> None:
@ -303,7 +303,7 @@ class UserGroupAPITestCase(ZulipTestCase):
othello = self.example_user('othello')
add = [othello.id]
params = {'add': ujson.dumps(add)}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 4)
@ -311,9 +311,9 @@ class UserGroupAPITestCase(ZulipTestCase):
self.assertEqual(len(members), 2)
# Test adding a member already there.
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_error(result, "User {} is already a member of this group".format(othello.id))
self.assert_json_error(result, f"User {othello.id} is already a member of this group")
self.assertEqual(UserGroupMembership.objects.count(), 4)
members = get_memberships_of_users(user_group, [hamlet, othello])
self.assertEqual(len(members), 2)
@ -324,7 +324,7 @@ class UserGroupAPITestCase(ZulipTestCase):
self.login_user(cordelia)
add = [cordelia.id]
params = {'add': ujson.dumps(add)}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_error(result, "Only group members and organization administrators can administer this group.")
self.assertEqual(UserGroupMembership.objects.count(), 4)
@ -336,7 +336,7 @@ class UserGroupAPITestCase(ZulipTestCase):
aaron = self.example_user('aaron')
add = [aaron.id]
params = {'add': ujson.dumps(add)}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 5)
@ -348,7 +348,7 @@ class UserGroupAPITestCase(ZulipTestCase):
self.login_user(hamlet)
# Test remove members
params = {'delete': ujson.dumps([othello.id])}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 4)
@ -357,15 +357,15 @@ class UserGroupAPITestCase(ZulipTestCase):
# Test remove a member that's already removed
params = {'delete': ujson.dumps([othello.id])}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_error(result, "There is no member '{}' in this user group".format(othello.id))
self.assert_json_error(result, f"There is no member '{othello.id}' in this user group")
self.assertEqual(UserGroupMembership.objects.count(), 4)
members = get_memberships_of_users(user_group, [hamlet, othello, aaron])
self.assertEqual(len(members), 2)
# Test when nothing is provided
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info={})
msg = 'Nothing to do. Specify at least one of "add" or "delete".'
self.assert_json_error(result, msg)
@ -374,7 +374,7 @@ class UserGroupAPITestCase(ZulipTestCase):
self.logout()
self.login_user(cordelia)
params = {'delete': ujson.dumps([hamlet.id])}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_error(result, "Only group members and organization administrators can administer this group.")
self.assertEqual(UserGroupMembership.objects.count(), 4)
@ -383,7 +383,7 @@ class UserGroupAPITestCase(ZulipTestCase):
# Test when organization admin tries to remove members from group
iago = self.example_user('iago')
self.login_user(iago)
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 3)
@ -460,13 +460,13 @@ class UserGroupAPITestCase(ZulipTestCase):
# Test add member
params = {'add': ujson.dumps([cordelia.id])}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_success(result)
# Test remove member
params = {'delete': ujson.dumps([cordelia.id])}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_success(result)
@ -475,11 +475,11 @@ class UserGroupAPITestCase(ZulipTestCase):
'name': 'help',
'description': 'Troubleshooting',
}
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params)
self.assert_json_success(result)
# Test delete a group
result = self.client_delete('/json/user_groups/{}'.format(user_group.id))
result = self.client_delete(f'/json/user_groups/{user_group.id}')
self.assert_json_success(result)
user_group = create_user_group(name='support',
@ -502,12 +502,12 @@ class UserGroupAPITestCase(ZulipTestCase):
# Test add member
params = {'add': ujson.dumps([cordelia.id])}
result = self.client_post('/json/user_groups/{}/members'.format(user_group.id),
result = self.client_post(f'/json/user_groups/{user_group.id}/members',
info=params)
self.assert_json_error(result, "Must be an organization administrator")
# Test delete a group
result = self.client_delete('/json/user_groups/{}'.format(user_group.id))
result = self.client_delete(f'/json/user_groups/{user_group.id}')
self.assert_json_error(result, "Must be an organization administrator")
# Test changing groups name
@ -515,5 +515,5 @@ class UserGroupAPITestCase(ZulipTestCase):
'name': 'help',
'description': 'Troubleshooting',
}
result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params)
result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params)
self.assert_json_error(result, "Must be an organization administrator")

View File

@ -116,7 +116,7 @@ class PermissionTest(ZulipTestCase):
do_change_user_role(admin, UserProfile.ROLE_REALM_ADMINISTRATOR)
invalid_user_id = 1000
result = self.client_patch('/json/users/{}'.format(invalid_user_id), {})
result = self.client_patch(f'/json/users/{invalid_user_id}', {})
self.assert_json_error(result, 'No such user')
def test_admin_api(self) -> None:
@ -142,7 +142,7 @@ class PermissionTest(ZulipTestCase):
events: List[Mapping[str, Any]] = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(othello.id), req)
result = self.client_patch(f'/json/users/{othello.id}', req)
self.assert_json_success(result)
admin_users = realm.get_human_admin_users()
self.assertTrue(othello in admin_users)
@ -154,7 +154,7 @@ class PermissionTest(ZulipTestCase):
req = dict(role=ujson.dumps(UserProfile.ROLE_MEMBER))
events = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(othello.id), req)
result = self.client_patch(f'/json/users/{othello.id}', req)
self.assert_json_success(result)
admin_users = realm.get_human_admin_users()
self.assertFalse(othello in admin_users)
@ -167,7 +167,7 @@ class PermissionTest(ZulipTestCase):
req = dict(role=ujson.dumps(UserProfile.ROLE_MEMBER))
events = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(desdemona.id), req)
result = self.client_patch(f'/json/users/{desdemona.id}', req)
self.assert_json_success(result)
admin_users = realm.get_human_admin_users()
self.assertFalse(desdemona in admin_users)
@ -175,12 +175,12 @@ class PermissionTest(ZulipTestCase):
self.assertEqual(person['user_id'], desdemona.id)
self.assertEqual(person['role'], UserProfile.ROLE_MEMBER)
with tornado_redirected_to_list([]):
result = self.client_patch('/json/users/{}'.format(iago.id), req)
result = self.client_patch(f'/json/users/{iago.id}', req)
self.assert_json_error(result, 'Cannot remove the only organization administrator')
# Make sure only admins can patch other user's info.
self.login('othello')
result = self.client_patch('/json/users/{}'.format(hamlet.id), req)
result = self.client_patch(f'/json/users/{hamlet.id}', req)
self.assert_json_error(result, 'Insufficient permission')
def test_admin_api_hide_emails(self) -> None:
@ -261,7 +261,7 @@ class PermissionTest(ZulipTestCase):
self.login('iago')
hamlet = self.example_user('hamlet')
req = dict(full_name=ujson.dumps(new_name))
result = self.client_patch('/json/users/{}'.format(hamlet.id), req)
result = self.client_patch(f'/json/users/{hamlet.id}', req)
self.assert_json_success(result)
hamlet = self.example_user('hamlet')
self.assertEqual(hamlet.full_name, new_name)
@ -355,7 +355,7 @@ class PermissionTest(ZulipTestCase):
req = dict(role=ujson.dumps(UserProfile.ROLE_GUEST))
events: List[Mapping[str, Any]] = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(hamlet.id), req)
result = self.client_patch(f'/json/users/{hamlet.id}', req)
self.assert_json_success(result)
hamlet = self.example_user("hamlet")
@ -374,7 +374,7 @@ class PermissionTest(ZulipTestCase):
req = dict(role=ujson.dumps(UserProfile.ROLE_MEMBER))
events: List[Mapping[str, Any]] = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(polonius.id), req)
result = self.client_patch(f'/json/users/{polonius.id}', req)
self.assert_json_success(result)
polonius = self.example_user("polonius")
@ -397,7 +397,7 @@ class PermissionTest(ZulipTestCase):
req = dict(role=ujson.dumps(UserProfile.ROLE_GUEST))
events: List[Mapping[str, Any]] = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(hamlet.id), req)
result = self.client_patch(f'/json/users/{hamlet.id}', req)
self.assert_json_success(result)
hamlet = self.example_user("hamlet")
@ -421,7 +421,7 @@ class PermissionTest(ZulipTestCase):
req = dict(role=ujson.dumps(UserProfile.ROLE_REALM_ADMINISTRATOR))
events: List[Mapping[str, Any]] = []
with tornado_redirected_to_list(events):
result = self.client_patch('/json/users/{}'.format(polonius.id), req)
result = self.client_patch(f'/json/users/{polonius.id}', req)
self.assert_json_success(result)
polonius = self.example_user("polonius")
@ -457,7 +457,7 @@ class PermissionTest(ZulipTestCase):
'value': fields[field_name],
})
result = self.client_patch('/json/users/{}'.format(cordelia.id),
result = self.client_patch(f'/json/users/{cordelia.id}',
{'profile_data': ujson.dumps(new_profile_data)})
self.assert_json_success(result)
@ -482,7 +482,7 @@ class PermissionTest(ZulipTestCase):
'value': field_value,
})
result = self.client_patch('/json/users/{}'.format(cordelia.id),
result = self.client_patch(f'/json/users/{cordelia.id}',
{'profile_data': ujson.dumps(new_profile_data)})
self.assert_json_error(result, error_msg)
@ -491,7 +491,7 @@ class PermissionTest(ZulipTestCase):
'id': 9001,
'value': ''
}]
result = self.client_patch('/json/users/{}'.format(cordelia.id),
result = self.client_patch(f'/json/users/{cordelia.id}',
{'profile_data': ujson.dumps(invalid_profile_data)})
self.assert_json_error(result, 'Field id 9001 not found.')
@ -500,7 +500,7 @@ class PermissionTest(ZulipTestCase):
'id': 9001,
'value': 'some data'
}]
result = self.client_patch('/json/users/{}'.format(cordelia.id),
result = self.client_patch(f'/json/users/{cordelia.id}',
{'profile_data': ujson.dumps(invalid_profile_data)})
self.assert_json_error(result, 'Field id 9001 not found.')
@ -515,7 +515,7 @@ class PermissionTest(ZulipTestCase):
'id': field.id,
'value': value,
})
result = self.client_patch('/json/users/{}'.format(cordelia.id),
result = self.client_patch(f'/json/users/{cordelia.id}',
{'profile_data': ujson.dumps(empty_profile_data)})
self.assert_json_success(result)
for field_dict in cordelia.profile_data:
@ -544,7 +544,7 @@ class PermissionTest(ZulipTestCase):
'id': field.id,
'value': value,
})
result = self.client_patch('/json/users/{}'.format(cordelia.id),
result = self.client_patch(f'/json/users/{cordelia.id}',
{'profile_data': ujson.dumps(new_profile_data)})
self.assert_json_success(result)
for field_dict in cordelia.profile_data:
@ -562,7 +562,7 @@ class PermissionTest(ZulipTestCase):
'id': field.id,
'value': "New hamlet Biography",
})
result = self.client_patch('/json/users/{}'.format(hamlet.id),
result = self.client_patch(f'/json/users/{hamlet.id}',
{'profile_data': ujson.dumps(new_profile_data)})
self.assert_json_error(result, 'Insufficient permission')
@ -586,7 +586,7 @@ class BulkCreateUserTest(ZulipTestCase):
fred = get_user_by_delivery_email('fred@zulip.com', realm)
self.assertEqual(
fred.email,
'user{}@zulip.testserver'.format(fred.id)
f'user{fred.id}@zulip.testserver'
)
lisa = get_user_by_delivery_email('lisa@zulip.com', realm)
@ -970,12 +970,12 @@ class ActivateTest(ZulipTestCase):
user = self.example_user('hamlet')
self.assertTrue(user.is_active)
result = self.client_delete('/json/users/{}'.format(user.id))
result = self.client_delete(f'/json/users/{user.id}')
self.assert_json_success(result)
user = self.example_user('hamlet')
self.assertFalse(user.is_active)
result = self.client_post('/json/users/{}/reactivate'.format(user.id))
result = self.client_post(f'/json/users/{user.id}/reactivate')
self.assert_json_success(result)
user = self.example_user('hamlet')
self.assertTrue(user.is_active)
@ -990,7 +990,7 @@ class ActivateTest(ZulipTestCase):
# Cannot deactivate a nonexistent user.
invalid_user_id = 1000
result = self.client_delete('/json/users/{}'.format(invalid_user_id))
result = self.client_delete(f'/json/users/{invalid_user_id}')
self.assert_json_error(result, 'No such user')
result = self.client_delete('/json/users/{}'.format(self.example_user("webhook_bot").id))
@ -999,12 +999,12 @@ class ActivateTest(ZulipTestCase):
result = self.client_delete('/json/users/{}'.format(self.example_user("iago").id))
self.assert_json_success(result)
result = self.client_delete('/json/users/{}'.format(admin.id))
result = self.client_delete(f'/json/users/{admin.id}')
self.assert_json_error(result, 'Cannot deactivate the only organization administrator')
# Cannot reactivate a nonexistent user.
invalid_user_id = 1000
result = self.client_post('/json/users/{}/reactivate'.format(invalid_user_id))
result = self.client_post(f'/json/users/{invalid_user_id}/reactivate')
self.assert_json_error(result, 'No such user')
def test_api_with_insufficient_permissions(self) -> None:
@ -1398,7 +1398,7 @@ class GetProfileTest(ZulipTestCase):
# Tests the GET ../users/{id} api endpoint.
user = self.example_user('hamlet')
result = ujson.loads(self.client_get('/json/users/{}'.format(user.id)).content)
result = ujson.loads(self.client_get(f'/json/users/{user.id}').content)
self.assertEqual(result['user']['email'], user.email)
self.assertEqual(result['user']['full_name'], user.full_name)
self.assertIn("user_id", result['user'])
@ -1407,14 +1407,14 @@ class GetProfileTest(ZulipTestCase):
self.assertFalse(result['user']['is_admin'])
self.assertFalse(result['user']['is_owner'])
result = ujson.loads(self.client_get('/json/users/{}?include_custom_profile_fields=true'.format(user.id)).content)
result = ujson.loads(self.client_get(f'/json/users/{user.id}?include_custom_profile_fields=true').content)
self.assertIn('profile_data', result['user'])
result = self.client_get('/json/users/{}?'.format(30))
result = self.client_get(f'/json/users/{30}?')
self.assert_json_error(result, "No such user")
bot = self.example_user("default_bot")
result = ujson.loads(self.client_get('/json/users/{}'.format(bot.id)).content)
result = ujson.loads(self.client_get(f'/json/users/{bot.id}').content)
self.assertEqual(result['user']['email'], bot.email)
self.assertTrue(result['user']['is_bot'])

View File

@ -96,7 +96,7 @@ def check_send_webhook_fixture_message(request: HttpRequest,
try:
custom_headers_dict = ujson.loads(custom_headers)
except ValueError as ve:
return json_error("Custom HTTP headers are not in a valid JSON format. {}".format(ve)) # nolint
return json_error(f"Custom HTTP headers are not in a valid JSON format. {ve}") # nolint
response = send_webhook_fixture_message(url, body, is_json,
custom_headers_dict)

View File

@ -153,12 +153,12 @@ def add_integrations_open_graph_context(context: Dict[str, Any], request: HttpRe
if path_name in INTEGRATIONS:
integration = INTEGRATIONS[path_name]
context['OPEN_GRAPH_TITLE'] = 'Connect {name} to Zulip'.format(name=integration.display_name)
context['OPEN_GRAPH_TITLE'] = f'Connect {integration.display_name} to Zulip'
context['OPEN_GRAPH_DESCRIPTION'] = description
elif path_name in CATEGORIES:
category = CATEGORIES[path_name]
context['OPEN_GRAPH_TITLE'] = 'Connect your {category} tools to Zulip'.format(category=category)
context['OPEN_GRAPH_TITLE'] = f'Connect your {category} tools to Zulip'
context['OPEN_GRAPH_DESCRIPTION'] = description
elif path_name == 'integrations':

View File

@ -223,7 +223,7 @@ class NarrowBuilder:
if ord(c) >= 128:
# convert the character to hex postgres regex will take
# \uXXXX
s[i] = '\\u{:0>4x}'.format(ord(c))
s[i] = f'\\u{ord(c):0>4x}'
else:
s[i] = '\\' + c
return ''.join(s)

View File

@ -24,11 +24,11 @@ def api_alertmanager_webhook(request: HttpRequest, user_profile: UserProfile,
name = labels.get(
name_field, annotations.get(name_field, "(unknown)"))
desc = labels.get(
desc_field, annotations.get(desc_field, "<missing field: {}>".format(desc_field)))
desc_field, annotations.get(desc_field, f"<missing field: {desc_field}>"))
url = alert.get("generatorURL").replace("tab=1", "tab=0")
body = "{description} ([graph]({url}))".format(description=desc, url=url)
body = f"{desc} ([graph]({url}))"
if name not in topics:
topics[name] = {"firing": [], "resolved": []}
topics[name][alert["status"]].append(body)
@ -51,7 +51,7 @@ def api_alertmanager_webhook(request: HttpRequest, user_profile: UserProfile,
title=title,
message=messages[0])
else:
message_list = "\n".join(["* {}".format(m) for m in messages])
message_list = "\n".join([f"* {m}" for m in messages])
body = "{icon} **{title}**\n{messages}".format(
icon=icon,
title=title,

View File

@ -80,7 +80,7 @@ def get_verb(event: str, prefix: str) -> str:
def add_punctuation_if_necessary(body: str, title: str) -> str:
if title[-1] not in string.punctuation:
body = '{}.'.format(body)
body = f'{body}.'
return body
def get_document_body(event: str, payload: Dict[str, Any]) -> str:

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