Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
ed674b8c
by Philipp Hörist at 2023-05-28T21:12:04+02:00
-
fbb470b7
by Philipp Hörist at 2023-05-28T21:12:32+02:00
19 changed files:
- gajim/common/jingle_session.py
- gajim/common/modules/base.py
- gajim/common/modules/omemo.py
- gajim/common/preview_helpers.py
- gajim/common/settings.py
- gajim/common/structs.py
- gajim/common/styling.py
- gajim/common/util/text.py
- gajim/gajim.py
- gajim/gtk/accounts.py
- gajim/gtk/application.py
- gajim/gtk/certificate_dialog.py
- gajim/gtk/css_config.py
- gajim/gtk/discovery.py
- gajim/gtk/exception.py
- gajim/gtk/groupchat_join.py
- gajim/gtk/omemo_trust_manager.py
- gajim/gtk/util.py
- pyproject.toml
Changes:
| ... | ... | @@ -731,8 +731,7 @@ def __broadcast(self, |
| 731 | 731 | name = content['name']
|
| 732 | 732 | creator = content['creator']
|
| 733 | 733 | if (creator, name) not in self.contents:
|
| 734 | - text = 'Content %s (created by %s) does not exist' % (name,
|
|
| 735 | - creator)
|
|
| 734 | + text = f'Content {name} (created by {creator}) does not exist'
|
|
| 736 | 735 | self.__send_error(stanza,
|
| 737 | 736 | 'bad-request',
|
| 738 | 737 | text=text,
|
| ... | ... | @@ -753,7 +752,7 @@ def __on_session_terminate(self, |
| 753 | 752 | if reason not in ('success', 'cancel', 'decline'):
|
| 754 | 753 | self.__dispatch_error(reason, text)
|
| 755 | 754 | if text:
|
| 756 | - text = '%s (%s)' % (reason, text)
|
|
| 755 | + text = f'{reason} ({text})'
|
|
| 757 | 756 | else:
|
| 758 | 757 | # TODO
|
| 759 | 758 | text = reason
|
| ... | ... | @@ -828,7 +827,7 @@ def __dispatch_error(self, |
| 828 | 827 | type_: str | None = None
|
| 829 | 828 | ) -> None:
|
| 830 | 829 | if text:
|
| 831 | - text = '%s (%s)' % (error, text)
|
|
| 830 | + text = '{error} ({text})'
|
|
| 832 | 831 | if type_ != 'modify':
|
| 833 | 832 | self._raise_event('jingle-error-received', reason=text or error)
|
| 834 | 833 | |
| ... | ... | @@ -877,7 +876,7 @@ def __send_error(self, |
| 877 | 876 | text: str | None = None,
|
| 878 | 877 | type_: str | None = None
|
| 879 | 878 | ) -> None:
|
| 880 | - err_stanza = nbxmpp.Error(stanza, '%s %s' % (Namespace.STANZAS, error))
|
|
| 879 | + err_stanza = nbxmpp.Error(stanza, f'{Namespace.STANZAS} {error}')
|
|
| 881 | 880 | err = err_stanza.getTag('error')
|
| 882 | 881 | if type_:
|
| 883 | 882 | err.setAttr('type', type_)
|
| ... | ... | @@ -65,9 +65,9 @@ def _set_logger(self, plugin: bool) -> LogAdapter: |
| 65 | 65 | def __getattr__(self, key: str) -> Any:
|
| 66 | 66 | if key not in self._nbxmpp_methods:
|
| 67 | 67 | raise AttributeError(
|
| 68 | - "attribute '%s' is neither part of object '%s' "
|
|
| 69 | - " nor declared in '_nbxmpp_methods'" % (
|
|
| 70 | - key, self.__class__.__name__))
|
|
| 68 | + f'attribute "{key}" is neither part of object '
|
|
| 69 | + f'"{self.__class__.__name__}" nor declared in '
|
|
| 70 | + '"_nbxmpp_methods"')
|
|
| 71 | 71 | |
| 72 | 72 | if not app.account_is_connected(self._account):
|
| 73 | 73 | self._log.warning('Account not connected, can’t use %s', key)
|
| ... | ... | @@ -317,7 +317,7 @@ def _encrypt_file_thread(transfer: HTTPFileTransfer, |
| 317 | 317 | transfer.size = len(result.payload)
|
| 318 | 318 | fragment = binascii.hexlify(result.iv + result.key).decode()
|
| 319 | 319 | transfer.set_uri_transform_func(
|
| 320 | - lambda uri: 'aesgcm%s#%s' % (uri[5:], fragment))
|
|
| 320 | + lambda uri: f'aesgcm{uri[5:]}#{fragment}')
|
|
| 321 | 321 | transfer.set_encrypted_data(result.payload)
|
| 322 | 322 | GLib.idle_add(callback, transfer)
|
| 323 | 323 |
| ... | ... | @@ -391,7 +391,7 @@ def fmt(f: float) -> str: |
| 391 | 391 | slon = p_('positive longitude', '%sE') % fmt(lon)
|
| 392 | 392 | else:
|
| 393 | 393 | slon = p_('negative longitude', '%sW') % fmt(-lon)
|
| 394 | - return '%s %s' % (slat, slon)
|
|
| 394 | + return f'{slat} {slon}'
|
|
| 395 | 395 | |
| 396 | 396 | |
| 397 | 397 | def filename_from_uri(uri: str) -> str:
|
| ... | ... | @@ -92,18 +92,18 @@ |
| 92 | 92 | settings TEXT
|
| 93 | 93 | );
|
| 94 | 94 | |
| 95 | - INSERT INTO settings(name, settings) VALUES ('app', '{}');
|
|
| 96 | - INSERT INTO settings(name, settings) VALUES ('soundevents', '{}');
|
|
| 97 | - INSERT INTO settings(name, settings) VALUES ('status_presets', '%s');
|
|
| 98 | - INSERT INTO settings(name, settings) VALUES ('proxies', '%s');
|
|
| 99 | - INSERT INTO settings(name, settings) VALUES ('plugins', '{}');
|
|
| 100 | - INSERT INTO settings(name, settings) VALUES ('workspaces', '%s');
|
|
| 101 | - |
|
| 102 | - PRAGMA user_version=%s;
|
|
| 103 | - ''' % (json.dumps(STATUS_PRESET_EXAMPLES),
|
|
| 104 | - json.dumps(PROXY_EXAMPLES),
|
|
| 105 | - json.dumps(INITAL_WORKSPACE),
|
|
| 106 | - CURRENT_USER_VERSION)
|
|
| 95 | + INSERT INTO settings(name, settings) VALUES ('app', '{{}}');
|
|
| 96 | + INSERT INTO settings(name, settings) VALUES ('soundevents', '{{}}');
|
|
| 97 | + INSERT INTO settings(name, settings) VALUES ('status_presets', '{status}');
|
|
| 98 | + INSERT INTO settings(name, settings) VALUES ('proxies', '{proxies}');
|
|
| 99 | + INSERT INTO settings(name, settings) VALUES ('plugins', '{{}}');
|
|
| 100 | + INSERT INTO settings(name, settings) VALUES ('workspaces', '{workspaces}');
|
|
| 101 | + |
|
| 102 | + PRAGMA user_version={version};
|
|
| 103 | + '''.format(status=json.dumps(STATUS_PRESET_EXAMPLES),
|
|
| 104 | + proxies=json.dumps(PROXY_EXAMPLES),
|
|
| 105 | + workspaces=json.dumps(INITAL_WORKSPACE),
|
|
| 106 | + version=CURRENT_USER_VERSION)
|
|
| 107 | 107 | |
| 108 | 108 | |
| 109 | 109 | _SignalCallable = Callable[[Any, str, str | None, JID | None], Any]
|
| ... | ... | @@ -106,7 +106,7 @@ def __init__(self, |
| 106 | 106 | ) -> None:
|
| 107 | 107 | |
| 108 | 108 | if type_ not in ('chat', 'groupchat', 'normal', 'headline'):
|
| 109 | - raise ValueError('Unknown message type: %s' % type_)
|
|
| 109 | + raise ValueError(f'Unknown message type: {type_}')
|
|
| 110 | 110 | |
| 111 | 111 | if not message and chatstate is None and marker is None:
|
| 112 | 112 | raise ValueError('Trying to send message without content')
|
| ... | ... | @@ -286,7 +286,7 @@ def _get_type_and_variant_string(self, |
| 286 | 286 | if 'JID' in field_type:
|
| 287 | 287 | return JID, f'{variant_str}s'
|
| 288 | 288 | |
| 289 | - raise ValueError('unknown type: %s' % field_type)
|
|
| 289 | + raise ValueError(f'unknown type: {field_type}')
|
|
| 290 | 290 | |
| 291 | 291 | def to_variant(self) -> GLib.Variant:
|
| 292 | 292 | __types = {}
|
| ... | ... | @@ -299,8 +299,7 @@ def to_variant(self) -> GLib.Variant: |
| 299 | 299 | continue
|
| 300 | 300 | |
| 301 | 301 | if not isinstance(value, field_t):
|
| 302 | - raise ValueError('invalid type: %s is not a %s' % (value,
|
|
| 303 | - field_t))
|
|
| 302 | + raise ValueError(f'invalid type: {value} is not a {field_t}')
|
|
| 304 | 303 | |
| 305 | 304 | conversion_func = self._type_to_variant_funcs.get(field_t)
|
| 306 | 305 | if conversion_func is not None:
|
| ... | ... | @@ -322,6 +321,6 @@ def from_variant(cls: type[_T], variant: GLib.Variant) -> _T: |
| 322 | 321 | value = vdict[field_name]
|
| 323 | 322 | conversion_func = cls._variant_to_type_funcs.get(value_t_name)
|
| 324 | 323 | if conversion_func is None:
|
| 325 | - raise ValueError('no conversion for: %s' % value_t_name)
|
|
| 324 | + raise ValueError(f'no conversion for: {value_t_name}')
|
|
| 326 | 325 | vdict[field_name] = conversion_func(value)
|
| 327 | 326 | return cls(**vdict) |
| ... | ... | @@ -185,7 +185,7 @@ def find_byte_index(text: str, index: int): |
| 185 | 185 | if index == index_:
|
| 186 | 186 | return byte_index
|
| 187 | 187 | |
| 188 | - raise ValueError('index not in string: %s, %s' % (text, index))
|
|
| 188 | + raise ValueError(f'index not in string: {text}, {index}')
|
|
| 189 | 189 | |
| 190 | 190 | |
| 191 | 191 | def process(text: str | bytes, level: int = 0) -> ParsingResult:
|
| ... | ... | @@ -14,6 +14,8 @@ |
| 14 | 14 | |
| 15 | 15 | from __future__ import annotations
|
| 16 | 16 | |
| 17 | +from typing import Literal
|
|
| 18 | + |
|
| 17 | 19 | import re
|
| 18 | 20 | |
| 19 | 21 | from gi.repository import GLib
|
| ... | ... | @@ -70,3 +72,18 @@ def format_duration(ns: float, total_ns: float) -> str: |
| 70 | 72 | return (f'%0{width}d' % i_minutes) + f':{i_seconds:02d}'
|
| 71 | 73 | |
| 72 | 74 | return f'0:{i_seconds:02d}'
|
| 75 | + |
|
| 76 | + |
|
| 77 | +def format_sha_bytes(algo: Literal['sha1', 'sha256'], sha_bytes: bytes) -> str:
|
|
| 78 | + if algo == 'sha1':
|
|
| 79 | + stop, step = 20, 10
|
|
| 80 | + elif algo == 'sha256':
|
|
| 81 | + stop, step = 32, 8
|
|
| 82 | + else:
|
|
| 83 | + raise ValueError(f'Unknown algo: {algo}')
|
|
| 84 | + |
|
| 85 | + lines: list[str] = []
|
|
| 86 | + hex_list = [f'{b:02X}' for b in sha_bytes]
|
|
| 87 | + for pos in range(0, stop, step):
|
|
| 88 | + lines.append(':'.join(hex_list[pos:pos + step]))
|
|
| 89 | + return '\n'.join(lines) |
| ... | ... | @@ -40,22 +40,22 @@ |
| 40 | 40 | |
| 41 | 41 | def check_version(dep_name: str, current_ver: str, min_ver: str) -> None:
|
| 42 | 42 | if V(current_ver) < V(min_ver):
|
| 43 | - sys.exit('Gajim needs %s >= %s (found %s) to run. '
|
|
| 44 | - 'Quitting...' % (dep_name, min_ver, current_ver))
|
|
| 43 | + sys.exit(f'Gajim needs {dep_name} >= {min_ver} '
|
|
| 44 | + f'(found {current_ver}) to run. Quitting...')
|
|
| 45 | 45 | |
| 46 | 46 | |
| 47 | 47 | def _check_required_deps() -> None:
|
| 48 | - error_message = 'Gajim needs %s to run. Quitting… (Error: %s)'
|
|
| 48 | + error_message = 'Gajim needs {lib} to run. Quitting… (Error: {error})'
|
|
| 49 | 49 | |
| 50 | 50 | try:
|
| 51 | 51 | import nbxmpp
|
| 52 | 52 | except ImportError as error:
|
| 53 | - sys.exit(error_message % ('python-nbxmpp', error))
|
|
| 53 | + sys.exit(error_message.format('python-nbxmpp', error))
|
|
| 54 | 54 | |
| 55 | 55 | try:
|
| 56 | 56 | import gi
|
| 57 | 57 | except ImportError as error:
|
| 58 | - sys.exit(error_message % ('pygobject', error))
|
|
| 58 | + sys.exit(error_message.format('pygobject', error))
|
|
| 59 | 59 | |
| 60 | 60 | try:
|
| 61 | 61 | gi.require_versions({'GLib': '2.0',
|
| ... | ... | @@ -66,17 +66,17 @@ def _check_required_deps() -> None: |
| 66 | 66 | 'Pango': '1.0',
|
| 67 | 67 | 'PangoCairo': '1.0'})
|
| 68 | 68 | except ValueError as error:
|
| 69 | - sys.exit('Missing dependency: %s' % error)
|
|
| 69 | + sys.exit(f'Missing dependency: {error}')
|
|
| 70 | 70 | |
| 71 | 71 | try:
|
| 72 | 72 | import cairo
|
| 73 | 73 | except ImportError as error:
|
| 74 | - sys.exit(error_message % ('pycairo', error))
|
|
| 74 | + sys.exit(error_message.format('pycairo', error))
|
|
| 75 | 75 | |
| 76 | 76 | from gi.repository import Gtk
|
| 77 | - gtk_ver = '%s.%s.%s' % (Gtk.get_major_version(),
|
|
| 78 | - Gtk.get_minor_version(),
|
|
| 79 | - Gtk.get_micro_version())
|
|
| 77 | + gtk_ver = '.'.join(map(str, [Gtk.get_major_version(),
|
|
| 78 | + Gtk.get_minor_version(),
|
|
| 79 | + Gtk.get_micro_version()]))
|
|
| 80 | 80 | |
| 81 | 81 | from gi.repository import GLib
|
| 82 | 82 | glib_ver = '.'.join(map(str, [GLib.MAJOR_VERSION,
|
| ... | ... | @@ -941,9 +941,9 @@ def __init__(self, account: str) -> None: |
| 941 | 941 | |
| 942 | 942 | btbv_label = Gtk.Label()
|
| 943 | 943 | btbv_label.set_xalign(0)
|
| 944 | - markup = '<a href="%s">%s</a>' % (
|
|
| 945 | - 'https://dev.gajim.org/gajim/gajim/-/wikis/help/OMEMO',
|
|
| 946 | - _('Read more about blind trust'))
|
|
| 944 | + wiki_url = 'https://dev.gajim.org/gajim/gajim/-/wikis/help/OMEMO'
|
|
| 945 | + link_text = _('Read more about blind trust')
|
|
| 946 | + markup = f'<a href="{wiki_url}">{link_text}</a>'
|
|
| 947 | 947 | btbv_label.set_markup(markup)
|
| 948 | 948 | self.add(btbv_label)
|
| 949 | 949 |
| ... | ... | @@ -372,7 +372,7 @@ def _handle_local_options(self, |
| 372 | 372 | # Incorporate profile name into application id
|
| 373 | 373 | # to have a single app instance for each profile.
|
| 374 | 374 | profile = profile.get_string()
|
| 375 | - app_id = '%s.%s' % (self.get_application_id(), profile)
|
|
| 375 | + app_id = f'{self.get_application_id()}.{profile}'
|
|
| 376 | 376 | self.set_application_id(app_id)
|
| 377 | 377 | configpaths.set_profile(profile)
|
| 378 | 378 |
| ... | ... | @@ -29,6 +29,7 @@ |
| 29 | 29 | from gajim.common import app
|
| 30 | 30 | from gajim.common.helpers import get_x509_cert_from_gio_cert
|
| 31 | 31 | from gajim.common.i18n import _
|
| 32 | +from gajim.common.util.text import format_sha_bytes
|
|
| 32 | 33 | |
| 33 | 34 | from gajim.gtk.builder import get_builder
|
| 34 | 35 | |
| ... | ... | @@ -109,13 +110,10 @@ def __init__(self, account: str, certificate: Gio.TlsCertificate) -> None: |
| 109 | 110 | self._expires = cert.not_valid_after.strftime('%c %Z')
|
| 110 | 111 | |
| 111 | 112 | sha1_bytes = cert.fingerprint(hashes.SHA1())
|
| 112 | - sha1 = ':'.join(f'{b:02X}' for b in sha1_bytes)
|
|
| 113 | - self._sha1 = '%s\n%s' % (sha1[:29], sha1[30:])
|
|
| 113 | + self._sha1 = format_sha_bytes('sha1', sha1_bytes)
|
|
| 114 | 114 | |
| 115 | 115 | sha256_bytes = cert.fingerprint(hashes.SHA256())
|
| 116 | - sha256 = ':'.join(f'{b:02X}' for b in sha256_bytes)
|
|
| 117 | - self._sha256 = '%s\n%s\n%s\n%s' % (
|
|
| 118 | - sha256[:23], sha256[24:47], sha256[48:71], sha256[72:])
|
|
| 116 | + self._sha256 = format_sha_bytes('sha256', sha256_bytes)
|
|
| 119 | 117 | |
| 120 | 118 | public_key = cert.public_key()
|
| 121 | 119 | self._pk_algorithm = ''
|
| ... | ... | @@ -640,7 +640,7 @@ def refresh(self) -> None: |
| 640 | 640 | for index, account in enumerate(accounts):
|
| 641 | 641 | color = app.settings.get_account_setting(account, 'account_color')
|
| 642 | 642 | css_class = f'gajim_class_{index}'
|
| 643 | - css += '.%s { background-color: %s }\n' % (css_class, color)
|
|
| 643 | + css += f'.{css_class} {{ background-color: {color} }}\n'
|
|
| 644 | 644 | self._dynamic_dict[account] = css_class
|
| 645 | 645 | |
| 646 | 646 | self._dynamic_provider.load_from_data(css.encode())
|
| ... | ... | @@ -208,7 +208,7 @@ def get_agent_address(jid, node=None): |
| 208 | 208 | Get an agent's address for displaying in the GUI
|
| 209 | 209 | '''
|
| 210 | 210 | if node:
|
| 211 | - return '%s@%s' % (node, str(jid))
|
|
| 211 | + return f'{node}@{str(jid)}'
|
|
| 212 | 212 | return str(jid)
|
| 213 | 213 | |
| 214 | 214 | |
| ... | ... | @@ -301,7 +301,7 @@ def get_icon(self, identities=None, addr=''): |
| 301 | 301 | service_name = addr.split('.')[0]
|
| 302 | 302 | |
| 303 | 303 | # Or load it
|
| 304 | - icon_name = 'gajim-agent-%s' % service_name
|
|
| 304 | + icon_name = f'gajim-agent-{service_name}'
|
|
| 305 | 305 | if icon_exists(icon_name):
|
| 306 | 306 | return icon_name
|
| 307 | 307 | return 'gajim-agent-jabber'
|
| ... | ... | @@ -1139,7 +1139,7 @@ def __init__(self, *args): |
| 1139 | 1139 | |
| 1140 | 1140 | def add_self_line(self):
|
| 1141 | 1141 | addr = get_agent_address(self.jid, self.node)
|
| 1142 | - descr = '<b>%s</b>' % addr
|
|
| 1142 | + descr = f'<b>{addr}</b>'
|
|
| 1143 | 1143 | # Guess which kind of service this is
|
| 1144 | 1144 | identities = []
|
| 1145 | 1145 | type_ = app.get_transport_name_from_jid(self.jid,
|
| ... | ... | @@ -1541,9 +1541,9 @@ def _add_item(self, jid, node, parent_node, item, force): |
| 1541 | 1541 | # Row text
|
| 1542 | 1542 | addr = get_agent_address(jid, node)
|
| 1543 | 1543 | if 'name' in item:
|
| 1544 | - descr = '<b>%s</b>\n%s' % (item['name'], addr)
|
|
| 1544 | + descr = f'<b>{item["name"]}</b>\n{addr}'
|
|
| 1545 | 1545 | else:
|
| 1546 | - descr = '<b>%s</b>' % addr
|
|
| 1546 | + descr = f'<b>{addr}</b>'
|
|
| 1547 | 1547 | # Guess which kind of service this is
|
| 1548 | 1548 | identities = []
|
| 1549 | 1549 | type_ = app.get_transport_name_from_jid(
|
| ... | ... | @@ -1570,21 +1570,21 @@ def _add_item(self, jid, node, parent_node, item, force): |
| 1570 | 1570 | def _update_item(self, iter_, jid, node, item):
|
| 1571 | 1571 | addr = get_agent_address(jid, node)
|
| 1572 | 1572 | if 'name' in item:
|
| 1573 | - descr = '<b>%s</b>\n%s' % (item['name'], addr)
|
|
| 1573 | + descr = f'<b>{item["name"]}</b>\n{addr}'
|
|
| 1574 | 1574 | else:
|
| 1575 | - descr = '<b>%s</b>' % addr
|
|
| 1575 | + descr = f'<b>{addr}</b>'
|
|
| 1576 | 1576 | self.model[iter_][3] = descr
|
| 1577 | 1577 | |
| 1578 | 1578 | def _update_info(self, iter_, jid, node, identities, features, data):
|
| 1579 | 1579 | addr = get_agent_address(jid, node)
|
| 1580 | 1580 | if not identities:
|
| 1581 | - descr = '<b>%s</b>' % addr
|
|
| 1581 | + descr = '<b>{addr}</b>'
|
|
| 1582 | 1582 | else:
|
| 1583 | 1583 | name = identities[0].name or ''
|
| 1584 | 1584 | if name:
|
| 1585 | - descr = '<b>%s</b>\n%s' % (name, addr)
|
|
| 1585 | + descr = f'<b>{name}</b>\n{addr}'
|
|
| 1586 | 1586 | else:
|
| 1587 | - descr = '<b>%s</b>' % addr
|
|
| 1587 | + descr = f'<b>{addr}</b>'
|
|
| 1588 | 1588 | |
| 1589 | 1589 | # Update progress
|
| 1590 | 1590 | self._progress += 1
|
| ... | ... | @@ -190,13 +190,13 @@ def _request_sentry_endpoint(self) -> None: |
| 190 | 190 | |
| 191 | 191 | def _parse_endpoint(self, request: HTTPRequest) -> str:
|
| 192 | 192 | if not request.is_complete():
|
| 193 | - raise ValueError('Failed to retrieve sentry endpoint: %s %s' % (
|
|
| 194 | - request.get_status(), request.get_error()))
|
|
| 193 | + raise ValueError('Failed to retrieve sentry endpoint: '
|
|
| 194 | + f'{request.get_status()} {request.get_error()}')
|
|
| 195 | 195 | |
| 196 | 196 | try:
|
| 197 | 197 | data = json.loads(request.get_data())
|
| 198 | 198 | except Exception as error:
|
| 199 | - raise ValueError('Json parsing error: %s' % error)
|
|
| 199 | + raise ValueError(f'Json parsing error: {error}')
|
|
| 200 | 200 | |
| 201 | 201 | endpoint = data.get('sentry_endpoint')
|
| 202 | 202 | if endpoint is None:
|
| ... | ... | @@ -142,7 +142,7 @@ def _set_error(self, error: StanzaError) -> None: |
| 142 | 142 | if error.condition == 'gone':
|
| 143 | 143 | reason = error.get_text(get_rfc5646_lang())
|
| 144 | 144 | if reason:
|
| 145 | - text = '%s:\n%s' % (text, reason)
|
|
| 145 | + text = f'{text}:\n{reason}'
|
|
| 146 | 146 | self._show_error_page(text)
|
| 147 | 147 | |
| 148 | 148 | def _set_error_from_code(self, error_code: str) -> None:
|
| ... | ... | @@ -355,7 +355,7 @@ def update(self) -> None: |
| 355 | 355 | |
| 356 | 356 | if not self._row.active:
|
| 357 | 357 | css_class = 'omemo-inactive-color'
|
| 358 | - tooltip = '%s - %s' % (_('Inactive'), tooltip)
|
|
| 358 | + tooltip = f'{_("Inactive")} - {tooltip}'
|
|
| 359 | 359 | |
| 360 | 360 | image.get_style_context().add_class(css_class)
|
| 361 | 361 | self._css_class = css_class
|
| ... | ... | @@ -323,7 +323,7 @@ def convert_rgba_to_hex(rgba: Gdk.RGBA) -> str: |
| 323 | 323 | red = int(rgba.red * 255)
|
| 324 | 324 | green = int(rgba.green * 255)
|
| 325 | 325 | blue = int(rgba.blue * 255)
|
| 326 | - return '#%02x%02x%02x' % (red, green, blue)
|
|
| 326 | + return f'#{red:02x}{green:02x}{blue:02x}'
|
|
| 327 | 327 | |
| 328 | 328 | |
| 329 | 329 | def convert_rgb_to_hex(rgb_string: str) -> str:
|
| ... | ... | @@ -428,8 +428,7 @@ def format_location(location: LocationData) -> str: |
| 428 | 428 | tag = LOCATION_DATA.get(attr)
|
| 429 | 429 | if tag is None:
|
| 430 | 430 | continue
|
| 431 | - location_string += '\n<b>%(tag)s</b>: %(text)s' % {
|
|
| 432 | - 'tag': tag.capitalize(), 'text': text}
|
|
| 431 | + location_string += f'\n<b>{tag.capitalize()}</b>: {text}'
|
|
| 433 | 432 | |
| 434 | 433 | return location_string.strip()
|
| 435 | 434 | |
| ... | ... | @@ -456,7 +455,7 @@ def format_fingerprint(fingerprint: str) -> str: |
| 456 | 455 | wordsize = fplen // 8
|
| 457 | 456 | buf = ''
|
| 458 | 457 | for char in range(0, fplen, wordsize):
|
| 459 | - buf += '{0} '.format(fingerprint[char:char + wordsize])
|
|
| 458 | + buf += f'{fingerprint[char:char + wordsize]} '
|
|
| 460 | 459 | buf = textwrap.fill(buf, width=36)
|
| 461 | 460 | return buf.rstrip().upper()
|
| 462 | 461 | |
| ... | ... | @@ -670,8 +669,8 @@ def _to_href(match: Match[str]) -> str: |
| 670 | 669 | url = match.group()
|
| 671 | 670 | if '://' not in url:
|
| 672 | 671 | url = 'https://' + url
|
| 673 | - return '<a href="%s"><span foreground="%s">%s</span></a>' % (
|
|
| 674 | - url, color, match.group())
|
|
| 672 | + return (f'<a href="{url}"><span foreground="{color}">'
|
|
| 673 | + f'{match.group()}</span></a>')
|
|
| 675 | 674 | |
| 676 | 675 | return URL_REGEX.sub(_to_href, string)
|
| 677 | 676 |
| ... | ... | @@ -233,8 +233,6 @@ ignore = [ |
| 233 | 233 | "SIM201", # Use x instead of not x
|
| 234 | 234 | "SIM212", # Use `value if value else ''` instead of `'' if not value else value`
|
| 235 | 235 | "SIM300", # Yoda conditions are discouraged use x instead
|
| 236 | - "UP030", # Use implicit references for positional format fields
|
|
| 237 | - "UP031", # Use format specifiers instead of percent format
|
|
| 238 | 236 | "UP032", # Use f-string instead of `format` call
|
| 239 | 237 | "UP034", # Avoid extraneous parentheses
|
| 240 | 238 | "UP035", # Import from `collections.abc` instead: `Callable`
|