Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-py3status for 
openSUSE:Factory checked in at 2023-06-30 20:00:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-py3status (Old)
 and      /work/SRC/openSUSE:Factory/.python-py3status.new.13546 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-py3status"

Fri Jun 30 20:00:08 2023 rev:12 rq:1096164 version:3.51

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-py3status/python-py3status.changes        
2023-04-19 17:44:12.300621601 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-py3status.new.13546/python-py3status.changes 
    2023-06-30 20:00:33.242243650 +0200
@@ -1,0 +2,31 @@
+Fri Jun 30 15:06:00 UTC 2023 - Matej Cepl <mc...@suse.com>
+
+- Clean up SPEC file.
+
+-------------------------------------------------------------------
+Fri Jun 30 14:31:54 UTC 2023 - Dawid Adam <nys...@gmail.com>
+- Update to 3.51:
+  * NEW: thanks to Andreas Grapentin, py3status can now run in lots of other 
containers (tmux, term, dzen2, lemonbar...)
+  * IMPORTANT: modules are moving away from the obsolete pydbus library
+  * core: implement handling of output_format in py3status for i3bar, dzen2, 
xmobar, lemonbar, tmux, term, none (#2104), by Andreas Grapentin
+  * core: autodetect output_format (#2202), by lasers
+  * fix(module): report module post_config_hook errors thx to @lasers (#2208)
+  * docs(user): add a section to specify that modules dependencies are up to 
the users
+  * docs(mkdocs): drop mkdocs-simple-hooks closes #2195
+  * docs: fix two DeprecationWarning (#2191), by lasers
+  * docs(audiosink): fix screenshots (#2194), by lasers
+  * docs(autodoc): remove dead code thx to @lasers, closes #2183 (#2193)
+  * arch_updates module: add support for pikaur (#2182), by vim
+  * arch_updates module: remove cower support (gone) (#2190), by lasers
+  * backlight module: drop pydbus, switch to dbus-python
+  * bluetooth module: report battery percentage if available (#2185), by Alex 
Tsitsimpis
+  * clock module: added timezone information to times implicitly using local 
system timezone (#2197), by Andreas Grapentin
+  * clock module: minor patch to get the local timezone. (#2189), by Josh 
Sixsmith
+  * diskdata module: fix variable init type
+  * diskdata module: make module work on FreeBSD (#2200), by Björn Busse
+  * mpd_status module: fix UnboundLocalError (#2199), by Björn Busse
+  * ns_checker module: replace query() with resolve() (#2207), by Björn Busse
+  * systemd module: drop pydbus, switch to dbus-python
+  * vpn_status module: drop pydbus, switch to dbus-python
+
+-------------------------------------------------------------------

Old:
----
  py3status-3.50.tar.gz

New:
----
  py3status-3.51.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-py3status.spec ++++++
--- /var/tmp/diff_new_pack.gAOaqe/_old  2023-06-30 20:00:33.922247695 +0200
+++ /var/tmp/diff_new_pack.gAOaqe/_new  2023-06-30 20:00:33.930247743 +0200
@@ -17,24 +17,25 @@
 
 
 %define skip_python2 1
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-py3status
-Version:        3.50
+Version:        3.51
 Release:        0
 Summary:        Python extensible i3status wrapper
 License:        BSD-3-Clause
 URL:            https://github.com/ultrabug/py3status
 Source:         
https://files.pythonhosted.org/packages/source/p/py3status/py3status-%{version}.tar.gz
 BuildRequires:  %{python_module gevent >= 1.1}
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module pyudev >= 0.21.0}
-BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 Requires:       python-setuptools
 Requires(post): update-alternatives
 Requires(postun):update-alternatives
 Recommends:     i3status
+Recommends:     python-dbus-python
 Recommends:     python-gevent >= 1.1
 Recommends:     python-pyudev >= 0.21.0
 Provides:       py3status = %{version}
@@ -59,10 +60,10 @@
 %setup -q -n py3status-%{version}
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_clone -a %{buildroot}%{_bindir}/py3status
 %python_clone -a %{buildroot}%{_bindir}/py3-cmd
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
@@ -84,6 +85,7 @@
 %doc CHANGELOG README.md
 %python_alternative %{_bindir}/py3status
 %python_alternative %{_bindir}/py3-cmd
-%{python_sitelib}/py3status*
+%{python_sitelib}/py3status
+%{python_sitelib}/py3status-%{version}*-info
 
 %changelog

++++++ py3status-3.50.tar.gz -> py3status-3.51.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/CHANGELOG new/py3status-3.51/CHANGELOG
--- old/py3status-3.50/CHANGELOG        2023-04-17 18:42:48.000000000 +0200
+++ new/py3status-3.51/CHANGELOG        2023-06-27 09:27:54.000000000 +0200
@@ -1,3 +1,27 @@
+version 3.51 (2023-06-27)
+* NEW: thanks to Andreas Grapentin, py3status can now run in lots of other 
containers (tmux, term, dzen2, lemonbar...)
+* IMPORTANT: modules are moving away from the obsolete pydbus library
+* core: implement handling of output_format in py3status for i3bar, dzen2, 
xmobar, lemonbar, tmux, term, none (#2104), by Andreas Grapentin
+* core: autodetect output_format (#2202), by lasers
+* fix(module): report module post_config_hook errors thx to @lasers (#2208)
+* docs(user): add a section to specify that modules dependencies are up to the 
users
+* docs(mkdocs): drop mkdocs-simple-hooks closes #2195
+* docs: fix two DeprecationWarning (#2191), by lasers
+* docs(audiosink): fix screenshots (#2194), by lasers
+* docs(autodoc): remove dead code thx to @lasers, closes #2183 (#2193)
+* arch_updates module: add support for pikaur (#2182), by vim
+* arch_updates module: remove cower support (gone) (#2190), by lasers
+* backlight module: drop pydbus, switch to dbus-python
+* bluetooth module: report battery percentage if available (#2185), by Alex 
Tsitsimpis
+* clock module: added timezone information to times implicitly using local 
system timezone (#2197), by Andreas Grapentin
+* clock module: minor patch to get the local timezone. (#2189), by Josh 
Sixsmith
+* diskdata module: fix variable init type
+* diskdata module: make module work on FreeBSD (#2200), by Björn Busse
+* mpd_status module: fix UnboundLocalError (#2199), by Björn Busse
+* ns_checker module: replace query() with resolve() (#2207), by Björn Busse
+* systemd module: drop pydbus, switch to dbus-python
+* vpn_status module: drop pydbus, switch to dbus-python
+
 version 3.50 (2023-04-17)
 * update alpine install doc (#2176), by raspbeguy
 * battery_level module: fix invalid indexing, skip batteries with unavailable 
info (#2180), by lasers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/PKG-INFO new/py3status-3.51/PKG-INFO
--- old/py3status-3.50/PKG-INFO 2023-04-17 18:44:18.737956300 +0200
+++ new/py3status-3.51/PKG-INFO 2023-06-27 10:33:46.732813100 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: py3status
-Version: 3.50
+Version: 3.51
 Summary: py3status: an extensible i3status wrapper written in python
 Home-page: https://github.com/ultrabug/py3status
 Author: Ultrabug
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/autodoc.py 
new/py3status-3.51/py3status/autodoc.py
--- old/py3status-3.50/py3status/autodoc.py     2021-08-30 10:15:50.000000000 
+0200
+++ new/py3status-3.51/py3status/autodoc.py     2023-06-18 11:40:47.000000000 
+0200
@@ -1,117 +1,9 @@
-import ast
-import inspect
 import re
 
 from pathlib import Path
 
-from docutils import nodes
-from docutils.parsers.rst import Directive
-from pygments.lexer import RegexLexer, bygroups
-import pygments.token as pygments_token
-
 from py3status.docstrings import core_module_docstrings
-from py3status.screenshots import create_screenshots, get_samples, process
-from py3status.py3 import Py3
-
-
-# some Py3 methods have constants as defaults we need to identify them here
-CONSTANT_PARAMS = [("log", "level"), ("notify_user", "level")]
-
-
-class Py3statusLexer(RegexLexer):
-    """
-    A simple lexer for py3status configuration files.
-    This helps make the documentation more beautiful
-    """
-
-    name = "Py3status"
-    aliases = ["py3status"]
-    filenames = ["*.conf"]
-
-    tokens = {
-        "root": [
-            (r"#.*?$", pygments_token.Comment),  # comments
-            (  # double quoted strings
-                r'"(?:[^"\\]|\\.)*"',
-                pygments_token.String.Double,
-            ),
-            (  # single quoted strings
-                r"'(?:[^'\\]|\\.)*'",
-                pygments_token.String.Single,
-            ),
-            (r"([0-9]+)|([0-9]*)\.([0-9]*)", pygments_token.Number),  # numbers
-            (r"[Tt]rue|[Ff]alse|[Nn]one", pygments_token.Literal),  # True, 
False & None
-            (r"(\+=)|=", pygments_token.Operator),  # = and +=
-            (r"[{}\[\](),:]", pygments_token.Punctuation),  # other things 
like (){}[],:
-            (  # config functions eg env(value, type)
-                r"(\S+)([(])(([^)\\]|\\.)*)((\s*,\s*)(\w+))?([)])",
-                bygroups(
-                    pygments_token.Name.Function,
-                    pygments_token.Punctuation,
-                    pygments_token.Literal,
-                    None,
-                    None,
-                    pygments_token.Punctuation,
-                    pygments_token.Keyword.Type,
-                    pygments_token.Punctuation,
-                ),
-            ),
-            (  # module names
-                r"(\S+)(\s*)([^=]*)(\s*)(\{)",
-                bygroups(
-                    pygments_token.Keyword.Reserved,
-                    pygments_token.Whitespace,
-                    pygments_token.Keyword.Reserved,
-                    pygments_token.Whitespace,
-                    pygments_token.Punctuation,
-                ),
-            ),
-            (  # order += ....
-                r"^(order)(\s+)(\+=)",
-                bygroups(
-                    pygments_token.Keyword.Reserved,
-                    pygments_token.Whitespace,
-                    pygments_token.Punctuation,
-                ),
-            ),
-            (r"on_click\s*\d", pygments_token.Name.Variable),  # on_click x
-            (  # module parameters
-                r"(\w+)((:)(\S+))?",
-                bygroups(
-                    pygments_token.Name.Variable,
-                    None,
-                    pygments_token.Punctuation,
-                    pygments_token.Keyword.Type,
-                ),
-            ),
-            (r"\s+", pygments_token.Whitespace),  # whitespace
-        ]
-    }
-
-
-def markdown_2_rst(lines):
-    """
-    Convert markdown to restructured text
-    """
-    out = []
-    code = False
-    for line in lines:
-        # code blocks
-        if line.strip() == "```":
-            code = not code
-            space = " " * (len(line.rstrip()) - 3)
-            if code:
-                out.append(f"\n\n{space}.. code-block:: none\n\n")
-            else:
-                out.append("\n")
-        else:
-            if code and line.strip():
-                line = "    " + line
-            else:
-                # escape any backslashes
-                line = line.replace("\\", "\\\\")
-            out.append(line)
-    return out
+from py3status.screenshots import create_screenshots, get_samples
 
 
 def file_sort(my_list):
@@ -177,184 +69,10 @@
     return config
 
 
-def get_variable_docstrings(filename):
-    """
-    Go through the file and find all documented variables.
-    That is ones that have a literal expression following them.
-
-    Also get a dict of assigned values so that we can substitute constants.
-    """
-
-    def walk_node(parent, values=None, prefix=""):
-        """
-        walk the ast searching for docstrings/values
-        """
-        docstrings = {}
-        if values is None:
-            values = {}
-        key = None
-        for node in ast.iter_child_nodes(parent):
-            if isinstance(node, ast.ClassDef):
-                # We are in a class so walk the class
-                docs = walk_node(node, values, prefix + node.name + ".")[0]
-                docstrings[node.name] = docs
-            elif isinstance(node, ast.Assign):
-                key = node.targets[0].id
-                if isinstance(node.value, ast.Num):
-                    values[key] = node.value.n
-                if isinstance(node.value, ast.Str):
-                    values[key] = node.value.s
-                if isinstance(node.value, ast.Name):
-                    if node.value.id in values:
-                        values[prefix + key] = values[node.value.id]
-            elif isinstance(node, ast.Expr) and key:
-                docstrings[key] = node.value.s
-            else:
-                key = None
-        return docstrings, values
-
-    return walk_node(ast.parse(filename.read_text()))
-
-
-def get_py3_info():
-    """
-    Inspect Py3 class and get constants, exceptions, methods
-    along with their docstrings.
-    """
-    # get all documented constants and their values
-    constants, values = get_variable_docstrings(Path("../py3status/py3.py"))
-    # we only care about ones defined in Py3
-    constants = constants["Py3"]
-    # sort them alphabetically
-    constants = sorted(constants.items())
-
-    # filter values as we only care about values defined in Py3
-    values = {v: k[4:] for k, v in values.items() if k.startswith("Py3.")}
-
-    def make_value(attr, arg, default):
-        """
-        If the methods parameter is defined as a constant then do a
-        replacement.  Otherwise return the values representation.
-        """
-        if (attr, arg) in CONSTANT_PARAMS and default in values:
-            return values[default]
-        return repr(default)
-
-    # inspect Py3 to find it's methods etc
-    py3 = Py3()
-    # no private ones
-    attrs = [x for x in dir(py3) if not x.startswith("_")]
-    exceptions = []
-    methods = []
-    for attr in attrs:
-        item = getattr(py3, attr)
-        if "method" in str(item):
-            # a method so we need to get the call parameters
-            args, vargs, kw, defaults = inspect.getargspec(item)
-            args = args[1:]
-            len_defaults = len(defaults) if defaults else 0
-            len_args = len(args)
-
-            sig = []
-            for index, arg in enumerate(args):
-                # default values set?
-                if len_args - index <= len_defaults:
-                    default = defaults[len_defaults - len_args + index]
-                    sig.append("{}={}".format(arg, make_value(attr, arg, 
default)))
-                else:
-                    sig.append(arg)
-
-            definition = "{}({})".format(attr, ", ".join(sig))
-            methods.append((definition, item.__doc__))
-            continue
-        try:
-            # find any exceptions
-            if isinstance(item(), Exception):
-                exceptions.append((attr, item.__doc__))
-                continue
-        except:  # noqa e722
-            pass
-    return {"methods": methods, "exceptions": exceptions, "constants": 
constants}
-
-
-def auto_undent(string):
-    """
-    Unindent a docstring.
-    """
-    lines = string.splitlines()
-    while lines[0].strip() == "":
-        lines = lines[1:]
-        if not lines:
-            return []
-    spaces = len(lines[0]) - len(lines[0].lstrip(" "))
-    out = []
-    for line in lines:
-        num_spaces = len(line) - len(line.lstrip(" "))
-        out.append(line[min(spaces, num_spaces) :])
-    return out
-
-
-def create_py3_docs():
-    """
-    Create the include files for py3 documentation.
-    """
-    # we want the correct .rst 'type' for our data
-    trans = {"methods": "function", "exceptions": "exception", "constants": 
"attribute"}
-    data = get_py3_info()
-    for k, v in data.items():
-        output = []
-        for name, desc in v:
-            output.append("")
-            output.append(f".. _{name}:")  # reference for linking
-            output.append("")
-            output.append(f".. py:{trans[k]}:: {name}")
-            output.append("")
-            output.extend(auto_undent(desc))
-        Path(f"../docs/py3-{k}-info.inc").write_text("\n".join(output))
-
-
-def create_auto_documentation(config):
+def on_config(config):
     """
     Create any include files needed for sphinx documentation
     """
     create_screenshots(config)
     create_module_docs(config)
     return config
-
-
-class ScreenshotDirective(Directive):
-    """
-    Adds the ability to add screenshots dynamically in sphinx documentation
-
-    .. screenshot::
-
-        {'color': '#00FF00', 'full_text': 'Example output'}
-
-    """
-
-    has_content = True
-
-    def run(self):
-        env = self.state.document.settings.env
-
-        targetid = f"screenshot-{env.new_serialno('screenshot')}"
-        targetnode = nodes.target("", "", ids=[targetid])
-
-        image_name = f"_{targetid}"
-        try:
-            content = ast.literal_eval("\n".join(self.content))
-        except:  # noqa e722
-            content = {
-                "color": "#990000",
-                "background": "#FFFF00",
-                "full_text": " IMAGE DATA ERROR ",
-            }
-
-        process(image_name, content, False)
-        image_path = Path("screenshots") / (image_name + ".png")
-        screenshot_node = nodes.image(uri=image_path)
-        return [targetnode, screenshot_node]
-
-
-if __name__ == "__main__":
-    create_auto_documentation()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/constants.py 
new/py3status-3.51/py3status/constants.py
--- old/py3status-3.50/py3status/constants.py   2022-10-02 17:24:36.000000000 
+0200
+++ new/py3status-3.51/py3status/constants.py   2023-06-18 14:26:19.000000000 
+0200
@@ -7,7 +7,7 @@
     "color_separator": "#333333",
     "colors": True,
     "interval": 5,
-    "output_format": "i3bar",
+    "output_format": None,
 }
 
 MAX_NESTING_LEVELS = 4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/core.py 
new/py3status-3.51/py3status/core.py
--- old/py3status-3.50/py3status/core.py        2022-10-27 12:10:18.000000000 
+0200
+++ new/py3status-3.51/py3status/core.py        2023-06-18 14:26:19.000000000 
+0200
@@ -3,7 +3,6 @@
 import time
 
 from collections import deque
-from json import dumps
 from pathlib import Path
 from pprint import pformat
 from signal import signal, Signals, SIGTERM, SIGUSR1, SIGTSTP, SIGCONT
@@ -19,6 +18,7 @@
 from py3status.i3status import I3status
 from py3status.parse_config import process_config
 from py3status.module import Module
+from py3status.output import OutputFormat
 from py3status.profiling import profile
 from py3status.udev_monitor import UdevMonitor
 
@@ -613,6 +613,16 @@
         self.log("config file: {}".format(self.config["i3status_config_path"]))
         self.config["py3_config"] = process_config(config_path, self)
 
+        # autodetect output_format
+        output_format = self.config["py3_config"]["general"]["output_format"]
+        if output_format is None:
+            if sys.stdout.isatty():
+                print("py3status: trying to auto-detect output_format setting")
+                print('py3status: auto-detected "term"')
+                output_format = "term"
+
+        self.config["py3_config"]["general"]["output_format"] = output_format 
or "i3bar"
+
         # read resources
         if "resources" in str(self.config["py3_config"].values()):
             from subprocess import check_output
@@ -722,6 +732,20 @@
             # load and spawn i3status.conf configured modules threads
             self.load_modules(self.py3_modules, user_modules)
 
+        # determine the target output format
+        self.output_format = OutputFormat.instance_for(
+            self.config["py3_config"]["general"]["output_format"]
+        )
+
+        # determine the output separator, if needed
+        color_separator = None
+        if self.config["py3_config"]["general"]["colors"]:
+            color_separator = 
self.config["py3_config"]["general"]["color_separator"]
+        self.output_format.format_separator(
+            self.config["py3_config"]["general"].get("separator", None),
+            color_separator,
+        )
+
     def notify_user(
         self,
         msg,
@@ -1015,8 +1039,8 @@
                     # Color: substitute the config defined color
                     if "color" not in output:
                         output["color"] = color
-        # Create the json string output.
-        return ",".join(dumps(x) for x in outputs)
+        # format output and return
+        return self.output_format.format(outputs)
 
     def i3bar_stop(self, signum, frame):
         if (
@@ -1089,17 +1113,13 @@
         # items in the bar
         output = [None] * len(py3_config["order"])
 
-        write = sys.__stdout__.write
-        flush = sys.__stdout__.flush
-
         # start our output
         header = {
             "version": 1,
             "click_events": self.config["click_events"],
             "stop_signal": self.stop_signal or 0,
         }
-        write(dumps(header))
-        write("\n[[]\n")
+        self.output_format.write_header(header)
 
         update_due = None
         # main loop
@@ -1126,8 +1146,5 @@
                         # store the output as json
                         output[index] = out
 
-                # build output string
-                out = ",".join(x for x in output if x)
-                # dump the line to stdout
-                write(f",[{out}]\n")
-                flush()
+                # build output string and dump to stdout
+                self.output_format.write_line(output)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/i3status.py 
new/py3status-3.51/py3status/i3status.py
--- old/py3status-3.50/py3status/i3status.py    2022-10-02 20:12:35.000000000 
+0200
+++ new/py3status-3.51/py3status/i3status.py    2023-06-18 11:22:17.000000000 
+0200
@@ -330,6 +330,12 @@
                         value = TZTIME_FORMAT
                     if key == "format_time":
                         continue
+                # Set output_format to i3bar in general section so that we
+                # receive predictable output from i3status, regardless of our
+                # own output_format configuration
+                if section_name == "general":
+                    if key == "output_format":
+                        value = "i3bar"
                 if isinstance(value, bool):
                     value = f"{value}".lower()
                 self.write_in_tmpfile(f'    {key} = "{value}"\n', tmpfile)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/module.py 
new/py3status-3.51/py3status/module.py
--- old/py3status-3.50/py3status/module.py      2023-01-09 18:39:16.000000000 
+0100
+++ new/py3status-3.51/py3status/module.py      2023-06-27 09:04:06.000000000 
+0200
@@ -150,12 +150,10 @@
 
                 self.error_messages = [
                     self.module_nice_name,
-                    "{}: {}".format(
-                        self.module_nice_name, str(e) or e.__class__.__name__
-                    ),
+                    f"{e}",
                 ]
-                self.runtime_error(self.error_messages[0], "post_config_hook")
-                msg = f"Exception in `{self.module_full_name}` 
post_config_hook()"
+                self.runtime_error(self.error_messages[1], "post_config_hook")
+                msg = f"Exception in `{self.module_full_name}` 
post_config_hook() : {self.error_messages}"
                 self._py3_wrapper.report_exception(msg, notify_user=False)
                 self._py3_wrapper.log(f"terminating module 
{self.module_full_name}")
         self.enabled = True
@@ -175,7 +173,7 @@
         # only show first line of error
         msg = msg.splitlines()[0]
 
-        errors = [self.module_nice_name, f"{self.module_nice_name}: {msg}"]
+        errors = [self.module_nice_name, f"{self.module_nice_name}[{method}]: 
{msg}"]
 
         # if we have shown this error then keep in the same state
         if self.error_messages != errors:
@@ -202,7 +200,11 @@
             "name": self.module_name,
         }
         for method in self.methods.values():
-            if method_affected and method["method"] != method_affected:
+            if (
+                method_affected
+                and method["method"] != method_affected
+                and method_affected != "post_config_hook"
+            ):
                 continue
 
             method["last_output"] = [error]
@@ -338,11 +340,17 @@
 
         separator = fn(self.module_full_name, "separator")
         if not hasattr(separator, "none_setting"):
-            if not isinstance(separator, bool):
-                err = "Invalid `separator` attribute, should be a boolean. "
-                err += f"Got `{separator}`."
-                raise TypeError(err)
-            self.i3bar_module_options["separator"] = separator
+            # HACK: separator is a valid setting in the general section
+            # of the configuration. but it's a string, not a boolean.
+            # revisit how i3status and py3status differ in this regard.
+            # if not isinstance(separator, bool):
+
+            #     err = "Invalid `separator` attribute, should be a boolean. "
+            #     err += f"Got `{separator}`."
+            #     raise TypeError(err)
+            # self.i3bar_module_options["separator"] = separator
+            if isinstance(separator, bool):
+                self.i3bar_module_options["separator"] = separator
 
         separator_block_width = fn(self.module_full_name, 
"separator_block_width")
         if not hasattr(separator_block_width, "none_setting"):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/arch_updates.py 
new/py3status-3.51/py3status/modules/arch_updates.py
--- old/py3status-3.50/py3status/modules/arch_updates.py        2022-10-02 
16:25:48.000000000 +0200
+++ new/py3status-3.51/py3status/modules/arch_updates.py        2023-06-05 
13:45:55.000000000 +0200
@@ -17,6 +17,7 @@
     trizen: lightweight pacman wrapper and AUR helper
     yay: yet another yogurt. pacman wrapper and aur helper written in go
     paru: feature packed AUR helper
+    pikaur: pacman wrapper and AUR helper written in python
 
 @author Iain Tatch <iain.ta...@gmail.com>
 @license BSD
@@ -46,7 +47,7 @@
         helper = {
             "pacman": self.py3.check_commands(["checkupdates"]),
             "aur": self.py3.check_commands(
-                ["auracle", "trizen", "yay", "cower", "paru"]
+                ["auracle", "trizen", "yay", "paru", "pikaur"]
             ),
         }
         if self.format:
@@ -88,13 +89,6 @@
         except self.py3.CommandError as ce:
             return None if ce.error else 0
 
-    def _get_cower_updates(self):
-        try:
-            self.py3.command_output(["cower", "-u"])
-            return None
-        except self.py3.CommandError as ce:
-            return len(ce.output.splitlines())
-
     def _get_trizen_updates(self):
         try:
             updates = self.py3.command_output(["trizen", "-Suaq"])
@@ -115,6 +109,13 @@
             return len(updates.splitlines())
         except self.py3.CommandError as ce:
             return None if ce.error else 0
+
+    def _get_pikaur_updates(self):
+        try:
+            updates = self.py3.command_output(["pikaur", "-Qua"])
+            return len(updates.splitlines())
+        except self.py3.CommandError as ce:
+            return None if ce.error else 0
 
     def arch_updates(self):
         pacman, aur, total, full_text = None, None, None, ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/audiosink.py 
new/py3status-3.51/py3status/modules/audiosink.py
--- old/py3status-3.50/py3status/modules/audiosink.py   2022-08-25 
16:38:50.000000000 +0200
+++ new/py3status-3.51/py3status/modules/audiosink.py   2023-06-18 
10:05:11.000000000 +0200
@@ -26,12 +26,14 @@
 }
 ```
 
+@author Jens Brandt <py3sta...@brandt-george.de>
+@license BSD
+
 SAMPLE OUTPUT
 {'full_text': 'Dock'}
-{'full_text': 'Int'}
 
-@author Jens Brandt <py3sta...@brandt-george.de>
-@license BSD
+int
+{'full_text': 'Int'}
 """
 
 import os
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/backlight.py 
new/py3status-3.51/py3status/modules/backlight.py
--- old/py3status-3.50/py3status/modules/backlight.py   2023-02-02 
16:30:54.000000000 +0100
+++ new/py3status-3.51/py3status/modules/backlight.py   2023-06-27 
09:04:06.000000000 +0200
@@ -35,7 +35,7 @@
 Requires: one of
     xbacklight: need for changing brightness, not detection
     light: program to easily change brightness on backlight-controllers
-    pydbus + logind v243: logind to change brightness without X
+    dbus-python + logind v243: logind to change brightness without X
 
 @author Tjaart van der Walt (github:tjaartvdwalt), Jérémy Rosen 
(github:boucman)
 @license BSD
@@ -46,10 +46,7 @@
 
 from pathlib import Path
 
-try:
-    from pydbus import SystemBus
-except ImportError:
-    pass
+import dbus
 
 STRING_NOT_AVAILABLE = "no available device"
 
@@ -103,9 +100,9 @@
 
     def post_config_hook(self):
         try:
-            self._logind_proxy = SystemBus().get(
-                bus_name="org.freedesktop.login1",
-                object_path="/org/freedesktop/login1/session/self",
+            bus = dbus.SystemBus()
+            self._logind_proxy = bus.get_object(
+                "org.freedesktop.login1", 
"/org/freedesktop/login1/session/self"
             )
         except NameError:
             self._logind_proxy = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/bluetooth.py 
new/py3status-3.51/py3status/modules/bluetooth.py
--- old/py3status-3.50/py3status/modules/bluetooth.py   2023-01-10 
13:36:52.000000000 +0100
+++ new/py3status-3.51/py3status/modules/bluetooth.py   2023-05-30 
19:01:27.000000000 +0200
@@ -39,6 +39,7 @@
     {address}          eg, 00:00:00:00:00:00
     {addresstype}      eg, public
     {alias}            eg, MSFT Mouse
+    {battery}          eg, 95
     {class}            eg, 1234
     {connected}        eg, False
     {icon}             eg, input-mouse
@@ -130,7 +131,8 @@
             for name, match in self.names_and_matches:
                 if match in interface_keys:
                     interface = {k.lower(): v for k, v in 
interfaces[match].items()}
-                    interface.update({"path": path, "uuids": []})
+                    battery = interfaces.get("org.bluez.Battery1", 
{}).get("Percentage")
+                    interface.update({"path": path, "uuids": [], "battery": 
battery})
                     temporary.setdefault(name, []).append(interface)
                     break
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/clock.py 
new/py3status-3.51/py3status/modules/clock.py
--- old/py3status-3.50/py3status/modules/clock.py       2022-10-27 
10:35:49.000000000 +0200
+++ new/py3status-3.51/py3status/modules/clock.py       2023-06-18 
11:23:36.000000000 +0200
@@ -189,10 +189,7 @@
         """
         # special Local timezone
         if tz == "Local":
-            try:
-                return zoneinfo.ZoneInfo("localtime")
-            except zoneinfo.ZoneInfoNotFoundError:
-                return "?"
+            return None
         # get the timezone
         try:
             zone = zoneinfo.ZoneInfo(tz)
@@ -251,7 +248,12 @@
                     idx = int(h / self.block_hours * len(self.blocks))
                     icon = self.blocks[idx]
 
-                timezone = zone.key
+                # special case for handling Local timezone
+                if zone is None:
+                    t = t.astimezone()
+                    timezone = t.tzname()
+                else:
+                    timezone = zone.key
                 tzname = timezone.split("/")[-1].replace("_", " ")
 
                 if self.multiple_tz:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/diskdata.py 
new/py3status-3.51/py3status/modules/diskdata.py
--- old/py3status-3.50/py3status/modules/diskdata.py    2022-10-02 
16:25:48.000000000 +0200
+++ new/py3status-3.51/py3status/modules/diskdata.py    2023-06-18 
11:28:19.000000000 +0200
@@ -6,7 +6,7 @@
     disk: show stats for disk or partition, i.e. `sda1`. None for all disks.
         (default None)
     format: display format for this module.
-        (default "{disk}: {used_percent}% ({total})")
+        (default "{disk}: {used_percent}%[ ({total})]")
     format_rate: display format for rates value
         (default "[\?min_length=11 {value:.1f} {unit}]")
     format_space: display format for disk space values
@@ -65,7 +65,7 @@
     # available configuration parameters
     cache_timeout = 10
     disk = None
-    format = "{disk}: {used_percent}% ({total})"
+    format = "{disk}: {used_percent}%[ ({total})]"
     format_rate = r"[\?min_length=11 {value:.1f} {unit}]"
     format_space = r"[\?min_length=5 {value:.1f}]"
     sector_size = 512
@@ -90,8 +90,11 @@
                 self.init[name] = {"placeholders": placeholders, "keys": match}
 
         if self.init["diskstats"]:
-            self.last_diskstats = self._get_diskstats(self.disk)
-            self.last_time = time.monotonic()
+            try:
+                self.last_diskstats = self._get_diskstats(self.disk)
+                self.last_time = time.monotonic()
+            except Exception:
+                self.init["diskstats"] = {}
 
         self.thresholds_init = self.py3.get_color_names_list(self.format)
 
@@ -102,12 +105,16 @@
             df_usages = ce.output
         total, used, free, devs = 0, 0, 0, []
 
-        if disk and not disk.startswith("/dev/"):
-            disk = "/dev/" + disk
+        disk_dev = None
+
+        if disk:
+            disk_dev = "/dev/" + disk
 
         for line in df_usages.splitlines():
-            if (disk and line.startswith(disk)) or (
-                disk is None and line.startswith("/dev/")
+            if (
+                (disk and line.startswith(disk))
+                or (disk_dev and line.startswith(disk_dev))
+                or (disk is None and line.startswith("/dev/"))
             ):
                 data = line.split()
                 if data[0] in devs:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/mpd_status.py 
new/py3status-3.51/py3status/modules/mpd_status.py
--- old/py3status-3.50/py3status/modules/mpd_status.py  2022-10-02 
16:25:48.000000000 +0200
+++ new/py3status-3.51/py3status/modules/mpd_status.py  2023-06-18 
11:20:01.000000000 +0200
@@ -256,8 +256,7 @@
                     text = "Failed to authenticate to mpd!"
                     self._get_mpd(disconnect=True)
 
-                state = None
-                self.current_status = (text, status)
+                self.current_status = (text, None)
                 return
             finally:
                 self.py3.update()  # to propagate error message
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/ns_checker.py 
new/py3status-3.51/py3status/modules/ns_checker.py
--- old/py3status-3.50/py3status/modules/ns_checker.py  2022-10-02 
16:25:48.000000000 +0200
+++ new/py3status-3.51/py3status/modules/ns_checker.py  2023-06-27 
09:04:06.000000000 +0200
@@ -72,7 +72,7 @@
         if self.resolvers:
             my_resolver.nameservers = self.resolvers
 
-        my_ns = my_resolver.query(self.domain, "NS")
+        my_ns = my_resolver.resolve(self.domain, "NS")
 
         # Insert each NS ip address in nameservers
         for ns in my_ns:
@@ -84,7 +84,7 @@
         for ns in nameservers:
             my_resolver.nameservers = [ns]
             try:
-                my_resolver.query(self.domain, "A")
+                my_resolver.resolve(self.domain, "A")
                 count_ok += 1
             except:  # noqa e722
                 count_nok += 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/systemd.py 
new/py3status-3.51/py3status/modules/systemd.py
--- old/py3status-3.50/py3status/modules/systemd.py     2022-10-02 
16:25:48.000000000 +0200
+++ new/py3status-3.51/py3status/modules/systemd.py     2023-06-27 
09:04:06.000000000 +0200
@@ -25,7 +25,8 @@
     color_degraded: unit not-found
 
 Requires:
-    pydbus: pythonic dbus library
+    dbus-python: to interact with dbus
+    pygobject: which in turn requires libcairo2-dev, libgirepository1.0-dev
 
 Examples:
 ```
@@ -51,7 +52,7 @@
 {'color': '#FFFF00', 'full_text': 'sshd.service: not-found'}
 """
 
-from pydbus import SessionBus, SystemBus
+import dbus
 
 
 class Py3status:
@@ -67,16 +68,30 @@
 
     def post_config_hook(self):
         if self.user:
-            bus = SessionBus()
+            bus = dbus.SessionBus()
         else:
-            bus = SystemBus()
-        systemd = bus.get("org.freedesktop.systemd1")
-        self.systemd_unit = bus.get(".systemd1", systemd.LoadUnit(self.unit))
+            bus = dbus.SystemBus()
+        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"
+        )
 
     def systemd(self):
-        status = self.systemd_unit.Get("org.freedesktop.systemd1.Unit", 
"ActiveState")
-        exists = self.systemd_unit.Get("org.freedesktop.systemd1.Unit", 
"LoadState")
-        state = self.systemd_unit.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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/modules/vpn_status.py 
new/py3status-3.51/py3status/modules/vpn_status.py
--- old/py3status-3.50/py3status/modules/vpn_status.py  2023-04-17 
18:41:49.000000000 +0200
+++ new/py3status-3.51/py3status/modules/vpn_status.py  2023-06-27 
09:04:06.000000000 +0200
@@ -22,7 +22,8 @@
     color_good: VPN down
 
 Requires:
-    pydbus: Which further requires PyGi. Check your distribution's 
repositories.
+    dbus-python: to interact with dbus
+    pygobject: which in turn requires libcairo2-dev, libgirepository1.0-dev
 
 @author Nathan Smith <nathan AT praisetopia.org>
 
@@ -33,12 +34,14 @@
 {'color': '#FF0000', 'full_text': u'VPN: no'}
 """
 
-from pydbus import SystemBus
-from gi.repository import GObject
+from dbus.mainloop.glib import DBusGMainLoop
+from gi.repository import GLib
 from threading import Thread
 from time import sleep
 from pathlib import Path
 
+import dbus
+
 
 class Py3status:
     """ """
@@ -66,15 +69,25 @@
     def _start_loop(self):
         """Starts main event handler loop, run in handler thread t."""
         # Create our main loop, get our bus, and add the signal handler
-        loop = GObject.MainLoop()
-        bus = SystemBus()
-        manager = bus.get(".NetworkManager")
-        manager.onPropertiesChanged = self._vpn_signal_handler
+        loop = DBusGMainLoop(set_as_default=True)
+        dbus.set_default_main_loop(loop)
 
-        # initialize active connections, some of them might be VPNs
-        self.active = manager.ActiveConnections
+        bus = dbus.SystemBus()
+        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"
+        )
 
-        # Loop forever
+        # Loop forever to listen for events
+        loop = GLib.MainLoop()
         loop.run()
 
     def _vpn_signal_handler(self, *args):
@@ -97,12 +110,23 @@
         # Sleep for a bit to let any changes in state finish
         sleep(0.3)
         # Check if any active connections are a VPN
-        bus = SystemBus()
+        bus = dbus.SystemBus()
         ids = []
         for name in self.active:
-            conn = bus.get(".NetworkManager", name)
-            if conn.Vpn or conn.Type == "wireguard":
-                ids.append(conn.Id)
+            manager = bus.get_object(
+                "org.freedesktop.NetworkManager",
+                name,
+            )
+            interface = dbus.Interface(manager, 
"org.freedesktop.DBus.Properties")
+            try:
+                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:
+                # the connection id has disappeared
+                pass
         # No active VPN
         return ids
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/output.py 
new/py3status-3.51/py3status/output.py
--- old/py3status-3.50/py3status/output.py      1970-01-01 01:00:00.000000000 
+0100
+++ new/py3status-3.51/py3status/output.py      2023-06-18 11:22:17.000000000 
+0200
@@ -0,0 +1,269 @@
+import sys
+from json import dumps
+
+
+class OutputFormat:
+    """
+    A base class for formatting the output of py3status for various
+    different consumers
+    """
+
+    @classmethod
+    def instance_for(cls, output_format):
+        """
+        A factory for OutputFormat objects
+        """
+        supported_output_formats = {
+            "dzen2": Dzen2OutputFormat,
+            "i3bar": I3barOutputFormat,
+            "lemonbar": LemonbarOutputFormat,
+            "none": NoneOutputFormat,
+            "term": TermOutputFormat,
+            "tmux": TmuxOutputFormat,
+            "xmobar": XmobarOutputFormat,
+        }
+
+        if output_format in supported_output_formats:
+            return supported_output_formats[output_format]()
+        raise ValueError(
+            f"Invalid `output_format` attribute, should be one of `{'`, 
`'.join(supported_output_formats.keys())}`. Got `{output_format}`."
+        )
+
+    def __init__(self):
+        """
+        Constructor
+        """
+        self.separator = None
+
+    def format_separator(self, separator, color):
+        """
+        Produce a formatted and colorized separator for the output format,
+        if the output_format requires it, and None otherwise.
+        """
+        pass
+
+    def format(self, outputs):
+        """
+        Produce a line of output from a list of module output dictionaries
+        """
+        raise NotImplementedError()
+
+    def write_header(self, header):
+        """
+        Write the header to output, if supported by the output_format
+        """
+        raise NotImplementedError()
+
+    def write_line(self, output):
+        """
+        Write a line of py3status containing the given module output
+        """
+        raise NotImplementedError()
+
+
+class I3barOutputFormat(OutputFormat):
+    """
+    Format the output for consumption by i3bar
+    """
+
+    def format(self, outputs):
+        """
+        Produce a line of output from a list of module outputs for
+        consumption by i3bar. separator is ignored.
+        """
+        return ",".join(dumps(x) for x in outputs)
+
+    def write_header(self, header):
+        """
+        Write the i3bar header to output
+        """
+        write = sys.__stdout__.write
+        flush = sys.__stdout__.flush
+
+        write(dumps(header))
+        write("\n[[]\n")
+        flush()
+
+    def write_line(self, output):
+        """
+        Write a line of py3status output for consumption by i3bar
+        """
+        write = sys.__stdout__.write
+        flush = sys.__stdout__.flush
+
+        out = ",".join(x for x in output if x)
+        write(f",[{out}]\n")
+        flush()
+
+
+class SeparatedOutputFormat(OutputFormat):
+    """
+    Base class for formatting output as an enriched string containing
+    separators
+    """
+
+    def begin_color(self, color):
+        """
+        Produce a format string for a colorized output for the output format
+        """
+        raise NotImplementedError()
+
+    def end_color(self):
+        """
+        Produce a format string for ending a colorized output for the output 
format
+        """
+        raise NotImplementedError()
+
+    def end_color_quick(self):
+        """
+        Produce a format string for ending a colorized output, but only
+        if it is syntactically required. (for example because a new color
+        declaration immediately follows)
+        """
+        return self.end_color()
+
+    def get_default_separator(self):
+        """
+        Produce the default separator for the output format
+        """
+        return " | "
+
+    def format_separator(self, separator, color):
+        """
+        Format the given separator with the given color
+        """
+        if separator is None:
+            separator = self.get_default_separator()
+        if color is not None:
+            separator = self.begin_color(color) + separator + self.end_color()
+        self.separator = separator
+
+    def format_color(self, block):
+        """
+        Format the given block of module output
+        """
+        full_text = block["full_text"]
+        if "color" in block:
+            full_text = (
+                self.begin_color(block["color"]) + full_text + 
self.end_color_quick()
+            )
+        return full_text
+
+    def format(self, outputs):
+        """
+        Produce a line of output from a list of module outputs by
+        concatenating individual blocks of formatted output
+        """
+        return "".join(self.format_color(x) for x in outputs)
+
+    def write_header(self, header):
+        """
+        Not supported in separated output formats
+        """
+        pass
+
+    def write_line(self, output):
+        """
+        Write a line of py3status output separated by the formatted separator
+        """
+        write = sys.__stdout__.write
+        flush = sys.__stdout__.flush
+
+        out = self.separator.join(x for x in output if x)
+        write(f"{out}\n")
+        flush()
+
+
+class Dzen2OutputFormat(SeparatedOutputFormat):
+    """
+    Format the output for consumption by dzen2
+    """
+
+    def begin_color(self, color):
+        return f"^fg({color})"
+
+    def end_color(self):
+        return "^fg()"
+
+    def end_color_quick(self):
+        return ""
+
+    def get_default_separator(self):
+        """
+        Produce the default separator for the output format
+        """
+        return "^p(5;-2)^ro(2)^p()^p(5)"
+
+
+class XmobarOutputFormat(SeparatedOutputFormat):
+    """
+    Format the output for consumption by xmobar
+    """
+
+    def begin_color(self, color):
+        return f"<fc={color}>"
+
+    def end_color(self):
+        return "</fc>"
+
+
+class LemonbarOutputFormat(SeparatedOutputFormat):
+    """
+    Format the output for consumption by lemonbar
+    """
+
+    def begin_color(self, color):
+        return f"%{{F{color}}}"
+
+    def end_color(self):
+        return "%{F-}"
+
+    def end_color_quick(self):
+        return ""
+
+
+class TmuxOutputFormat(SeparatedOutputFormat):
+    """
+    Format the output for consumption by tmux
+    """
+
+    def begin_color(self, color):
+        return f"#[fg={color.lower()}]"
+
+    def end_color(self):
+        return "#[default]"
+
+    def end_color_quick(self):
+        return ""
+
+
+class TermOutputFormat(SeparatedOutputFormat):
+    """
+    Format the output using terminal escapes
+    """
+
+    def begin_color(self, color):
+        col = int(color[1:], 16)
+        r = (col & (0xFF << 0)) // 0x80
+        g = (col & (0xFF << 8)) // 0x8000
+        b = (col & (0xFF << 16)) // 0x800000
+        col = (r << 2) | (g << 1) | b
+        return f"\033[3{col};1m"
+
+    def end_color(self):
+        return "\033[0m"
+
+    def end_color_quick(self):
+        return ""
+
+
+class NoneOutputFormat(SeparatedOutputFormat):
+    """
+    Format the output without colors
+    """
+
+    def begin_color(self, color):
+        return ""
+
+    def end_color(self):
+        return ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/screenshots.py 
new/py3status-3.51/py3status/screenshots.py
--- old/py3status-3.50/py3status/screenshots.py 2022-10-02 16:25:48.000000000 
+0200
+++ new/py3status-3.51/py3status/screenshots.py 2023-06-05 13:45:55.000000000 
+0200
@@ -148,7 +148,7 @@
             color = COLOR_URGENT
             background = COLOR_URGENT_BG
 
-        size = font.getsize(text)
+        size = font.getbbox(text)[-2:]
 
         if background:
             d.rectangle(
@@ -167,7 +167,7 @@
         d_text = ImageDraw.Draw(txt)
         d_text.text((0, 0), text, font=font, fill=color)
         # resize to actual size wanted and add to image
-        txt = txt.resize((size[0] // SCALE, size[1] // SCALE), Image.ANTIALIAS)
+        txt = txt.resize((size[0] // SCALE, size[1] // SCALE), Image.LANCZOS)
         img.paste(txt, (WIDTH - x, TOP_BAR_HEIGHT + PADDING))
 
         if separator:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status/version.py 
new/py3status-3.51/py3status/version.py
--- old/py3status-3.50/py3status/version.py     2023-04-17 18:43:02.000000000 
+0200
+++ new/py3status-3.51/py3status/version.py     2023-06-27 09:28:29.000000000 
+0200
@@ -1 +1 @@
-version = "3.50"
+version = "3.51"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status.egg-info/PKG-INFO 
new/py3status-3.51/py3status.egg-info/PKG-INFO
--- old/py3status-3.50/py3status.egg-info/PKG-INFO      2023-04-17 
18:44:18.000000000 +0200
+++ new/py3status-3.51/py3status.egg-info/PKG-INFO      2023-06-27 
10:33:46.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: py3status
-Version: 3.50
+Version: 3.51
 Summary: py3status: an extensible i3status wrapper written in python
 Home-page: https://github.com/ultrabug/py3status
 Author: Ultrabug
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py3status-3.50/py3status.egg-info/SOURCES.txt 
new/py3status-3.51/py3status.egg-info/SOURCES.txt
--- old/py3status-3.50/py3status.egg-info/SOURCES.txt   2023-04-17 
18:44:18.000000000 +0200
+++ new/py3status-3.51/py3status.egg-info/SOURCES.txt   2023-06-27 
10:33:46.000000000 +0200
@@ -30,6 +30,7 @@
 py3status/i3status.py
 py3status/module.py
 py3status/module_test.py
+py3status/output.py
 py3status/parse_config.py
 py3status/private.py
 py3status/profiling.py

Reply via email to