We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TW production parser down
## Description

This is an automatic error report generated for Taiwan (TW).

Issues:
- No recent data found for `production` parser

## Suggestions
- Try running the parser locally using the command `poetry run test_parser TW production`
- <a href="https://kibana.electricitymap.org/app/kibana#/discover/10af54f0-0c4a-11e9-85c1-1d63df8c862c?_g=(refreshInterval:('$$hashKey':'object:232',display:'5%20minutes',pause:!f,section:2,value:300000),time:(from:now-24h,mode:quick,to:now))&_a=(columns:!(message,extra.key,level),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!t,index:'96f67170-0c49-11e9-85c1-1d63df8c862c',key:level,negate:!f,params:(query:ERROR,type:phrase),type:phrase,value:ERROR),query:(match:(level:(query:ERROR,type:phrase)))),('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'96f67170-0c49-11e9-85c1-1d63df8c862c',key:extra.key,negate:!f,params:(query:TW,type:phrase),type:phrase,value:TW),query:(match:(extra.key:(query:TW,type:phrase))))),index:'96f67170-0c49-11e9-85c1-1d63df8c862c',interval:auto,query:(language:lucene,query:''),sort:!('@timestamp',desc))">Explore the runtime logs</a>

You can see an overview of all parser issues [here](https://github.com/tmrowco/electricitymap-contrib/wiki/Parser-issues).


--- 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/TW.py`
Content:
```
1 #!/usr/bin/env python3
2 import arrow
3 import requests
4 import pandas
5 import dateutil
6 
7 
8 def fetch_production(zone_key='TW', session=None, target_datetime=None, logger=None) -> dict:
9     if target_datetime:
10         raise NotImplementedError('This parser is not yet able to parse past dates')
11 
12     url = 'http://www.taipower.com.tw/d006/loadGraph/loadGraph/data/genary.txt'
13     s = session or requests.Session()
14     response = s.get(url)
15     data = response.json()
16 
17     dumpDate = data['']
18     prodData = data['aaData']
19 
20     tz = 'Asia/Taipei'
21     dumpDate = arrow.get(dumpDate, 'YYYY-MM-DD HH:mm').replace(tzinfo=dateutil.tz.gettz(tz))
22 
23     objData = pandas.DataFrame(prodData)
24 
25     objData.columns = ['fueltype', 'name', 'capacity', 'output', 'percentage',
26                        'additional']
27 
28     objData['fueltype'] = objData.fueltype.str.split('(').str[1]
29     objData['fueltype'] = objData.fueltype.str.split(')').str[0]
30     objData.drop('additional', axis=1, inplace=True)
31     objData.drop('percentage', axis=1, inplace=True)
32 
33     objData['capacity'] = pandas.to_numeric(objData['capacity'], errors='coerce')
34     objData['output'] = pandas.to_numeric(objData['output'], errors='coerce')
35     production = pandas.DataFrame(objData.groupby('fueltype').sum())
36     production.columns = ['capacity', 'output']
37 
38     coal_capacity = production.loc['Coal'].capacity + production.loc['IPP-Coal'].capacity
39     gas_capacity = production.loc['LNG'].capacity + production.loc['IPP-LNG'].capacity
40     oil_capacity = production.loc['Oil'].capacity + production.loc['Diesel'].capacity
41 
42     coal_production = production.loc['Coal'].output + production.loc['IPP-Coal'].output
43     gas_production = production.loc['LNG'].output + production.loc['IPP-LNG'].output
44     oil_production = production.loc['Oil'].output + production.loc['Diesel'].output
45 
46     # For storage, note that load will be negative, and generation positive.
47     # We require the opposite
48 
49     returndata = {
50         'zoneKey': zone_key,
51         'datetime': dumpDate.datetime,
52         'production': {
53             'coal': coal_production,
54             'gas': gas_production,
55             'oil': oil_production,
56             'hydro': production.loc['Hydro'].output,
57             'nuclear': production.loc['Nuclear'].output,
58             'solar': production.loc['Solar'].output,
59             'wind': production.loc['Wind'].output,
60             'unknown': production.loc['Co-Gen'].output
61         },
62         'capacity': {
63             'coal': coal_capacity,
64             'gas': gas_capacity,
65             'oil': oil_capacity,
66             'hydro': production.loc['Hydro'].capacity,
67             'hydro storage':production.loc['Pumping Gen'].capacity,
68             'nuclear': production.loc['Nuclear'].capacity,
69             'solar': production.loc['Solar'].capacity,
70             'wind': production.loc['Wind'].capacity,
71             'unknown': production.loc['Co-Gen'].capacity
72         },
73         'storage': {
74             'hydro': -1 * production.loc['Pumping Load'].output - production.loc['Pumping Gen'].output
75         },
76         'source': 'taipower.com.tw'
77     }
78 
79     return returndata
80 
81 
82 if __name__ == '__main__':
83     print(fetch_production())
84
```
--- 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/TW.py b/parsers/TW.py
--- a/parsers/TW.py
+++ b/parsers/TW.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python3
 import arrow
-import requests
-import pandas
 import dateutil
+import pandas as pd
+import requests
 
 
 def fetch_production(zone_key='TW', session=None, target_datetime=None, logger=None) -> dict:
@@ -20,21 +20,27 @@
     tz = 'Asia/Taipei'
     dumpDate = arrow.get(dumpDate, 'YYYY-MM-DD HH:mm').replace(tzinfo=dateutil.tz.gettz(tz))
 
-    objData = pandas.DataFrame(prodData)
+    objData = pd.DataFrame(prodData)
 
-    objData.columns = ['fueltype', 'name', 'capacity', 'output', 'percentage',
-                       'additional']
+    columns = ['fueltype', 'additional_1', 'name', 'capacity', 'output', 'percentage', 'additional_2']
+    assert len(objData.iloc[0]) == len(columns), "number of input columns changed"
+    objData.columns = columns
 
     objData['fueltype'] = objData.fueltype.str.split('(').str[1]
     objData['fueltype'] = objData.fueltype.str.split(')').str[0]
-    objData.drop('additional', axis=1, inplace=True)
-    objData.drop('percentage', axis=1, inplace=True)
+    objData.loc[:,['capacity', 'output']] = objData[['capacity', 'output']].apply(pd.to_numeric, errors='coerce')
+    assert not objData.capacity.isna().all(), "capacity data is entirely NaN - input column order may have changed"
+    assert not objData.output.isna().all(), "output data is entirely NaN - input column order may have changed"
 
-    objData['capacity'] = pandas.to_numeric(objData['capacity'], errors='coerce')
-    objData['output'] = pandas.to_numeric(objData['output'], errors='coerce')
-    production = pandas.DataFrame(objData.groupby('fueltype').sum())
+    objData.drop(columns=['additional_1', 'name', 'additional_2', 'percentage'], axis=1, inplace=True)
+    # summing because items in returned object are for each power plant and operational units
+    production = pd.DataFrame(objData.groupby('fueltype').sum())
     production.columns = ['capacity', 'output']
 
+    # check output values coincide with total capacity by fuel type
+    check_values = production.output <= production.capacity
+    assert check_values.loc[~check_values.index.isin(["Co-Gen"])].all(), "output > capacity" # HACK: Co-Gen capacity is underestimated
+
     coal_capacity = production.loc['Coal'].capacity + production.loc['IPP-Coal'].capacity
     gas_capacity = production.loc['LNG'].capacity + production.loc['IPP-LNG'].capacity
     oil_capacity = production.loc['Oil'].capacity + production.loc['Diesel'].capacity

{"golden_diff": "diff --git a/parsers/TW.py b/parsers/TW.py\n--- a/parsers/TW.py\n+++ b/parsers/TW.py\n@@ -1,8 +1,8 @@\n #!/usr/bin/env python3\n import arrow\n-import requests\n-import pandas\n import dateutil\n+import pandas as pd\n+import requests\n \n \n def fetch_production(zone_key='TW', session=None, target_datetime=None, logger=None) -> dict:\n@@ -20,21 +20,27 @@\n     tz = 'Asia/Taipei'\n     dumpDate = arrow.get(dumpDate, 'YYYY-MM-DD HH:mm').replace(tzinfo=dateutil.tz.gettz(tz))\n \n-    objData = pandas.DataFrame(prodData)\n+    objData = pd.DataFrame(prodData)\n \n-    objData.columns = ['fueltype', 'name', 'capacity', 'output', 'percentage',\n-                       'additional']\n+    columns = ['fueltype', 'additional_1', 'name', 'capacity', 'output', 'percentage', 'additional_2']\n+    assert len(objData.iloc[0]) == len(columns), \"number of input columns changed\"\n+    objData.columns = columns\n \n     objData['fueltype'] = objData.fueltype.str.split('(').str[1]\n     objData['fueltype'] = objData.fueltype.str.split(')').str[0]\n-    objData.drop('additional', axis=1, inplace=True)\n-    objData.drop('percentage', axis=1, inplace=True)\n+    objData.loc[:,['capacity', 'output']] = objData[['capacity', 'output']].apply(pd.to_numeric, errors='coerce')\n+    assert not objData.capacity.isna().all(), \"capacity data is entirely NaN - input column order may have changed\"\n+    assert not objData.output.isna().all(), \"output data is entirely NaN - input column order may have changed\"\n \n-    objData['capacity'] = pandas.to_numeric(objData['capacity'], errors='coerce')\n-    objData['output'] = pandas.to_numeric(objData['output'], errors='coerce')\n-    production = pandas.DataFrame(objData.groupby('fueltype').sum())\n+    objData.drop(columns=['additional_1', 'name', 'additional_2', 'percentage'], axis=1, inplace=True)\n+    # summing because items in returned object are for each power plant and operational units\n+    production = pd.DataFrame(objData.groupby('fueltype').sum())\n     production.columns = ['capacity', 'output']\n \n+    # check output values coincide with total capacity by fuel type\n+    check_values = production.output <= production.capacity\n+    assert check_values.loc[~check_values.index.isin([\"Co-Gen\"])].all(), \"output > capacity\" # HACK: Co-Gen capacity is underestimated\n+\n     coal_capacity = production.loc['Coal'].capacity + production.loc['IPP-Coal'].capacity\n     gas_capacity = production.loc['LNG'].capacity + production.loc['IPP-LNG'].capacity\n     oil_capacity = production.loc['Oil'].capacity + production.loc['Diesel'].capacity\n", "issue": "TW production parser down\n## Description\n\nThis is an automatic error report generated for Taiwan (TW).\n\nIssues:\n- No recent data found for `production` parser\n\n## Suggestions\n- Try running the parser locally using the command `poetry run test_parser TW production`\n- <a href=\"https://kibana.electricitymap.org/app/kibana#/discover/10af54f0-0c4a-11e9-85c1-1d63df8c862c?_g=(refreshInterval:('$$hashKey':'object:232',display:'5%20minutes',pause:!f,section:2,value:300000),time:(from:now-24h,mode:quick,to:now))&_a=(columns:!(message,extra.key,level),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!t,index:'96f67170-0c49-11e9-85c1-1d63df8c862c',key:level,negate:!f,params:(query:ERROR,type:phrase),type:phrase,value:ERROR),query:(match:(level:(query:ERROR,type:phrase)))),('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'96f67170-0c49-11e9-85c1-1d63df8c862c',key:extra.key,negate:!f,params:(query:TW,type:phrase),type:phrase,value:TW),query:(match:(extra.key:(query:TW,type:phrase))))),index:'96f67170-0c49-11e9-85c1-1d63df8c862c',interval:auto,query:(language:lucene,query:''),sort:!('@timestamp',desc))\">Explore the runtime logs</a>\n\nYou can see an overview of all parser issues [here](https://github.com/tmrowco/electricitymap-contrib/wiki/Parser-issues).\n\n", "before_files": [{"content": "#!/usr/bin/env python3\nimport arrow\nimport requests\nimport pandas\nimport dateutil\n\n\ndef fetch_production(zone_key='TW', session=None, target_datetime=None, logger=None) -> dict:\n    if target_datetime:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    url = 'http://www.taipower.com.tw/d006/loadGraph/loadGraph/data/genary.txt'\n    s = session or requests.Session()\n    response = s.get(url)\n    data = response.json()\n\n    dumpDate = data['']\n    prodData = data['aaData']\n\n    tz = 'Asia/Taipei'\n    dumpDate = arrow.get(dumpDate, 'YYYY-MM-DD HH:mm').replace(tzinfo=dateutil.tz.gettz(tz))\n\n    objData = pandas.DataFrame(prodData)\n\n    objData.columns = ['fueltype', 'name', 'capacity', 'output', 'percentage',\n                       'additional']\n\n    objData['fueltype'] = objData.fueltype.str.split('(').str[1]\n    objData['fueltype'] = objData.fueltype.str.split(')').str[0]\n    objData.drop('additional', axis=1, inplace=True)\n    objData.drop('percentage', axis=1, inplace=True)\n\n    objData['capacity'] = pandas.to_numeric(objData['capacity'], errors='coerce')\n    objData['output'] = pandas.to_numeric(objData['output'], errors='coerce')\n    production = pandas.DataFrame(objData.groupby('fueltype').sum())\n    production.columns = ['capacity', 'output']\n\n    coal_capacity = production.loc['Coal'].capacity + production.loc['IPP-Coal'].capacity\n    gas_capacity = production.loc['LNG'].capacity + production.loc['IPP-LNG'].capacity\n    oil_capacity = production.loc['Oil'].capacity + production.loc['Diesel'].capacity\n\n    coal_production = production.loc['Coal'].output + production.loc['IPP-Coal'].output\n    gas_production = production.loc['LNG'].output + production.loc['IPP-LNG'].output\n    oil_production = production.loc['Oil'].output + production.loc['Diesel'].output\n\n    # For storage, note that load will be negative, and generation positive.\n    # We require the opposite\n\n    returndata = {\n        'zoneKey': zone_key,\n        'datetime': dumpDate.datetime,\n        'production': {\n            'coal': coal_production,\n            'gas': gas_production,\n            'oil': oil_production,\n            'hydro': production.loc['Hydro'].output,\n            'nuclear': production.loc['Nuclear'].output,\n            'solar': production.loc['Solar'].output,\n            'wind': production.loc['Wind'].output,\n            'unknown': production.loc['Co-Gen'].output\n        },\n        'capacity': {\n            'coal': coal_capacity,\n            'gas': gas_capacity,\n            'oil': oil_capacity,\n            'hydro': production.loc['Hydro'].capacity,\n            'hydro storage':production.loc['Pumping Gen'].capacity,\n            'nuclear': production.loc['Nuclear'].capacity,\n            'solar': production.loc['Solar'].capacity,\n            'wind': production.loc['Wind'].capacity,\n            'unknown': production.loc['Co-Gen'].capacity\n        },\n        'storage': {\n            'hydro': -1 * production.loc['Pumping Load'].output - production.loc['Pumping Gen'].output\n        },\n        'source': 'taipower.com.tw'\n    }\n\n    return returndata\n\n\nif __name__ == '__main__':\n    print(fetch_production())\n", "path": "parsers/TW.py"}], "after_files": [{"content": "#!/usr/bin/env python3\nimport arrow\nimport dateutil\nimport pandas as pd\nimport requests\n\n\ndef fetch_production(zone_key='TW', session=None, target_datetime=None, logger=None) -> dict:\n    if target_datetime:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    url = 'http://www.taipower.com.tw/d006/loadGraph/loadGraph/data/genary.txt'\n    s = session or requests.Session()\n    response = s.get(url)\n    data = response.json()\n\n    dumpDate = data['']\n    prodData = data['aaData']\n\n    tz = 'Asia/Taipei'\n    dumpDate = arrow.get(dumpDate, 'YYYY-MM-DD HH:mm').replace(tzinfo=dateutil.tz.gettz(tz))\n\n    objData = pd.DataFrame(prodData)\n\n    columns = ['fueltype', 'additional_1', 'name', 'capacity', 'output', 'percentage', 'additional_2']\n    assert len(objData.iloc[0]) == len(columns), \"number of input columns changed\"\n    objData.columns = columns\n\n    objData['fueltype'] = objData.fueltype.str.split('(').str[1]\n    objData['fueltype'] = objData.fueltype.str.split(')').str[0]\n    objData.loc[:,['capacity', 'output']] = objData[['capacity', 'output']].apply(pd.to_numeric, errors='coerce')\n    assert not objData.capacity.isna().all(), \"capacity data is entirely NaN - input column order may have changed\"\n    assert not objData.output.isna().all(), \"output data is entirely NaN - input column order may have changed\"\n\n    objData.drop(columns=['additional_1', 'name', 'additional_2', 'percentage'], axis=1, inplace=True)\n    # summing because items in returned object are for each power plant and operational units\n    production = pd.DataFrame(objData.groupby('fueltype').sum())\n    production.columns = ['capacity', 'output']\n\n    # check output values coincide with total capacity by fuel type\n    check_values = production.output <= production.capacity\n    assert check_values.loc[~check_values.index.isin([\"Co-Gen\"])].all(), \"output > capacity\" # HACK: Co-Gen capacity is underestimated\n\n    coal_capacity = production.loc['Coal'].capacity + production.loc['IPP-Coal'].capacity\n    gas_capacity = production.loc['LNG'].capacity + production.loc['IPP-LNG'].capacity\n    oil_capacity = production.loc['Oil'].capacity + production.loc['Diesel'].capacity\n\n    coal_production = production.loc['Coal'].output + production.loc['IPP-Coal'].output\n    gas_production = production.loc['LNG'].output + production.loc['IPP-LNG'].output\n    oil_production = production.loc['Oil'].output + production.loc['Diesel'].output\n\n    # For storage, note that load will be negative, and generation positive.\n    # We require the opposite\n\n    returndata = {\n        'zoneKey': zone_key,\n        'datetime': dumpDate.datetime,\n        'production': {\n            'coal': coal_production,\n            'gas': gas_production,\n            'oil': oil_production,\n            'hydro': production.loc['Hydro'].output,\n            'nuclear': production.loc['Nuclear'].output,\n            'solar': production.loc['Solar'].output,\n            'wind': production.loc['Wind'].output,\n            'unknown': production.loc['Co-Gen'].output\n        },\n        'capacity': {\n            'coal': coal_capacity,\n            'gas': gas_capacity,\n            'oil': oil_capacity,\n            'hydro': production.loc['Hydro'].capacity,\n            'hydro storage':production.loc['Pumping Gen'].capacity,\n            'nuclear': production.loc['Nuclear'].capacity,\n            'solar': production.loc['Solar'].capacity,\n            'wind': production.loc['Wind'].capacity,\n            'unknown': production.loc['Co-Gen'].capacity\n        },\n        'storage': {\n            'hydro': -1 * production.loc['Pumping Load'].output - production.loc['Pumping Gen'].output\n        },\n        'source': 'taipower.com.tw'\n    }\n\n    return returndata\n\n\nif __name__ == '__main__':\n    print(fetch_production())\n", "path": "parsers/TW.py"}]}