Philipp Hörist pushed to branch master at gajim / gajim
Commits: fd47095e by Philipp Hörist at 2022-12-04T23:54:56+01:00 refactor: Remove unnecessary map() usage
- - - - - 6c666114 by Philipp Hörist at 2022-12-04T23:54:56+01:00 refactor: Remove unnecessary method arguments
- - - - - 532e2249 by Philipp Hörist at 2022-12-04T23:54:56+01:00 refactor: Use "not in" for inclusion check
- - - - - f256b6ec by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: Remove unnecessary variable assignment before return
- - - - - 90cd87a2 by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: Simplify import
- - - - - c4068f05 by Philipp Hörist at 2022-12-05T00:00:21+01:00 cq: Reorder comparison
- - - - - 012daf50 by Philipp Hörist at 2022-12-05T00:00:21+01:00 cq: Add noqa for false positive ruff checks
- - - - - 53f96919 by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: PluginManager: Simplify setting module attribute
- - - - - 90a53769 by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: Rename AppIndicator import
- - - - - d14e1ee9 by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: Follow CapWords convention for classes
- - - - - b73700ee by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: Assistant: Use dict literal
- - - - - 93890f8d by Philipp Hörist at 2022-12-05T00:00:21+01:00 refactor: Remove unnecessary method cache
This method is not expensive and only called a few times
- - - - - 6440fd60 by Philipp Hörist at 2022-12-05T00:00:21+01:00 ci: Update ruff configuration
- - - - - 9e9101a7 by Philipp Hörist at 2022-12-05T00:00:21+01:00 ci: Repace pylint/flake8 with ruff
- - - - -
28 changed files:
- − .ci/pylint.sh - .gitignore - .gitlab-ci.yml - gajim/common/app.py - gajim/common/const.py - gajim/common/helpers.py - gajim/common/i18n.py - gajim/common/logging_helpers.py - gajim/common/modules/bookmarks.py - gajim/common/modules/bytestream.py - gajim/common/regex.py - gajim/common/setting_values.py - gajim/gtk/adhoc.py - gajim/gtk/assistant.py - gajim/gtk/chat_function_page.py - gajim/gtk/css_config.py - gajim/gtk/dataform.py - gajim/gtk/menus.py - gajim/gtk/message_input.py - gajim/gtk/status_icon.py - gajim/gtk/util.py - gajim/plugins/pluginmanager.py - − pylintrc - pyproject.toml - scripts/pre-push-tests.sh - setup.cfg - setup.py - test/no_gui/test_styling.py
Changes:
===================================== .ci/pylint.sh deleted ===================================== @@ -1,24 +0,0 @@ -#!/bin/sh - -# exit when any command fails -set -e - -PYLINT=${PYLINT:-pylint} - -# Ignore but need fixing - -# C0103 invalid-name -# C0415 import-outside-toplevel -# R1710 inconsistent-return-statements -# W0201 attribute-defined-outside-init -# W0221 arguments-differ -# W0233 non-parent-init-called -# W0613 unused-argument - -NEED_FIXING=C0103,C0415,R1710,W0201,W0221,W0233,W0613 - - -"$PYLINT" --version -"$PYLINT" --disable="$NEED_FIXING" --ignore=modules,dbus "$@" -"$PYLINT" --disable="C0415" "$@/common/modules" -"$PYLINT" "$@/common/dbus"
===================================== .gitignore ===================================== @@ -16,6 +16,7 @@ gajim/gui/*
__pycache__/ .mypy_cache/ +.ruff_cache/
# Build folders
===================================== .gitlab-ci.yml ===================================== @@ -33,23 +33,14 @@ test-pyright: - $(npm bin)/pyright interruptible: true
-test-flake8: +test-ruff: stage: test rules: - changes: - "**/*.py" script: - - flake8 - interruptible: true - -test-pylint: - stage: test - rules: - - changes: - - "**/*.py" - script: - - pip3 install -I git+https://dev.gajim.org/gajim/python-nbxmpp.git - - .ci/pylint.sh --jobs=2 gajim + - pip3 install ruff + - ruff . interruptible: true
test-unittest:
===================================== gajim/common/app.py ===================================== @@ -474,8 +474,7 @@ def get_jid_from_account(account_name: str) -> str: ''' name = settings.get_account_setting(account_name, 'name') hostname = settings.get_account_setting(account_name, 'hostname') - jid = name + '@' + hostname - return jid + return name + '@' + hostname
def get_hostname_from_account(account_name: str, use_srv: bool = False) -> str: @@ -502,10 +501,13 @@ def get_priority(account: str, show: str) -> int: prio = settings.get_account_setting(account, 'autopriority_' + show) else: prio = settings.get_account_setting(account, 'priority') + if prio < -128: - prio = -128 - elif prio > 127: - prio = 127 + return -128 + + if prio > 127: + return 127 + return prio
===================================== gajim/common/const.py ===================================== @@ -247,7 +247,7 @@ class MUCJoinedState(Enum): CREATING = 'creating' CAPTCHA_REQUEST = 'captcha in progress' CAPTCHA_FAILED = 'captcha failed' - PASSWORD_REQUEST = 'password request' + PASSWORD_REQUEST = 'password request' # noqa: S105
def __str__(self): return self.name
===================================== gajim/common/helpers.py ===================================== @@ -183,28 +183,28 @@ def get_uf_show(show: str, use_mnemonic: bool = False) -> str:
def get_uf_sub(sub: str) -> str: if sub == 'none': - uf_sub = p_('Contact subscription', 'None') - elif sub == 'to': - uf_sub = p_('Contact subscription', 'To') - elif sub == 'from': - uf_sub = p_('Contact subscription', 'From') - elif sub == 'both': - uf_sub = p_('Contact subscription', 'Both') - else: - uf_sub = p_('Contact subscription', 'Unknown') + return p_('Contact subscription', 'None') + + if sub == 'to': + return p_('Contact subscription', 'To') + + if sub == 'from': + return p_('Contact subscription', 'From')
- return uf_sub + if sub == 'both': + return p_('Contact subscription', 'Both') + + return p_('Contact subscription', 'Unknown')
def get_uf_ask(ask: Union[str, None]) -> str: if ask is None: - uf_ask = p_('Contact subscription', 'None') - elif ask == 'subscribe': - uf_ask = p_('Contact subscription', 'Subscribe') - else: - uf_ask = ask + return p_('Contact subscription', 'None') + + if ask == 'subscribe': + return p_('Contact subscription', 'Subscribe')
- return uf_ask + return ask
def get_uf_role(role: Union[Role, str], plural: bool = False) -> str: @@ -280,13 +280,7 @@ def get_uf_relative_time(timestamp: float) -> str:
def to_one_line(msg: str) -> str: msg = msg.replace('\', '\\') - msg = msg.replace('\n', '\n') - # s1 = 'test\ntest\ntest' - # s11 = s1.replace('\', '\\') - # s12 = s11.replace('\n', '\n') - # s12 - # 'test\ntest\\ntest' - return msg + return msg.replace('\n', '\n')
def from_one_line(msg: str) -> str: @@ -296,13 +290,7 @@ def from_one_line(msg: str) -> str: # So here match '\n' but not if you have a '' before that expr = re.compile(r'(?<!\)\n') msg = expr.sub('\n', msg) - msg = msg.replace('\\', '\') - # s12 = 'test\ntest\\ntest' - # s13 = re.sub('\n', s12) - # s14 s13.replace('\\', '\') - # s14 - # 'test\ntest\ntest' - return msg + return msg.replace('\\', '\')
def chatstate_to_string(chatstate: Optional[Chatstate]) -> str: @@ -345,8 +333,7 @@ def build_command(executable: str, parameter: str) -> str: # we add to the parameter (can hold path with spaces) # "" so we have good parsing from shell parameter = parameter.replace('"', '\"') # but first escape " - command = f'{executable} "{parameter}"' - return command + return f'{executable} "{parameter}"'
def sanitize_filename(filename: str) -> str: @@ -364,7 +351,7 @@ def sanitize_filename(filename: str) -> str: ] filename = ''.join(char for char in filename if char not in blacklist)
- filename = ''.join(char for char in filename if 31 < ord(char)) + filename = ''.join(char for char in filename if ord(char) > 31)
filename = unicodedata.normalize('NFKD', filename) filename = filename.rstrip('. ') @@ -565,12 +552,12 @@ def get_auth_sha(sid: str, initiator: str, target: str) -> str: Return sha of sid + initiator + target used for proxy auth ''' return hashlib.sha1( - (f'{sid}{initiator}{target}').encode('utf-8')).hexdigest() + (f'{sid}{initiator}{target}').encode()).hexdigest()
def remove_invalid_xml_chars(string_: str) -> str: if string_: - string_ = re.sub(INVALID_XML_CHARS_REGEX, '', string_) + return re.sub(INVALID_XML_CHARS_REGEX, '', string_) return string_
@@ -681,9 +668,8 @@ def jid_is_blocked(account: str, jid: str) -> bool:
def get_subscription_request_msg(account: Optional[str] = None) -> str: - message = _('I would like to add you to my contact list.') if account is None: - return message + return _('I would like to add you to my contact list.')
message = app.settings.get_account_setting( account, 'subscription_request_msg') @@ -795,10 +781,9 @@ class AdditionalDataDict(collections.UserDict):
@staticmethod def _get_path_childs(full_path: str) -> list[str]: - path_childs = [full_path] if ':' in full_path: - path_childs = full_path.split(':') - return path_childs + return full_path.split(':') + return [full_path]
def set_value(self, full_path: str, key: str, value: Optional[str]) -> None: path_childs = self._get_path_childs(full_path) @@ -851,7 +836,7 @@ class Singleton(type):
def __call__(cls, *args: Any, **kwargs: Any): if cls not in cls._instances: - cls._instances[cls] = super(Singleton, cls).__call__( + cls._instances[cls] = super().__call__( *args, **kwargs) return cls._instances[cls]
@@ -1459,28 +1444,25 @@ def warn_about_plain_connection(account: str, def get_idle_status_message(state: str, status_message: str) -> str: message = app.settings.get(f'auto{state}_message') if not message: - message = status_message - else: - message = message.replace('$S', '%(status)s') - message = message.replace('$T', '%(time)s') - message = message % { - 'status': status_message, - 'time': app.settings.get(f'auto{state}time') - } - return message + return status_message
+ message = message.replace('$S', '%(status)s') + message = message.replace('$T', '%(time)s') + return message % { + 'status': status_message, + 'time': app.settings.get(f'auto{state}time') + }
-def get_group_chat_nick(account: str, room_jid: Union[JID, str]) -> str: - nick = app.nicks[account]
+def get_group_chat_nick(account: str, room_jid: Union[JID, str]) -> str: client = app.get_client(account)
bookmark = client.get_module('Bookmarks').get_bookmark(room_jid) if bookmark is not None: if bookmark.nick is not None: - nick = bookmark.nick + return bookmark.nick
- return nick + return app.nicks[account]
def get_random_muc_localpart() -> str: @@ -1528,15 +1510,13 @@ def get_os_version() -> str:
def get_gobject_version() -> str: - gobject_ver = '.'.join(map(str, GObject.pygobject_version)) - return gobject_ver + return '.'.join(map(str, GObject.pygobject_version))
def get_glib_version() -> str: - glib_ver = '.'.join(map(str, [GLib.MAJOR_VERSION, - GLib.MINOR_VERSION, - GLib.MICRO_VERSION])) - return glib_ver + return '.'.join(map(str, [GLib.MAJOR_VERSION, + GLib.MINOR_VERSION, + GLib.MICRO_VERSION]))
def make_path_from_jid(base_path: Path, jid: JID) -> Path:
===================================== gajim/common/i18n.py ===================================== @@ -140,9 +140,10 @@ def ngettext(s_sing: str, ''' text = _translation.ngettext(s_sing, s_plural, n) if n == 1 and replace_sing is not None: - text = text % replace_sing - elif n > 1 and replace_plural is not None: - text = text % replace_plural + return text % replace_sing + + if n > 1 and replace_plural is not None: + return text % replace_plural return text
===================================== gajim/common/logging_helpers.py ===================================== @@ -81,7 +81,7 @@ def parseAndSetLogLevels(arg: str) -> None: file=sys.stderr)
-class colors: +class Colors: NONE = chr(27) + '[0m' BLACK = chr(27) + '[30m' RED = chr(27) + '[31m' @@ -102,19 +102,19 @@ class colors:
def colorize(text: str, color: str) -> str: - return color + text + colors.NONE + return color + text + Colors.NONE
class FancyFormatter(logging.Formatter): ''' - An eye-candy formatter with colors + An eye-candy formatter with Colors ''' colors_mapping = { - 'DEBUG': colors.BLUE, - 'INFO': colors.GREEN, - 'WARNING': colors.BROWN, - 'ERROR': colors.RED, - 'CRITICAL': colors.BRIGHT_RED, + 'DEBUG': Colors.BLUE, + 'INFO': Colors.GREEN, + 'WARNING': Colors.BROWN, + 'ERROR': Colors.RED, + 'CRITICAL': Colors.BRIGHT_RED, }
def __init__(self, @@ -129,7 +129,7 @@ def formatTime(self, datefmt: Optional[str] = None) -> str: f = logging.Formatter.formatTime(self, record, datefmt) if self.use_color: - f = colorize(f, colors.DARK_GRAY) + f = colorize(f, Colors.DARK_GRAY) return f
def format(self, record: logging.LogRecord) -> str: @@ -139,7 +139,7 @@ def format(self, record: logging.LogRecord) -> str: if self.use_color: c = FancyFormatter.colors_mapping.get(level, '') record.levelname = colorize(record.levelname, c) - record.name = '%-25s' % colorize(record.name, colors.CYAN) + record.name = '%-25s' % colorize(record.name, Colors.CYAN) else: record.name = '%-25s|' % record.name
===================================== gajim/common/modules/bookmarks.py ===================================== @@ -21,8 +21,6 @@ from typing import Optional from typing import cast
-import functools - from nbxmpp.namespaces import Namespace from nbxmpp.protocol import JID from nbxmpp.structs import BookmarkData @@ -153,7 +151,6 @@ def pass_disco(self, info: DiscoInfo) -> None: self._compat = Namespace.BOOKMARKS_COMPAT in info.features self._conversion = Namespace.BOOKMARK_CONVERSION in info.features
- @functools.lru_cache(maxsize=1) def _bookmark_module(self) -> str: if not self._con.get_module('PubSub').publish_options: return 'PrivateBookmarks'
===================================== gajim/common/modules/bytestream.py ===================================== @@ -321,7 +321,7 @@ def _add_local_ips_as_streamhosts_to_query(self, my_ips = [my_ip] # all IPs from local DNS for addr in socket.getaddrinfo(socket.gethostname(), None): - if (not addr[4][0] in my_ips and + if (addr[4][0] not in my_ips and not addr[4][0].startswith('127') and not addr[4][0] == '::1'): my_ips.append(addr[4][0])
===================================== gajim/common/regex.py ===================================== @@ -95,13 +95,13 @@ class PRECIS: IdentifierClass: Any
-class PRECIS_IdentifierClass: +class PRECISIdentifierClass: _p = PRECIS Valid = fr'{_p.LetterDigits}\x21-\x7e' Disallowed = fr'{_p.Spaces}{_p.Symbols}{_p.HasCompat}' # there's a ton more
-PRECIS.IdentifierClass = PRECIS_IdentifierClass +PRECIS.IdentifierClass = PRECISIdentifierClass
# (Rough approximation of) Jabber IDs, as defined in [XMPP: Address Format]
===================================== gajim/common/setting_values.py ===================================== @@ -27,12 +27,12 @@ class _DEFAULT: pass
-class _ACCOUNT_DEFAULT: +class _ACCOUNTDEFAULT: pass
HAS_APP_DEFAULT = _DEFAULT() -HAS_ACCOUNT_DEFAULT = _ACCOUNT_DEFAULT() +HAS_ACCOUNT_DEFAULT = _ACCOUNTDEFAULT()
BoolSettings = Literal[
===================================== gajim/gtk/adhoc.py ===================================== @@ -329,9 +329,7 @@ def _on_is_valid(self, _widget: DataFormWidget, is_valid: bool) -> None: self.update_page_complete()
def get_visible_buttons(self) -> list[str]: - actions = list(map(lambda action: action.value, - self._last_stage_data.actions)) - return actions + return [action.value for action in self._last_stage_data.actions]
def get_default_button(self) -> str: return self._last_stage_data.default.value
===================================== gajim/gtk/assistant.py ===================================== @@ -30,17 +30,17 @@
class Assistant(Gtk.ApplicationWindow, EventHelper):
- __gsignals__ = dict( - button_clicked=( + __gsignals__ = { + 'button-clicked': ( GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, (str, ) ), - page_changed=( + 'page-changed': ( GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, (str, ) - )) + )}
def __init__(self, transient_for: Optional[Gtk.Window] = None,
===================================== gajim/gtk/chat_function_page.py ===================================== @@ -44,7 +44,7 @@ class FunctionMode(Enum): CHANGE_NICKNAME = 'change-nickname' KICK = 'kick' BAN = 'ban' - PASSWORD_REQUEST = 'password-request' + PASSWORD_REQUEST = 'password-request' # noqa: S105 CAPTCHA_REQUEST = 'captcha-request' CAPTCHA_ERROR = 'captcha-error' JOIN_FAILED = 'join-failed'
===================================== gajim/gtk/css_config.py ===================================== @@ -169,7 +169,7 @@ def _load_css_from_file(self, ) -> None: path = configpaths.get('STYLE') / filename try: - with open(path, 'r', encoding='utf8') as file_: + with open(path, encoding='utf8') as file_: css = file_.read() except Exception as exc: log.error('Error loading css: %s', exc)
===================================== gajim/gtk/dataform.py ===================================== @@ -516,9 +516,7 @@ def __init__(self, self._store.append( [label, value, label, value in field.values])
- labels_over_max_width = map(lambda x: len(x) > 40, - [option[0] for option in field.options]) - if any(labels_over_max_width): + if any(filter(lambda x: len(x[0]) > 40, field.options)): self.set_tooltip_column(2)
self.set_model(self._store)
===================================== gajim/gtk/menus.py ===================================== @@ -671,8 +671,7 @@ def get_chat_row_menu(contact: types.ChatContactT, 'win.retract-message', param))
- menu = GajimMenu.from_list(menu_items) - return menu + return GajimMenu.from_list(menu_items)
def get_preview_menu(preview: Preview) -> GajimMenu:
===================================== gajim/gtk/message_input.py ===================================== @@ -225,7 +225,7 @@ def _get_spell_checker_language(self, assert isinstance(lang, str) lang = Gspell.language_lookup(lang) if lang is None: - lang = Gspell.language_get_default() + return Gspell.language_get_default() return lang
def _on_language_changed(self, @@ -347,8 +347,7 @@ def has_text(self) -> bool: def get_text(self) -> str: buf = self.get_buffer() start, end = buf.get_bounds() - text = self.get_buffer().get_text(start, end, True) - return text + return self.get_buffer().get_text(start, end, True)
def _on_toggle_spell_check(self, *args: Any) -> None: if not app.is_installed('GSPELL'):
===================================== gajim/gtk/status_icon.py ===================================== @@ -46,11 +46,11 @@
if app.is_installed('APPINDICATOR'): # pylint: disable=ungrouped-imports - from gi.repository import AppIndicator3 as appindicator + from gi.repository import AppIndicator3 as AppIndicator
elif app.is_installed('AYATANA_APPINDICATOR'): # pylint: disable=ungrouped-imports - from gi.repository import AyatanaAppIndicator3 as appindicator + from gi.repository import AyatanaAppIndicator3 as AppIndicator
log = logging.getLogger('gajim.gui.statusicon') @@ -61,7 +61,7 @@ def __init__(self) -> None: if self._can_use_libindicator(): app.settings.connect_signal('show_trayicon', self._on_setting_changed) - self._backend = AppIndicator() + self._backend = AppIndicatorIcon() log.info('Use AppIndicator3 backend') elif app.is_display(Display.WAYLAND): self._backend = NoneBackend() @@ -295,16 +295,16 @@ def _build_menu(self, button: int, event_time: int) -> None: None, None, None, None, button, event_time)
-class AppIndicator(GtkMenuBackend): +class AppIndicatorIcon(GtkMenuBackend): def __init__(self) -> None: GtkMenuBackend.__init__(self)
- self._status_icon = appindicator.Indicator.new( + self._status_icon = AppIndicator.Indicator.new( 'Gajim', 'org.gajim.Gajim', - appindicator.IndicatorCategory.COMMUNICATIONS) + AppIndicator.IndicatorCategory.COMMUNICATIONS) self._status_icon.set_icon_theme_path(str(configpaths.get('ICONS'))) - self._status_icon.set_status(appindicator.IndicatorStatus.ACTIVE) + self._status_icon.set_status(AppIndicator.IndicatorStatus.ACTIVE) self._status_icon.set_menu(self._ui.systray_context_menu) self._status_icon.set_secondary_activate_target( self._ui.toggle_window_menuitem) @@ -313,10 +313,10 @@ def __init__(self) -> None:
def update_state(self, init: bool = False) -> None: if not app.settings.get('show_trayicon'): - self._status_icon.set_status(appindicator.IndicatorStatus.PASSIVE) + self._status_icon.set_status(AppIndicator.IndicatorStatus.PASSIVE) return
- self._status_icon.set_status(appindicator.IndicatorStatus.ACTIVE) + self._status_icon.set_status(AppIndicator.IndicatorStatus.ACTIVE)
if not init and app.window.get_total_unread_count(): icon_name = 'dcraven-message-new' @@ -335,7 +335,7 @@ def update_state(self, init: bool = False) -> None:
def is_visible(self) -> bool: status = self._status_icon.get_status() - return status == appindicator.IndicatorStatus.ACTIVE + return status == AppIndicator.IndicatorStatus.ACTIVE
def shutdown(self) -> None: pass
===================================== gajim/gtk/util.py ===================================== @@ -406,11 +406,10 @@ def format_tune(data: TuneData) -> str: title = GLib.markup_escape_text(data.title or _('Unknown Title')) source = GLib.markup_escape_text(data.source or _('Unknown Source'))
- tune_string = _('<b>"%(title)s"</b> by <i>%(artist)s</i>\n' - 'from <i>%(source)s</i>') % {'title': title, - 'artist': artist, - 'source': source} - return tune_string + return _('<b>"%(title)s"</b> by <i>%(artist)s</i>\n' + 'from <i>%(source)s</i>') % {'title': title, + 'artist': artist, + 'source': source}
def get_account_tune_icon_name(account: str) -> Optional[str]: @@ -720,11 +719,10 @@ def open_window(name: str, **kwargs: Any) -> Any:
def get_gtk_version() -> str: - gtk_ver = '%i.%i.%i' % ( + return '%i.%i.%i' % ( Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) - return gtk_ver
class EventHelper(CommonEventHelper):
===================================== gajim/plugins/pluginmanager.py ===================================== @@ -268,8 +268,8 @@ def _load_plugin_module(self, for module_attr_name in dir(module): module_attr = getattr(module, module_attr_name) if issubclass(module_attr, GajimPlugin): - setattr(module_attr, 'manifest', manifest) - setattr(module_attr, '__path__', str(manifest.path)) + module_attr.manifest = manifest + module_attr.__path__ = str(manifest.path) return module_attr return None
===================================== pylintrc deleted ===================================== @@ -1,439 +0,0 @@ -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-whitelist= - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=gui - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -jobs=2 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then re-enable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -# -# Errors which are covered by pyright -# -# E0401 import-error -# E1101 no-member -# E1102 not-callable -# E1111 assignment-from-no-return -# E1120 no-value-for-parameter -# E1121 too-many-function-args -# E1123 unexpected-keyword-arg -# E1124 redundant-keyword-arg -# E1125 missing-kwoa -# E1126 invalid-sequence-index -# E1127 invalid-slice-index -# E1128 assignment-from-none -# E1129 not-context-manager -# E1130 invalid-unary-operand-type -# E1131 unsupported-binary-operation -# E1132 repeated-keyword -# E1133 not-an-iterable -# E1134 not-a-mapping -# E1135 unsupported-membership-test -# E1136 unsubscriptable-object -# E1137 unsupported-assignment-operation -# E1138 unsupported-delete-operation -# E1139 invalid-metaclass -# E1140 unhashable-dict-key -# E1141 dict-iter-missing-items -# E1142 await-outside-async -# I1101 c-extension-no-member -# W0212 protected-access -# W1113 keyword-arg-before-vararg -# W1114 arguments-out-of-order -# W1115 non-str-assignment-to-dunder-name -# W1116 isinstance-second-argument-not-valid-type -# -# Errors which are covered by flake8 -# -# C0301 line-too-long -# C0303 trailing-whitespace -# C0304 missing-final-newline -# C0321 multiple-statements -# W0301 unnecessary-semicolon -# W0311 bad-indentation -# W0611 unused-import -# -# Ignore Always, we don’t need these checks -# -# C0111 missing-docstring -# C0209 use-f-string -# C0302 too-many-lines -# C0411 wrong-import-order -# C0413 wrong-import-position -# R0801 duplicat-code -# R0904 too-many-public-methods -# R0913 too-many-arguments -# R0915 too-many-statements -# R1725 super-with-arguments -# R1732 consider-using-with -# W0237 arguments-renamed -# W0511 fix-me -# W0707 raise-missing-from -# W1404 implicit-str-concat -# W1406 redundant-u-string-prefix - -disable=E0401,E1101,E1102,E1111,E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1128,E1129,E1130,E1131,E1132,E1133,E1134,E1135,E1136,E1137,E1138,E1139,E1140,E1141,E1142,I1101,W0212,W1113,W1114,W1115,W1116,C0301,C0303,C0304,C0321,C0411,C0413,W0301,W0311,W0611,C0111,C0209,C0302,R0801,R0904,R0913,R0915,R1725,R1732,W0237,W0311,W0511,W0707,W1404,W1406 - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= - - -[REPORTS] - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -reports=no - -# Activate the evaluation score. -score=no - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=(_.*|kwargs|args) - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local,gi.repository.GLib.Error - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules=gi.repository,cairo,gajim.gui - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )?<?https?://\S+>?$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=80 - -# Maximum number of lines in a module -max-module-lines=3000 - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[BASIC] - -# Regular expression matching correct argument names -argument-rgx=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct attribute names -attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression matching correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression matching correct constant names -const-rgx= - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Regular expression matching correct function names -function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_,iq - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Regular expression matching correct method names -method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Regular expression matching correct variable names -variable-rgx=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$ - - -[IMPORTS] - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=optparse,tkinter.tix - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=15 - -# Maximum number of attributes for a class (see R0902). -max-attributes=9999 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - -# Maximum number of branch for function / method body -max-branches=50 - -# Maximum number of locals for function / method body -max-locals=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=50 - -# Maximum number of return / yield for function / method body -max-returns=100 - -# Maximum number of statements in function / method body -max-statements=100 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=0 - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=
===================================== pyproject.toml ===================================== @@ -163,24 +163,42 @@ select = [ "C901", # mccabe # "D", # pydocstyle "E", # pycodestyle + # "ERA", # eradicate "F", # pyflakes # "FBT", # flake8-boolean-trap # "I", # flake8-tidy-imports, isort - "M", # Meta rules "N", # pep8-naming + "PGH", # pylint + "PLC", # pylint + "PLE", # pylint + "PLR", # pylint + "PLW", # pylint "Q", # flake8-quotes "RUF", # Ruff-specific rules + # "RET", # flake8-return "S", # flake8-bandit - "T", # flake8-debugger, flake8-print - "U", # pyupgrade + # "T", # flake8-debugger, flake8-print + "UP", # pyupgrade "W", # pycodestyle "YTT", # flake8-2020 ]
ignore = [ - "S101", # Use of `assert` detected - "FBT003", # Boolean positional value in function call + "A003", # Class attribute is shadowing python builtin + "B904", # Within an except clause .. "BLE001", # Blind except Exception: statement + "C901", # too complex + "FBT003", # Boolean positional value in function call + "N802", # Function name should be lower case + "N806", # Variable should be lower case + "N817", # CamelCase imported as acronym + "N818", # Exception name should be named with an Error suffix + "RUF001", # AmbiguousUnicodeCharacterString + "RUF002", # AmbiguousUnicodeCharacterDocstring + "RUF003", # AmbiguousUnicodeCharacterComment + "RUF100", # Unused `noqa` directive + "S101", # Use of `assert` detected + "UP007", # Use X | Y for type annotations ]
exclude = [ @@ -197,7 +215,7 @@ exclude = [ "typings", "gajim/common/config.py", # legacy module, will be removed "gajim/common/optparser.py", # legacy module, will be removed - "gajim/common/socks5.py", # legacy module, will be removed + "gajim/common/socks5.py", # legacy module, will be removed ]
# Allow unused variables when underscore-prefixed.
===================================== scripts/pre-push-tests.sh ===================================== @@ -6,10 +6,10 @@ set -e GREEN='\033[0;32m'
-./scripts/dev/pylint-ci.sh gajim -echo "${GREEN}pylint: \t OK" -mypy gajim -echo "${GREEN}mypy: \t\t OK" -codespell -I codespell.conf --skip="*__pycache__*,gajim/data/icons,gajim/data/sounds,gajim/data/emoticons" gajim +pyright +echo "${GREEN}pyright: \t OK" +ruff . +echo "${GREEN}ruff: \t\t OK" +codespell gajim echo "${GREEN}codespell: \t OK" echo "${GREEN}ready to push"
===================================== setup.cfg ===================================== @@ -1,27 +1,3 @@ -[flake8] -ignore = W504, C901 -exclude = - __pycache__, - build, - dist, - debian_build, - test, - typings, - gajim/common/config.py, - gajim/common/optparser.py, - gajim/common/regex.py, - gajim/common/socks5.py, - gajim/gui, -max-complexity = 15 -builtins=_ -max-line-length = 80 -statistics = True -count = True - -inline-quotes = single -multiline-quotes = ''' -docstring-quotes = ''' - [metadata] name = gajim version = attr: gajim.__version__
===================================== setup.py ===================================== @@ -156,7 +156,7 @@ def merge(in_file: Path, log.info('Compiling %s >> %s', in_file, out_file)
-class build(_build): +class Build(_build): def run(self): build_translation() if sys.platform != 'win32': @@ -165,7 +165,7 @@ def run(self): _build.run(self)
-class install(_install): +class Install(_install): def run(self): data_files = cast(DataFilesT, self.distribution.data_files) # pyright: ignore # noqa: E501 install_trans(data_files) @@ -187,8 +187,8 @@ def run(self):
setup( cmdclass={ - 'build_py': build, - 'install': install, + 'build_py': Build, + 'install': Install, }, entry_points={ 'console_scripts': [
===================================== test/no_gui/test_styling.py ===================================== @@ -5,7 +5,7 @@ gui.init('gtk')
from gajim.common import app # Avoids circular imports from common.helpers -import gajim.common.styling as styling +from gajim.common import styling from gajim.common.styling import PlainBlock from gajim.common.styling import PreBlock from gajim.common.styling import QuoteBlock
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/5265a80ce7ac7343cb299c8eb1e79cf3...