diff --git a/.git-hooks/pre-push b/.git-hooks/pre-push index 444caab8ff..5b35a131a4 100755 --- a/.git-hooks/pre-push +++ b/.git-hooks/pre-push @@ -5,16 +5,8 @@ # $ git config core.hooksPath .git-hooks # (in dir) to add hooks # $ git config --unset core.hooksPath # (in dir) to remove hooks -if command -v black &>/dev/null; then - black --diff --check --quiet py3status/ || exit 1 - black --diff --check --quiet setup.py fastentrypoints.py || exit 1 - black --diff --check --quiet tests/ || exit 1 +if command -v hatch &>/dev/null; then + hatch run all else - echo 'hooks/pre-push: command "black" not found, skipping black tests' -fi - -if command -v pytest &>/dev/null; then - pytest --flake8 || exit 1 -else - echo 'hooks/pre-push: command "pytest" not found, skipping flake8 tests' + echo 'hooks/pre-push: command "hatch" not found, skipping hatch tests' fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86fb75c0a1..2661963800 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Test with tox - run: tox \ No newline at end of file + pip install -r requirements/project.txt + - name: Test with hatch + run: hatch run all \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG index d23683885a..e7287d72a2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ -version 3.52 (2023-07-11) +version 3.52 (2023-07-29) +* IMPORTANT: the project has moved from setuptools to pyproject.toml and hatch * IMPORTANT: gevent support is now deprecated and removed * core: drop gevent support diff --git a/MANIFEST.in b/MANIFEST.in index 84b19c0a5d..cb87dc74d6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,4 +5,3 @@ recursive-include doc *.rst *.md *.txt *.py include CHANGELOG include LICENSE include README.md -include fastentrypoints.py diff --git a/Makefile b/Makefile index f6fd881b4e..b4f81ae9f4 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,22 @@ qa: - tox + hatch run style:format + hatch run style:check clean: - rm -rf dist + hatch clean -release: clean qa test - python3 setup.py sdist && python3 -m twine upload dist/* +release: clean qa test build + hatch publish -u __token__ serve: mkdocs serve build: - mkdocs build + hatch build # TODO: maybe move the docs to github #deploy: qa test # mkdocs gh-deploy test: - pytest -xsvv + hatch run all diff --git a/fastentrypoints.py b/fastentrypoints.py deleted file mode 100644 index a1e8af29cb..0000000000 --- a/fastentrypoints.py +++ /dev/null @@ -1,114 +0,0 @@ -# noqa: D300,D400 -# Copyright (c) 2016, Aaron Christianson -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -""" -Monkey patch setuptools to write faster console_scripts with this format: - - import sys - from mymodule import entry_function - sys.exit(entry_function()) - -This is better. - -(c) 2016, Aaron Christianson -http://github.com/ninjaaron/fast-entry_points -""" -from setuptools.command import easy_install -import re - -TEMPLATE = r"""\ -# -*- coding: utf-8 -*- -# EASY-INSTALL-ENTRY-SCRIPT: '{3}','{4}','{5}' -__requires__ = '{3}' -import re -import sys - -from {0} import {1} - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit({2}())""" - - -@classmethod -def get_args(cls, dist, header=None): # noqa: D205,D400 - """ - Yield write_script() argument tuples for a distribution's - console_scripts and gui_scripts entry points. - """ - if header is None: - # pylint: disable=E1101 - header = cls.get_header() - spec = str(dist.as_requirement()) - for type_ in "console", "gui": - group = type_ + "_scripts" - for name, ep in dist.get_entry_map(group).items(): - # ensure_safe_name - if re.search(r"[\\/]", name): - raise ValueError("Path separators not allowed in script names") - script_text = TEMPLATE.format( - ep.module_name, ep.attrs[0], ".".join(ep.attrs), spec, group, name - ) - # pylint: disable=E1101 - args = cls._get_script_args(type_, name, header, script_text) - yield from args - - -# pylint: disable=E1101 -easy_install.ScriptWriter.get_args = get_args - - -def main(): - import os - import re - import shutil - import sys - - dests = sys.argv[1:] or ["."] - filename = re.sub(r"\.pyc$", ".py", __file__) - - for dst in dests: - shutil.copy(filename, dst) - manifest_path = os.path.join(dst, "MANIFEST.in") - setup_path = os.path.join(dst, "setup.py") - - # Insert the include statement to MANIFEST.in if not present - with open(manifest_path, "a+") as manifest: - manifest.seek(0) - manifest_content = manifest.read() - if "include fastentrypoints.py" not in manifest_content: - manifest.write( - ("\n" if manifest_content else "") + "include fastentrypoints.py" - ) - - # Insert the import statement to setup.py if not present - with open(setup_path, "a+") as setup: - setup.seek(0) - setup_content = setup.read() - if "import fastentrypoints" not in setup_content: - setup.seek(0) - setup.truncate() - setup.write("import fastentrypoints\n" + setup_content) diff --git a/py3status/argparsers.py b/py3status/argparsers.py index f5d32ef798..a43d79a0c5 100644 --- a/py3status/argparsers.py +++ b/py3status/argparsers.py @@ -2,9 +2,9 @@ import os import subprocess from pathlib import Path +from platform import python_version from shutil import which -from platform import python_version from py3status.version import version diff --git a/py3status/autodoc.py b/py3status/autodoc.py index 36841871a3..24a88b60b5 100644 --- a/py3status/autodoc.py +++ b/py3status/autodoc.py @@ -1,5 +1,4 @@ import re - from pathlib import Path from py3status.docstrings import core_module_docstrings diff --git a/py3status/command.py b/py3status/command.py index 2a4d538251..8d8d178fda 100644 --- a/py3status/command.py +++ b/py3status/command.py @@ -3,7 +3,6 @@ import os import socket import threading - from pathlib import Path SERVER_ADDRESS = "/tmp/py3status_uds" @@ -419,6 +418,7 @@ def _check_value(self, action, value): elif options.version: # print version from platform import python_version + from py3status.version import version print(f"py3status {version} (python {python_version()})") @@ -460,9 +460,7 @@ def parse_list_or_docstring(options, sps): # HARDCODE: make include path to search for user modules home_path = Path.home() - xdg_home_path = Path( - os.environ.get("XDG_CONFIG_HOME", home_path / ".config") - ).resolve() + xdg_home_path = Path(os.environ.get("XDG_CONFIG_HOME", home_path / ".config")).resolve() options.include_paths = [ xdg_home_path / "py3status/modules", xdg_home_path / "i3status/py3status", diff --git a/py3status/core.py b/py3status/core.py index 2b52345c7a..befd7d7af7 100644 --- a/py3status/core.py +++ b/py3status/core.py @@ -1,24 +1,24 @@ -import pkg_resources import sys import time - from collections import deque from pathlib import Path from pprint import pformat -from signal import signal, Signals, SIGTERM, SIGUSR1, SIGTSTP, SIGCONT +from signal import SIGCONT, SIGTERM, SIGTSTP, SIGUSR1, Signals, signal from subprocess import Popen +from syslog import LOG_ERR, LOG_INFO, LOG_WARNING, syslog from threading import Event, Thread -from syslog import syslog, LOG_ERR, LOG_INFO, LOG_WARNING -from traceback import extract_tb, format_tb, format_stack +from traceback import extract_tb, format_stack, format_tb + +import pkg_resources from py3status.command import CommandServer from py3status.events import Events from py3status.formatter import expand_color from py3status.helpers import print_stderr from py3status.i3status import I3status -from py3status.parse_config import process_config from py3status.module import Module from py3status.output import OutputFormat +from py3status.parse_config import process_config from py3status.profiling import profile from py3status.udev_monitor import UdevMonitor @@ -217,9 +217,7 @@ def report_exception(self, msg, notify_user=True, level="error", error_frame=Non if found: break # all done! create our message. - msg = "{} ({}) {} line {}.".format( - msg, exc_type.__name__, filename, line_no - ) + msg = "{} ({}) {} line {}.".format(msg, exc_type.__name__, filename, line_no) except: # noqa e722 # something went wrong report what we can. msg = f"{msg}." @@ -549,8 +547,7 @@ def _log_gitversion(self): out = f.readline() except OSError: self.log( - "Unable to read git HEAD. " - "Use python git package for more repo information" + "Unable to read git HEAD. " "Use python git package for more repo information" ) return branch = "/".join(out.strip().split("/")[2:]) @@ -636,9 +633,7 @@ def setup(self): time.sleep(0.1) if self.config["debug"]: self.log( - "i3status thread {} with config {}".format( - i3s_mode, self.config["py3_config"] - ) + "i3status thread {} with config {}".format(i3s_mode, self.config["py3_config"]) ) # add i3status thread monitoring task @@ -671,9 +666,7 @@ def setup(self): # make sure we honor custom i3bar protocol stop/resume signals # while providing users a way to opt out from that feature # using the 0 value as specified by the i3bar protocol - custom_stop_signal = ( - self.config["py3_config"].get("py3status", {}).get("stop_signal") - ) + custom_stop_signal = self.config["py3_config"].get("py3status", {}).get("stop_signal") if custom_stop_signal is not None: try: # 0 is a special value for i3bar protocol, use it as-is @@ -769,9 +762,7 @@ def notify_user( if msg_hash in self.notified_messages: return elif module_name: - log_msg = 'Module `{}` sent a notification. "{}: {}"'.format( - module_name, title, msg - ) + log_msg = 'Module `{}` sent a notification. "{}: {}"'.format(module_name, title, msg) self.log(log_msg, level) else: self.log(msg, level) @@ -1021,10 +1012,7 @@ def process_module_output(self, module): return self.output_format.format(outputs) def i3bar_stop(self, signum, frame): - if ( - self.next_allowed_signal == signum - and time.monotonic() > self.inhibit_signal_ts - ): + if self.next_allowed_signal == signum and time.monotonic() > self.inhibit_signal_ts: self.log(f"received stop_signal {Signals(signum).name}") self.i3bar_running = False # i3status should be stopped @@ -1036,10 +1024,7 @@ def i3bar_stop(self, signum, frame): self.inhibit_signal_ts = time.monotonic() + 0.1 def i3bar_start(self, signum, frame): - if ( - self.next_allowed_signal == signum - and time.monotonic() > self.inhibit_signal_ts - ): + if self.next_allowed_signal == signum and time.monotonic() > self.inhibit_signal_ts: self.log(f"received resume signal {Signals(signum).name}") self.i3bar_running = True self.wake_modules() diff --git a/py3status/docstrings.py b/py3status/docstrings.py index 8884bcafbb..032f964a7c 100644 --- a/py3status/docstrings.py +++ b/py3status/docstrings.py @@ -1,7 +1,6 @@ import ast -import re import difflib - +import re from pathlib import Path from py3status.helpers import print_stderr @@ -38,9 +37,7 @@ def parse_readme(): return modules_dict -def core_module_docstrings( - include_core=True, include_user=False, config=None, format="md" -): +def core_module_docstrings(include_core=True, include_user=False, config=None, format="md"): """ Get docstrings for all core modules and user ones if requested returns a dict of {: } @@ -79,13 +76,9 @@ def core_module_docstrings( docstring = parts[0] if format == "md": - docstring = [ - d for d in _from_docstring_md(str(docstring).strip().split("\n")) - ] + docstring = [d for d in _from_docstring_md(str(docstring).strip().split("\n"))] elif format == "rst": - docstring = [ - d for d in _from_docstring_rst(str(docstring).strip().split("\n")) - ] + docstring = [d for d in _from_docstring_rst(str(docstring).strip().split("\n"))] else: raise Exception("`md` and `rst` format supported only") @@ -316,9 +309,7 @@ def update_docstrings(): if quotes and row.strip().startswith(quotes) and not done: out.append(row) if not replaced: - out = out + [ - "".join(_to_docstring(modules_dict[mod])).strip() + "\n" - ] + out = out + ["".join(_to_docstring(modules_dict[mod])).strip() + "\n"] replaced = True if lines: done = True @@ -403,9 +394,7 @@ def show_modules(config, modules_list): core_mods = not config["user"] user_mods = not config["core"] - modules = core_module_docstrings( - include_core=core_mods, include_user=user_mods, config=config - ) + modules = core_module_docstrings(include_core=core_mods, include_user=user_mods, config=config) new_modules = [] if modules_list: diff --git a/py3status/events.py b/py3status/events.py index f43e2963e4..7a00e31a3b 100644 --- a/py3status/events.py +++ b/py3status/events.py @@ -1,10 +1,9 @@ import select import sys - -from threading import Thread -from subprocess import Popen, PIPE from json import loads from shlex import quote as shell_quote +from subprocess import PIPE, Popen +from threading import Thread from py3status.profiling import profile @@ -33,10 +32,7 @@ def readline(self, timeout=500): line = self.io.readline().strip() # when using pydev.debugger sys.stdin gets overwritten and placed # into sys.stdin.original_stdin issue #2090 - if ( - self.io == getattr(sys.stdin, "original_stdin", sys.stdin) - and line == "[" - ): + if self.io == getattr(sys.stdin, "original_stdin", sys.stdin) and line == "[": # skip first event line wrt issue #19 line = self.io.readline().strip() try: @@ -61,9 +57,7 @@ def __init__(self, module_name, event, default_event, events_thread): self.event = event def run(self): - self.events_thread.process_event( - self.module_full_name, self.event, self.default_event - ) + self.events_thread.process_event(self.module_full_name, self.event, self.default_event) class EventClickTask: @@ -78,9 +72,7 @@ def __init__(self, module_name, event, events_thread, command): self.event = event def run(self): - self.events_thread.on_click_dispatcher( - self.module_name, self.event, self.command - ) + self.events_thread.on_click_dispatcher(self.module_name, self.event, self.command) class Events(Thread): @@ -229,9 +221,7 @@ def dispatch_event(self, event): if self.config["debug"]: self.py3_wrapper.log( - 'trying to dispatch event to module "{}"'.format( - f"{name} {instance}".strip() - ) + 'trying to dispatch event to module "{}"'.format(f"{name} {instance}".strip()) ) # guess the module config name diff --git a/py3status/formatter.py b/py3status/formatter.py index b266d02c3d..a732fe65d5 100644 --- a/py3status/formatter.py +++ b/py3status/formatter.py @@ -122,9 +122,7 @@ def update_placeholders(self, format_string, placeholders): for token in self.tokens(format_string): if token.group("key") in placeholders: output.append( - "{{{}{}}}".format( - placeholders[token.group("key")], token.group("format") - ) + "{{{}{}}}".format(placeholders[token.group("key")], token.group("format")) ) continue elif token.group("command"): @@ -149,9 +147,7 @@ def update_placeholders(self, format_string, placeholders): value_ = condition.value else: value_ = "" - value = "{}{}{}{}".format( - not_, variable, condition_, value_ - ) + value = "{}{}{}{}".format(not_, variable, condition_, value_) if value: items.append(f"{key}={value}") else: @@ -177,9 +173,7 @@ def update_placeholder_formats(self, format_string, placeholder_formats): and (not token.group("format")) and token.group("key") in placeholder_formats ): - output.append( - f"{{{token.group('key')}{placeholder_formats[token.group('key')]}}}" - ) + output.append(f"{{{token.group('key')}{placeholder_formats[token.group('key')]}}}") continue value = token.group(0) output.append(value) @@ -498,9 +492,7 @@ def update_commands(self, commands_str): self._if = Condition(_if) self._set_int(commands, "max_length") self._set_int(commands, "min_length") - self.color = expand_color( - commands.get("color"), passthrough=True, block=self.color - ) + self.color = expand_color(commands.get("color"), passthrough=True, block=self.color) self.not_zero = "not_zero" in commands or self.not_zero self.show = "show" in commands or self.show @@ -524,7 +516,6 @@ class representing a [block] of a format string """ def __init__(self, parent, base_block=None, py3_wrapper=None): - self.base_block = base_block self.commands = BlockConfig(parent) self.content = [] @@ -556,9 +547,7 @@ def switch(self): option and return it to the user. """ base_block = self.base_block or self - self.next_block = Block( - self.parent, base_block=base_block, py3_wrapper=self.py3_wrapper - ) + self.next_block = Block(self.parent, base_block=base_block, py3_wrapper=self.py3_wrapper) return self.next_block def __repr__(self): @@ -611,12 +600,8 @@ def render(self, get_params, module, _if=None): valid = valid or sub_valid if not valid: if self.next_block: - valid, output = self.next_block.render( - get_params, module, _if=self.commands._if - ) - elif self.parent is None and ( - (not self.next_block and enough) or self.base_block - ): + valid, output = self.next_block.render(get_params, module, _if=self.commands._if) + elif self.parent is None and ((not self.next_block and enough) or self.base_block): valid = True else: output = [] diff --git a/py3status/i3status.py b/py3status/i3status.py index dc9277b86f..af1d01e543 100644 --- a/py3status/i3status.py +++ b/py3status/i3status.py @@ -1,18 +1,13 @@ import sys import time - from copy import deepcopy -from json import loads from datetime import datetime, timezone -from subprocess import Popen -from subprocess import PIPE -from signal import SIGTSTP, SIGSTOP, SIGUSR1, SIG_IGN, signal +from json import loads +from signal import SIG_IGN, SIGSTOP, SIGTSTP, SIGUSR1, signal +from subprocess import PIPE, Popen from tempfile import NamedTemporaryFile from threading import Thread -from py3status.profiling import profile -from py3status.py3 import Py3 -from py3status.events import IOPoller from py3status.constants import ( I3S_ALLOWED_COLORS, I3S_COLOR_MODULES, @@ -20,6 +15,9 @@ TIME_MODULES, TZTIME_FORMAT, ) +from py3status.events import IOPoller +from py3status.profiling import profile +from py3status.py3 import Py3 class I3statusModule: @@ -145,9 +143,7 @@ def update_from_item(self, item): # we had an issue with an invalid time zone probably due to # suspending. re check the time zone when we next can. self.time_zone_check_due = 0 - elif self.time_zone_check_due and ( - t - self.time_zone_check_due > 5 + interval - ): + elif self.time_zone_check_due and (t - self.time_zone_check_due > 5 + interval): self.time_zone_check_due = 0 else: # Check again in 30 mins. We do this in case the timezone @@ -210,9 +206,9 @@ def set_time_zone(self, item): date = datetime.strptime(i3s_datetime, TIME_FORMAT) # calculate the time delta utcnow = datetime.utcnow() - delta = datetime( - date.year, date.month, date.day, date.hour, date.minute - ) - datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute) + delta = datetime(date.year, date.month, date.day, date.hour, date.minute) - datetime( + utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute + ) # create our custom timezone try: self.tz = timezone(delta, i3s_time_tz) @@ -250,9 +246,7 @@ def __init__(self, py3_wrapper): self.update_due = 0 # the update interval is useful to know - self.update_interval = self.py3_wrapper.get_config_attribute( - "general", "interval" - ) + self.update_interval = self.py3_wrapper.get_config_attribute("general", "interval") # do any initialization self.setup() @@ -386,9 +380,7 @@ def spawn_i3status(self): preexec_fn=lambda: signal(SIGTSTP, SIG_IGN), ) - self.py3_wrapper.log( - f"i3status spawned using config file {tmpfile.name}" - ) + self.py3_wrapper.log(f"i3status spawned using config file {tmpfile.name}") self.poller_inp = IOPoller(i3status_pipe.stdout) self.poller_err = IOPoller(i3status_pipe.stderr) diff --git a/py3status/module.py b/py3status/module.py index 5d5009ce78..b8e99479d4 100644 --- a/py3status/module.py +++ b/py3status/module.py @@ -1,6 +1,5 @@ import inspect import time - from collections import OrderedDict from importlib.machinery import SourceFileLoader from pathlib import Path @@ -9,9 +8,9 @@ from py3status.composite import Composite from py3status.constants import MARKUP_LANGUAGES, ON_ERROR_VALUES, POSITIONS -from py3status.py3 import Py3, ModuleErrorException -from py3status.profiling import profile from py3status.formatter import Formatter +from py3status.profiling import profile +from py3status.py3 import ModuleErrorException, Py3 def make_quotes(options): @@ -545,9 +544,7 @@ def process_composite(self, response): # padding if left: - response["composite"][0]["full_text"] = ( - left + response["composite"][0]["full_text"] - ) + response["composite"][0]["full_text"] = left + response["composite"][0]["full_text"] if right: response["composite"][-1]["full_text"] += right @@ -602,15 +599,12 @@ def load_methods(self, module, user_modules): # load from py3status provided modules else: self._py3_wrapper.log( - 'loading module "{}" from py3status.modules.{}'.format( - module, self.module_name - ) + 'loading module "{}" from py3status.modules.{}'.format(module, self.module_name) ) self.module_class = self.load_from_namespace(self.module_name) class_inst = self.module_class if class_inst: - try: # containers have items attribute set to a list of contained # module instance names. If there are no contained items then @@ -668,9 +662,7 @@ def deprecation_log(item): param = item.get("param") if param: msg = f"`{param}` {msg}" - msg = "DEPRECATION WARNING: {} {}".format( - self.module_full_name, msg - ) + msg = "DEPRECATION WARNING: {} {}".format(self.module_full_name, msg) self._py3_wrapper.log(msg) if "rename" in deprecated: @@ -704,9 +696,7 @@ def deprecation_log(item): format_string = mod_config.get(format_param) if not format_string: continue - format = Formatter().update_placeholders( - format_string, placeholders - ) + format = Formatter().update_placeholders(format_string, placeholders) mod_config[format_param] = format if "update_placeholder_format" in deprecated: @@ -732,10 +722,7 @@ def deprecation_log(item): substitute = item["substitute"] substitute_param = substitute["param"] substitute_value = substitute["value"] - if ( - mod_config.get(param) == value - and substitute_param not in mod_config - ): + if mod_config.get(param) == value and substitute_param not in mod_config: mod_config[substitute_param] = substitute_value deprecation_log(item) if "function" in deprecated: @@ -938,7 +925,6 @@ def run(self): cache_time = None # execute each method of this module for meth, my_method in self.methods.items(): - # always check py3status is running if not self._py3_wrapper.running: break diff --git a/py3status/module_test.py b/py3status/module_test.py index d43187b58f..57d351b753 100644 --- a/py3status/module_test.py +++ b/py3status/module_test.py @@ -1,5 +1,4 @@ import time - from ast import literal_eval from sys import argv from threading import Event @@ -60,7 +59,6 @@ def log(self, *arg, **kw): def module_test(module_class, config=None): - if not config: config = {} diff --git a/py3status/modules/air_quality.py b/py3status/modules/air_quality.py index 434996416a..8bae11f871 100644 --- a/py3status/modules/air_quality.py +++ b/py3status/modules/air_quality.py @@ -137,9 +137,7 @@ def post_config_hook(self): self.url = f"https://api.waqi.info/feed/{self.location}/" self.init_datetimes = [] for word in self.format_datetime: - if (self.py3.format_contains(self.format, word)) and ( - word in self.format_datetime - ): + if (self.py3.format_contains(self.format, word)) and (word in self.format_datetime): self.init_datetimes.append(word) if isinstance(self.thresholds, dict): @@ -173,9 +171,7 @@ def _manipulate(self, data): for k in self.init_datetimes: if k in data: data[k] = self.py3.safe_format( - datetime.strftime( - datetime.fromtimestamp(data[k]), self.format_datetime[k] - ) + datetime.strftime(datetime.fromtimestamp(data[k]), self.format_datetime[k]) ) return data diff --git a/py3status/modules/arch_updates.py b/py3status/modules/arch_updates.py index 3771bf74bd..089bdf4538 100644 --- a/py3status/modules/arch_updates.py +++ b/py3status/modules/arch_updates.py @@ -46,9 +46,7 @@ class Meta: def post_config_hook(self): helper = { "pacman": self.py3.check_commands(["checkupdates"]), - "aur": self.py3.check_commands( - ["auracle", "trizen", "yay", "paru", "pikaur"] - ), + "aur": self.py3.check_commands(["auracle", "trizen", "yay", "paru", "pikaur"]), } if self.format: placeholders = self.py3.get_placeholders_list(self.format) diff --git a/py3status/modules/async_script.py b/py3status/modules/async_script.py index d6edd425bd..63519cc3c6 100644 --- a/py3status/modules/async_script.py +++ b/py3status/modules/async_script.py @@ -36,7 +36,7 @@ import re import shlex -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen from threading import Thread @@ -74,9 +74,7 @@ def async_script(self): if self.command_color is not None: response["color"] = self.command_color - response["full_text"] = self.py3.safe_format( - self.format, {"output": self.command_output} - ) + response["full_text"] = self.py3.safe_format(self.format, {"output": self.command_output}) return response def _command_start(self): diff --git a/py3status/modules/audiosink.py b/py3status/modules/audiosink.py index 5277069b2b..e61cad615b 100644 --- a/py3status/modules/audiosink.py +++ b/py3status/modules/audiosink.py @@ -76,7 +76,7 @@ def _get_state(self): # filter for not ignored (or active) devices state = list( filter( - lambda d: (not d["name"] in self.sinks_to_ignore) or d["is_active"], + lambda d: (d["name"] not in self.sinks_to_ignore) or d["is_active"], state, ) ) diff --git a/py3status/modules/aws_bill.py b/py3status/modules/aws_bill.py index 7d21c5a398..31a8d096a9 100644 --- a/py3status/modules/aws_bill.py +++ b/py3status/modules/aws_bill.py @@ -35,12 +35,11 @@ {'full_text': u'108.78$'} """ -import boto import csv import datetime - from pathlib import Path +import boto from boto.s3.connection import Key @@ -119,9 +118,7 @@ def aws_bill(self): elif bill_amount == "conn_error": response["full_text"] = "Check your internet access" elif bill_amount is not False: - response["full_text"] = self.py3.safe_format( - self.format, {"bill_amount": bill_amount} - ) + response["full_text"] = self.py3.safe_format(self.format, {"bill_amount": bill_amount}) response["color"] = self.py3.COLOR_GOOD else: response["full_text"] = "Global error - WTF exception" diff --git a/py3status/modules/backlight.py b/py3status/modules/backlight.py index 3cc91e5695..165f46548c 100644 --- a/py3status/modules/backlight.py +++ b/py3status/modules/backlight.py @@ -117,9 +117,7 @@ def post_config_hook(self): else: raise Exception(STRING_NOT_AVAILABLE) - self.format = self.py3.update_placeholder_formats( - self.format, {"level": ":.0f"} - ) + self.format = self.py3.update_placeholder_formats(self.format, {"level": ":.0f"}) # check for an error code and an output self.command_available = False try: diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py index 19c84d7d96..da694be2e5 100644 --- a/py3status/modules/battery_level.py +++ b/py3status/modules/battery_level.py @@ -92,13 +92,10 @@ {'color': '#FF0000', 'full_text': u'\u2340'} """ -from re import findall - import itertools import math - from pathlib import Path - +from re import findall BLOCKS = "_▁▂▃▄▅▆▇█" CHARGING_CHARACTER = "⚡" @@ -254,21 +251,16 @@ def _extract_battery_info_from_acpi(self): def _parse_battery_info(acpi_battery_lines): battery = {} - battery["percent_charged"] = int( - findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0] - ) + battery["percent_charged"] = int(findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]) battery["charging"] = "Charging" in acpi_battery_lines[0] - battery["capacity"] = int( - findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1] - ) + battery["capacity"] = int(findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]) # ACPI only shows time remaining if battery is discharging or # charging try: battery["time_remaining"] = "".join( findall( - r"(?<=, )(\d+:\d+:\d+)(?= remaining)|" - r"(?<=, )(\d+:\d+:\d+)(?= until)", + r"(?<=, )(\d+:\d+:\d+)(?= remaining)|" r"(?<=, )(\d+:\d+:\d+)(?= until)", acpi_battery_lines[0], )[0] ) @@ -327,9 +319,7 @@ def _parse_battery_info(sys_path): battery_list = [] bglobs = ["BAT*", "*bat*"] - path_its = itertools.chain( - *[Path(self.sys_battery_path).glob(bglob) for bglob in bglobs] - ) + path_its = itertools.chain(*[Path(self.sys_battery_path).glob(bglob) for bglob in bglobs]) for path in path_its: r = _parse_battery_info(path) @@ -337,19 +327,13 @@ def _parse_battery_info(sys_path): if not r: continue - capacity = r.get( - "POWER_SUPPLY_ENERGY_FULL", r.get("POWER_SUPPLY_CHARGE_FULL") - ) + capacity = r.get("POWER_SUPPLY_ENERGY_FULL", r.get("POWER_SUPPLY_CHARGE_FULL")) present_rate = r.get( "POWER_SUPPLY_POWER_NOW", r.get("POWER_SUPPLY_CURRENT_NOW", r.get("POWER_SUPPLY_VOLTAGE_NOW")), ) - remaining_energy = r.get( - "POWER_SUPPLY_ENERGY_NOW", r.get("POWER_SUPPLY_CHARGE_NOW") - ) - current_now = r.get( - "POWER_SUPPLY_CURRENT_NOW", r.get("POWER_SUPPLY_POWER_NOW", 0) - ) + remaining_energy = r.get("POWER_SUPPLY_ENERGY_NOW", r.get("POWER_SUPPLY_CHARGE_NOW")) + current_now = r.get("POWER_SUPPLY_CURRENT_NOW", r.get("POWER_SUPPLY_POWER_NOW", 0)) voltage_now = r.get("POWER_SUPPLY_VOLTAGE_NOW", 0) # missing values may indicate this is not a battery and should be skipped @@ -417,10 +401,7 @@ def _refresh_battery_info(self, battery_list): active_battery = None inactive_battery = battery_list[:] for battery_id, battery in enumerate(battery_list): - if ( - battery["time_remaining"] - and battery["time_remaining"] != FULLY_CHARGED - ): + if battery["time_remaining"] and battery["time_remaining"] != FULLY_CHARGED: active_battery = battery del inactive_battery[battery_id] @@ -432,13 +413,10 @@ def _refresh_battery_info(self, battery_list): if active_battery and inactive_battery: inactive_battery = inactive_battery[0] - time_remaining_seconds = self._hms_to_seconds( - active_battery["time_remaining"] - ) + time_remaining_seconds = self._hms_to_seconds(active_battery["time_remaining"]) try: rate_second_per_mah = time_remaining_seconds / ( - active_battery["capacity"] - * (active_battery["percent_charged"] / 100) + active_battery["capacity"] * (active_battery["percent_charged"] / 100) ) time_remaining_seconds += ( inactive_battery["capacity"] @@ -469,9 +447,7 @@ def _update_ascii_bar(self): if self.charging: self.ascii_bar += EMPTY_BLOCK_CHARGING * (10 - self.percent_charged // 10) else: - self.ascii_bar += EMPTY_BLOCK_DISCHARGING * ( - 10 - self.percent_charged // 10 - ) + self.ascii_bar += EMPTY_BLOCK_DISCHARGING * (10 - self.percent_charged // 10) def _update_status(self): if self.charging: @@ -550,11 +526,7 @@ def _set_bar_color(self): else: battery_status = "good" - if ( - notify_msg - and self.notify_low_level - and self.last_known_status != battery_status - ): + if notify_msg and self.notify_low_level and self.last_known_status != battery_status: self.py3.notify_user( notify_msg["msg"].format(self.percent_charged), notify_msg["level"] ) diff --git a/py3status/modules/bluetooth.py b/py3status/modules/bluetooth.py index 6d3711d8e7..9fd763b2fb 100644 --- a/py3status/modules/bluetooth.py +++ b/py3status/modules/bluetooth.py @@ -118,9 +118,7 @@ def post_config_hook(self): self.thresholds_init = {} for name in ["format", "format_adapter", "format_device"]: - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _get_bluez_data(self): objects = self.bluez_manager.GetManagedObjects() @@ -139,9 +137,7 @@ def _get_bluez_data(self): for device in temporary.pop("devices", []): for index, adapter in enumerate(temporary["adapters"]): if device["adapter"] == adapter["path"]: - temporary["adapters"][index].setdefault("devices", []).append( - device - ) + temporary["adapters"][index].setdefault("devices", []).append(device) break return temporary diff --git a/py3status/modules/clock.py b/py3status/modules/clock.py index a2369f4e21..2dbc526434 100644 --- a/py3status/modules/clock.py +++ b/py3status/modules/clock.py @@ -222,7 +222,6 @@ def on_click(self, event): self._change_active(1) def clock(self): - # cycling if self.cycle and time.time() >= self._cycle_time: self._change_active(1) diff --git a/py3status/modules/coin_balance.py b/py3status/modules/coin_balance.py index 67253b849e..a294205fda 100644 --- a/py3status/modules/coin_balance.py +++ b/py3status/modules/coin_balance.py @@ -99,10 +99,10 @@ """ from errno import ENOENT -import requests -from string import Formatter from pathlib import Path +from string import Formatter +import requests COIN_PORTS = {"bitcoin": 8332, "dogecoin": 22555, "litecoin": 9332} diff --git a/py3status/modules/coin_market.py b/py3status/modules/coin_market.py index 7363fe18f0..98546c615a 100644 --- a/py3status/modules/coin_market.py +++ b/py3status/modules/coin_market.py @@ -115,7 +115,9 @@ class Py3status: api_key = None cache_timeout = 600 format = "{format_coin}" - format_coin = r"{name} ${usd_price:.2f} [\?color=usd_percent_change_24h {usd_percent_change_24h:.1f}%]" + format_coin = ( + r"{name} ${usd_price:.2f} [\?color=usd_percent_change_24h {usd_percent_change_24h:.1f}%]" + ) format_coin_separator = " " markets = ["btc", "eth"] thresholds = [(-100, "bad"), (0, "good")] @@ -180,9 +182,7 @@ def coin_market(self): return { "cached_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - self.format, {"format_coin": format_coin} - ), + "full_text": self.py3.safe_format(self.format, {"format_coin": format_coin}), } diff --git a/py3status/modules/conky.py b/py3status/modules/conky.py index e8beca8227..92cce4ac26 100644 --- a/py3status/modules/conky.py +++ b/py3status/modules/conky.py @@ -322,11 +322,11 @@ ] """ -from subprocess import Popen, PIPE, STDOUT -from threading import Thread -from tempfile import NamedTemporaryFile from json import dumps from pathlib import Path +from subprocess import PIPE, STDOUT, Popen +from tempfile import NamedTemporaryFile +from threading import Thread STRING_NOT_INSTALLED = "not installed" STRING_MISSING_FORMAT = "missing format" @@ -369,9 +369,7 @@ def post_config_hook(self): tmp = f"conky.config = {config}\nconky.text = [[{text}]]" # write tmp output to '/tmp/py3status-conky_*', make a command - self.tmpfile = NamedTemporaryFile( - prefix="py3status_conky-", suffix=".conf", delete=False - ) + self.tmpfile = NamedTemporaryFile(prefix="py3status_conky-", suffix=".conf", delete=False) self.tmpfile.write(str.encode(tmp)) self.tmpfile.close() self.conky_command = f"conky -c {self.tmpfile.name}".split() diff --git a/py3status/modules/deadbeef.py b/py3status/modules/deadbeef.py index 796a063900..e20ddb9d17 100644 --- a/py3status/modules/deadbeef.py +++ b/py3status/modules/deadbeef.py @@ -82,9 +82,7 @@ def post_config_hook(self): raise Exception(STRING_NOT_INSTALLED) self.separator = "|SEPARATOR|" - self.placeholders = list( - set(self.py3.get_placeholders_list(self.format) + ["isplaying"]) - ) + self.placeholders = list(set(self.py3.get_placeholders_list(self.format) + ["isplaying"])) self.deadbeef_command = 'deadbeef --nowplaying-tf "{}"'.format( self.separator.join(f"%{x}%" for x in self.placeholders) ) diff --git a/py3status/modules/diskdata.py b/py3status/modules/diskdata.py index 451951dea2..89fd8f3ff3 100644 --- a/py3status/modules/diskdata.py +++ b/py3status/modules/diskdata.py @@ -172,9 +172,7 @@ def diskdata(self): threshold_data.update(data) for x in self.init["df"]["placeholders"]: - disk_data[x] = self.py3.safe_format( - self.format_space, {"value": data[x]} - ) + disk_data[x] = self.py3.safe_format(self.format_space, {"value": data[x]}) if self.init["diskstats"]: diskstats = self._calc_diskstats(self._get_diskstats(self.disk)) @@ -182,9 +180,7 @@ def diskdata(self): threshold_data.update(data) for x in self.init["diskstats"]["placeholders"]: - value, unit = self.py3.format_units( - data[x], unit=self.unit, si=self.si_units - ) + value, unit = self.py3.format_units(data[x], unit=self.unit, si=self.si_units) disk_data[x] = self.py3.safe_format( self.format_rate, {"value": value, "unit": unit} ) diff --git a/py3status/modules/do_not_disturb.py b/py3status/modules/do_not_disturb.py index d5cd82854d..cd600782a1 100644 --- a/py3status/modules/do_not_disturb.py +++ b/py3status/modules/do_not_disturb.py @@ -109,9 +109,7 @@ def get_state(self): def toggle(self, state): if self.has_dunstctl: - self.parent.py3.command_run( - "dunstctl set-paused {}".format(str(state).lower()) - ) + self.parent.py3.command_run("dunstctl set-paused {}".format(str(state).lower())) elif state: # pause self.parent.py3.command_run("pkill -SIGUSR1 dunst") diff --git a/py3status/modules/dropboxd_status.py b/py3status/modules/dropboxd_status.py index a24added2f..5542e7bb41 100644 --- a/py3status/modules/dropboxd_status.py +++ b/py3status/modules/dropboxd_status.py @@ -82,9 +82,7 @@ def post_config_hook(self): raise Exception(STRING_NOT_INSTALLED) def dropboxd_status(self): - status = self.py3.command_output( - "dropbox-cli status", localized=True - ).splitlines()[0] + status = self.py3.command_output("dropbox-cli status", localized=True).splitlines()[0] if status == "Dropbox isn't running!": color = self.py3.COLOR_BAD diff --git a/py3status/modules/emerge_status.py b/py3status/modules/emerge_status.py index 9ace6f56c3..68e9a8d655 100644 --- a/py3status/modules/emerge_status.py +++ b/py3status/modules/emerge_status.py @@ -47,8 +47,8 @@ {'full_text': 'emrg : 0/0'} """ -import re import copy +import re STRING_NOT_INSTALLED = "not installed" diff --git a/py3status/modules/fedora_updates.py b/py3status/modules/fedora_updates.py index 5c8dc3a4ec..2893fb82c3 100644 --- a/py3status/modules/fedora_updates.py +++ b/py3status/modules/fedora_updates.py @@ -27,8 +27,8 @@ {'color': '#FFFF00', 'full_text': 'DNF: 14'} """ -import subprocess import re +import subprocess class Py3status: @@ -69,11 +69,7 @@ def fedora_updates(self): if self._updates > updates: # we have installed some updates so re-check security self._security_notice = False - if ( - self.check_security - and not self._security_notice - and self._updates != updates - ): + if self.check_security and not self._security_notice and self._updates != updates: output, error = subprocess.Popen( ["dnf", "updateinfo"], stdout=subprocess.PIPE, diff --git a/py3status/modules/file_status.py b/py3status/modules/file_status.py index f8a2852dd0..31ade9497b 100644 --- a/py3status/modules/file_status.py +++ b/py3status/modules/file_status.py @@ -54,7 +54,6 @@ from pathlib import Path - STRING_NO_PATHS = "missing paths" @@ -116,9 +115,7 @@ def post_config_hook(self): def file_status(self): # init data - paths = sorted( - files for path in self.paths for files in path.parent.glob(path.name) - ) + paths = sorted(files for path in self.paths for files in path.parent.glob(path.name)) count_path = len(paths) format_path = None diff --git a/py3status/modules/frame.py b/py3status/modules/frame.py index 303d933220..cf30d72544 100644 --- a/py3status/modules/frame.py +++ b/py3status/modules/frame.py @@ -111,7 +111,6 @@ def _urgent_function(self, module_list): self.urgent = True def frame(self): - if not self.items: return {"full_text": "", "cached_until": self.py3.CACHE_FOREVER} diff --git a/py3status/modules/github.py b/py3status/modules/github.py index c2879ffa3f..83bdcbfd5f 100644 --- a/py3status/modules/github.py +++ b/py3status/modules/github.py @@ -149,8 +149,7 @@ def _notifications(self): if not self.username or not self.auth_token: if not self.notification_warning: self.py3.notify_user( - "Github module needs username and " - "auth_token to check notifications." + "Github module needs username and " "auth_token to check notifications." ) self.notification_warning = True return "?" @@ -179,9 +178,7 @@ def _notifications(self): if last_page == 1: return len(info.json()) try: - last_page_info = self.py3.request( - last_url, auth=(self.username, self.auth_token) - ) + last_page_info = self.py3.request(last_url, auth=(self.username, self.auth_token)) except self.py3.RequestException: return diff --git a/py3status/modules/gitlab.py b/py3status/modules/gitlab.py index 726e1a6422..d48ee0b853 100644 --- a/py3status/modules/gitlab.py +++ b/py3status/modules/gitlab.py @@ -72,9 +72,7 @@ class Py3status: button_open = 1 button_refresh = 2 cache_timeout = 900 - format = ( - r"[{name} ][[{open_issues_count}][\?soft /]" "[{open_merge_requests_count}]]" - ) + format = r"[{name} ][[{open_issues_count}][\?soft /]" "[{open_merge_requests_count}]]" project = "gitlab-org/gitlab-ce" thresholds = [] diff --git a/py3status/modules/google_calendar.py b/py3status/modules/google_calendar.py index 9872598e71..ef3a834c92 100644 --- a/py3status/modules/google_calendar.py +++ b/py3status/modules/google_calendar.py @@ -152,22 +152,22 @@ ] """ -import httplib2 import datetime import time from pathlib import Path +import httplib2 + try: from googleapiclient import discovery except ImportError: from apiclient import discovery -from oauth2client import client -from oauth2client import clientsecrets -from oauth2client import tools -from oauth2client.file import Storage -from httplib2 import ServerNotFoundError + from dateutil import parser from dateutil.tz import tzlocal +from httplib2 import ServerNotFoundError +from oauth2client import client, clientsecrets, tools +from oauth2client.file import Storage SCOPES = "https://www.googleapis.com/auth/calendar.readonly" APPLICATION_NAME = "py3status google_calendar module" @@ -325,9 +325,7 @@ def _get_events(self): # filter out blacklisted event names if event["summary"] is not None: - if event["summary"].lower() in ( - e.lower() for e in self.blacklist_events - ): + if event["summary"].lower() in (e.lower() for e in self.blacklist_events): continue events.append(event) @@ -416,9 +414,7 @@ def _build_response(self): event_dict["summary"] = event.get("summary") event_dict["location"] = event.get("location") event_dict["description"] = event.get("description") - self.event_urls.append( - event.get(self.preferred_event_link, event.get("htmlLink")) - ) + self.event_urls.append(event.get(self.preferred_event_link, event.get("htmlLink"))) if event["start"].get("date") is not None: start_dt = self._gstr_to_date(event["start"].get("date")) @@ -443,9 +439,7 @@ def _build_response(self): else: is_current = False - event_dict["format_timer"] = self._format_timedelta( - index, time_delta, is_current - ) + event_dict["format_timer"] = self._format_timedelta(index, time_delta, is_current) if self.warn_threshold > 0: self._check_warn_threshold(time_delta, event_dict) diff --git a/py3status/modules/graphite.py b/py3status/modules/graphite.py index 16d8daacdd..0a721b4222 100644 --- a/py3status/modules/graphite.py +++ b/py3status/modules/graphite.py @@ -69,8 +69,9 @@ SAMPLE OUTPUT {'full_text': '412 req/s'} """ +from syslog import LOG_INFO, syslog + from requests import get -from syslog import syslog, LOG_INFO def format_value(num, value_round=True): @@ -172,9 +173,7 @@ def _render_graphite_json(self): # compare this value to the configured thresholds # and use the worst color to display - _color = self._check_threshold_and_get_color( - displayed_value, target, value - ) + _color = self._check_threshold_and_get_color(displayed_value, target, value) if _color == "bad": color_key = "bad" elif _color == "degraded" and color_key != "bad": @@ -196,9 +195,7 @@ def _store_notification(self, target, threshold, value): def _notify_user(self): if self.notifications: - self.py3.notify_user( - "\n".join(self.notifications), level=self.notification_level - ) + self.py3.notify_user("\n".join(self.notifications), level=self.notification_level) def _check_threshold_and_get_color(self, displayed_value, target, value): func = {"max": max, "min": min} @@ -211,9 +208,7 @@ def _check_threshold_and_get_color(self, displayed_value, target, value): if self.threshold_degraded: test = func[self.value_comparator](self.threshold_degraded, value) if test == value: - self._store_notification( - target, self.threshold_degraded, displayed_value - ) + self._store_notification(target, self.threshold_degraded, displayed_value) return "degraded" return "good" diff --git a/py3status/modules/hddtemp.py b/py3status/modules/hddtemp.py index ab76f45e35..1d5fd9d280 100644 --- a/py3status/modules/hddtemp.py +++ b/py3status/modules/hddtemp.py @@ -107,8 +107,8 @@ ] """ -from telnetlib import Telnet from string import printable +from telnetlib import Telnet class Py3status: diff --git a/py3status/modules/i3block.py b/py3status/modules/i3block.py index 7d96308c0b..6c4d76d328 100644 --- a/py3status/modules/i3block.py +++ b/py3status/modules/i3block.py @@ -81,9 +81,8 @@ import fcntl import os import re - from os import environ -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen from threading import Thread RESPONSE_FIELDS = [ @@ -254,9 +253,7 @@ def _run_command(self, env): if hash(msg) not in self.errors: self.py3.log(msg, level=self.py3.LOG_ERROR) self.errors.append(hash(msg)) - _output = "Error\nError\n{}".format( - self.py3.COLOR_ERROR or self.py3.COLOR_BAD - ) + _output = "Error\nError\n{}".format(self.py3.COLOR_ERROR or self.py3.COLOR_BAD) # we have got output so update the received output # this provides support for i3blocks pseudo click support if _output: @@ -318,9 +315,7 @@ def i3block(self): # blocklet label gets prepended if self.label: - block_response["full_text"] = "{}{}".format( - self.label, block_response["full_text"] - ) + block_response["full_text"] = "{}{}".format(self.label, block_response["full_text"]) if "short_text" in block_response: block_response["short_text"] = "{}{}".format( self.label, block_response["short_text"] diff --git a/py3status/modules/i3pystatus.py b/py3status/modules/i3pystatus.py index 7346cb34b3..b528ec60ff 100644 --- a/py3status/modules/i3pystatus.py +++ b/py3status/modules/i3pystatus.py @@ -254,8 +254,7 @@ def post_config_hook(self): except i3pystatus.core.exceptions.ConfigMissingError as e: msg = e.message msg = ( - "i3pystatus module `{}` backend `{}`" - "missing configuration options {}" + "i3pystatus module `{}` backend `{}`" "missing configuration options {}" ).format(self.module, key, msg[msg.index("{") :]) self.py3.notify_user(msg) raise Exception("Missing configuration options") diff --git a/py3status/modules/imap.py b/py3status/modules/imap.py index 072b34c5b4..aac3616267 100644 --- a/py3status/modules/imap.py +++ b/py3status/modules/imap.py @@ -62,11 +62,12 @@ {'full_text': 'Mail: 36', 'color': '#00FF00'} """ import imaplib +from pathlib import Path +from socket import error as socket_error +from socket import setdefaulttimeout +from ssl import create_default_context from threading import Thread from time import sleep -from ssl import create_default_context -from socket import setdefaulttimeout, error as socket_error -from pathlib import Path STRING_UNAVAILABLE = "N/A" NO_DATA_YET = -1 @@ -117,9 +118,7 @@ def post_config_hook(self): self.connection = None self.mail_error = None # cannot throw self.py3.error from thread self.network_error = None - self.command_tag = ( - 0 # IMAPcommands are tagged, so responses can be matched up to requests - ) + self.command_tag = 0 # IMAPcommands are tagged, so responses can be matched up to requests self.idle_thread = Thread() if self.client_secret: @@ -133,9 +132,7 @@ def imap(self): # I -- acquire mail_count if self.use_idle is not False: if not self.idle_thread.is_alive(): - sleep( - self.read_timeout - ) # rate-limit thread-restarting (when network is offline) + sleep(self.read_timeout) # rate-limit thread-restarting (when network is offline) self.idle_thread = Thread(target=self._get_mail_count) self.idle_thread.daemon = True self.idle_thread.start() @@ -148,9 +145,7 @@ def imap(self): self.mail_error = None # II -- format response - response["full_text"] = self.py3.safe_format( - self.format, {"unseen": self.mail_count} - ) + response["full_text"] = self.py3.safe_format(self.format, {"unseen": self.mail_count}) if self.mail_count is None: response["color"] = (self.py3.COLOR_BAD,) @@ -178,11 +173,12 @@ def _check_if_idle(self, connection): self.py3.error("Server does not support IDLE") def _get_creds(self): - from google_auth_oauthlib.flow import InstalledAppFlow - from google.auth.transport.requests import Request - from google.auth.exceptions import TransportError import pickle + from google.auth.exceptions import TransportError + from google.auth.transport.requests import Request + from google_auth_oauthlib.flow import InstalledAppFlow + self.creds = None # Open pickle file with access and refresh tokens if it exists @@ -300,9 +296,7 @@ def _idle(self): try: response = socket.read(4096).decode("ascii") except socket_error: - raise imaplib.IMAP4.abort( - "Server sent more continuations, but no 'DONE' ack" - ) + raise imaplib.IMAP4.abort("Server sent more continuations, but no 'DONE' ack") expected_response = (command_tag + b" OK").decode("ascii") if not response.lower().startswith(expected_response.lower()): @@ -379,9 +373,7 @@ def _get_mail_count(self): if retry_counter <= retry_max: if self.debug: self.py3.log( - "Will retry after 60 seconds ({}/{})".format( - retry_counter, retry_max - ), + "Will retry after 60 seconds ({}/{})".format(retry_counter, retry_max), level=self.py3.LOG_INFO, ) sleep(60) diff --git a/py3status/modules/insync.py b/py3status/modules/insync.py index 0fed1a64d6..307a1c8283 100644 --- a/py3status/modules/insync.py +++ b/py3status/modules/insync.py @@ -61,9 +61,7 @@ def post_config_hook(self): def insync(self): # sync progress try: - queued = self.py3.command_output( - ["insync", "get_sync_progress"] - ).splitlines() + queued = self.py3.command_output(["insync", "get_sync_progress"]).splitlines() except Exception: return { "cached_until": self.py3.time_in(self.cache_timeout), @@ -107,9 +105,7 @@ def insync(self): return { "color": color, "cached_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - format, {"status": status, "queued": queued} - ), + "full_text": self.py3.safe_format(format, {"status": status, "queued": queued}), } diff --git a/py3status/modules/kdeconnector.py b/py3status/modules/kdeconnector.py index ecfd99b6bd..71d1fc9e24 100644 --- a/py3status/modules/kdeconnector.py +++ b/py3status/modules/kdeconnector.py @@ -214,15 +214,11 @@ def _reachable_on_change( self._update_conn_info() self.py3.update() - def _battery_on_change( - self, connection, owner, object_path, interface_name, event, new_value - ): + def _battery_on_change(self, connection, owner, object_path, interface_name, event, new_value): if self._is_current_device(object_path): if event == "refreshed": if new_value[1] != -1: - self._set_battery_status( - isCharging=new_value[0], charge=new_value[1] - ) + self._set_battery_status(isCharging=new_value[0], charge=new_value[1]) elif event == "stateChanged": self._set_battery_status(isCharging=new_value[0], charge=None) elif event == "chargeChanged": @@ -240,9 +236,7 @@ def _conn_report_on_change( self._result["net_type"] != new_value[0] or self._result["net_strength_raw"] != new_value[1] ): - self._set_conn_status( - net_type=new_value[0], net_strength=new_value[1] - ) + self._set_conn_status(net_type=new_value[0], net_strength=new_value[1]) self.py3.update() else: self._update_conn_info() @@ -447,9 +441,7 @@ def _set_notifications_status(self, activeNotifications): Get the notifications status """ size = len(activeNotifications) - self._result["notif_status"] = ( - self.status_notif if size > 0 else self.status_no_notif - ) + self._result["notif_status"] = self.status_notif if size > 0 else self.status_no_notif self._result["notif_size"] = size def _set_conn_status(self, net_type, net_strength): @@ -457,9 +449,7 @@ def _set_conn_status(self, net_type, net_strength): Get the conn status """ self._result["net_strength_raw"] = net_strength - self._result["net_strength"] = ( - net_strength * 25 if net_strength > -1 else UNKNOWN_SYMBOL - ) + self._result["net_strength"] = net_strength * 25 if net_strength > -1 else UNKNOWN_SYMBOL self._result["net_type"] = net_type def _get_text(self): @@ -472,9 +462,7 @@ def _get_text(self): if not device["isReachable"] or not device["isTrusted"]: return ( - self.py3.safe_format( - self.format_disconnected, {"name": device["name"]} - ), + self.py3.safe_format(self.format_disconnected, {"name": device["name"]}), self.py3.COLOR_BAD, ) @@ -498,9 +486,7 @@ def _update_notif_info(self): def _update_battery_info(self): battery = self._get_battery() - self._set_battery_status( - isCharging=battery["isCharging"], charge=battery["charge"] - ) + self._set_battery_status(isCharging=battery["isCharging"], charge=battery["charge"]) def kill(self): self._kill = True diff --git a/py3status/modules/keyboard_layout.py b/py3status/modules/keyboard_layout.py index 865a1b8df0..ae1ccce45e 100644 --- a/py3status/modules/keyboard_layout.py +++ b/py3status/modules/keyboard_layout.py @@ -105,9 +105,7 @@ def keyboard_layout(self): response = { "cached_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - self.format, {"layout": lang, "variant": variant} - ), + "full_text": self.py3.safe_format(self.format, {"layout": lang, "variant": variant}), } if self.colors and not self.colors_dict: @@ -135,9 +133,9 @@ def keyboard_layout(self): def _get_xkblayout(self): layout, variant = [ x.strip() - for x in self.py3.command_output( - ["xkblayout-state", "print", "%s|SEPARATOR|%v"] - ).split("|SEPARATOR|") + for x in self.py3.command_output(["xkblayout-state", "print", "%s|SEPARATOR|%v"]).split( + "|SEPARATOR|" + ) ] return layout, variant @@ -165,9 +163,7 @@ def _set_setxkbmap(self): def _set_xkblayout(self): layout = self._layouts[self._active] layout_pos = ( - self.py3.command_output(["xkblayout-state", "print", "%E"]) - .split() - .index(layout) + self.py3.command_output(["xkblayout-state", "print", "%E"]).split().index(layout) ) self.py3.command_run(f"xkblayout-state set {layout_pos}") diff --git a/py3status/modules/khal_calendar.py b/py3status/modules/khal_calendar.py index 4b6b8851f5..be959bfea6 100644 --- a/py3status/modules/khal_calendar.py +++ b/py3status/modules/khal_calendar.py @@ -24,9 +24,10 @@ """ from datetime import datetime from re import compile as re_compile -from khal.settings import get_config + from khal.cli import build_collection from khal.controllers import khal_list +from khal.settings import get_config class Py3status: @@ -51,9 +52,7 @@ def _init_config(self): def khal_calendar(self): self._init_config() - daterange = ( - str(datetime.now().strftime(self.datetimeformat)) + " " + self.date_end - ) + daterange = str(datetime.now().strftime(self.datetimeformat)) + " " + self.date_end output = khal_list(self.collection, daterange, self.config, self.output_format) output = [self._format_output(x) for x in output[1:]][: self.max_results] diff --git a/py3status/modules/lm_sensors.py b/py3status/modules/lm_sensors.py index 473149b575..ebfa6b9b58 100644 --- a/py3status/modules/lm_sensors.py +++ b/py3status/modules/lm_sensors.py @@ -188,9 +188,7 @@ def post_config_hook(self): placeholders = self.py3.get_placeholders_list(self.format_sensor) format_sensor = {x: ":g" for x in placeholders if x != "name"} self.sensor_placeholders = [x for x in placeholders if x != "name"] - self.format_sensor = self.py3.update_placeholder_formats( - self.format_sensor, format_sensor - ) + self.format_sensor = self.py3.update_placeholder_formats(self.format_sensor, format_sensor) self.first_run = True @@ -298,9 +296,7 @@ def lm_sensors(self): auto_input.append((_crit, self.color_crit)) key = "{}/{}".format(chip["name"], sensor["name"]) - self.py3.threshold_get_color( - _input, ("auto.input", key, auto_input) - ) + self.py3.threshold_get_color(_input, ("auto.input", key, auto_input)) for x in self.sensor_placeholders: if x not in sensor: @@ -322,9 +318,7 @@ def lm_sensors(self): return { "cached_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - self.format, {"format_chip": format_chip} - ), + "full_text": self.py3.safe_format(self.format, {"format_chip": format_chip}), } diff --git a/py3status/modules/loadavg.py b/py3status/modules/loadavg.py index 24d1d3dd2c..1305bb958e 100644 --- a/py3status/modules/loadavg.py +++ b/py3status/modules/loadavg.py @@ -198,8 +198,8 @@ ] """ -from os import getloadavg from multiprocessing import cpu_count +from os import getloadavg class Py3status: @@ -207,10 +207,7 @@ class Py3status: # available configuration parameters cache_timeout = 5 - format = ( - r"Loadavg [\?color=1avg {1min}] " - r"[\?color=5avg {5min}] [\?color=15avg {15min}]" - ) + format = r"Loadavg [\?color=1avg {1min}] " r"[\?color=5avg {5min}] [\?color=15avg {15min}]" thresholds = [ (0, "#9dd7fb"), (20, "good"), diff --git a/py3status/modules/mail.py b/py3status/modules/mail.py index 7b4cd8ad80..995b0f8060 100644 --- a/py3status/modules/mail.py +++ b/py3status/modules/mail.py @@ -158,7 +158,7 @@ import mailbox import os from csv import reader -from imaplib import IMAP4_SSL, IMAP4 +from imaplib import IMAP4, IMAP4_SSL from pathlib import Path STRING_MISSING = "missing {} {}" @@ -215,9 +215,7 @@ def post_config_hook(self): if mail == box.lower(): if "path" not in account: raise Exception(STRING_MISSING.format(mail, "path")) - path = Path( - os.path.expandvars(account["path"]) - ).expanduser() + path = Path(os.path.expandvars(account["path"])).expanduser() if not path.exists(): path = f"path: {path}" raise Exception(STRING_MISSING.format(mail, path)) @@ -279,9 +277,7 @@ def mail(self): except IMAP4.error: pass else: - inbox = getattr(mailbox, account["box"])( - account["path"], create=False - ) + inbox = getattr(mailbox, account["box"])(account["path"], create=False) count_mail = len(inbox) inbox.close() if "name" in account: diff --git a/py3status/modules/mega_sync.py b/py3status/modules/mega_sync.py index 56aa525fde..7243d7d8e3 100644 --- a/py3status/modules/mega_sync.py +++ b/py3status/modules/mega_sync.py @@ -56,9 +56,7 @@ def mega_sync(self): return { "cached_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - self.format, {"format_sync": format_sync} - ), + "full_text": self.py3.safe_format(self.format, {"format_sync": format_sync}), } diff --git a/py3status/modules/moc.py b/py3status/modules/moc.py index a80438c976..2dc829130a 100644 --- a/py3status/modules/moc.py +++ b/py3status/modules/moc.py @@ -144,7 +144,7 @@ def moc(self): is_playing=is_playing, is_started=is_started, is_stopped=is_stopped, - **data + **data, ), ), } diff --git a/py3status/modules/mpd_status.py b/py3status/modules/mpd_status.py index 2b5b37bd6d..fbf73f8bb0 100644 --- a/py3status/modules/mpd_status.py +++ b/py3status/modules/mpd_status.py @@ -68,11 +68,13 @@ import datetime import re import socket -from py3status.composite import Composite -from mpd import MPDClient, CommandError, ConnectionError from threading import Thread from time import sleep +from mpd import CommandError, ConnectionError, MPDClient + +from py3status.composite import Composite + def song_attr(song, attr): def parse_mtime(date_str): diff --git a/py3status/modules/mpris.py b/py3status/modules/mpris.py index f3264a5985..2061b97fdc 100644 --- a/py3status/modules/mpris.py +++ b/py3status/modules/mpris.py @@ -101,17 +101,20 @@ {'color': '#00FF00', 'full_text': u'Happy Mondays - Fat Lady Wrestlers'} ] """ +import re +import sys from datetime import timedelta +from enum import IntEnum +from threading import Thread + +from dbus import DBusException, SessionBus from dbus.mainloop.glib import DBusGMainLoop from gi.repository import GLib -from threading import Thread -import re -import sys -from dbus import SessionBus, DBusException -from mpris2 import Player as dPlayer, MediaPlayer2 as dMediaPlayer2 -from mpris2 import get_players_uri, Interfaces +from mpris2 import Interfaces +from mpris2 import MediaPlayer2 as dMediaPlayer2 +from mpris2 import Player as dPlayer +from mpris2 import get_players_uri from mpris2.types import Metadata_Map -from enum import IntEnum class STATE(IntEnum): @@ -146,9 +149,7 @@ def __init__( self._player_shortname = name_from_id self._dPlayer = dPlayer(dbus_interface_info={"dbus_uri": player_id}) self._full_name = f"{self._identity} {self._identity_index}" - self._hide_non_canplay = ( - self._player_shortname in self.parent.player_hide_non_canplay - ) + self._hide_non_canplay = self._player_shortname in self.parent.player_hide_non_canplay self._placeholders = { "player": self._identity, @@ -205,9 +206,9 @@ def _set_response_buttons(self): } if buttons.get("toggle"): - buttons["toggle"]["full_text"] = self.parent._state_icon_color_map[ - self.state - ]["toggle_icon"] + buttons["toggle"]["full_text"] = self.parent._state_icon_color_map[self.state][ + "toggle_icon" + ] self._buttons = buttons @@ -276,9 +277,7 @@ def metadata(self, metadata=None): if artist: self._metadata["artist"] = artist[0] - self._metadata["length"] = self._get_time_str( - metadata.get(Metadata_Map.LENGTH) - ) + self._metadata["length"] = self._get_time_str(metadata.get(Metadata_Map.LENGTH)) self._metadata["nowplaying"] = metadata.get("vlc:nowplaying", None) @@ -483,10 +482,7 @@ def post_config_hook(self): self._format_contains_control_buttons = True self._used_can_properties.append(value["clickable"]) - if ( - len(self.player_hide_non_canplay) - and "CanPlay" not in self._used_can_properties - ): + if len(self.player_hide_non_canplay) and "CanPlay" not in self._used_can_properties: self._used_can_properties.append("CanPlay") self._format_contains_time = self.py3.format_contains(self.format, "time") @@ -781,9 +777,7 @@ def on_click(self, event): if order_asc: next_index = current_player_index % len(switchable_players) else: - next_index = (current_player_index - 1) % len( - switchable_players - ) + next_index = (current_player_index - 1) % len(switchable_players) self._set_data_entry_point_by_name_key( switchable_players[next_index], update=False diff --git a/py3status/modules/net_iplist.py b/py3status/modules/net_iplist.py index df2bf83e4c..c267ddc98d 100644 --- a/py3status/modules/net_iplist.py +++ b/py3status/modules/net_iplist.py @@ -77,9 +77,7 @@ class Py3status: def post_config_hook(self): self.iface_re = re.compile(r"\d+: (?P[\w\-@]+):") self.ip_re = re.compile(r"\s+inet (?P[\d.]+)(?:/| )") - self.ip6_re = re.compile( - r"\s+inet6 (?P[\da-f:]+)(?:/\d{1,3}| ) scope global dynamic" - ) + self.ip6_re = re.compile(r"\s+inet6 (?P[\da-f:]+)(?:/\d{1,3}| ) scope global dynamic") def net_iplist(self): response = { @@ -143,16 +141,12 @@ def _get_data(self): ip4 = self.ip_re.match(line) if ip4: - data.setdefault(cur_iface, {}).setdefault("ip4", []).append( - ip4.group("ip4") - ) + data.setdefault(cur_iface, {}).setdefault("ip4", []).append(ip4.group("ip4")) continue ip6 = self.ip6_re.match(line) if ip6: - data.setdefault(cur_iface, {}).setdefault("ip6", []).append( - ip6.group("ip6") - ) + data.setdefault(cur_iface, {}).setdefault("ip6", []).append(ip6.group("ip6")) continue return data diff --git a/py3status/modules/net_rate.py b/py3status/modules/net_rate.py index e880561c0f..6a32cbe482 100644 --- a/py3status/modules/net_rate.py +++ b/py3status/modules/net_rate.py @@ -78,18 +78,14 @@ def deprecate_function(config): # support old thresholds precision = config.get("precision", 1) padding = 3 + 1 + precision + 1 + 5 - format_value = ( - r"[\?min_length={padding} {{value:.{precision}f}} {{unit}}]".format( - padding=padding, precision=precision - ) + format_value = r"[\?min_length={padding} {{value:.{precision}f}} {{unit}}]".format( + padding=padding, precision=precision ) return {"format_value": format_value} deprecated = { "function": [{"function": deprecate_function}], - "remove": [ - {"param": "precision", "msg": "obsolete, use format_value instead"} - ], + "remove": [{"param": "precision", "msg": "obsolete, use format_value instead"}], } def post_config_hook(self): diff --git a/py3status/modules/networkmanager.py b/py3status/modules/networkmanager.py index 7a497367c8..110a829ef3 100644 --- a/py3status/modules/networkmanager.py +++ b/py3status/modules/networkmanager.py @@ -174,9 +174,7 @@ def networkmanager(self): return { "cache_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - self.format, {"format_device": format_device} - ), + "full_text": self.py3.safe_format(self.format, {"format_device": format_device}), } diff --git a/py3status/modules/ns_checker.py b/py3status/modules/ns_checker.py index b54a9c8859..3018d3b682 100644 --- a/py3status/modules/ns_checker.py +++ b/py3status/modules/ns_checker.py @@ -35,9 +35,10 @@ {'full_text': '10 NS OK'} """ -import dns.resolver import socket +import dns.resolver + class Py3status: """ """ diff --git a/py3status/modules/nvidia_smi.py b/py3status/modules/nvidia_smi.py index 16f877cf1b..9b041b897d 100644 --- a/py3status/modules/nvidia_smi.py +++ b/py3status/modules/nvidia_smi.py @@ -98,9 +98,7 @@ def post_config_hook(self): properties = self.py3.get_placeholders_list(self.format_gpu) format_gpu = {x: ":.1f" for x in properties if "used_percent" in x} - self.format_gpu = self.py3.update_placeholder_formats( - self.format_gpu, format_gpu - ) + self.format_gpu = self.py3.update_placeholder_formats(self.format_gpu, format_gpu) new_memory_properties = set() new_properties = {"memory.used", "memory.total"} @@ -157,9 +155,9 @@ def nvidia_smi(self): from sys import argv if "--list-properties" in argv: - from sys import exit from json import dumps from subprocess import check_output + from sys import exit help_cmd = "nvidia-smi --help-query-gpu" help_data = check_output(help_cmd.split()).decode() diff --git a/py3status/modules/online_status.py b/py3status/modules/online_status.py index f2cd9b8813..cfda4de49f 100644 --- a/py3status/modules/online_status.py +++ b/py3status/modules/online_status.py @@ -27,7 +27,7 @@ {'color': '#FF0000', 'full_text': u'\u25a0'} """ -from urllib.request import urlopen, URLError +from urllib.request import URLError, urlopen class Py3status: diff --git a/py3status/modules/pingdom.py b/py3status/modules/pingdom.py index f2a6f271e3..89f23d99cf 100644 --- a/py3status/modules/pingdom.py +++ b/py3status/modules/pingdom.py @@ -73,18 +73,14 @@ def pingdom(self): if "checks" in result: for check in [ck for ck in result["checks"] if ck["name"] in self.checks]: if check["status"] == "up": - pingdom += "{}: {}ms, ".format( - check["name"], check["lastresponsetime"] - ) + pingdom += "{}: {}ms, ".format(check["name"], check["lastresponsetime"]) if check["lastresponsetime"] > self.max_latency: response["color"] = self.py3.COLOR_DEGRADED else: response["color"] = self.py3.COLOR_BAD pingdom += "{}: DOWN".format(check["name"]) pingdom = pingdom.strip(", ") - response["full_text"] = self.py3.safe_format( - self.format, {"pingdom": pingdom} - ) + response["full_text"] = self.py3.safe_format(self.format, {"pingdom": pingdom}) return response diff --git a/py3status/modules/pomodoro.py b/py3status/modules/pomodoro.py index 427d49fb1d..29a34e15fc 100644 --- a/py3status/modules/pomodoro.py +++ b/py3status/modules/pomodoro.py @@ -59,7 +59,6 @@ from math import ceil from threading import Timer - PROGRESS_BAR_ITEMS = "▏▎▍▌▋▊▉" @@ -243,9 +242,7 @@ def pomodoro(self): cached_until = self.py3.CACHE_FOREVER response = { - "full_text": format.format( - breakno=self._break_number, format=formatted, **vals - ), + "full_text": format.format(breakno=self._break_number, format=formatted, **vals), "cached_until": cached_until, } diff --git a/py3status/modules/process_status.py b/py3status/modules/process_status.py index 704ac68703..bed3718088 100644 --- a/py3status/modules/process_status.py +++ b/py3status/modules/process_status.py @@ -83,9 +83,7 @@ def process_status(self): return { "cached_until": self.py3.time_in(self.cache_timeout), "color": color, - "full_text": self.py3.safe_format( - self.format, {"icon": icon, "process": self.process} - ), + "full_text": self.py3.safe_format(self.format, {"icon": icon, "process": self.process}), } diff --git a/py3status/modules/rainbow.py b/py3status/modules/rainbow.py index 599b35557d..7439dcdd9b 100644 --- a/py3status/modules/rainbow.py +++ b/py3status/modules/rainbow.py @@ -65,8 +65,8 @@ ] """ -import re import math +import re import time HEX_RE = re.compile("#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})") @@ -113,9 +113,7 @@ def to_hex(color): """ Convert [r, g, b] to hex. """ - return "#{:02X}{:02X}{:02X}".format( - int(color[0]), int(color[1]), int(color[2]) - ) + return "#{:02X}{:02X}{:02X}".format(int(color[0]), int(color[1]), int(color[2])) def make_color(c1, c2, t): """ diff --git a/py3status/modules/rate_counter.py b/py3status/modules/rate_counter.py index 723a7b0ca3..66fe0b081a 100644 --- a/py3status/modules/rate_counter.py +++ b/py3status/modules/rate_counter.py @@ -41,7 +41,6 @@ import time from pathlib import Path - # No "magic numbers" SECS_IN_MIN = 60 SECS_IN_HOUR = 60 * SECS_IN_MIN # 3600 @@ -136,13 +135,9 @@ def rate_counter(self): days, hours, mins, secs = self.secs_to_dhms(running_time) subtotal = self.hour_price * running_time / SECS_IN_HOUR total = subtotal * float(self.tax) - subtotal_cost = self.py3.safe_format( - self.format_money, {"price": f"{subtotal:.2f}"} - ) + subtotal_cost = self.py3.safe_format(self.format_money, {"price": f"{subtotal:.2f}"}) total_cost = self.py3.safe_format(self.format_money, {"price": f"{total:.2f}"}) - tax_cost = self.py3.safe_format( - self.format_money, {"price": f"{total - subtotal:.2f}"} - ) + tax_cost = self.py3.safe_format(self.format_money, {"price": f"{total - subtotal:.2f}"}) response = { "cached_until": self.py3.time_in(self.cache_timeout), "color": color, diff --git a/py3status/modules/rss_aggregator.py b/py3status/modules/rss_aggregator.py index 78fc3f2e8d..3a7732d13c 100644 --- a/py3status/modules/rss_aggregator.py +++ b/py3status/modules/rss_aggregator.py @@ -49,9 +49,10 @@ {'full_text': 'Feed: 488'} """ -import requests import json +import requests + class Py3status: """ """ @@ -97,9 +98,7 @@ def _get_count_owncloud(self): try: rss_count = 0 api_url = f"{self.server}/index.php/apps/news/api/v1-2/" - r = requests.get( - api_url + "feeds", auth=(self.user, self.password), timeout=10 - ) + r = requests.get(api_url + "feeds", auth=(self.user, self.password), timeout=10) for feed in r.json()["feeds"]: if ( (not self.feed_ids and not self.folder_ids) @@ -119,15 +118,11 @@ def _get_count_ttrss(self): api_url = f"{self.server}/api/" r = requests.post( api_url, - data=json.dumps( - {"op": "login", "user": self.user, "password": self.password} - ), + data=json.dumps({"op": "login", "user": self.user, "password": self.password}), ) sid = r.json()["content"]["session_id"] if not self.feed_ids and not self.folder_ids: - r = requests.post( - api_url, data=json.dumps({"sid": sid, "op": "getUnread"}) - ) + r = requests.post(api_url, data=json.dumps({"sid": sid, "op": "getUnread"})) rss_count = r.json()["content"]["unread"] else: for folder in self.folder_ids: diff --git a/py3status/modules/screenshot.py b/py3status/modules/screenshot.py index 7044e4fc7c..bccb488726 100644 --- a/py3status/modules/screenshot.py +++ b/py3status/modules/screenshot.py @@ -39,7 +39,6 @@ import random import string - from pathlib import Path diff --git a/py3status/modules/scroll.py b/py3status/modules/scroll.py index 0992f11815..0a00a2791c 100644 --- a/py3status/modules/scroll.py +++ b/py3status/modules/scroll.py @@ -39,9 +39,7 @@ def post_config_hook(self): def _set_scroll(self): length = sum( - len(output["full_text"]) - for item in self.items - for output in self.py3.get_output(item) + len(output["full_text"]) for item in self.items for output in self.py3.get_output(item) ) self.index += 1 diff --git a/py3status/modules/speedtest.py b/py3status/modules/speedtest.py index 48c0338a44..273ca054a4 100644 --- a/py3status/modules/speedtest.py +++ b/py3status/modules/speedtest.py @@ -130,7 +130,6 @@ from json import loads from threading import Thread - STRING_NOT_INSTALLED = "not installed" diff --git a/py3status/modules/spotify.py b/py3status/modules/spotify.py index 407a5d8217..29b87e7a8a 100644 --- a/py3status/modules/spotify.py +++ b/py3status/modules/spotify.py @@ -106,18 +106,14 @@ def post_config_hook(self): # - Remastered 2012 # / Radio Edit # ; Remastered - self.after_delimiter = self._compile_re( - r"([\-,;/])([^\-,;/])*(META_WORDS_HERE).*" - ) + self.after_delimiter = self._compile_re(r"([\-,;/])([^\-,;/])*(META_WORDS_HERE).*") # Match brackets with their content containing any metadata word # examples: # (Remastered 2017) # [Single] # (Bonus Track) - self.inside_brackets = self._compile_re( - r"([\(\[][^)\]]*?(META_WORDS_HERE)[^)\]]*?[\)\]])" - ) + self.inside_brackets = self._compile_re(r"([\(\[][^)\]]*?(META_WORDS_HERE)[^)\]]*?[\)\]])") def _compile_re(self, expression): """ diff --git a/py3status/modules/sql.py b/py3status/modules/sql.py index faab24eb5e..2054721eca 100644 --- a/py3status/modules/sql.py +++ b/py3status/modules/sql.py @@ -118,18 +118,14 @@ def post_config_hook(self): raise Exception(f"missing {config_name}") self.connect = getattr(import_module(self.database), "connect") - self.operational_error = getattr( - import_module(self.database), "OperationalError" - ) + self.operational_error = getattr(import_module(self.database), "OperationalError") self.is_parameters_a_dict = isinstance(self.parameters, dict) if not self.is_parameters_a_dict: self.parameters = Path(self.parameters).expanduser() self.thresholds_init = {} for name in ("format", "format_row"): - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _get_sql_data(self): if self.is_parameters_a_dict: diff --git a/py3status/modules/sway_idle.py b/py3status/modules/sway_idle.py index 68787919a8..c5a0090d8e 100644 --- a/py3status/modules/sway_idle.py +++ b/py3status/modules/sway_idle.py @@ -28,7 +28,6 @@ class Py3status: - # available configuration parameters cache_timeout = 1 format = "Inhibit Idle: {inhibit_idle}" diff --git a/py3status/modules/sysdata.py b/py3status/modules/sysdata.py index f6de19f28d..636e2cb648 100644 --- a/py3status/modules/sysdata.py +++ b/py3status/modules/sysdata.py @@ -103,11 +103,11 @@ ] """ +import re from fnmatch import fnmatch from json import loads from os import getloadavg from pathlib import Path -import re INVALID_CPU_TEMP_UNIT = "invalid cpu_temp_unit" STRING_NOT_INSTALLED = "not installed" @@ -136,9 +136,7 @@ class Meta: def update_deprecated_placeholder_format(config): padding = config.get("padding", 0) precision = config.get("precision", 2) - format_vals = ":{padding}.{precision}f".format( - padding=padding, precision=precision - ) + format_vals = ":{padding}.{precision}f".format(padding=padding, precision=precision) return { "cpu_freq_avg": format_vals, "cpu_freq_max": format_vals, @@ -434,9 +432,7 @@ def _calc_cpu_percent(self, cpu): if total != last_total: used_percent = (1 - (idle - last_idle) / (total - last_total)) * 100 - self.cpus["last"].setdefault(name, {}).update( - zip(["name", "idle", "total"], cpu) - ) + self.cpus["last"].setdefault(name, {}).update(zip(["name", "idle", "total"], cpu)) return used_percent def _get_cputemp(self, cpu_temp_unit): diff --git a/py3status/modules/systemd.py b/py3status/modules/systemd.py index 19105d7381..ecd3ac2129 100644 --- a/py3status/modules/systemd.py +++ b/py3status/modules/systemd.py @@ -71,27 +71,17 @@ def post_config_hook(self): bus = dbus.SessionBus() else: bus = dbus.SystemBus() - systemd = bus.get_object( - "org.freedesktop.systemd1", "/org/freedesktop/systemd1" - ) + systemd = bus.get_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1") systemd_unit = systemd.LoadUnit( self.unit, dbus_interface="org.freedesktop.systemd1.Manager" ) unit_proxy = bus.get_object("org.freedesktop.systemd1", systemd_unit) - self.systemd_interface = dbus.Interface( - unit_proxy, "org.freedesktop.DBus.Properties" - ) + self.systemd_interface = dbus.Interface(unit_proxy, "org.freedesktop.DBus.Properties") def systemd(self): - status = self.systemd_interface.Get( - "org.freedesktop.systemd1.Unit", "ActiveState" - ) - exists = self.systemd_interface.Get( - "org.freedesktop.systemd1.Unit", "LoadState" - ) - state = self.systemd_interface.Get( - "org.freedesktop.systemd1.Unit", "UnitFileState" - ) + status = self.systemd_interface.Get("org.freedesktop.systemd1.Unit", "ActiveState") + exists = self.systemd_interface.Get("org.freedesktop.systemd1.Unit", "LoadState") + state = self.systemd_interface.Get("org.freedesktop.systemd1.Unit", "UnitFileState") if exists == "not-found": color = self.py3.COLOR_DEGRADED diff --git a/py3status/modules/systemd_suspend_inhibitor.py b/py3status/modules/systemd_suspend_inhibitor.py index 7295e6fe9f..4e774e82e8 100644 --- a/py3status/modules/systemd_suspend_inhibitor.py +++ b/py3status/modules/systemd_suspend_inhibitor.py @@ -26,9 +26,9 @@ [{'full_text': 'SUSPEND OFF', 'color': '#FF0000'}] """ -from dbus import SystemBus from os import close +from dbus import SystemBus STRING_DBUS_EXCEPTION = "DBUS error, systemd-logind not started?" STRING_BAD_LOCK_TYPES = "DBUS error, bad lock types used" diff --git a/py3status/modules/thunderbird_todos.py b/py3status/modules/thunderbird_todos.py index 6a66f7df89..c658d3cfa5 100644 --- a/py3status/modules/thunderbird_todos.py +++ b/py3status/modules/thunderbird_todos.py @@ -138,9 +138,9 @@ {'full_text': 'New Task 1, New Task 2'} """ -from sqlite3 import connect from datetime import datetime from pathlib import Path +from sqlite3 import connect STRING_NO_PROFILE = "missing profile" STRING_NOT_INSTALLED = "not installed" @@ -171,9 +171,7 @@ def post_config_hook(self): with profile_ini.open() as f: for line in f: if line.startswith("Path="): - profile.append( - "{}/{}".format(directory, line.split("Path=")[-1].strip()) - ) + profile.append("{}/{}".format(directory, line.split("Path=")[-1].strip())) if not len(profile): raise Exception(STRING_NO_PROFILE) self.profile = profile[0] @@ -190,9 +188,7 @@ def post_config_hook(self): self.thresholds_init = {} for name in ["format", "format_todo"]: - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _get_thunderbird_todos_data(self): connection = connect(self.path) @@ -258,9 +254,7 @@ def thunderbird_todos(self): return { "cached_until": self.py3.time_in(self.cache_timeout), - "full_text": self.py3.safe_format( - self.format, dict(format_todo=format_todo, **count) - ), + "full_text": self.py3.safe_format(self.format, dict(format_todo=format_todo, **count)), } diff --git a/py3status/modules/timewarrior.py b/py3status/modules/timewarrior.py index de2f80eaaf..d60acb1e74 100644 --- a/py3status/modules/timewarrior.py +++ b/py3status/modules/timewarrior.py @@ -138,8 +138,8 @@ {'full_text': 'No Timew'} """ -from json import loads as json_loads import datetime as dt +from json import loads as json_loads STRING_NOT_INSTALLED = "not installed" DATETIME = "%Y%m%dT%H%M%SZ" @@ -204,9 +204,7 @@ def post_config_hook(self): self.tracking = None self.thresholds_init = {} for name in ("format", "format_tag", "format_time"): - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _get_timewarrior_data(self): return json_loads(self.py3.command_output(self.timewarrior_command)) diff --git a/py3status/modules/tor_rate.py b/py3status/modules/tor_rate.py index a1adb48c38..6950bc50d4 100644 --- a/py3status/modules/tor_rate.py +++ b/py3status/modules/tor_rate.py @@ -100,19 +100,11 @@ def tor_rate(self, outputs, config): return {"cached_until": self.py3.time_in(self.cache_timeout), "full_text": text} def _get_rates(self): - up, up_unit = self.py3.format_units( - self._up, unit=self.rate_unit, si=self.si_units - ) - down, down_unit = self.py3.format_units( - self._down, unit=self.rate_unit, si=self.si_units - ) + up, up_unit = self.py3.format_units(self._up, unit=self.rate_unit, si=self.si_units) + down, down_unit = self.py3.format_units(self._down, unit=self.rate_unit, si=self.si_units) return { - "up": self.py3.safe_format( - self.format_value, {"rate": up, "unit": up_unit} - ), - "down": self.py3.safe_format( - self.format_value, {"rate": down, "unit": down_unit} - ), + "up": self.py3.safe_format(self.format_value, {"rate": up, "unit": up_unit}), + "down": self.py3.safe_format(self.format_value, {"rate": down, "unit": down_unit}), } def _handle_event(self, event): @@ -120,9 +112,7 @@ def _handle_event(self, event): self._up = event.written def _register_event_handler(self): - self._control = Controller.from_port( - address=self.control_address, port=self.control_port - ) + self._control = Controller.from_port(address=self.control_address, port=self.control_port) if self.control_password: self._control.authenticate(password=self.control_password) self._control.add_event_listener(lambda e: self._handle_event(e), EventType.BW) diff --git a/py3status/modules/transmission.py b/py3status/modules/transmission.py index 7ecd20b484..8f0663ec24 100644 --- a/py3status/modules/transmission.py +++ b/py3status/modules/transmission.py @@ -164,9 +164,7 @@ def post_config_hook(self): raise Exception(STRING_NOT_INSTALLED) if self.arguments: self.command = f"{self.command} {self.arguments}" - self.init_summary = self.py3.format_contains( - self.format, ["up", "down", "have"] - ) + self.init_summary = self.py3.format_contains(self.format, ["up", "down", "have"]) self.id = 0 self.state = None self.reset_id = self.id @@ -177,9 +175,7 @@ def post_config_hook(self): self.thresholds_init = {} for name in ["format", "format_torrent"]: - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _scroll(self, direction=0): self.is_scrolling = True @@ -271,9 +267,7 @@ def transmission(self): format_separator = self.py3.safe_format(self.format_separator) format_torrent = self.py3.composite_join(format_separator, data) - summary_data.update( - {"torrent": self.count_torrent, "format_torrent": format_torrent} - ) + summary_data.update({"torrent": self.count_torrent, "format_torrent": format_torrent}) for x in self.thresholds_init["format"]: if x in summary_data: diff --git a/py3status/modules/twitch.py b/py3status/modules/twitch.py index 5d78b9166e..73fd4d2324 100644 --- a/py3status/modules/twitch.py +++ b/py3status/modules/twitch.py @@ -76,8 +76,8 @@ {'color': '#FF0000', 'full_text': 'exotic_bug is offline!'} """ -import time import datetime +import time STRING_MISSING = "missing {}" @@ -245,10 +245,7 @@ def _get_tags(self, user_id, cursor=None): for loc in self.locales: if loc in tag["localization_names"] and "name" not in tag_data: tag_data["name"] = tag["localization_names"][loc] - if ( - loc in tag["localization_descriptions"] - and "desc" not in tag_data - ): + if loc in tag["localization_descriptions"] and "desc" not in tag_data: tag_data["desc"] = tag["localization_descriptions"][loc] if tag_data: tags.append(self.py3.safe_format(self.format_tag, tag_data)) @@ -284,9 +281,7 @@ def twitch(self): del stream["user_name"] # calculate runtime and update data dict - stream["runtime"], stream["runtime_seconds"] = time_since( - stream["started_at"] - ) + stream["runtime"], stream["runtime_seconds"] = time_since(stream["started_at"]) twitch_data["stream"] = stream twitch_data["is_streaming"] = True @@ -319,9 +314,10 @@ def twitch(self): """ Run module in test mode. """ - from py3status.module_test import module_test from os import getenv + from py3status.module_test import module_test + config = { "client_id": getenv("TWITCH_CLIENT_ID"), "client_secret": getenv("TWITCH_CLIENT_SECRET"), diff --git a/py3status/modules/uname.py b/py3status/modules/uname.py index aa5a046a95..eed2b39163 100644 --- a/py3status/modules/uname.py +++ b/py3status/modules/uname.py @@ -28,9 +28,7 @@ class Py3status: format = "{system} {release}" class Meta: - deprecated = { - "remove": [{"param": "cache_timeout", "msg": "obsolete parameter"}] - } + deprecated = {"remove": [{"param": "cache_timeout", "msg": "obsolete parameter"}]} def uname(self): keys = ["system", "node", "release", "version", "machine", "processor"] diff --git a/py3status/modules/uptime.py b/py3status/modules/uptime.py index 81e2d33350..c49ee5cb35 100644 --- a/py3status/modules/uptime.py +++ b/py3status/modules/uptime.py @@ -61,8 +61,8 @@ """ import time -from datetime import datetime from collections import OrderedDict +from datetime import datetime from pathlib import Path diff --git a/py3status/modules/usbguard.py b/py3status/modules/usbguard.py index 1d1f6cc55a..251ed03724 100644 --- a/py3status/modules/usbguard.py +++ b/py3status/modules/usbguard.py @@ -44,9 +44,10 @@ ] """ -from threading import Thread -from gi.repository import GLib, Gio import re +from threading import Thread + +from gi.repository import Gio, GLib STRING_USBGUARD_DBUS = "start usbguard-dbus.service" @@ -63,9 +64,7 @@ class Py3status: def post_config_hook(self): self.init = { - "format_button": self.py3.get_placeholders_list( - self.format_device, "format_button_*" - ), + "format_button": self.py3.get_placeholders_list(self.format_device, "format_button_*"), "target": {"allow": 0, "reject": 2}, } diff --git a/py3status/modules/vnstat.py b/py3status/modules/vnstat.py index 5cafc134ee..b9d8029e57 100644 --- a/py3status/modules/vnstat.py +++ b/py3status/modules/vnstat.py @@ -77,9 +77,7 @@ def post_config_hook(self): elif self.statistics_type not in ["d", "m"]: raise Exception(STRING_INVALID_TYPE) self.slice = slice(*(3, 6) if self.statistics_type == "d" else (8, 11)) - self.value_format = "{{value:{}.{}f}} {{unit}}".format( - self.left_align, self.precision - ) + self.value_format = "{{value:{}.{}f}} {{unit}}".format(self.left_align, self.precision) # list of units, first one - value/initial_multi, second - value/1024, # third - value/1024^2, etc... self.units = ["kb", "mb", "gb", "tb"] @@ -87,9 +85,7 @@ def post_config_hook(self): # deprecations self.coloring = getattr(self, "coloring", None) if self.coloring and not self.thresholds: - self.thresholds = [ - (num * 1024**2, col) for num, col in self.coloring.items() - ] + self.thresholds = [(num * 1024**2, col) for num, col in self.coloring.items()] self.thresholds_init = self.py3.get_color_names_list(self.format) diff --git a/py3status/modules/volume_status.py b/py3status/modules/volume_status.py index 85b7c0ca8b..f4260a9bc5 100644 --- a/py3status/modules/volume_status.py +++ b/py3status/modules/volume_status.py @@ -80,9 +80,10 @@ {'color': '#FF0000', 'full_text': u'\u266a: muted'} """ -import re import math +import re from time import sleep + from py3status.exceptions import CommandError STRING_ERROR = "invalid command `{}`" @@ -292,9 +293,7 @@ def volume_up(self, delta): change = f"{self.max_volume}%" else: change = f"+{delta}%" - self.run_cmd( - ["pactl", "--", f"set-{self.device_type}-volume", self.device, change] - ) + self.run_cmd(["pactl", "--", f"set-{self.device_type}-volume", self.device, change]) def volume_down(self, delta): self.run_cmd( diff --git a/py3status/modules/vpn_status.py b/py3status/modules/vpn_status.py index fc67805ad2..160a20ad5f 100644 --- a/py3status/modules/vpn_status.py +++ b/py3status/modules/vpn_status.py @@ -34,13 +34,13 @@ {'color': '#FF0000', 'full_text': u'VPN: no'} """ -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib +from pathlib import Path from threading import Thread from time import sleep -from pathlib import Path import dbus +from dbus.mainloop.glib import DBusGMainLoop +from gi.repository import GLib class Py3status: @@ -73,18 +73,14 @@ def _start_loop(self): dbus.set_default_main_loop(loop) bus = dbus.SystemBus() - bus.add_signal_receiver( - self._vpn_signal_handler, path="/org/freedesktop/NetworkManager" - ) + bus.add_signal_receiver(self._vpn_signal_handler, path="/org/freedesktop/NetworkManager") # Initialize the already active connections manager = bus.get_object( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", ) interface = dbus.Interface(manager, "org.freedesktop.DBus.Properties") - self.active = interface.Get( - "org.freedesktop.NetworkManager", "ActiveConnections" - ) + self.active = interface.Get("org.freedesktop.NetworkManager", "ActiveConnections") # Loop forever to listen for events loop = GLib.MainLoop() @@ -119,9 +115,7 @@ def _get_vpn_status(self): ) interface = dbus.Interface(manager, "org.freedesktop.DBus.Properties") try: - properties = interface.GetAll( - "org.freedesktop.NetworkManager.Connection.Active" - ) + properties = interface.GetAll("org.freedesktop.NetworkManager.Connection.Active") if properties.get("Vpn") or properties.get("Type") == "wireguard": ids.append(properties.get("Id")) except dbus.DBusException: diff --git a/py3status/modules/wanda_the_fish.py b/py3status/modules/wanda_the_fish.py index 6c4fe0f9fa..728b99d952 100644 --- a/py3status/modules/wanda_the_fish.py +++ b/py3status/modules/wanda_the_fish.py @@ -110,9 +110,7 @@ def post_config_hook(self): timeout = None if self.fortune_timeout != fortune_timeout: timeout = time() + self.fortune_timeout - self.time = ( - timeout or self.py3.storage_get("time") or (time() + self.fortune_timeout) - ) + self.time = timeout or self.py3.storage_get("time") or (time() + self.fortune_timeout) def _set_fortune(self, state=None, new=False): if not self.fortune_command: diff --git a/py3status/modules/watson.py b/py3status/modules/watson.py index bd751f9828..52c9a4a65b 100644 --- a/py3status/modules/watson.py +++ b/py3status/modules/watson.py @@ -24,7 +24,6 @@ """ import json - from pathlib import Path from typing import Dict, List, Union @@ -67,9 +66,7 @@ def watson(self) -> Dict[str, str]: "cached_until": self.py3.time_in(seconds=self.cache_timeout), } - def _format_output( - self, session_data: Dict[str, Union[str, int, List[str]]] - ) -> Dict[str, str]: + def _format_output(self, session_data: Dict[str, Union[str, int, List[str]]]) -> Dict[str, str]: if not session_data: return {"full_text": "No project started", "color": self.py3.COLOR_BAD} diff --git a/py3status/modules/weather_owm.py b/py3status/modules/weather_owm.py index 65918574ca..8aa47dce02 100644 --- a/py3status/modules/weather_owm.py +++ b/py3status/modules/weather_owm.py @@ -262,7 +262,6 @@ import datetime - # API information OWM_CURR_ENDPOINT = "https://api.openweathermap.org/data/2.5/weather?" OWM_FUTURE_ENDPOINT = "https://api.openweathermap.org/data/2.5/forecast?" @@ -472,9 +471,7 @@ def post_config_hook(self): # Initialize per-format thresholds self.thresholds_init = {} for name in ("format_humidity",): - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _make_req(self, url, params=None): # Make a request expecting a JSON response @@ -637,12 +634,8 @@ def _format_snow(self, wthr): def _format_wind(self, wthr): wind = { - "deg": self._jpath( - wthr, OWM_WIND_DEG, self._jpath(wthr, OWN_CURRENT_WIND_DEG, 0) - ), - "gust": self._jpath( - wthr, OWM_WIND_GUST, self._jpath(wthr, OWN_CURRENT_WIND_GUST, 0) - ), + "deg": self._jpath(wthr, OWM_WIND_DEG, self._jpath(wthr, OWN_CURRENT_WIND_DEG, 0)), + "gust": self._jpath(wthr, OWM_WIND_GUST, self._jpath(wthr, OWN_CURRENT_WIND_GUST, 0)), "speed": self._jpath( wthr, OWM_WIND_SPEED, self._jpath(wthr, OWN_CURRENT_WIND_SPEED, 0) ), @@ -702,9 +695,7 @@ def _format_humidity(self, wthr): # Format the humidity (default zero humidity) humidity_data = { "icon": self.icon_humidity, - "humidity": self._jpath( - wthr, OWM_HUMIDITY, self._jpath(wthr, OWM_CURRENT_HUMIDITY, 0) - ), + "humidity": self._jpath(wthr, OWM_HUMIDITY, self._jpath(wthr, OWM_CURRENT_HUMIDITY, 0)), } for x in self.thresholds_init["format_humidity"]: @@ -717,9 +708,7 @@ def _format_pressure(self, wthr): # Get data and add the icon pressure = { "icon": self.icon_pressure, - "pressure": self._jpath( - wthr, OWM_PRESSURE, self._jpath(wthr, OWM_CURRENT_PRESSURE, 0) - ), + "pressure": self._jpath(wthr, OWM_PRESSURE, self._jpath(wthr, OWM_CURRENT_PRESSURE, 0)), } # Format the barometric pressure @@ -728,15 +717,9 @@ def _format_pressure(self, wthr): def _format_temp(self, wthr): # Get Kelvin data (default absolute zero) kelvin = { - "day": self._jpath( - wthr, OWM_TEMP_DAY, self._jpath(wthr, OWM_CURRENT_TEMP, "") - ), - "max": self._jpath( - wthr, OWM_TEMP_MAX, self._jpath(wthr, OWM_CURRENT_TEMP_MAX, "") - ), - "min": self._jpath( - wthr, OWM_TEMP_MIN, self._jpath(wthr, OWM_CURRENT_TEMP_MIN, "") - ), + "day": self._jpath(wthr, OWM_TEMP_DAY, self._jpath(wthr, OWM_CURRENT_TEMP, "")), + "max": self._jpath(wthr, OWM_TEMP_MAX, self._jpath(wthr, OWM_CURRENT_TEMP_MAX, "")), + "min": self._jpath(wthr, OWM_TEMP_MIN, self._jpath(wthr, OWM_CURRENT_TEMP_MIN, "")), } # Temperature conversion methods @@ -829,9 +812,7 @@ def _format(self, current_wthr, fcsts, city, country): # Give the final format format_forecast_separator = self.py3.safe_format(self.format_forecast_separator) - today["forecast"] = self.py3.composite_join( - format_forecast_separator, forecasts - ) + today["forecast"] = self.py3.composite_join(format_forecast_separator, forecasts) return self.py3.safe_format(self.format, today) @@ -883,6 +864,7 @@ def weather_owm(self): Run module in test mode. """ from os import getenv + from py3status.module_test import module_test def colorize(names, color="lightgreen", separator=None): @@ -915,9 +897,7 @@ def colorize(names, color="lightgreen", separator=None): "format_rain": colorize(["icon", "amount", "unit"]), "format_snow": colorize(["icon", "amount", "unit"]), "format_temperature": colorize(["icon", "max", "min", "current", "unit"]), - "format_wind": colorize( - ["icon", "degree", "direction", "gust", "speed", "unit"] - ), + "format_wind": colorize(["icon", "degree", "direction", "gust", "speed", "unit"]), } module_test(Py3status, config) diff --git a/py3status/modules/whoami.py b/py3status/modules/whoami.py index eedfdb3852..a312af81df 100644 --- a/py3status/modules/whoami.py +++ b/py3status/modules/whoami.py @@ -28,9 +28,7 @@ class Py3status: format = "{username}" class Meta: - deprecated = { - "remove": [{"param": "cache_timeout", "msg": "obsolete parameter"}] - } + deprecated = {"remove": [{"param": "cache_timeout", "msg": "obsolete parameter"}]} def whoami(self): return { diff --git a/py3status/modules/wifi.py b/py3status/modules/wifi.py index 9dcaa8ae40..cc1c18bd14 100644 --- a/py3status/modules/wifi.py +++ b/py3status/modules/wifi.py @@ -56,8 +56,8 @@ {'color': '#00FF00', 'full_text': u'W: 54.0 MBit/s 100% Chicken Remixed'} """ -import re import math +import re DEFAULT_FORMAT = "W: {bitrate} {bitrate_unit} {signal_percent}% {ssid}|W: down" STRING_NOT_INSTALLED = "iw not installed" diff --git a/py3status/modules/window.py b/py3status/modules/window.py index 64c15be805..a488925d10 100644 --- a/py3status/modules/window.py +++ b/py3status/modules/window.py @@ -180,10 +180,7 @@ def get_window_properties(self): if ( focused["border"] == "normal" or focused["type"] == "workspace" - or ( - parent["layout"] in ("stacked", "tabbed") - and len(parent["nodes"]) > 1 - ) + or (parent["layout"] in ("stacked", "tabbed") and len(parent["nodes"]) > 1) ): window_properties["title"] = None window_properties = self.compatibility(window_properties) diff --git a/py3status/modules/wwan.py b/py3status/modules/wwan.py index baa26cf629..d169af6c60 100644 --- a/py3status/modules/wwan.py +++ b/py3status/modules/wwan.py @@ -524,12 +524,8 @@ def wwan(self): if self.init["stats"]: stats = self._organize(self._get_stats(bearer)) if stats: - stats["duration_hms"] = format( - timedelta(seconds=stats["duration"]) - ) - wwan_data["format_stats"] = self.py3.safe_format( - self.format_stats, stats - ) + stats["duration_hms"] = format(timedelta(seconds=stats["duration"])) + wwan_data["format_stats"] = self.py3.safe_format(self.format_stats, stats) # message and format message if self.init["sms_message"]: @@ -552,11 +548,8 @@ def wwan(self): # notifications if self.format_notification: - # get a notification - format_notification = self.py3.safe_format( - self.format_notification, wwan_data - ) + format_notification = self.py3.safe_format(self.format_notification, wwan_data) notification = self.py3.get_composite_string(format_notification) if notification and notification != self.last_notification: diff --git a/py3status/modules/wwan_status.py b/py3status/modules/wwan_status.py index ef8585b24a..b13d7a2d98 100644 --- a/py3status/modules/wwan_status.py +++ b/py3status/modules/wwan_status.py @@ -54,12 +54,13 @@ {'color': '#FF0000', 'full_text': u'WWAN: down'} """ -import netifaces as ni import stat -import serial from pathlib import Path from time import sleep +import netifaces as ni +import serial + class Py3status: """ """ @@ -77,7 +78,6 @@ class Py3status: modem_timeout = 0.4 def wwan_status(self): - query = "AT^SYSINFOEX" target_line = "^SYSINFOEX" diff --git a/py3status/modules/xkb_input.py b/py3status/modules/xkb_input.py index 41eb3974a8..2e429d1222 100644 --- a/py3status/modules/xkb_input.py +++ b/py3status/modules/xkb_input.py @@ -147,7 +147,7 @@ def setup(self, parent): t.start() def start(self): - from subprocess import Popen, PIPE + from subprocess import PIPE, Popen try: self.process = Popen(self.listen_command, stdout=PIPE) @@ -331,8 +331,8 @@ class Swaymsg(Xkb): """ def setup(self, parent): - from json import loads from fnmatch import fnmatch + from json import loads self.excluded = ["alias"] self.fnmatch, self.loads = (fnmatch, loads) @@ -427,9 +427,7 @@ def post_config_hook(self): self.thresholds_init = {} for name in ["format", "format_input"]: - self.thresholds_init[name] = self.py3.get_color_names_list( - getattr(self, name) - ) + self.thresholds_init[name] = self.py3.get_color_names_list(getattr(self, name)) def _stop_on_errors(self): if self.error: @@ -481,7 +479,6 @@ def on_click(self, event): if __name__ == "__main__": - """ Run module in test mode. """ diff --git a/py3status/modules/xrandr.py b/py3status/modules/xrandr.py index ffc54778e0..7ba38a03b1 100644 --- a/py3status/modules/xrandr.py +++ b/py3status/modules/xrandr.py @@ -140,8 +140,7 @@ {'full_text': 'DP1'} """ -from collections import deque -from collections import OrderedDict +from collections import OrderedDict, deque from itertools import combinations from time import sleep @@ -199,9 +198,7 @@ def _get_layout(self): connected = list() active_layout = list() disconnected = list() - layout = OrderedDict( - {"connected": OrderedDict(), "disconnected": OrderedDict()} - ) + layout = OrderedDict({"connected": OrderedDict(), "disconnected": OrderedDict()}) self.old_layout = self.layout or layout current = self.py3.command_output("xrandr") @@ -298,10 +295,7 @@ def _choose_what_to_display(self, force_refresh=False): we display the last selected combination. """ for _ in range(len(self.available_combinations)): - if ( - self.displayed is None - and self.available_combinations[0] == self.active_layout - ): + if self.displayed is None and self.available_combinations[0] == self.active_layout: self.displayed = self.available_combinations[0] break else: @@ -358,17 +352,10 @@ def _apply(self, force=False): if mode == "clone" and previous_output is not None: cmd += f" {resolution} --same-as {previous_output}" else: - if ( - "above" in pos - or "below" in pos - or "left-of" in pos - or "right-of" in pos - ): + if "above" in pos or "below" in pos or "left-of" in pos or "right-of" in pos: cmd += f" {resolution} --{pos} --rotate {rotation}" else: - cmd += " {} --pos {} --rotate {}".format( - resolution, pos, rotation - ) + cmd += " {} --pos {} --rotate {}".format(resolution, pos, rotation) previous_output = output else: cmd += " --off" @@ -405,9 +392,7 @@ def _apply_workspaces(self, combination, mode): cmd = f'{self.py3.get_wm_msg()} workspace "{workspace}"' self.py3.command_run(cmd) # move it to output - cmd = '{} move workspace to output "{}"'.format( - self.py3.get_wm_msg(), output - ) + cmd = '{} move workspace to output "{}"'.format(self.py3.get_wm_msg(), output) self.py3.command_run(cmd) # log this self.py3.log(f"moved workspace {workspace} to output {output}") @@ -508,11 +493,7 @@ def xrandr(self): self._force_force_on_start() # follow on change - if ( - not self._no_force_on_change - and self.force_on_change - and self._layout_changed() - ): + if not self._no_force_on_change and self.force_on_change and self._layout_changed(): self.py3.log("detected change of monitor setup") self._force_on_change() diff --git a/py3status/modules/xrandr_rotate.py b/py3status/modules/xrandr_rotate.py index cda6c984ac..c5a3c11d80 100644 --- a/py3status/modules/xrandr_rotate.py +++ b/py3status/modules/xrandr_rotate.py @@ -104,9 +104,7 @@ def _switch_selection(self): def xrandr_rotate(self): all_outputs = self._get_active_outputs() - selected_screen_disconnected = ( - self.screen is not None and self.screen not in all_outputs - ) + selected_screen_disconnected = self.screen is not None and self.screen not in all_outputs if selected_screen_disconnected and self.hide_if_disconnected: self.displayed = "" full_text = "" diff --git a/py3status/modules/xscreensaver.py b/py3status/modules/xscreensaver.py index d098e31bde..37a39e8893 100644 --- a/py3status/modules/xscreensaver.py +++ b/py3status/modules/xscreensaver.py @@ -31,7 +31,7 @@ """ from os import setpgrp -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen STRING_UNAVAILABLE = "not installed" diff --git a/py3status/modules/yubikey.py b/py3status/modules/yubikey.py index 4fda2f3058..e4a123feb7 100644 --- a/py3status/modules/yubikey.py +++ b/py3status/modules/yubikey.py @@ -21,11 +21,10 @@ {'full_text': 'YubiKey', 'urgent': True} """ -import time import os import socket import threading - +import time from pathlib import Path diff --git a/py3status/modules/zypper_updates.py b/py3status/modules/zypper_updates.py index 8da65f40d6..9cda05236a 100644 --- a/py3status/modules/zypper_updates.py +++ b/py3status/modules/zypper_updates.py @@ -22,8 +22,8 @@ [{'full_text': 'zypper: '}, {'full_text': '0', 'color': '#00FF00'}] """ -import subprocess import re +import subprocess class Py3status: diff --git a/py3status/output.py b/py3status/output.py index 1ee0f66625..9d7dca8905 100644 --- a/py3status/output.py +++ b/py3status/output.py @@ -144,9 +144,7 @@ def format_color(self, block): """ full_text = block["full_text"] if "color" in block: - full_text = ( - self.begin_color(block["color"]) + full_text + self.end_color_quick() - ) + full_text = self.begin_color(block["color"]) + full_text + self.end_color_quick() return full_text def format(self, outputs): diff --git a/py3status/parse_config.py b/py3status/parse_config.py index cf70e47d52..ab0b3d9968 100644 --- a/py3status/parse_config.py +++ b/py3status/parse_config.py @@ -1,26 +1,24 @@ import os import re - from collections import OrderedDict from importlib import util from pathlib import Path from string import Template -from subprocess import check_output, CalledProcessError +from subprocess import CalledProcessError, check_output from py3status.constants import ( CONFIG_FILE_SPECIAL_SECTIONS, - I3S_SINGLE_NAMES, - I3S_MODULE_NAMES, - MAX_NESTING_LEVELS, ERROR_CONFIG, GENERAL_DEFAULTS, + I3S_MODULE_NAMES, + I3S_SINGLE_NAMES, + MAX_NESTING_LEVELS, RETIRED_MODULES, - TIME_MODULES, TIME_FORMAT, + TIME_MODULES, TZTIME_FORMAT, ) - -from py3status.private import PrivateHide, PrivateBase64 +from py3status.private import PrivateBase64, PrivateHide class ParseException(Exception): @@ -40,9 +38,7 @@ def __init__(self, error, line, line_no, position, token): def one_line(self, config_path): filename = config_path.name notif = "CONFIG ERROR: {} saw `{}` at line {} position {} in file {}" - return notif.format( - self.error, self.token, self.line_no, self.position, filename - ) + return notif.format(self.error, self.token, self.line_no, self.position, filename) def __str__(self): marker = " " * (self.position - 1) + "^" @@ -253,9 +249,7 @@ def tokenize(self, config): t_type = "unknown" else: continue - tokens.append( - {"type": t_type, "value": value, "match": token, "start": token.start()} - ) + tokens.append({"type": t_type, "value": value, "match": token, "start": token.start()}) self.tokens = tokens def next(self): @@ -393,9 +387,7 @@ def make_value_from_shell(self, param, value_type, function): value = False else: if self.py3_wrapper: - self.py3_wrapper.report_exception( - msg=f"shell: called with command `{param}`" - ) + self.py3_wrapper.report_exception(msg=f"shell: called with command `{param}`") self.notify_user("shell script exited with an error") value = None else: @@ -567,7 +559,6 @@ def process_value(self, name, value, module_name): # if we have a colon in the name of a setting then it # indicates that it has been encoded. if ":" in name: - if module_name.split(" ")[0] in I3S_MODULE_NAMES + ["general"]: self.error("Only py3status modules can use obfuscated") @@ -641,20 +632,14 @@ def parse(self, dictionary=None, end_token=None): # no instance name then give it an anon one. This allows # us to have multiple non-instance named modules defined # without them clashing. - if ( - self.level > 1 - and " " not in name - and name not in I3S_MODULE_NAMES - ): + if self.level > 1 and " " not in name and name not in I3S_MODULE_NAMES: name = f"{name} _anon_module_{self.anon_count}" self.anon_count += 1 dictionary[name] = value # assignment of value elif t_value == "=": try: - name, value = self.process_value( - name, value, self.current_module[-1] - ) + name, value = self.process_value(name, value, self.current_module[-1]) except IndexError: self.error("Missing {", previous=True) dictionary[name] = value @@ -704,9 +689,7 @@ def parse_config_error(e, config_path): # get the file encoding this is important with multi-byte unicode chars try: - encoding = check_output( - ["file", "-b", "--mime-encoding", "--dereference", config_path] - ) + encoding = check_output(["file", "-b", "--mime-encoding", "--dereference", config_path]) encoding = encoding.strip().decode("utf-8") except FileNotFoundError: # can be missing on NixOS (see #1961) @@ -879,8 +862,8 @@ def add_container_items(module_name): if __name__ == "__main__": # process a config file and display output # file name user supplied or ~/.i3/i3status.conf - import sys import pprint + import sys if len(sys.argv) > 1: file_name = sys.argv[1] diff --git a/py3status/py3.py b/py3status/py3.py index be2aba4701..8550f89f1b 100644 --- a/py3status/py3.py +++ b/py3status/py3.py @@ -1,8 +1,7 @@ import os -import sys import shlex +import sys import time - from collections.abc import Mapping from copy import deepcopy from fnmatch import fnmatch @@ -10,12 +9,12 @@ from pathlib import Path from pprint import pformat from shutil import which -from subprocess import Popen, PIPE, STDOUT +from subprocess import PIPE, STDOUT, Popen from time import sleep from uuid import uuid4 from py3status import exceptions -from py3status.formatter import Formatter, Composite, expand_color +from py3status.formatter import Composite, Formatter, expand_color from py3status.request import HttpResponse from py3status.storage import Storage from py3status.util import Gradients @@ -186,9 +185,7 @@ def _thresholds_init(self): value.sort() except TypeError: pass - self._thresholds[key] = [ - (x[0], self._get_color(x[1])) for x in value - ] + self._thresholds[key] = [(x[0], self._get_color(x[1])) for x in value] def _get_module_info(self, module_name): """ @@ -227,9 +224,7 @@ def _report_exception(self, msg, frame_skip=2): while frame_skip: error_frame = error_frame.f_back frame_skip -= 1 - self._py3_wrapper.report_exception( - msg, notify_user=False, error_frame=error_frame - ) + self._py3_wrapper.report_exception(msg, notify_user=False, error_frame=error_frame) def error(self, msg, timeout=None): """ @@ -304,9 +299,7 @@ def flatten_dict(self, d, delimiter="-", intermediates=False, parent_key=None): if isinstance(v, list): v = dict(enumerate(v)) if isinstance(v, Mapping): - items.extend( - self.flatten_dict(v, delimiter, intermediates, str(k)).items() - ) + items.extend(self.flatten_dict(v, delimiter, intermediates, str(k)).items()) else: items.append((str(k), v)) return dict(items) @@ -863,9 +856,7 @@ def safe_format( self._report_exception(f"Invalid format `{format_string}` ({err})") return f"invalid format ({err})" - def build_composite( - self, format_string, param_dict=None, composites=None, attr_getter=None - ): + def build_composite(self, format_string, param_dict=None, composites=None, attr_getter=None): """ .. note:: deprecated in 3.3 use safe_format(). @@ -979,9 +970,7 @@ def command_run(self, command): msg = f"Command `{pretty_cmd}` {e.errno}" raise exceptions.CommandError(msg, error_code=e.errno) - def command_output( - self, command, shell=False, capture_stderr=False, localized=False - ): + def command_output(self, command, shell=False, capture_stderr=False, localized=False): """ Run a command and return its output as unicode. The command can either be supplied as a sequence or string. @@ -1036,9 +1025,7 @@ def command_output( if output_oneline: msg += " ({output})" msg = msg.format(cmd=pretty_cmd, error=retcode, output=output_oneline) - raise exceptions.CommandError( - msg, error_code=retcode, error=error, output=output - ) + raise exceptions.CommandError(msg, error_code=retcode, error=error, output=output) return output def _storage_init(self): @@ -1159,9 +1146,7 @@ def threshold_get_color(self, value, name=None): if isinstance(name, tuple): name_used = "{}/{}".format(name[0], name[1]) if name[2]: - self._thresholds[name_used] = [ - (x[0], self._get_color(x[1])) for x in name[2] - ] + self._thresholds[name_used] = [(x[0], self._get_color(x[1])) for x in name[2]] name = name[0] else: # if name not in thresholds info then use defaults @@ -1193,9 +1178,7 @@ def threshold_get_color(self, value, name=None): try: colors, minimum, maximum = self._threshold_gradients[name_used] except KeyError: - colors = self._gradients.make_threshold_gradient( - self, thresholds - ) + colors = self._gradients.make_threshold_gradient(self, thresholds) minimum = min(thresholds)[0] maximum = max(thresholds)[0] self._threshold_gradients[name_used] = ( @@ -1210,9 +1193,7 @@ def threshold_get_color(self, value, name=None): color = colors[-1] else: value -= minimum - col_index = int( - ((len(colors) - 1) / (maximum - minimum)) * value - ) + col_index = int(((len(colors) - 1) / (maximum - minimum)) * value) color = colors[col_index] else: color = thresholds[0][1] diff --git a/py3status/request.py b/py3status/request.py index 20600fcf20..37c103e637 100644 --- a/py3status/request.py +++ b/py3status/request.py @@ -1,19 +1,11 @@ import base64 import json import socket +from urllib.error import HTTPError, URLError +from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit +from urllib.request import HTTPCookieProcessor, Request, build_opener, install_opener, urlopen -from urllib.error import URLError, HTTPError -from urllib.parse import urlsplit, urlunsplit, parse_qsl, urlencode -from urllib.request import ( - urlopen, - Request, - build_opener, - install_opener, - HTTPCookieProcessor, -) - - -from py3status.exceptions import RequestTimeout, RequestURLError, RequestInvalidJSON +from py3status.exceptions import RequestInvalidJSON, RequestTimeout, RequestURLError class HttpResponse: diff --git a/py3status/screenshots.py b/py3status/screenshots.py index 055d5ada57..26f010933f 100644 --- a/py3status/screenshots.py +++ b/py3status/screenshots.py @@ -13,13 +13,11 @@ import ast import re - from hashlib import md5 from pathlib import Path -from PIL import Image, ImageFont, ImageDraw from fontTools.ttLib import TTFont - +from PIL import Image, ImageDraw, ImageFont WIDTH = 650 TOP_BAR_HEIGHT = 5 @@ -49,9 +47,7 @@ FONT_SIZE = BAR_HEIGHT - (PADDING * 2) HEIGHT = TOP_BAR_HEIGHT + BAR_HEIGHT -SAMPLE_DATA_ERROR = dict( - color="#990000", background="#FFFF00", full_text=" SAMPLE DATA ERROR " -) +SAMPLE_DATA_ERROR = dict(color="#990000", background="#FFFF00", full_text=" SAMPLE DATA ERROR ") # font, glyph_data want caching for performance font = None @@ -121,12 +117,8 @@ def create_screenshot(name, data, path, font, is_module): # if this screenshot is for a module then add modules name etc if is_module: - data.append( - {"full_text": name.split("-")[0], "color": desktop_color, "separator": True} - ) - data.append( - {"full_text": "py3status", "color": COLOR_PY3STATUS, "separator": True} - ) + data.append({"full_text": name.split("-")[0], "color": desktop_color, "separator": True}) + data.append({"full_text": "py3status", "color": COLOR_PY3STATUS, "separator": True}) img = Image.new("RGB", (WIDTH, HEIGHT), COLOR_BG) d = ImageDraw.Draw(img) diff --git a/py3status/storage.py b/py3status/storage.py index 8264bbcfd7..2bef952aa7 100644 --- a/py3status/storage.py +++ b/py3status/storage.py @@ -1,13 +1,11 @@ import os import time - from pathlib import Path from pickle import dump, load from tempfile import NamedTemporaryFile class Storage: - data = {} initialized = False @@ -38,9 +36,7 @@ def init(self, py3_wrapper): # move legacy storage cache to new desired / default location if legacy_storage_path: self.py3_wrapper.log( - "moving legacy storage_path {} to {}".format( - legacy_storage_path, self.storage_path - ) + "moving legacy storage_path {} to {}".format(legacy_storage_path, self.storage_path) ) legacy_storage_path.rename(self.storage_path) @@ -59,9 +55,7 @@ def get_legacy_storage_path(self): """ Detect and return existing legacy storage path. """ - config_dir = Path( - self.py3_wrapper.config.get("i3status_config_path", "/tmp") - ).parent + config_dir = Path(self.py3_wrapper.config.get("i3status_config_path", "/tmp")).parent storage_path = config_dir / "py3status.data" if storage_path.exists(): return storage_path diff --git a/py3status/udev_monitor.py b/py3status/udev_monitor.py index 4e62c5202a..5306bbde87 100644 --- a/py3status/udev_monitor.py +++ b/py3status/udev_monitor.py @@ -1,6 +1,6 @@ -from collections import defaultdict, Counter -from time import sleep +from collections import Counter, defaultdict from datetime import datetime +from time import sleep from py3status.constants import ON_TRIGGER_ACTIONS diff --git a/py3status/util.py b/py3status/util.py index e1d30659f1..fc6fb8f005 100644 --- a/py3status/util.py +++ b/py3status/util.py @@ -1,5 +1,5 @@ import re -from colorsys import rgb_to_hsv, hsv_to_rgb +from colorsys import hsv_to_rgb, rgb_to_hsv from math import modf @@ -94,14 +94,11 @@ def generate_gradient(self, color_list, size=101): steps = end - start for j in range(steps): - data.append( - self.hsv_2_hex(*self.make_mid_color(color1, color2, j / steps)) - ) + data.append(self.hsv_2_hex(*self.make_mid_color(color1, color2, j / steps))) data.append(self.hsv_2_hex(*color2)) return data def make_threshold_gradient(self, py3, thresholds, size=100): - """ Given a thresholds list, creates a gradient list that covers the range of the thresholds. diff --git a/py3status/version.py b/py3status/version.py index 0d9952215e..33dce8f9a0 100644 --- a/py3status/version.py +++ b/py3status/version.py @@ -1 +1 @@ -version = "3.51" +version = "3.52" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..0a070d200a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,102 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "py3status" +dynamic = ["version"] +description = "py3status: an extensible i3status wrapper written in python" +readme = "README.md" +license = "BSD-2-Clause" +requires-python = ">=3.7" +authors = [ + { name = "Ultrabug", email = "ultrabug@ultrabug.net" }, +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = [] + +[project.optional-dependencies] +udev = ["pyudev >= 0.21.0"] + +[project.urls] +Download = "https://github.com/ultrabug/py3status/tags" +Homepage = "https://github.com/ultrabug/py3status" + +[project.scripts] +py3status = "py3status:main" +py3-cmd = "py3status.command:send_command" + +[tool.hatch.version] +path = "py3status/version.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/py3status", +] + +[tool.hatch.envs.default.scripts] +all = [ + "hatch run test:test", + "hatch run style:check", +] + +[tool.hatch.envs.test] +dependencies = [ + "pytest" +] + +[tool.hatch.envs.test.scripts] +test = [ + "pytest -xs", +] + +[[tool.hatch.envs.test.matrix]] +python = ["py37", "py38", "py39", "py310", "py311"] +type = ["default"] + +[tool.hatch.envs.style] +detached = true +dependencies = [ + "black", + "isort", + "ruff", +] + +[tool.hatch.envs.style.scripts] +check = [ + "isort --check-only --diff py3status", + "black -q --check --diff py3status", + "ruff py3status", +] +format = [ + "isort -q py3status", + "black -q py3status", +] + +[tool.black] +line-length = 100 +target-version = ["py310"] +skip-string-normalization = true + +[tool.isort] +profile = "black" +line_length = 100 + +[tool.ruff] +line-length = 100 +ignore = ["E501"] \ No newline at end of file diff --git a/requirements/project.txt b/requirements/project.txt index dc2dea7598..1e4cbe970a 100644 --- a/requirements/project.txt +++ b/requirements/project.txt @@ -1,4 +1 @@ -isort==5.10.1 -flake8==4.0.1 -black==22.8.0 -click==8.0.4 +hatch==1.7.0 diff --git a/requirements/tests.txt b/requirements/tests.txt deleted file mode 100644 index c05135192d..0000000000 --- a/requirements/tests.txt +++ /dev/null @@ -1,3 +0,0 @@ -tox==3.26.0 -pytest==7.1.3 -pytest-flake8==1.1.1 diff --git a/setup.py b/setup.py index 0145e993b4..6d9e986af6 100755 --- a/setup.py +++ b/setup.py @@ -1,64 +1,13 @@ -""" -py3status -""" +"""Installation using setup.py is no longer supported. +Use `python -m pip install .` instead.""" -from setuptools import find_packages, setup -import fastentrypoints # noqa f401 import sys -from pathlib import Path -module_path = Path(__file__).resolve().parent / "py3status" -sys.path.insert(0, str(module_path)) -from version import version # noqa e402 +from setuptools import setup -sys.path.remove(str(module_path)) - - -# Utility function to read the README file. -# Used for the long_description. It's nice, because now 1) we have a top level -# README file and 2) it's easier to type in the README file than to put a raw -# string in below ... -def read(fname): - return (Path(__file__).resolve().parent / fname).read_text() - - -# extra requirements -req_udev = ["pyudev >= 0.21.0"] -req_all = req_udev +sys.exit(__doc__) +# Fake reference so GitHub still considers it a real package for statistics purposes. setup( name="py3status", - version=version, - author="Ultrabug", - author_email="ultrabug@ultrabug.net", - description="py3status: an extensible i3status wrapper written in python", - long_description=read("README.md"), - long_description_content_type="text/markdown", - extras_require={"all": req_all, "udev": req_udev}, - url="https://github.com/ultrabug/py3status", - download_url="https://github.com/ultrabug/py3status/tags", - license="BSD", - platforms="any", - packages=find_packages(), - include_package_data=True, - install_requires=["setuptools"], - entry_points={ - "console_scripts": [ - "py3status = py3status:main", - "py3-cmd = py3status.command:send_command", - ] - }, - python_requires=">=3.7", - classifiers=[ - "License :: OSI Approved :: BSD License", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3 :: Only", - "Topic :: Software Development :: Libraries :: Python Modules", - ], ) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 58b154beae..0000000000 --- a/tox.ini +++ /dev/null @@ -1,35 +0,0 @@ -[tox] -envlist = py37, py38, py39, py310, py311, mypy -skip_missing_interpreters = True - -[testenv] -skip_install = True -deps = - -rrequirements/project.txt - -rrequirements/tests.txt -commands = - {envbindir}/black --diff --check py3status/ - {envbindir}/black --diff --check setup.py fastentrypoints.py - {envbindir}/black --diff --check tests/ - {envbindir}/pytest --flake8 --exitfirst --capture=no - -[pytest] -# see .flake8 file in the black project: -# https://github.com/ambv/black/blob/master/.flake8 -flake8-ignore = - C901 - E203 - E266 - E501 - W503 - py3status/modules/*.py W605 W504 -flake8-max-complexity = 18 -flake8-max-line-length = 88 - -[gh-actions] -python = - 3.7: py37 - 3.8: py38 - 3.9: py39, mypy - 3.10: py310 - 3.11: py311