We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Exception BO
feeder_electricity_1  | Exception while fetching production of BO
feeder_electricity_1  | Traceback (most recent call last):
feeder_electricity_1  |   File "feeder_electricity.py", line 111, in fetch_production
feeder_electricity_1  |     objs = parser(country_code, session)
feeder_electricity_1  |   File "/home/feeder/lib_electricitymap/parsers/BO.py", line 149, in fetch_production
feeder_electricity_1  |     sum(datapoint['production'].values()) != 0.0]):
feeder_electricity_1  | AttributeError: 'NoneType' object has no attribute 'values'

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `parsers/BO.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 # The arrow library is used to handle datetimes
4 import arrow
5 # The request library is used to fetch content through HTTP
6 import requests
7 # The numpy and pandas libraries are used to manipulate real time data
8 import pandas as pd
9 # The BeautifulSoup library is used parse web html
10 from bs4 import BeautifulSoup
11 
12 tz_bo = 'America/La_Paz'
13 
14 MAP_GENERATION = {
15     'hydro': 'Hidro',
16     'unknown': 'Termo',
17     'wind': 'Intermitentes'
18 }
19 
20 
21 def webparser(resp):
22     """Takes content from the corresponding webpage and returns the necessary outputs in a dataframe"""
23     # get the response as an html
24     soup = BeautifulSoup(resp.text, 'html.parser')
25     # Each variable correspond to a row
26     rows = soup.find_all("row")
27     # Extract the name of variables and position
28     variables = []
29     corresponding_row = []
30     hours = []
31     for i_row in range(len(rows)):
32         for tag in rows[i_row].find_all("string"):
33             if not tag.get_text().isdigit():
34                 variables.append(tag.get_text().strip())
35                 corresponding_row.append(i_row)
36             else:
37                 hours.append(int(tag.get_text()))
38     # Define output frame
39     obj = pd.DataFrame(0, index=range(24), columns=['hour'] + variables)
40     # Fill it with hours and variables' value
41     obj.hour = hours
42     for i_row, row in enumerate(corresponding_row):
43         numbers = [float(numb.text) for numb in rows[row].find_all("number")]
44         for i_num, num in enumerate(numbers):
45             obj.loc[i_num, (variables[i_row])] = num
46     # Define negative values to NaN
47     obj[obj < 0] = 0
48 
49     return obj
50 
51 
52 def fetch_hourly_production(country_code, obj, date):
53     """Returns a list of dictionaries."""
54 
55     production_by_hour = []
56     for index, row in obj.iterrows():
57 
58         data = {
59             'countryCode': country_code,
60             'production': {},
61             'storage': {},
62             'source': 'cndc.bo',
63         }
64         # Fill datetime variable
65         # Datetime are recorded from hour 1 to 24 in the web service
66         if row['hour'] == 24:
67             row['hour'] = 0
68             date = arrow.get(date, 'YYYY-MM-DD').shift(days=+1).format('YYYY-MM-DD')
69             # date = arrow.now(tz=tz_bo).format('YYYY-MM-DD')
70         data['datetime'] = arrow.get(date, 'YYYY-MM-DD').replace(tzinfo=tz_bo,
71                                                                  hour=int(row['hour'])).datetime
72 
73         # Fill production types
74         for i_type in MAP_GENERATION.keys():
75             try:
76                 data['production'][i_type] = row[MAP_GENERATION[i_type]]
77             except KeyError as e:
78                 data['production'] = None
79                 break
80 
81         production_by_hour.append(data)
82 
83     return production_by_hour
84 
85 
86 def fetch_production(country_code='BO', session=None):
87     """
88     Requests the last known production mix (in MW) of a given country
89     Arguments:
90     country_code (optional) -- used in case a parser is able to fetch multiple countries
91     Return:
92     A dictionary in the form:
93     {
94       'countryCode': 'FR',
95       'datetime': '2017-01-01T00:00:00Z',
96       'production': {
97           'biomass': 0.0,
98           'coal': 0.0,
99           'gas': 0.0,
100           'hydro': 0.0,
101           'nuclear': null,
102           'oil': 0.0,
103           'solar': 0.0,
104           'wind': 0.0,
105           'geothermal': 0.0,
106           'unknown': 0.0
107       },
108       'storage': {
109           'hydro': -10.0,
110       },
111       'source': 'mysource.com'
112     }
113     """
114 
115     # Define actual and previous day (for midnight data).
116     now = arrow.now(tz=tz_bo)
117     formatted_date = now.format('YYYY-MM-DD')
118     past_formatted_date = arrow.get(formatted_date, 'YYYY-MM-DD').shift(days=-1).format(
119         'YYYY-MM-DD')
120 
121     # initial path for url to request
122     url_init = 'http://www.cndc.bo/media/archivos/graf/gene_hora/despacho_diario.php?fechag='
123 
124     # Start with data for previous day in order to get midnight data.
125     url = url_init + past_formatted_date
126     r = session or requests.session()
127     response = r.get(url)
128     obj = webparser(response)
129     data_yesterday = fetch_hourly_production(country_code, obj, past_formatted_date)
130 
131     # Now get data for rest of today.
132     url = url_init + formatted_date
133     r = session or requests.session()
134     response = r.get(url)
135     obj = webparser(response)
136     data_today = fetch_hourly_production(country_code, obj, formatted_date)
137 
138     data = data_yesterday + data_today
139 
140     # Drop any datapoints where;
141     # 1) A type of generation is totally missing resulting in None.
142     # 2) Datapoint is in the future.
143     # 3) All production values are zero, this can happen because the data source
144     #    updates ~5mins after the hour so condition 2 will pass.
145     valid_data = []
146     for datapoint in data:
147         if all([datapoint['production'] is not None,
148                 now.datetime > datapoint['datetime'],
149                 sum(datapoint['production'].values()) != 0.0]):
150             valid_data.append(datapoint)
151 
152     return valid_data
153 
154 
155 def fetch_hourly_generation_forecast(country_code, obj, date):
156     """Returns a list of dictionaries."""
157 
158     hourly_forecast = []
159     for index, row in obj.iterrows():
160         data = {
161             'countryCode': country_code,
162             'value': {},
163             'source': 'cndc.bo',
164         }
165 
166         # Fill forecasted value
167         data['value'] = row['Gen.Prevista']
168 
169         # Fill datetime variable - changing format if midnight (datetime are recorded from hour 1 to 24 in the webservice)
170         if row['hour'] == 24:
171             row['hour'] = 0
172             date = arrow.get(date, 'YYYY-MM-DD').shift(days=+1).format('YYYY-MM-DD')
173         data['datetime'] = arrow.get(date, 'YYYY-MM-DD').replace(tzinfo=tz_bo,
174                                                                  hour=int(row['hour'])).datetime
175 
176         hourly_forecast.append(data)
177 
178     return hourly_forecast
179 
180 
181 def fetch_generation_forecast(country_code='BO', session=None):
182     # Define actual and last day (for midnight data)
183     formatted_date = arrow.now(tz=tz_bo).format('YYYY-MM-DD')
184 
185     # initial path for url to request
186     url_init = 'http://www.cndc.bo/media/archivos/graf/gene_hora/despacho_diario.php?fechag='
187     url = url_init + formatted_date
188 
189     r = session or requests.session()
190     response = r.get(url)
191     obj = webparser(response)
192     forecast = fetch_hourly_generation_forecast('BO', obj, formatted_date)
193 
194     return forecast
195 
196 
197 if __name__ == '__main__':
198     """Main method, never used by the Electricity Map backend, but handy for testing."""
199     print('fetch_production() ->')
200     print(fetch_production())
201     print('fetch_generation_forecast() ->')
202     print(fetch_generation_forecast())
203
```
--- 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/parsers/BO.py b/parsers/BO.py
--- a/parsers/BO.py
+++ b/parsers/BO.py
@@ -144,9 +144,13 @@
     #    updates ~5mins after the hour so condition 2 will pass.
     valid_data = []
     for datapoint in data:
-        if all([datapoint['production'] is not None,
-                now.datetime > datapoint['datetime'],
-                sum(datapoint['production'].values()) != 0.0]):
+        if datapoint['production'] is None:
+            continue
+        elif now.datetime < datapoint['datetime']:
+            continue
+        elif sum(datapoint['production'].values()) == 0.0:
+            continue
+        else:
             valid_data.append(datapoint)
 
     return valid_data

{"golden_diff": "diff --git a/parsers/BO.py b/parsers/BO.py\n--- a/parsers/BO.py\n+++ b/parsers/BO.py\n@@ -144,9 +144,13 @@\n     #    updates ~5mins after the hour so condition 2 will pass.\n     valid_data = []\n     for datapoint in data:\n-        if all([datapoint['production'] is not None,\n-                now.datetime > datapoint['datetime'],\n-                sum(datapoint['production'].values()) != 0.0]):\n+        if datapoint['production'] is None:\n+            continue\n+        elif now.datetime < datapoint['datetime']:\n+            continue\n+        elif sum(datapoint['production'].values()) == 0.0:\n+            continue\n+        else:\n             valid_data.append(datapoint)\n \n     return valid_data\n", "issue": "Exception BO\nfeeder_electricity_1  | Exception while fetching production of BO\r\nfeeder_electricity_1  | Traceback (most recent call last):\r\nfeeder_electricity_1  |   File \"feeder_electricity.py\", line 111, in fetch_production\r\nfeeder_electricity_1  |     objs = parser(country_code, session)\r\nfeeder_electricity_1  |   File \"/home/feeder/lib_electricitymap/parsers/BO.py\", line 149, in fetch_production\r\nfeeder_electricity_1  |     sum(datapoint['production'].values()) != 0.0]):\r\nfeeder_electricity_1  | AttributeError: 'NoneType' object has no attribute 'values'\n", "before_files": [{"content": "#!/usr/bin/env python3\n\n# The arrow library is used to handle datetimes\nimport arrow\n# The request library is used to fetch content through HTTP\nimport requests\n# The numpy and pandas libraries are used to manipulate real time data\nimport pandas as pd\n# The BeautifulSoup library is used parse web html\nfrom bs4 import BeautifulSoup\n\ntz_bo = 'America/La_Paz'\n\nMAP_GENERATION = {\n    'hydro': 'Hidro',\n    'unknown': 'Termo',\n    'wind': 'Intermitentes'\n}\n\n\ndef webparser(resp):\n    \"\"\"Takes content from the corresponding webpage and returns the necessary outputs in a dataframe\"\"\"\n    # get the response as an html\n    soup = BeautifulSoup(resp.text, 'html.parser')\n    # Each variable correspond to a row\n    rows = soup.find_all(\"row\")\n    # Extract the name of variables and position\n    variables = []\n    corresponding_row = []\n    hours = []\n    for i_row in range(len(rows)):\n        for tag in rows[i_row].find_all(\"string\"):\n            if not tag.get_text().isdigit():\n                variables.append(tag.get_text().strip())\n                corresponding_row.append(i_row)\n            else:\n                hours.append(int(tag.get_text()))\n    # Define output frame\n    obj = pd.DataFrame(0, index=range(24), columns=['hour'] + variables)\n    # Fill it with hours and variables' value\n    obj.hour = hours\n    for i_row, row in enumerate(corresponding_row):\n        numbers = [float(numb.text) for numb in rows[row].find_all(\"number\")]\n        for i_num, num in enumerate(numbers):\n            obj.loc[i_num, (variables[i_row])] = num\n    # Define negative values to NaN\n    obj[obj < 0] = 0\n\n    return obj\n\n\ndef fetch_hourly_production(country_code, obj, date):\n    \"\"\"Returns a list of dictionaries.\"\"\"\n\n    production_by_hour = []\n    for index, row in obj.iterrows():\n\n        data = {\n            'countryCode': country_code,\n            'production': {},\n            'storage': {},\n            'source': 'cndc.bo',\n        }\n        # Fill datetime variable\n        # Datetime are recorded from hour 1 to 24 in the web service\n        if row['hour'] == 24:\n            row['hour'] = 0\n            date = arrow.get(date, 'YYYY-MM-DD').shift(days=+1).format('YYYY-MM-DD')\n            # date = arrow.now(tz=tz_bo).format('YYYY-MM-DD')\n        data['datetime'] = arrow.get(date, 'YYYY-MM-DD').replace(tzinfo=tz_bo,\n                                                                 hour=int(row['hour'])).datetime\n\n        # Fill production types\n        for i_type in MAP_GENERATION.keys():\n            try:\n                data['production'][i_type] = row[MAP_GENERATION[i_type]]\n            except KeyError as e:\n                data['production'] = None\n                break\n\n        production_by_hour.append(data)\n\n    return production_by_hour\n\n\ndef fetch_production(country_code='BO', session=None):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given country\n    Arguments:\n    country_code (optional) -- used in case a parser is able to fetch multiple countries\n    Return:\n    A dictionary in the form:\n    {\n      'countryCode': 'FR',\n      'datetime': '2017-01-01T00:00:00Z',\n      'production': {\n          'biomass': 0.0,\n          'coal': 0.0,\n          'gas': 0.0,\n          'hydro': 0.0,\n          'nuclear': null,\n          'oil': 0.0,\n          'solar': 0.0,\n          'wind': 0.0,\n          'geothermal': 0.0,\n          'unknown': 0.0\n      },\n      'storage': {\n          'hydro': -10.0,\n      },\n      'source': 'mysource.com'\n    }\n    \"\"\"\n\n    # Define actual and previous day (for midnight data).\n    now = arrow.now(tz=tz_bo)\n    formatted_date = now.format('YYYY-MM-DD')\n    past_formatted_date = arrow.get(formatted_date, 'YYYY-MM-DD').shift(days=-1).format(\n        'YYYY-MM-DD')\n\n    # initial path for url to request\n    url_init = 'http://www.cndc.bo/media/archivos/graf/gene_hora/despacho_diario.php?fechag='\n\n    # Start with data for previous day in order to get midnight data.\n    url = url_init + past_formatted_date\n    r = session or requests.session()\n    response = r.get(url)\n    obj = webparser(response)\n    data_yesterday = fetch_hourly_production(country_code, obj, past_formatted_date)\n\n    # Now get data for rest of today.\n    url = url_init + formatted_date\n    r = session or requests.session()\n    response = r.get(url)\n    obj = webparser(response)\n    data_today = fetch_hourly_production(country_code, obj, formatted_date)\n\n    data = data_yesterday + data_today\n\n    # Drop any datapoints where;\n    # 1) A type of generation is totally missing resulting in None.\n    # 2) Datapoint is in the future.\n    # 3) All production values are zero, this can happen because the data source\n    #    updates ~5mins after the hour so condition 2 will pass.\n    valid_data = []\n    for datapoint in data:\n        if all([datapoint['production'] is not None,\n                now.datetime > datapoint['datetime'],\n                sum(datapoint['production'].values()) != 0.0]):\n            valid_data.append(datapoint)\n\n    return valid_data\n\n\ndef fetch_hourly_generation_forecast(country_code, obj, date):\n    \"\"\"Returns a list of dictionaries.\"\"\"\n\n    hourly_forecast = []\n    for index, row in obj.iterrows():\n        data = {\n            'countryCode': country_code,\n            'value': {},\n            'source': 'cndc.bo',\n        }\n\n        # Fill forecasted value\n        data['value'] = row['Gen.Prevista']\n\n        # Fill datetime variable - changing format if midnight (datetime are recorded from hour 1 to 24 in the webservice)\n        if row['hour'] == 24:\n            row['hour'] = 0\n            date = arrow.get(date, 'YYYY-MM-DD').shift(days=+1).format('YYYY-MM-DD')\n        data['datetime'] = arrow.get(date, 'YYYY-MM-DD').replace(tzinfo=tz_bo,\n                                                                 hour=int(row['hour'])).datetime\n\n        hourly_forecast.append(data)\n\n    return hourly_forecast\n\n\ndef fetch_generation_forecast(country_code='BO', session=None):\n    # Define actual and last day (for midnight data)\n    formatted_date = arrow.now(tz=tz_bo).format('YYYY-MM-DD')\n\n    # initial path for url to request\n    url_init = 'http://www.cndc.bo/media/archivos/graf/gene_hora/despacho_diario.php?fechag='\n    url = url_init + formatted_date\n\n    r = session or requests.session()\n    response = r.get(url)\n    obj = webparser(response)\n    forecast = fetch_hourly_generation_forecast('BO', obj, formatted_date)\n\n    return forecast\n\n\nif __name__ == '__main__':\n    \"\"\"Main method, never used by the Electricity Map backend, but handy for testing.\"\"\"\n    print('fetch_production() ->')\n    print(fetch_production())\n    print('fetch_generation_forecast() ->')\n    print(fetch_generation_forecast())\n", "path": "parsers/BO.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n# The arrow library is used to handle datetimes\nimport arrow\n# The request library is used to fetch content through HTTP\nimport requests\n# The numpy and pandas libraries are used to manipulate real time data\nimport pandas as pd\n# The BeautifulSoup library is used parse web html\nfrom bs4 import BeautifulSoup\n\ntz_bo = 'America/La_Paz'\n\nMAP_GENERATION = {\n    'hydro': 'Hidro',\n    'unknown': 'Termo',\n    'wind': 'Intermitentes'\n}\n\n\ndef webparser(resp):\n    \"\"\"Takes content from the corresponding webpage and returns the necessary outputs in a dataframe\"\"\"\n    # get the response as an html\n    soup = BeautifulSoup(resp.text, 'html.parser')\n    # Each variable correspond to a row\n    rows = soup.find_all(\"row\")\n    # Extract the name of variables and position\n    variables = []\n    corresponding_row = []\n    hours = []\n    for i_row in range(len(rows)):\n        for tag in rows[i_row].find_all(\"string\"):\n            if not tag.get_text().isdigit():\n                variables.append(tag.get_text().strip())\n                corresponding_row.append(i_row)\n            else:\n                hours.append(int(tag.get_text()))\n    # Define output frame\n    obj = pd.DataFrame(0, index=range(24), columns=['hour'] + variables)\n    # Fill it with hours and variables' value\n    obj.hour = hours\n    for i_row, row in enumerate(corresponding_row):\n        numbers = [float(numb.text) for numb in rows[row].find_all(\"number\")]\n        for i_num, num in enumerate(numbers):\n            obj.loc[i_num, (variables[i_row])] = num\n    # Define negative values to NaN\n    obj[obj < 0] = 0\n\n    return obj\n\n\ndef fetch_hourly_production(country_code, obj, date):\n    \"\"\"Returns a list of dictionaries.\"\"\"\n\n    production_by_hour = []\n    for index, row in obj.iterrows():\n\n        data = {\n            'countryCode': country_code,\n            'production': {},\n            'storage': {},\n            'source': 'cndc.bo',\n        }\n        # Fill datetime variable\n        # Datetime are recorded from hour 1 to 24 in the web service\n        if row['hour'] == 24:\n            row['hour'] = 0\n            date = arrow.get(date, 'YYYY-MM-DD').shift(days=+1).format('YYYY-MM-DD')\n            # date = arrow.now(tz=tz_bo).format('YYYY-MM-DD')\n        data['datetime'] = arrow.get(date, 'YYYY-MM-DD').replace(tzinfo=tz_bo,\n                                                                 hour=int(row['hour'])).datetime\n\n        # Fill production types\n        for i_type in MAP_GENERATION.keys():\n            try:\n                data['production'][i_type] = row[MAP_GENERATION[i_type]]\n            except KeyError as e:\n                data['production'] = None\n                break\n\n        production_by_hour.append(data)\n\n    return production_by_hour\n\n\ndef fetch_production(country_code='BO', session=None):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given country\n    Arguments:\n    country_code (optional) -- used in case a parser is able to fetch multiple countries\n    Return:\n    A dictionary in the form:\n    {\n      'countryCode': 'FR',\n      'datetime': '2017-01-01T00:00:00Z',\n      'production': {\n          'biomass': 0.0,\n          'coal': 0.0,\n          'gas': 0.0,\n          'hydro': 0.0,\n          'nuclear': null,\n          'oil': 0.0,\n          'solar': 0.0,\n          'wind': 0.0,\n          'geothermal': 0.0,\n          'unknown': 0.0\n      },\n      'storage': {\n          'hydro': -10.0,\n      },\n      'source': 'mysource.com'\n    }\n    \"\"\"\n\n    # Define actual and previous day (for midnight data).\n    now = arrow.now(tz=tz_bo)\n    formatted_date = now.format('YYYY-MM-DD')\n    past_formatted_date = arrow.get(formatted_date, 'YYYY-MM-DD').shift(days=-1).format(\n        'YYYY-MM-DD')\n\n    # initial path for url to request\n    url_init = 'http://www.cndc.bo/media/archivos/graf/gene_hora/despacho_diario.php?fechag='\n\n    # Start with data for previous day in order to get midnight data.\n    url = url_init + past_formatted_date\n    r = session or requests.session()\n    response = r.get(url)\n    obj = webparser(response)\n    data_yesterday = fetch_hourly_production(country_code, obj, past_formatted_date)\n\n    # Now get data for rest of today.\n    url = url_init + formatted_date\n    r = session or requests.session()\n    response = r.get(url)\n    obj = webparser(response)\n    data_today = fetch_hourly_production(country_code, obj, formatted_date)\n\n    data = data_yesterday + data_today\n\n    # Drop any datapoints where;\n    # 1) A type of generation is totally missing resulting in None.\n    # 2) Datapoint is in the future.\n    # 3) All production values are zero, this can happen because the data source\n    #    updates ~5mins after the hour so condition 2 will pass.\n    valid_data = []\n    for datapoint in data:\n        if datapoint['production'] is None:\n            continue\n        elif now.datetime < datapoint['datetime']:\n            continue\n        elif sum(datapoint['production'].values()) == 0.0:\n            continue\n        else:\n            valid_data.append(datapoint)\n\n    return valid_data\n\n\ndef fetch_hourly_generation_forecast(country_code, obj, date):\n    \"\"\"Returns a list of dictionaries.\"\"\"\n\n    hourly_forecast = []\n    for index, row in obj.iterrows():\n        data = {\n            'countryCode': country_code,\n            'value': {},\n            'source': 'cndc.bo',\n        }\n\n        # Fill forecasted value\n        data['value'] = row['Gen.Prevista']\n\n        # Fill datetime variable - changing format if midnight (datetime are recorded from hour 1 to 24 in the webservice)\n        if row['hour'] == 24:\n            row['hour'] = 0\n            date = arrow.get(date, 'YYYY-MM-DD').shift(days=+1).format('YYYY-MM-DD')\n        data['datetime'] = arrow.get(date, 'YYYY-MM-DD').replace(tzinfo=tz_bo,\n                                                                 hour=int(row['hour'])).datetime\n\n        hourly_forecast.append(data)\n\n    return hourly_forecast\n\n\ndef fetch_generation_forecast(country_code='BO', session=None):\n    # Define actual and last day (for midnight data)\n    formatted_date = arrow.now(tz=tz_bo).format('YYYY-MM-DD')\n\n    # initial path for url to request\n    url_init = 'http://www.cndc.bo/media/archivos/graf/gene_hora/despacho_diario.php?fechag='\n    url = url_init + formatted_date\n\n    r = session or requests.session()\n    response = r.get(url)\n    obj = webparser(response)\n    forecast = fetch_hourly_generation_forecast('BO', obj, formatted_date)\n\n    return forecast\n\n\nif __name__ == '__main__':\n    \"\"\"Main method, never used by the Electricity Map backend, but handy for testing.\"\"\"\n    print('fetch_production() ->')\n    print(fetch_production())\n    print('fetch_generation_forecast() ->')\n    print(fetch_generation_forecast())\n", "path": "parsers/BO.py"}]}