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
+
+- Clean up SPEC file.
+
+-------------------------------------------------------------------
+Fri Jun 30 14:31:54 UTC 2023 - Dawid Adam
+- 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
@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
+@license BSD
+
SAMPLE OUTPUT
{'full_text': 'Dock'}
-{'full_text': 'Int'}
-@author Jens Brandt
-@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""
+
+ 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