Repository: ultrabug/py3status

Issue:
Battery module error
**Describe the bug**
The bug seems to ocurr when my battery is fully charged and I'm using the acpi measurement mode (I'd wish to be able to use acpi measuring to get the time that the battery has)
**Your py3status version**
py3status version 3.49 (python 3.10.9) on sway

**To Reproduce**
Steps to reproduce the behavior along with your py3status configuration (filter out any private values):
1. Add module 'battery_level'
2. Configure module like the following:
```
battery_level {
    blocks = ""
    #battery_id = all
    battery_id = 1 
    format = "{percent}% {icon}[\?if=time_remainin>
    threshold_degraded = 20
    hide_when_full = true
    hide_seconds = true
    notify_low_level = true
    #measurement_mode = "sys"
    measurement_mode = "acpi"
    notification = true
}
```
3. Wait until the battery is at 100% and the error sometimes pops up.
4. See error.

**Expected behavior**
The battery level to continue being hidden and no error to pop up.

**Additional context**
The error says `battery_level: list index out of range`, which I presume means some error with the acpi handling?
The logs say the following:
```
2023-03-25 10:26:23 WARNING Instance `battery_level`, user method `battery_level` failed.
2023-03-25 10:26:23 INFO Traceback
IndexError: list index out of range
  File "/usr/lib/python3.10/site-packages/py3status/module.py", line 949, in run 
    response = method()
  File "/usr/lib/python3.10/site-packages/py3status/modules/battery_level.py", line 198, in battery_level
    battery_list = self.get_battery_info()
  File "/usr/lib/python3.10/site-packages/py3status/modules/battery_level.py", line 290, in _extract_battery_info_from_acpi
    return [_parse_battery_info(battery) for battery in acpi_list]
  File "/usr/lib/python3.10/site-packages/py3status/modules/battery_level.py", line 290, in <listcomp>
    return [_parse_battery_info(battery) for battery in acpi_list]
  File "/usr/lib/python3.10/site-packages/py3status/modules/battery_level.py", line 262, in _parse_battery_info
    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
```


Discussion:
More information needed. Paste `acpi -b -i` output and... maybe again when/if the error occurs.

I think the output hides some values when it's full. The fix might be something like this. Not `0` tho.
```diff
diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
index 2a48b83..809e5d5 100644
--- a/py3status/modules/battery_level.py
+++ b/py3status/modules/battery_level.py
@@ -258,13 +258,13 @@ class Py3status:
                 findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
             )
             battery["charging"] = "Charging" in acpi_battery_lines[0]
-            battery["capacity"] = int(
-                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
-            )
 
             # ACPI only shows time remaining if battery is discharging or
             # charging
             try:
+                battery["capacity"] = int(
+                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
+                )
                 battery["time_remaining"] = "".join(
                     findall(
                         r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
@@ -274,6 +274,7 @@ class Py3status:
                 )
             except IndexError:
                 battery["time_remaining"] = FULLY_CHARGED
+                battery["capacity"] = 0
 
             # TODO: Not implemented yet
             battery["power"] = 0.0

```
> More information needed. Paste `acpi -b -i` output and... maybe again when/if the error occurs.
> 
> I think the output hides some values when it's full. The fix might be something like this. Not `0` tho.
> 
> ```diff
> diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
> index 2a48b83..809e5d5 100644
> --- a/py3status/modules/battery_level.py
> +++ b/py3status/modules/battery_level.py
> @@ -258,13 +258,13 @@ class Py3status:
>                  findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
>              )
>              battery["charging"] = "Charging" in acpi_battery_lines[0]
> -            battery["capacity"] = int(
> -                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> -            )
>  
>              # ACPI only shows time remaining if battery is discharging or
>              # charging
>              try:
> +                battery["capacity"] = int(
> +                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> +                )
>                  battery["time_remaining"] = "".join(
>                      findall(
>                          r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
> @@ -274,6 +274,7 @@ class Py3status:
>                  )
>              except IndexError:
>                  battery["time_remaining"] = FULLY_CHARGED
> +                battery["capacity"] = 0
>  
>              # TODO: Not implemented yet
>              battery["power"] = 0.0
> ```
```
Battery 0: Discharging, 0%, rate information unavailable
Battery 1: Full, 100%
Battery 1: design capacity 3100 mAh, last full capacity 2905 mAh = 93%
```
The battery 1 is the important one, I don't really know what battery 0 is.
I could probably make a check if "percent" == 100 (pseudocode), and if so not write the module, as making a module with a empty text makes it not show it. (For some reason, I think it's intended tho.)
(The error is ocurring right now)
The fix 

> > More information needed. Paste `acpi -b -i` output and... maybe again when/if the error occurs.
> > I think the output hides some values when it's full. The fix might be something like this. Not `0` tho.
> > ```diff
> > diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
> > index 2a48b83..809e5d5 100644
> > --- a/py3status/modules/battery_level.py
> > +++ b/py3status/modules/battery_level.py
> > @@ -258,13 +258,13 @@ class Py3status:
> >                  findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
> >              )
> >              battery["charging"] = "Charging" in acpi_battery_lines[0]
> > -            battery["capacity"] = int(
> > -                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> > -            )
> >  
> >              # ACPI only shows time remaining if battery is discharging or
> >              # charging
> >              try:
> > +                battery["capacity"] = int(
> > +                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> > +                )
> >                  battery["time_remaining"] = "".join(
> >                      findall(
> >                          r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
> > @@ -274,6 +274,7 @@ class Py3status:
> >                  )
> >              except IndexError:
> >                  battery["time_remaining"] = FULLY_CHARGED
> > +                battery["capacity"] = 0
> >  
> >              # TODO: Not implemented yet
> >              battery["power"] = 0.0
> > ```
> 
> ```
> Battery 0: Discharging, 0%, rate information unavailable
> Battery 1: Full, 100%
> Battery 1: design capacity 3100 mAh, last full capacity 2905 mAh = 93%
> ```
> 
> The battery 1 is the important one, I don't really know what battery 0 is. I could probably make a check if "percent" == 100 (pseudocode), and if so not write the module, as making a module with a empty text makes it not show it. (For some reason, I think it's intended tho.) (The error is ocurring right now)

The fix seems to work with `battery["capacity"]` being `100`.
@lasers Could it be applied as a pull request?

I can't seem to get my error consistently. I tried to apply the patch but even when unpatching the error works weirdly.
You can keep modified `battery_level.py` in `~/.config/py3status/modules/`. I don't have a setup ready to test this module nor have I studied the module code. My trivial concern is that what would happen with multiple working batteries.

Also, yes, you can make a pull request.
> You can keep modified `battery_level.py` in `~/.config/py3status/modules/`. I don't have a setup ready to test this module nor have I studied the module code. My trivial concern is that what would happen with multiple working batteries.
> 
> Also, yes, you can make a pull request.

I'll then apply the patch properly as I can have it in my user folder, I dislike overriding python...

But the issue I have is that I can't seem what I should put in the value as if I put 0 it causes a divisionbyzero, but if I put 1 it causes the battery to be at 0%.
Less issue for you, but still not right due to not storing battery index too in the cache.

Use last known capacity. Untested. It should be 1 on first run, then whatever capacity acpi gave.
```diff
diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
index 2a48b83..f5cb943 100644
--- a/py3status/modules/battery_level.py
+++ b/py3status/modules/battery_level.py
@@ -178,6 +178,7 @@ class Py3status:
 
     def post_config_hook(self):
         self.last_known_status = ""
+        self.last_known_capacity = 1  # fake
         # Guess mode if not set
         if self.measurement_mode is None:
             if Path(self.sys_battery_path).is_dir():
@@ -258,13 +259,14 @@ class Py3status:
                 findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
             )
             battery["charging"] = "Charging" in acpi_battery_lines[0]
-            battery["capacity"] = int(
-                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
-            )
 
             # ACPI only shows time remaining if battery is discharging or
             # charging
             try:
+                battery["capacity"] = int(
+                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
+                )
+                self.last_known_capacity = battery["capacity"]
                 battery["time_remaining"] = "".join(
                     findall(
                         r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
@@ -274,6 +276,7 @@ class Py3status:
                 )
             except IndexError:
                 battery["time_remaining"] = FULLY_CHARGED
+                battery["capacity"] = self.last_known_capacity
 
             # TODO: Not implemented yet
             battery["power"] = 0.0

```
The PR should come from somebody confirming this to be working, not writing untested PRs like me.
> Less issue for you, but still not right due to not storing battery index too in the cache.
> 
> Use last known capacity. Untested. It should be 1 on first run, then whatever capacity acpi gave.
> 
> ```diff
> diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
> index 2a48b83..f5cb943 100644
> --- a/py3status/modules/battery_level.py
> +++ b/py3status/modules/battery_level.py
> @@ -178,6 +178,7 @@ class Py3status:
>  
>      def post_config_hook(self):
>          self.last_known_status = ""
> +        self.last_known_capacity = 1  # fake
>          # Guess mode if not set
>          if self.measurement_mode is None:
>              if Path(self.sys_battery_path).is_dir():
> @@ -258,13 +259,14 @@ class Py3status:
>                  findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
>              )
>              battery["charging"] = "Charging" in acpi_battery_lines[0]
> -            battery["capacity"] = int(
> -                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> -            )
>  
>              # ACPI only shows time remaining if battery is discharging or
>              # charging
>              try:
> +                battery["capacity"] = int(
> +                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> +                )
> +                self.last_known_capacity = battery["capacity"]
>                  battery["time_remaining"] = "".join(
>                      findall(
>                          r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
> @@ -274,6 +276,7 @@ class Py3status:
>                  )
>              except IndexError:
>                  battery["time_remaining"] = FULLY_CHARGED
> +                battery["capacity"] = self.last_known_capacity
>  
>              # TODO: Not implemented yet
>              battery["power"] = 0.0
> ```
> 
> The PR should come from somebody confirming this to be working, not writing untested PRs like me.

Thanks, applied that patch, will wait for a week or two to see if I experience any issues.
Issue: It still thinks the battery doesn't have capacity. It doesn't seem to save the data...
Can you give me the following outputs? Charging, Discharging, ~~and Full~~.

EDIT: It might work better if it got a charging / discharging output just once.
Supposedly charging:
```
Battery 0: Not charging, 98%
Battery 1: Discharging, 0%, rate information unavailable
```
Discharging:
```
Battery 0: Discharging, 98%, 03:47:31 remaining
Battery 1: Discharging, 0%, rate information unavailable
```
Charging:
```
Battery 0: Charging, 98%, 00:02:03 until charged
Battery 1: Discharging, 0%, rate information unavailable
```
The other battery sometimes appears and disappears randomly, but note that the hardware only has one physical battery.
Taken with `acpi -b -i`?  If yes, well, it doesn't print capacity for your batteries... It should look something like this.
```python
        """
        # Get the battery info from acpi

        # Example Discharging
        Battery 0: Discharging, 94%, 09:23:28 remaining
        Battery 0: design capacity 5703 mAh, last full capacity 5283 mAh = 92%
        Battery 1: Unknown, 98%
        Battery 1: design capacity 1880 mAh, last full capacity 1370 mAh = 72%

        # Example Charging
        Battery 0: Charging, 96%, 00:20:40 until charged
        Battery 0: design capacity 5566 mAh, last full capacity 5156 mAh = 92%
        Battery 1: Unknown, 98%
        Battery 1: design capacity 1879 mAh, last full capacity 1370 mAh = 72%
        """
```
Nothing we can do here. Possibly better to fix up `sys` and/or to look into adding `tlp` support if there is a good battery statistics output py3status can use on the bar.
> Taken with `acpi -b -i`? If yes, well, it doesn't print capacity for your batteries... It should look something like this.
> 
> ```python
>         """
>         # Get the battery info from acpi
> 
>         # Example Discharging
>         Battery 0: Discharging, 94%, 09:23:28 remaining
>         Battery 0: design capacity 5703 mAh, last full capacity 5283 mAh = 92%
>         Battery 1: Unknown, 98%
>         Battery 1: design capacity 1880 mAh, last full capacity 1370 mAh = 72%
> 
>         # Example Charging
>         Battery 0: Charging, 96%, 00:20:40 until charged
>         Battery 0: design capacity 5566 mAh, last full capacity 5156 mAh = 92%
>         Battery 1: Unknown, 98%
>         Battery 1: design capacity 1879 mAh, last full capacity 1370 mAh = 72%
>         """
> ```
> 
> Nothing we can do here. Possibly better to fix up `sys` and/or to look into adding `tlp` support if there is a good battery statistics output py3status can use on the bar.

Oh, sorry. wait a sec.
```
# Supposedly charging (it really discharges)
Battery 0: Discharging, 0%, rate information unavailable
Battery 1: Not charging, 99%
Battery 1: design capacity 3100 mAh, last full capacity 2813 mAh = 90%

# Discharging 
Battery 0: Discharging, 0%, rate information unavailable
Battery 1: Discharging, 99%, 13:23:49 remaining
Battery 1: design capacity 3100 mAh, last full capacity 2813 mAh = 90%

# Charging
Battery 0: Discharging, 0%, rate information unavailable
Battery 1: Charging, 98%, charging at zero rate - will never fully charge.
Battery 1: design capacity 3100 mAh, last full capacity 2821 mAh = 91%

# Charging (later)
Battery 0: Discharging, 0%, rate information unavailable
Battery 1: Charging, 98%, 00:36:09 until charged
Battery 1: design capacity 3100 mAh, last full capacity 2821 mAh = 91% 
```
```diff
diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
index 2a48b83..a1d0210 100644
--- a/py3status/modules/battery_level.py
+++ b/py3status/modules/battery_level.py
@@ -92,7 +92,7 @@ discharging
 {'color': '#FF0000', 'full_text': u'\u2340'}
 """
 
-from re import findall
+from re import findall, search
 
 import itertools
 import math
@@ -178,6 +178,7 @@ class Py3status:
 
     def post_config_hook(self):
         self.last_known_status = ""
+        self.last_known_capacity = 1  # fake
         # Guess mode if not set
         if self.measurement_mode is None:
             if Path(self.sys_battery_path).is_dir():
@@ -258,13 +259,14 @@ class Py3status:
                 findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
             )
             battery["charging"] = "Charging" in acpi_battery_lines[0]
-            battery["capacity"] = int(
-                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
-            )
 
             # ACPI only shows time remaining if battery is discharging or
             # charging
             try:
+                battery["capacity"] = int(
+                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
+                )
+                self.last_known_capacity = battery["capacity"]
                 battery["time_remaining"] = "".join(
                     findall(
                         r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
@@ -273,6 +275,7 @@ class Py3status:
                     )[0]
                 )
             except IndexError:
+                battery["capacity"] = self.last_known_capacity
                 battery["time_remaining"] = FULLY_CHARGED
 
             # TODO: Not implemented yet
@@ -285,9 +288,12 @@ class Py3status:
         # Separate the output because each pair of lines corresponds to a
         # single battery.  Now the list index will correspond to the index of
         # the battery we want to look at
-        acpi_list = [acpi_list[i : i + 2] for i in range(0, len(acpi_list) - 1, 2)]
+        new_acpi_list = {}
+        for line in acpi_list:
+            number = int(search(r"Battery (\d+)", line).group(1))
+            new_acpi_list.setdefault(number, []).append(line)
 
-        return [_parse_battery_info(battery) for battery in acpi_list]
+        return [_parse_battery_info(battery) for battery in new_acpi_list.values()]
 
     def _extract_battery_info_from_sys(self):
         """

```
> ```diff
> new_acpi_list.setdefault(number, []).append(line)
> ```

Thanks, will wait a few days to see if this one works properly. :)
I just found a issue, for some weird reason it seems to just out of the blue change the percentage from 99% to 50%, I can prove any debug data needed if I am given the command (as I know `py3status -dl file` won't work properly as no exception is ocurring)
I don't remember if this is how it works, but you can try adding `self.py3.log(new_acpi_list.values())` line right after that loop. It should show up in `file` along with other noises. Check to see if it's working.... and when you ran into that issue again, check the file immediately.
```
2023-04-03 14:44:37 INFO Module `battery_level`: dict_values([['Battery 0: Not charging, 99%', 'Battery 0: design capacity 3100 mAh, last full capacity 2814 mAh = 90%'], ['Battery 1: Discharging, 0%, rate information unavailable']])
2023-04-03 14:44:37 INFO method battery_level returned {'composite': [{'full_text': '49% \uf242 (None)', 'instance': ' 0', 'name': 'battery_level', 'background': '#282828'}], 'instance': '', 'name': 'battery_level'}.
```
I think I just found out the error, there's a extra battery (which I can't practically remove), that always has 0% so the avereage of the percentages is 49%.

- Found the device which makes the issue, I'll try to see how can I bodge it to not present a empty battery (it's a wireless mouse receiver) (seems like when I use it via bluetooth it doesn't show it, which is nice but that also can break my workflow once I add more hosts on my kvm (that is, more laptops because I'm not using the mouse on the rare times I switch to the output of my local server)), I think it's a issue with acpi not handling `hidpp_battery_25` properly. (As /sys/class/power_supply/hidpp_battery_25/capacity shows 95, which means the mouse is 95% full)
Yeah. Your `Battery 0` gave capacity this time. This wasn't in one of your outputs before. There is a method later down the road that puts all batteries together to make an average percent... thus this issue. It may be ideal to split everything up so we loop through each battery (ie with `format_battery`).

Few ways to fix this.
1) Rewriting this module from scratch to loop batteries.
2) Add `batteries` config to follow certain batteries. If empty, all.
3) Find a fix via acpi.
> Yeah. Your `Battery 0` gave capacity this time. This wasn't in one of your outputs before. There is a method later down the road that puts all batteries together to make an average percent... thus this issue. It may be ideal to split everything up so we loop through each battery (ie with `format_battery`).
> 
> Few ways to fix this.
> 
> 1. Rewriting this module from scratch to loop batteries.
That'd take a lot of work.
> 2. Add `batteries` config to follow certain batteries. If empty, all.
That would have a way to somehow tell the battery without using a identifier as the id changes when the remote thing is unplugged
> 3. Find a fix via acpi.
^ That'd be the best solution, as checking the internal files in `/sys/class/power_supply` there's the battery and the capacity shows up properly.

I ended up going with the current aproach of using the mouse via bluetooth. I'll just have to remember to disable bluetooth when I go out with my laptop (as that consumes battery).

Currently I will rename the module override file and see if no issues ocurr and if any issues ocurr (the system still giving me some kind of error), I'd make a PR, but even then, it's a bit sad that they don't expose all the proper files so acpi doesn't work.

@lasers Is it possible to detect a invalid battery (by the fact that it doesn't report rated capacity) and remove it from the dictionary of batteries?
```diff
diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
index 2a48b83..046e30f 100644
--- a/py3status/modules/battery_level.py
+++ b/py3status/modules/battery_level.py
@@ -92,7 +92,7 @@ discharging
 {'color': '#FF0000', 'full_text': u'\u2340'}
 """
 
-from re import findall
+from re import findall, search
 
 import itertools
 import math
@@ -178,6 +178,7 @@ class Py3status:
 
     def post_config_hook(self):
         self.last_known_status = ""
+        self.last_known_capacity = 1
         # Guess mode if not set
         if self.measurement_mode is None:
             if Path(self.sys_battery_path).is_dir():
@@ -258,13 +259,14 @@ class Py3status:
                 findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
             )
             battery["charging"] = "Charging" in acpi_battery_lines[0]
-            battery["capacity"] = int(
-                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
-            )
 
             # ACPI only shows time remaining if battery is discharging or
             # charging
             try:
+                battery["capacity"] = int(
+                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
+                )
+                self.last_known_capacity = battery["capacity"]
                 battery["time_remaining"] = "".join(
                     findall(
                         r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
@@ -273,6 +275,7 @@ class Py3status:
                     )[0]
                 )
             except IndexError:
+                battery["capacity"] = self.last_known_capacity
                 battery["time_remaining"] = FULLY_CHARGED
 
             # TODO: Not implemented yet
@@ -285,9 +288,17 @@ class Py3status:
         # Separate the output because each pair of lines corresponds to a
         # single battery.  Now the list index will correspond to the index of
         # the battery we want to look at
-        acpi_list = [acpi_list[i : i + 2] for i in range(0, len(acpi_list) - 1, 2)]
+        temp_acpi_list = {}
+        for line in acpi_list:
+            number = search(r"Battery (\d+)", line).group(1)
+            temp_acpi_list.setdefault(number, []).append(line)
+
+        new_acpi_list = {}
+        for k, v in temp_acpi_list.items():
+            if "rate information unavailable" not in "|".join(v):
+                new_acpi_list[k] = v
 
-        return [_parse_battery_info(battery) for battery in acpi_list]
+        return [_parse_battery_info(battery) for battery in new_acpi_list.values()]
 
     def _extract_battery_info_from_sys(self):
         """

```
> ```diff
> diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
> index 2a48b83..046e30f 100644
> --- a/py3status/modules/battery_level.py
> +++ b/py3status/modules/battery_level.py
> @@ -92,7 +92,7 @@ discharging
>  {'color': '#FF0000', 'full_text': u'\u2340'}
>  """
>  
> -from re import findall
> +from re import findall, search
>  
>  import itertools
>  import math
> @@ -178,6 +178,7 @@ class Py3status:
>  
>      def post_config_hook(self):
>          self.last_known_status = ""
> +        self.last_known_capacity = 1
>          # Guess mode if not set
>          if self.measurement_mode is None:
>              if Path(self.sys_battery_path).is_dir():
> @@ -258,13 +259,14 @@ class Py3status:
>                  findall(r"(?<= )(\d+)(?=%)", acpi_battery_lines[0])[0]
>              )
>              battery["charging"] = "Charging" in acpi_battery_lines[0]
> -            battery["capacity"] = int(
> -                findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> -            )
>  
>              # ACPI only shows time remaining if battery is discharging or
>              # charging
>              try:
> +                battery["capacity"] = int(
> +                    findall(r"(?<= )(\d+)(?= mAh)", acpi_battery_lines[1])[1]
> +                )
> +                self.last_known_capacity = battery["capacity"]
>                  battery["time_remaining"] = "".join(
>                      findall(
>                          r"(?<=, )(\d+:\d+:\d+)(?= remaining)|"
> @@ -273,6 +275,7 @@ class Py3status:
>                      )[0]
>                  )
>              except IndexError:
> +                battery["capacity"] = self.last_known_capacity
>                  battery["time_remaining"] = FULLY_CHARGED
>  
>              # TODO: Not implemented yet
> @@ -285,9 +288,17 @@ class Py3status:
>          # Separate the output because each pair of lines corresponds to a
>          # single battery.  Now the list index will correspond to the index of
>          # the battery we want to look at
> -        acpi_list = [acpi_list[i : i + 2] for i in range(0, len(acpi_list) - 1, 2)]
> +        temp_acpi_list = {}
> +        for line in acpi_list:
> +            number = search(r"Battery (\d+)", line).group(1)
> +            temp_acpi_list.setdefault(number, []).append(line)
> +
> +        new_acpi_list = {}
> +        for k, v in temp_acpi_list.items():
> +            if "rate information unavailable" not in "|".join(v):
> +                new_acpi_list[k] = v
>  
> -        return [_parse_battery_info(battery) for battery in acpi_list]
> +        return [_parse_battery_info(battery) for battery in new_acpi_list.values()]
>  
>      def _extract_battery_info_from_sys(self):
>          """
> ```

Thanks, seems to work properly. Do you think this would negatively affect other users?, if it won't I'm pretty sure a PR can be made.

Resolving patch:
diff --git a/py3status/modules/battery_level.py b/py3status/modules/battery_level.py
--- a/py3status/modules/battery_level.py
+++ b/py3status/modules/battery_level.py
@@ -285,9 +285,17 @@ def _parse_battery_info(acpi_battery_lines):
         # Separate the output because each pair of lines corresponds to a
         # single battery.  Now the list index will correspond to the index of
         # the battery we want to look at
-        acpi_list = [acpi_list[i : i + 2] for i in range(0, len(acpi_list) - 1, 2)]
+        temporary = {}
+        for line in acpi_list:
+            number = line.split(":", 1)[0].strip("Battery ")
+            temporary.setdefault(number, []).append(line)
 
-        return [_parse_battery_info(battery) for battery in acpi_list]
+        new_acpi = {}
+        for k, v in temporary.items():
+            if "rate information unavailable" not in "|".join(v):
+                new_acpi[k] = v
+
+        return [_parse_battery_info(battery) for battery in new_acpi.values()]
 
     def _extract_battery_info_from_sys(self):
         """


Test patch: