internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: ultrabug/py3status

Issue:
[clock] It is more intuitive to round clock emoji to the nearest 15 or 45 minutes
The emoji clock is being used in many apps these days, and I noticed that py3status implementation is not consistent with the rest and is less intuitive to me.

Currently the clock emoji is not being updated until the hour exactly reaches the next step, so for example:
- 14:59 🕝

Instead, it is more intuitive to choose icon for the time rounded to the nearest 15 or 45 minutes, that is:

- 14:01 🕑
- 14:14 🕑
- 14:15 🕝
- 14:44 🕝
- 14:45 🕒
- 14:59 🕒

/cc @tobes as you created this module.


Discussion:
I'm quite happy for you to make this change, it makes sense to be consistent


Resolving patch:
diff --git a/py3status/modules/clock.py b/py3status/modules/clock.py
--- a/py3status/modules/clock.py
+++ b/py3status/modules/clock.py
@@ -38,6 +38,10 @@
         a list.  The one used can be changed by button click.
         *(default ['[{name_unclear} ]%c', '[{name_unclear} ]%x %X',
         '[{name_unclear} ]%a %H:%M', '[{name_unclear} ]{icon}'])*
+    round_to_nearest_block: defines how a block icon is chosen. Examples:
+        when set to True,  '13:14' is '🕐', '13:16' is '🕜' and '13:31' is '🕜';
+        when set to False, '13:14' is '🕐', '13:16' is '🕐' and '13:31' is '🕜'.
+        (default True)
 
 Format placeholders:
     {icon} a character representing the time from `blocks`
@@ -87,9 +91,9 @@
 london
 {'full_text': 'Thursday Feb 23 1:42 AM London'}
 """
+from __future__ import division
 
 import re
-import math
 from datetime import datetime
 from time import time
 
@@ -116,6 +120,7 @@ class Py3status:
         '[{name_unclear} ]%a %H:%M',
         '[{name_unclear} ]{icon}',
     ]
+    round_to_nearest_block = True
 
     def post_config_hook(self):
         # Multiple clocks are possible that can be cycled through
@@ -234,10 +239,11 @@ def clock(self, i3s_output_list, i3s_config):
                 if self.py3.format_contains(format_time, 'icon'):
                     # calculate the decimal hour
                     h = t.hour + t.minute / 60.
+                    if self.round_to_nearest_block:
+                        h += (self.block_hours / len(self.blocks)) / 2
                     # make 12 hourly etc
                     h = h % self.block_hours
-                    idx = int(math.floor(h / self.block_hours * (len(
-                        self.blocks))))
+                    idx = int(h / self.block_hours * len(self.blocks))
                     icon = self.blocks[idx]
 
                 timezone = zone.zone


Test patch:
Repository: ultrabug/py3status

Issue:
GitHub: Show correct count of unread notifications
If you have more than 50 unread notifications in total, and you want to see that total notification count, the GitHub module still only shows 50 due to pagination:

https://github.com/ultrabug/py3status/blob/master/py3status/modules/github.py#L155


Discussion:

Resolving patch:
diff --git a/py3status/modules/github.py b/py3status/modules/github.py
--- a/py3status/modules/github.py
+++ b/py3status/modules/github.py
@@ -152,7 +152,32 @@ def _notifications(self):
         except (self.py3.RequestException):
             return
         if info.status_code == 200:
-            return len(info.json())
+            links = info._response.headers.get('Link', '').split(', ')
+            if not links:
+                return len(info.json())
+
+            last_page = 1
+            for link in links:
+                if 'rel="last"' in link:
+                    import sys
+                    if sys.version_info[0] == 2:
+                        import urlparse
+                    else:
+                        import urllib.parse as urlparse
+                    last_url = link[link.find('<') + 1:link.find('>')]
+                    parsed = urlparse.urlparse(last_url)
+                    last_page = int(urlparse.parse_qs(parsed.query)['page'][0])
+
+            if last_page == 1:
+                return len(info.json())
+            try:
+                last_page_info = self.py3.request(last_url, timeout=10,
+                                                  auth=(self.username, self.auth_token))
+            except self.py3.RequestException:
+                return
+
+            return len(info.json()) * (last_page - 1) + len(last_page_info.json())
+
         if info.status_code == 404:
             if not self.repo_warning:
                 self.py3.notify_user('Github repo cannot be found.')


Test patch:
Repository: ultrabug/py3status

Issue:
Formatting returns empty when closing with a False or None placeholder
Formatting returns empty when closing with a `False` or `None` placeholder.
```diff
diff --git a/py3status/modules/static_string.py b/py3status/modules/static_string.py
index dbcec8c6..593b3740 100644
--- a/py3status/modules/static_string.py
+++ b/py3status/modules/static_string.py
@@ -18,10 +18,17 @@ class Py3status:
     # available configuration parameters
     format = 'Hello, world!'
 
+    # format = 'A, B, C // {true}'    # IS OK     | A, B, C // True
+    # format = 'A, B, C // {false}'   # IS NOT OK |
+    # format = 'A, B, C // {none}'    # IS NOT OK |
+    # format = 'A, B, C // {false} '  # IS OK     | A, B, C // False
+    # format = 'A, B, C // {none} '   # IS OK     | A, B, C // None
+
     def static_string(self):
+        new_dict = {'true': True, 'false': False, 'none': None}
         return {
             'cached_until': self.py3.CACHE_FOREVER,
-            'full_text': self.py3.safe_format(self.format),
+            'full_text': self.py3.safe_format(self.format, new_dict),
         }
```


Discussion:

Resolving patch:
diff --git a/py3status/formatter.py b/py3status/formatter.py
--- a/py3status/formatter.py
+++ b/py3status/formatter.py
@@ -268,7 +268,9 @@ def get(self, get_params, block):
                 output = u'{%s%s}' % (self.key, self.format)
                 value = value_ = output.format(**{self.key: value})
 
-            if block.commands.not_zero:
+            if block.parent is None:
+                valid = True
+            elif block.commands.not_zero:
                 valid = value_ not in ['', 'None', None, False, '0', '0.0', 0, 0.0]
             else:
                 # '', None, and False are ignored


Test patch:
diff --git a/tests/test_formatter.py b/tests/test_formatter.py
--- a/tests/test_formatter.py
+++ b/tests/test_formatter.py
@@ -296,10 +296,18 @@ def test_26():
 
 
 def test_27():
-    run_formatter({'format': '{None}', 'expected': '', })
+    run_formatter({'format': '{None}', 'expected': 'None', })
 
 
 def test_27a():
+    run_formatter({'format': '{None} {no}', 'expected': 'None False', })
+
+
+def test_27b():
+    run_formatter({'format': '[Hello {None}] {no}', 'expected': ' False', })
+
+
+def test_27c():
     run_formatter({'format': '[Hi, my name is {None_str}]', 'expected': '', })
 
 
@@ -312,7 +320,7 @@ def test_29():
 
 
 def test_30():
-    run_formatter({'format': '{no}', 'expected': '', })
+    run_formatter({'format': '{no}', 'expected': 'False', })
 
 
 def test_31():
@@ -1134,7 +1142,7 @@ def test_module_true_value():
 
 
 def test_module_false_value():
-    run_formatter({'format': '{module_false}', 'expected': ''})
+    run_formatter({'format': '{module_false}', 'expected': 'False'})
 
 
 def test_zero_format_1():
Repository: ultrabug/py3status

Issue:
Formatting bug with not_zero
Possible formatting bug with `\?not_zero` and/or the inheritance. 

`valid format`.
```
    format_duration = u'\?not_zero [{years}y][{weeks}w][{months}m][{days}d]' +\
        u'[\?soft  ][{hours}][\?soft :][{minutes:02d}][\?soft :][{seconds:02d}]'

```
`invalid format`.
```
    format_duration = u'\?not_zero [{years}y][{weeks}w][{months}m][{days}d]' +\
        u'[\?soft  ][{hours}][\?soft :][{minutes:02d}]:[{seconds:02d}]'
```
Look at `seconds`'s colon `:` between `]` and `[`... or anything else (eg `Hey`) between the brackets will result in an `invalid format`. Is that a bug or if that is how it should work with the formatter allowing some commands to be inherited? I asked because it does not trip when I takes out the inherited `\?not_zero`. Thx.


Discussion:

Resolving patch:
diff --git a/py3status/formatter.py b/py3status/formatter.py
--- a/py3status/formatter.py
+++ b/py3status/formatter.py
@@ -583,8 +583,9 @@ def render(self, get_params, module, _if=None):
                 text += conversion(item)
                 continue
             elif text:
-                if (not first and
-                        (text.strip() == '' or out[-1].get('color') == color)):
+                if (not first and (
+                        text.strip() == '' or out and
+                        out[-1].get('color') == color)):
                     out[-1]['full_text'] += text
                 else:
                     part = {'full_text': text}


Test patch:
Repository: ultrabug/py3status

Issue:
Make notify_user less ambiguous in the logs
```
2017-09-18 06:33:52 INFO Example
```


Discussion:

Resolving patch:
diff --git a/py3status/core.py b/py3status/core.py
--- a/py3status/core.py
+++ b/py3status/core.py
@@ -378,10 +378,10 @@ def gevent_monkey_patch_report(self):
             if gevent.socket.socket is socket.socket:
                 self.log('gevent monkey patching is active')
             else:
-                self.notify_user('gevent monkey patching failed')
+                self.notify_user('gevent monkey patching failed.')
         except ImportError:
             self.notify_user(
-                'gevent is not installed, monkey patching failed')
+                'gevent is not installed, monkey patching failed.')
 
     def get_user_modules(self):
         """
@@ -596,9 +596,12 @@ def notify_user(self, msg, level='error', rate_limit=None, module_name=''):
         msg_hash = hash(u'{}#{}#{}'.format(module_name, limit_key, msg))
         if msg_hash in self.notified_messages:
             return
+        elif module_name:
+            log_msg = 'Module `%s` sent a notification. "%s"' % (module_name, msg)
+            self.log(log_msg, level)
         else:
             self.log(msg, level)
-            self.notified_messages.add(msg_hash)
+        self.notified_messages.add(msg_hash)
 
         try:
             if dbus:


Test patch:
Repository: ultrabug/py3status

Issue:
support shorthand hexadecimal
Right now, the config support six-digit hexadecimal.
```python
# working - success
module {
    color_good = '#00FF00'
    color_bad = '#FF0000'
    color_degraded = '#FFFF00'
    color_charging = '#00FFFF'
}
```
Request feature: The config is to support shorthand three-digit hexadecimal too.
```python
# not working - failure
module {
    color_good = '#0F0'
    color_bad = '#F00'
    color_degraded = '#FF0'
    color_charging = '#0FF'
}
```
Optional: The config is to support x11 color names too.
```python
# not working - future rgb names
module {
    color_good = 'steelblue`
    color_bad = 'rosered'
    color_degraded = 'cornyellow`
    color_charging = 'tobespink`
}
```
Too much! The config is to support rgb numbers too.
```python
# not working - future rgb numbers
module {
    color_good = rgb(0, 255, 0)
    color_bad = rgb(255, 0, 0)
    color_degraded = rgb(255, 255, 0)
    color_charging = rgb(255, 0, 255)
}
```


Discussion:
> `color_charging = '#0FF'`

This should be implemented we should support `#FF00FF` and `#F0F` universally

> `color_good = rgb(0, 255, 0)`

I'd be happy for us to support this in the config if it is implemented

> `color_charging = 'tobespink'`

This I don't mind too much either `color_charging = tobespink` would also work because we allow unquoted strings, I'd be inclined to use css3 colors rather than x11.  It might be a little confusing to user though.  Unfortunately `tobespink` is still not through the committee stages.

Filing a possible issue... Composite might not parse shorthand hexadecimal too.

Resolving patch:
diff --git a/py3status/core.py b/py3status/core.py
--- a/py3status/core.py
+++ b/py3status/core.py
@@ -65,6 +65,9 @@ class NoneSetting:
     # this attribute is used to identify that this is a none setting
     none_setting = True
 
+    def __len__(self):
+        return 0
+
     def __repr__(self):
         # this is for output via module_test
         return 'None'
@@ -106,6 +109,14 @@ def get_config_attribute(self, name, attribute):
         if hasattr(param, 'none_setting'):
             # check py3status general section
             param = config['general'].get(attribute, self.none_setting)
+        # If this is a color and it is like #123 convert it to #112233
+        if param and (attribute == 'color' or attribute.startswith('color_')):
+            if len(param) == 4 and param[0] == '#':
+                param = (
+                    '#' + param[1] + param[1] + param[2] +
+                    param[2] + param[3] + param[3]
+                )
+
         return param
 
     def report_exception(self, msg, notify_user=True, level='error',


Test patch:
Repository: ultrabug/py3status

Issue:
Disk read/write stats in diskdata isn't computed correctly when a disk is specified
When a disk is specified, a logic error in _get_io_stats() results in statistics for all drives being summed, rather than just the selected drive.

Additionally, the filtering is a simple string match, so specifying "sda" or "/dev/sda" will sum stats for "sda", "sda1", "sda2", etc resulting in incorrect values.

Pull request is incoming momentarily to fix both of these issues.


Discussion:

Resolving patch:
diff --git a/py3status/modules/diskdata.py b/py3status/modules/diskdata.py
--- a/py3status/modules/diskdata.py
+++ b/py3status/modules/diskdata.py
@@ -165,12 +165,12 @@ def _get_io_stats(self, disk):
         write = 0
         with open('/proc/diskstats', 'r') as fd:
             for line in fd:
-                if disk and disk in line:
-                    data = line.split()
-                    read += int(data[5]) * self.sector_size
-                    write += int(data[9]) * self.sector_size
+                data = line.split()
+                if disk:
+                    if data[2] == disk:
+                        read += int(data[5]) * self.sector_size
+                        write += int(data[9]) * self.sector_size
                 else:
-                    data = line.split()
                     if data[1] == '0':
                         read += int(data[5]) * self.sector_size
                         write += int(data[9]) * self.sector_size


Test patch:
Repository: ultrabug/py3status

Issue:
Better handling of transient interfaces in net_rate
I use net_rate for a couple of tun interfaces that are transient depending on VPN connections. It would be nice if net_rate had some additional configuration on what to do for non-existent interfaces. Currently, the hardcoded text "net_rate" shows up, where ideally I'd just have no output from net_rate.

I saw "format_no_connection" - it doesn't help with this case but seems like a potential candidate to tie in to this (where no connection and no device are arguably similar).

I'll look into implementing this, but figured I'd park the feature request here for now.


Discussion:
Ah! So it's actually a bug, I think:

```
ValueError: max() arg is an empty sequence
  File "/usr/lib/python3/dist-packages/py3status/module.py", line 729, in run
    response = method()
  File "/usr/lib/python3/dist-packages/py3status/modules/net_rate.py", line 143, in currentSpeed
    interface = max(deltas, key=lambda x: deltas[x]['total'])
```

This is good, because it shouldn't be too hard to fix. Working on a solution now...

Resolving patch:
diff --git a/py3status/modules/net_rate.py b/py3status/modules/net_rate.py
--- a/py3status/modules/net_rate.py
+++ b/py3status/modules/net_rate.py
@@ -161,7 +161,7 @@ def currentSpeed(self):
             # get the deltas into variable
             delta = deltas[interface] if interface else None
 
-        except TypeError:
+        except (TypeError, ValueError):
             delta = None
             interface = None
             hide = self.hide_if_zero


Test patch:
Repository: ultrabug/py3status

Issue:
whatismyip not working
I get this error when running python whatismyip.py, with the current version of that file (from the master branch, py3status version 3.11). 

> 'NoneType' object has no attribute 'get' (AttributeError) module.py line 732.
> Traceback
> AttributeError: 'NoneType' object has no attribute 'get'
>   File "/home/user/.anaconda3/lib/python3.6/site-packages/py3status/module.py", line 732, in run
>     response = method()
>   File "whatismyip.py", line 135, in whatismyip
>     info = self._get_my_ip_info()
>   File "whatismyip.py", line 127, in _get_my_ip_info
>     info[old] = info.get(new)


Configuration file: 
whatismyip {
format = "{ip} ({country})"
hide_when_offline = True
color_good = '#e89393'
color_bad = '#e89393'
color_degraded = '#e89393'
}

I am running python 3.6.6, ananconda build. 
I can run `curl https://ifconfig.co/json` successfully.

Any idea, what might cause this behavior? Any changes in the py3status structure, specifically the self.py3.request part?


Discussion:
Most likely related to https://github.com/ultrabug/py3status/pull/1398 because this returns `None` instead of a (dict) data.

Resolving patch:
diff --git a/py3status/py3.py b/py3status/py3.py
--- a/py3status/py3.py
+++ b/py3status/py3.py
@@ -11,6 +11,7 @@
 from pprint import pformat
 from subprocess import Popen, PIPE, STDOUT
 from time import time
+from uuid import uuid4
 
 from py3status import exceptions
 from py3status.constants import COLOR_NAMES
@@ -18,6 +19,7 @@
 from py3status.request import HttpResponse
 from py3status.storage import Storage
 from py3status.util import Gradiants
+from py3status.version import version
 
 
 PY3_CACHE_FOREVER = -1
@@ -114,6 +116,7 @@ def __init__(self, module=None):
         self._report_exception_cache = set()
         self._thresholds = None
         self._threshold_gradients = {}
+        self._uid = uuid4()
 
         if module:
             self._i3s_config = module._py3_wrapper.config['py3_config']['general']
@@ -1157,6 +1160,11 @@ def request(self, url, params=None, data=None, headers=None,
         if headers is None:
             headers = {}
 
+        if 'User-Agent' not in headers:
+            headers['User-Agent'] = 'py3status/{} {}'.format(
+                version, self._uid
+            )
+
         return HttpResponse(url,
                             params=params,
                             data=data,


Test patch:
Repository: ultrabug/py3status

Issue:
mail: namecollision in dict with mailbox named 'mail'
If you have a mailbox with 
```
'name' = 'mail'
```
the unread mails in this mailbox are counted twice and will reset the count for the mailboxes that have come before it. This is caused by line [208](https://github.com/ultrabug/py3status/blob/109e60a360db6deebe719a67afa07ade4e03640a/py3status/modules/mail.py#L208) as `mail_data['mail']` is set to count_mail and at Line [213](https://github.com/ultrabug/py3status/blob/109e60a360db6deebe719a67afa07ade4e03640a/py3status/modules/mail.py#L213)
 it is added again.


Discussion:

Resolving patch:
diff --git a/py3status/modules/mail.py b/py3status/modules/mail.py
--- a/py3status/modules/mail.py
+++ b/py3status/modules/mail.py
@@ -138,6 +138,8 @@
 from imaplib import IMAP4_SSL
 from os.path import exists, expanduser, expandvars
 STRING_MISSING = 'missing {} {}'
+STRING_WRONG_NAME = 'Accountname ({}) collides with "Maildir", "mbox", "mh", \
+"Babyl", "MMDF", "mail" or "IMAP".'
 
 
 class Py3status:
@@ -160,6 +162,9 @@ def post_config_hook(self):
                 continue
             self.mailboxes[mail] = []
             for account in accounts:
+                if account['name'] in [x.lower() for x in mailboxes] \
+                        + ['mail']:
+                    raise Exception(STRING_WRONG_NAME.format(account['name']))
                 account.setdefault('urgent', True)
                 if mail == 'imap':
                     for v in ['user', 'password', 'server']:


Test patch:
Repository: ultrabug/py3status

Issue:
default config location
I have installed ubuntu 18.04 and it makes sense to put my `i3status.conf` in `~/.config/i3/` but this is not found by default.  I think we should add this path.


Discussion:
You are absolutely right, we should definitely do this

Resolving patch:
diff --git a/py3status/cli.py b/py3status/cli.py
--- a/py3status/cli.py
+++ b/py3status/cli.py
@@ -19,6 +19,7 @@ def parse_cli():
         "{}/i3status/config".format(
             os.environ.get("XDG_CONFIG_HOME", "{}/.config".format(home_path))
         ),
+        "{}/.config/i3/".format(home_path),
         "/etc/i3status.conf",
         "{}/i3status/config".format(os.environ.get("XDG_CONFIG_DIRS", "/etc/xdg")),
     ]


Test patch:
Repository: ultrabug/py3status

Issue:
Module information printed to stderr
Using `py3status module details` or `py3status module list` sends the output to stderr instead of stdout.

I was trying to pipe details into a file to read it with my text editor and got surprised with an empty file. Is there any reason for this, or can I submit a PR? 


Discussion:

Resolving patch:
diff --git a/py3status/docstrings.py b/py3status/docstrings.py
--- a/py3status/docstrings.py
+++ b/py3status/docstrings.py
@@ -425,9 +425,9 @@ def show_modules(config, params):
                 user_mods = False
                 core_mods = True
     if details:
-        print_stderr("Module details:")
+        print("Module details:")
     else:
-        print_stderr("Available modules:")
+        print("Available modules:")
     modules = core_module_docstrings(
         include_core=core_mods, include_user=user_mods, config=config
     )
@@ -438,10 +438,10 @@ def show_modules(config, params):
         desc = module[0][:-1]
         if details:
             dash_len = len(name)
-            print_stderr("=" * dash_len)
-            print_stderr(name)
-            print_stderr("=" * dash_len)
+            print("=" * dash_len)
+            print(name)
+            print("=" * dash_len)
             for description in module:
-                print_stderr(description[:-1])
+                print(description[:-1])
         else:
-            print_stderr("  %-22s %s" % (name, desc))
+            print("  %-22s %s" % (name, desc))


Test patch: