We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `py3status/modules/net_rate.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 """
3 Display network transfer rate.
4 
5 Configuration parameters:
6     all_interfaces: ignore self.interfaces, but not self.interfaces_blacklist
7         (default True)
8     cache_timeout: how often we refresh this module in seconds
9         (default 2)
10     devfile: location of dev file under /proc
11         (default '/proc/net/dev')
12     format: format of the module output
13         (default '{interface}: {total}')
14     format_no_connection: when there is no data transmitted from the start of the plugin
15         (default '')
16     format_value: format to use for values
17         (default "[\?min_length=11 {value:.1f} {unit}]")
18     hide_if_zero: hide indicator if rate == 0
19         (default False)
20     interfaces: comma separated list of interfaces to track
21         (default [])
22     interfaces_blacklist: comma separated list of interfaces to ignore
23         (default 'lo')
24     si_units: use SI units
25         (default False)
26     sum_values: sum values of each interface instead of taking the top one
27         (default False)
28     thresholds: thresholds to use for colors
29         (default [(0, 'bad'), (1024, 'degraded'), (1024 * 1024, 'good')])
30     unit: unit to use. If the unit contains a multiplier prefix, only this
31         exact unit will ever be used
32         (default "B/s")
33 
34 Format placeholders:
35     {down} download rate
36     {interface} name of interface
37     {total} total rate
38     {up} upload rate
39 
40 format_value placeholders:
41     {unit} current unit
42     {value} numeric value
43 
44 Color thresholds:
45     {down} Change color based on the value of down
46     {total} Change color based on the value of total
47     {up} Change color based on the value of up
48 
49 @author shadowprince
50 @license Eclipse Public License
51 
52 SAMPLE OUTPUT
53 {'full_text': 'eno1:  852.2 KiB/s'}
54 """
55 
56 from __future__ import division  # python2 compatibility
57 from time import time
58 
59 
60 class Py3status:
61     """
62     """
63     # available configuration parameters
64     all_interfaces = True
65     cache_timeout = 2
66     devfile = '/proc/net/dev'
67     format = "{interface}: {total}"
68     format_no_connection = ''
69     format_value = "[\?min_length=11 {value:.1f} {unit}]"
70     hide_if_zero = False
71     interfaces = []
72     interfaces_blacklist = 'lo'
73     si_units = False
74     sum_values = False
75     thresholds = [(0, "bad"), (1024, "degraded"), (1024 * 1024, "good")]
76     unit = "B/s"
77 
78     class Meta:
79 
80         def deprecate_function(config):
81             # support old thresholds
82             precision = config.get('precision', 1)
83             padding = 3 + 1 + precision + 1 + 5
84             format_value = "[\?min_length={padding} {{value:.{precision}f}} {{unit}}]".format(
85                 padding=padding, precision=precision
86             )
87             return {'format_value': format_value}
88 
89         deprecated = {
90             'function': [
91                 {'function': deprecate_function},
92             ],
93             'remove': [
94                 {
95                     'param': 'precision',
96                     'msg': 'obsolete, use format_value instead',
97                 },
98             ]
99         }
100 
101     def post_config_hook(self):
102         # parse some configuration parameters
103         if not isinstance(self.interfaces, list):
104             self.interfaces = self.interfaces.split(',')
105         if not isinstance(self.interfaces_blacklist, list):
106             self.interfaces_blacklist = self.interfaces_blacklist.split(',')
107         placeholders = self.py3.get_placeholder_formats_list(self.format_value)
108         values = ['{%s}' % x[1] for x in placeholders if x[0] == 'value']
109         self._value_formats = values
110         # last
111         self.last_interface = None
112         self.last_stat = self._get_stat()
113         self.last_time = time()
114 
115     def currentSpeed(self):
116         ns = self._get_stat()
117         deltas = {}
118         try:
119             # time from previous check
120             timedelta = time() - self.last_time
121 
122             # calculate deltas for all interfaces
123             for old, new in zip(self.last_stat, ns):
124                 down = int(new[1]) - int(old[1])
125                 up = int(new[9]) - int(old[9])
126 
127                 down /= timedelta
128                 up /= timedelta
129 
130                 deltas[new[0]] = {'total': up + down, 'up': up, 'down': down, }
131 
132             # update last_ info
133             self.last_stat = self._get_stat()
134             self.last_time = time()
135 
136             # get the interface with max rate
137             if self.sum_values:
138                 interface = 'sum'
139                 sum_up = sum([itm['up'] for _, itm in deltas.items()])
140                 sum_down = sum([itm['down'] for _, itm in deltas.items()])
141                 deltas[interface] = {'total': sum_up + sum_down, 'up': sum_up, 'down': sum_down}
142             else:
143                 interface = max(deltas, key=lambda x: deltas[x]['total'])
144 
145             # if there is no rate - show last active interface, or hide
146 
147             # we need to check if it will be zero after it is formatted
148             # with the desired unit eg MB/s
149             total, _ = self.py3.format_units(
150                 deltas[interface]['total'], unit=self.unit, si=self.si_units
151             )
152             values = [float(x.format(total)) for x in self._value_formats]
153             if max(values) == 0:
154                 interface = self.last_interface
155                 hide = self.hide_if_zero
156             # if there is - update last_interface
157             else:
158                 self.last_interface = interface
159                 hide = False
160 
161             # get the deltas into variable
162             delta = deltas[interface] if interface else None
163 
164         except TypeError:
165             delta = None
166             interface = None
167             hide = self.hide_if_zero
168 
169         response = {'cached_until': self.py3.time_in(self.cache_timeout)}
170 
171         if hide:
172             response['full_text'] = ""
173         elif not interface:
174             response['full_text'] = self.format_no_connection
175         else:
176             self.py3.threshold_get_color(delta['down'], 'down')
177             self.py3.threshold_get_color(delta['total'], 'total')
178             self.py3.threshold_get_color(delta['up'], 'up')
179             response['full_text'] = self.py3.safe_format(self.format, {
180                 'down': self._format_value(delta['down']),
181                 'total': self._format_value(delta['total']),
182                 'up': self._format_value(delta['up']),
183                 'interface': interface[:-1],
184             })
185 
186         return response
187 
188     def _get_stat(self):
189         """
190         Get statistics from devfile in list of lists of words
191         """
192         def dev_filter(x):
193             # get first word and remove trailing interface number
194             x = x.strip().split(" ")[0][:-1]
195 
196             if x in self.interfaces_blacklist:
197                 return False
198 
199             if self.all_interfaces:
200                 return True
201 
202             if x in self.interfaces:
203                 return True
204 
205             return False
206 
207         # read devfile, skip two header files
208         x = filter(dev_filter, open(self.devfile).readlines()[2:])
209 
210         try:
211             # split info into words, filter empty ones
212             return [list(filter(lambda x: x, _x.split(" "))) for _x in x]
213 
214         except StopIteration:
215             return None
216 
217     def _format_value(self, value):
218         """
219         Return formatted string
220         """
221         value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)
222         return self.py3.safe_format(self.format_value, {'value': value, 'unit': unit})
223 
224 
225 if __name__ == "__main__":
226     """
227     Run module in test mode.
228     """
229     from py3status.module_test import module_test
230     module_test(Py3status)
231
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 @@
             # 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

{"golden_diff": "diff --git a/py3status/modules/net_rate.py b/py3status/modules/net_rate.py\n--- a/py3status/modules/net_rate.py\n+++ b/py3status/modules/net_rate.py\n@@ -161,7 +161,7 @@\n             # get the deltas into variable\n             delta = deltas[interface] if interface else None\n \n-        except TypeError:\n+        except (TypeError, ValueError):\n             delta = None\n             interface = None\n             hide = self.hide_if_zero\n", "issue": "Better handling of transient interfaces in net_rate\nI 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.\r\n\r\nI 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).\r\n\r\nI'll look into implementing this, but figured I'd park the feature request here for now.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"\nDisplay network transfer rate.\n\nConfiguration parameters:\n    all_interfaces: ignore self.interfaces, but not self.interfaces_blacklist\n        (default True)\n    cache_timeout: how often we refresh this module in seconds\n        (default 2)\n    devfile: location of dev file under /proc\n        (default '/proc/net/dev')\n    format: format of the module output\n        (default '{interface}: {total}')\n    format_no_connection: when there is no data transmitted from the start of the plugin\n        (default '')\n    format_value: format to use for values\n        (default \"[\\?min_length=11 {value:.1f} {unit}]\")\n    hide_if_zero: hide indicator if rate == 0\n        (default False)\n    interfaces: comma separated list of interfaces to track\n        (default [])\n    interfaces_blacklist: comma separated list of interfaces to ignore\n        (default 'lo')\n    si_units: use SI units\n        (default False)\n    sum_values: sum values of each interface instead of taking the top one\n        (default False)\n    thresholds: thresholds to use for colors\n        (default [(0, 'bad'), (1024, 'degraded'), (1024 * 1024, 'good')])\n    unit: unit to use. If the unit contains a multiplier prefix, only this\n        exact unit will ever be used\n        (default \"B/s\")\n\nFormat placeholders:\n    {down} download rate\n    {interface} name of interface\n    {total} total rate\n    {up} upload rate\n\nformat_value placeholders:\n    {unit} current unit\n    {value} numeric value\n\nColor thresholds:\n    {down} Change color based on the value of down\n    {total} Change color based on the value of total\n    {up} Change color based on the value of up\n\n@author shadowprince\n@license Eclipse Public License\n\nSAMPLE OUTPUT\n{'full_text': 'eno1:  852.2 KiB/s'}\n\"\"\"\n\nfrom __future__ import division  # python2 compatibility\nfrom time import time\n\n\nclass Py3status:\n    \"\"\"\n    \"\"\"\n    # available configuration parameters\n    all_interfaces = True\n    cache_timeout = 2\n    devfile = '/proc/net/dev'\n    format = \"{interface}: {total}\"\n    format_no_connection = ''\n    format_value = \"[\\?min_length=11 {value:.1f} {unit}]\"\n    hide_if_zero = False\n    interfaces = []\n    interfaces_blacklist = 'lo'\n    si_units = False\n    sum_values = False\n    thresholds = [(0, \"bad\"), (1024, \"degraded\"), (1024 * 1024, \"good\")]\n    unit = \"B/s\"\n\n    class Meta:\n\n        def deprecate_function(config):\n            # support old thresholds\n            precision = config.get('precision', 1)\n            padding = 3 + 1 + precision + 1 + 5\n            format_value = \"[\\?min_length={padding} {{value:.{precision}f}} {{unit}}]\".format(\n                padding=padding, precision=precision\n            )\n            return {'format_value': format_value}\n\n        deprecated = {\n            'function': [\n                {'function': deprecate_function},\n            ],\n            'remove': [\n                {\n                    'param': 'precision',\n                    'msg': 'obsolete, use format_value instead',\n                },\n            ]\n        }\n\n    def post_config_hook(self):\n        # parse some configuration parameters\n        if not isinstance(self.interfaces, list):\n            self.interfaces = self.interfaces.split(',')\n        if not isinstance(self.interfaces_blacklist, list):\n            self.interfaces_blacklist = self.interfaces_blacklist.split(',')\n        placeholders = self.py3.get_placeholder_formats_list(self.format_value)\n        values = ['{%s}' % x[1] for x in placeholders if x[0] == 'value']\n        self._value_formats = values\n        # last\n        self.last_interface = None\n        self.last_stat = self._get_stat()\n        self.last_time = time()\n\n    def currentSpeed(self):\n        ns = self._get_stat()\n        deltas = {}\n        try:\n            # time from previous check\n            timedelta = time() - self.last_time\n\n            # calculate deltas for all interfaces\n            for old, new in zip(self.last_stat, ns):\n                down = int(new[1]) - int(old[1])\n                up = int(new[9]) - int(old[9])\n\n                down /= timedelta\n                up /= timedelta\n\n                deltas[new[0]] = {'total': up + down, 'up': up, 'down': down, }\n\n            # update last_ info\n            self.last_stat = self._get_stat()\n            self.last_time = time()\n\n            # get the interface with max rate\n            if self.sum_values:\n                interface = 'sum'\n                sum_up = sum([itm['up'] for _, itm in deltas.items()])\n                sum_down = sum([itm['down'] for _, itm in deltas.items()])\n                deltas[interface] = {'total': sum_up + sum_down, 'up': sum_up, 'down': sum_down}\n            else:\n                interface = max(deltas, key=lambda x: deltas[x]['total'])\n\n            # if there is no rate - show last active interface, or hide\n\n            # we need to check if it will be zero after it is formatted\n            # with the desired unit eg MB/s\n            total, _ = self.py3.format_units(\n                deltas[interface]['total'], unit=self.unit, si=self.si_units\n            )\n            values = [float(x.format(total)) for x in self._value_formats]\n            if max(values) == 0:\n                interface = self.last_interface\n                hide = self.hide_if_zero\n            # if there is - update last_interface\n            else:\n                self.last_interface = interface\n                hide = False\n\n            # get the deltas into variable\n            delta = deltas[interface] if interface else None\n\n        except TypeError:\n            delta = None\n            interface = None\n            hide = self.hide_if_zero\n\n        response = {'cached_until': self.py3.time_in(self.cache_timeout)}\n\n        if hide:\n            response['full_text'] = \"\"\n        elif not interface:\n            response['full_text'] = self.format_no_connection\n        else:\n            self.py3.threshold_get_color(delta['down'], 'down')\n            self.py3.threshold_get_color(delta['total'], 'total')\n            self.py3.threshold_get_color(delta['up'], 'up')\n            response['full_text'] = self.py3.safe_format(self.format, {\n                'down': self._format_value(delta['down']),\n                'total': self._format_value(delta['total']),\n                'up': self._format_value(delta['up']),\n                'interface': interface[:-1],\n            })\n\n        return response\n\n    def _get_stat(self):\n        \"\"\"\n        Get statistics from devfile in list of lists of words\n        \"\"\"\n        def dev_filter(x):\n            # get first word and remove trailing interface number\n            x = x.strip().split(\" \")[0][:-1]\n\n            if x in self.interfaces_blacklist:\n                return False\n\n            if self.all_interfaces:\n                return True\n\n            if x in self.interfaces:\n                return True\n\n            return False\n\n        # read devfile, skip two header files\n        x = filter(dev_filter, open(self.devfile).readlines()[2:])\n\n        try:\n            # split info into words, filter empty ones\n            return [list(filter(lambda x: x, _x.split(\" \"))) for _x in x]\n\n        except StopIteration:\n            return None\n\n    def _format_value(self, value):\n        \"\"\"\n        Return formatted string\n        \"\"\"\n        value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)\n        return self.py3.safe_format(self.format_value, {'value': value, 'unit': unit})\n\n\nif __name__ == \"__main__\":\n    \"\"\"\n    Run module in test mode.\n    \"\"\"\n    from py3status.module_test import module_test\n    module_test(Py3status)\n", "path": "py3status/modules/net_rate.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"\nDisplay network transfer rate.\n\nConfiguration parameters:\n    all_interfaces: ignore self.interfaces, but not self.interfaces_blacklist\n        (default True)\n    cache_timeout: how often we refresh this module in seconds\n        (default 2)\n    devfile: location of dev file under /proc\n        (default '/proc/net/dev')\n    format: format of the module output\n        (default '{interface}: {total}')\n    format_no_connection: when there is no data transmitted from the start of the plugin\n        (default '')\n    format_value: format to use for values\n        (default \"[\\?min_length=11 {value:.1f} {unit}]\")\n    hide_if_zero: hide indicator if rate == 0\n        (default False)\n    interfaces: comma separated list of interfaces to track\n        (default [])\n    interfaces_blacklist: comma separated list of interfaces to ignore\n        (default 'lo')\n    si_units: use SI units\n        (default False)\n    sum_values: sum values of each interface instead of taking the top one\n        (default False)\n    thresholds: thresholds to use for colors\n        (default [(0, 'bad'), (1024, 'degraded'), (1024 * 1024, 'good')])\n    unit: unit to use. If the unit contains a multiplier prefix, only this\n        exact unit will ever be used\n        (default \"B/s\")\n\nFormat placeholders:\n    {down} download rate\n    {interface} name of interface\n    {total} total rate\n    {up} upload rate\n\nformat_value placeholders:\n    {unit} current unit\n    {value} numeric value\n\nColor thresholds:\n    {down} Change color based on the value of down\n    {total} Change color based on the value of total\n    {up} Change color based on the value of up\n\n@author shadowprince\n@license Eclipse Public License\n\nSAMPLE OUTPUT\n{'full_text': 'eno1:  852.2 KiB/s'}\n\"\"\"\n\nfrom __future__ import division  # python2 compatibility\nfrom time import time\n\n\nclass Py3status:\n    \"\"\"\n    \"\"\"\n    # available configuration parameters\n    all_interfaces = True\n    cache_timeout = 2\n    devfile = '/proc/net/dev'\n    format = \"{interface}: {total}\"\n    format_no_connection = ''\n    format_value = \"[\\?min_length=11 {value:.1f} {unit}]\"\n    hide_if_zero = False\n    interfaces = []\n    interfaces_blacklist = 'lo'\n    si_units = False\n    sum_values = False\n    thresholds = [(0, \"bad\"), (1024, \"degraded\"), (1024 * 1024, \"good\")]\n    unit = \"B/s\"\n\n    class Meta:\n\n        def deprecate_function(config):\n            # support old thresholds\n            precision = config.get('precision', 1)\n            padding = 3 + 1 + precision + 1 + 5\n            format_value = \"[\\?min_length={padding} {{value:.{precision}f}} {{unit}}]\".format(\n                padding=padding, precision=precision\n            )\n            return {'format_value': format_value}\n\n        deprecated = {\n            'function': [\n                {'function': deprecate_function},\n            ],\n            'remove': [\n                {\n                    'param': 'precision',\n                    'msg': 'obsolete, use format_value instead',\n                },\n            ]\n        }\n\n    def post_config_hook(self):\n        # parse some configuration parameters\n        if not isinstance(self.interfaces, list):\n            self.interfaces = self.interfaces.split(',')\n        if not isinstance(self.interfaces_blacklist, list):\n            self.interfaces_blacklist = self.interfaces_blacklist.split(',')\n        placeholders = self.py3.get_placeholder_formats_list(self.format_value)\n        values = ['{%s}' % x[1] for x in placeholders if x[0] == 'value']\n        self._value_formats = values\n        # last\n        self.last_interface = None\n        self.last_stat = self._get_stat()\n        self.last_time = time()\n\n    def currentSpeed(self):\n        ns = self._get_stat()\n        deltas = {}\n        try:\n            # time from previous check\n            timedelta = time() - self.last_time\n\n            # calculate deltas for all interfaces\n            for old, new in zip(self.last_stat, ns):\n                down = int(new[1]) - int(old[1])\n                up = int(new[9]) - int(old[9])\n\n                down /= timedelta\n                up /= timedelta\n\n                deltas[new[0]] = {'total': up + down, 'up': up, 'down': down, }\n\n            # update last_ info\n            self.last_stat = self._get_stat()\n            self.last_time = time()\n\n            # get the interface with max rate\n            if self.sum_values:\n                interface = 'sum'\n                sum_up = sum([itm['up'] for _, itm in deltas.items()])\n                sum_down = sum([itm['down'] for _, itm in deltas.items()])\n                deltas[interface] = {'total': sum_up + sum_down, 'up': sum_up, 'down': sum_down}\n            else:\n                interface = max(deltas, key=lambda x: deltas[x]['total'])\n\n            # if there is no rate - show last active interface, or hide\n\n            # we need to check if it will be zero after it is formatted\n            # with the desired unit eg MB/s\n            total, _ = self.py3.format_units(\n                deltas[interface]['total'], unit=self.unit, si=self.si_units\n            )\n            values = [float(x.format(total)) for x in self._value_formats]\n            if max(values) == 0:\n                interface = self.last_interface\n                hide = self.hide_if_zero\n            # if there is - update last_interface\n            else:\n                self.last_interface = interface\n                hide = False\n\n            # get the deltas into variable\n            delta = deltas[interface] if interface else None\n\n        except (TypeError, ValueError):\n            delta = None\n            interface = None\n            hide = self.hide_if_zero\n\n        response = {'cached_until': self.py3.time_in(self.cache_timeout)}\n\n        if hide:\n            response['full_text'] = \"\"\n        elif not interface:\n            response['full_text'] = self.format_no_connection\n        else:\n            self.py3.threshold_get_color(delta['down'], 'down')\n            self.py3.threshold_get_color(delta['total'], 'total')\n            self.py3.threshold_get_color(delta['up'], 'up')\n            response['full_text'] = self.py3.safe_format(self.format, {\n                'down': self._format_value(delta['down']),\n                'total': self._format_value(delta['total']),\n                'up': self._format_value(delta['up']),\n                'interface': interface[:-1],\n            })\n\n        return response\n\n    def _get_stat(self):\n        \"\"\"\n        Get statistics from devfile in list of lists of words\n        \"\"\"\n        def dev_filter(x):\n            # get first word and remove trailing interface number\n            x = x.strip().split(\" \")[0][:-1]\n\n            if x in self.interfaces_blacklist:\n                return False\n\n            if self.all_interfaces:\n                return True\n\n            if x in self.interfaces:\n                return True\n\n            return False\n\n        # read devfile, skip two header files\n        x = filter(dev_filter, open(self.devfile).readlines()[2:])\n\n        try:\n            # split info into words, filter empty ones\n            return [list(filter(lambda x: x, _x.split(\" \"))) for _x in x]\n\n        except StopIteration:\n            return None\n\n    def _format_value(self, value):\n        \"\"\"\n        Return formatted string\n        \"\"\"\n        value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)\n        return self.py3.safe_format(self.format_value, {'value': value, 'unit': unit})\n\n\nif __name__ == \"__main__\":\n    \"\"\"\n    Run module in test mode.\n    \"\"\"\n    from py3status.module_test import module_test\n    module_test(Py3status)\n", "path": "py3status/modules/net_rate.py"}]}