prompt: 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()
  
  ```
  
golden_diff: 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
  
verification_info: {"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"}]}