prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Add US-MISO day ahead wind & solar forecasts
  Both Wind Production and Total Load seem available with a day-head forecast from the following webpage https://www.misoenergy.org/markets-and-operations/real-time-displays/
  
  These forecasts could be added to the MISO parser 
  
  
  --- 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/US_MISO.py`
  Content:
  ```
  1 #!/usr/bin/env python3
  2 
  3 """Parser for the MISO area of the United States."""
  4 
  5 import requests
  6 from dateutil import parser, tz
  7 
  8 mix_url = 'https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType' \
  9           '=getfuelmix&returnType=json'
  10 
  11 mapping = {'Coal': 'coal',
  12            'Natural Gas': 'gas',
  13            'Nuclear': 'nuclear',
  14            'Wind': 'wind',
  15            'Other': 'unknown'}
  16 
  17 
  18 # To quote the MISO data source;
  19 # "The category listed as “Other” is the combination of Hydro, Pumped Storage Hydro, Diesel, Demand Response Resources,
  20 # External Asynchronous Resources and a varied assortment of solid waste, garbage and wood pulp burners".
  21 
  22 # Timestamp reported by data source is in format 23-Jan-2018 - Interval 11:45 EST
  23 # Unsure exactly why EST is used, possibly due to operational connections with PJM.
  24 
  25 
  26 def get_json_data(logger, session=None):
  27     """Returns 5 minute generation data in json format."""
  28 
  29     s = session or requests.session()
  30     json_data = s.get(mix_url).json()
  31 
  32     return json_data
  33 
  34 
  35 def data_processer(json_data, logger):
  36     """
  37     Identifies any unknown fuel types and logs a warning.
  38     Returns a tuple containing datetime object and production dictionary.
  39     """
  40 
  41     generation = json_data['Fuel']['Type']
  42 
  43     production = {}
  44     for fuel in generation:
  45         try:
  46             k = mapping[fuel['CATEGORY']]
  47         except KeyError as e:
  48             logger.warning("Key '{}' is missing from the MISO fuel mapping.".format(
  49                 fuel['CATEGORY']))
  50             k = 'unknown'
  51         v = float(fuel['ACT'])
  52         production[k] = production.get(k, 0.0) + v
  53 
  54     # Remove unneeded parts of timestamp to allow datetime parsing.
  55     timestamp = json_data['RefId']
  56     split_time = timestamp.split(" ")
  57     time_junk = {1, 2}  # set literal
  58     useful_time_parts = [v for i, v in enumerate(split_time) if i not in time_junk]
  59 
  60     if useful_time_parts[-1] != 'EST':
  61         raise ValueError('Timezone reported for US-MISO has changed.')
  62 
  63     time_data = " ".join(useful_time_parts)
  64     tzinfos = {"EST": tz.gettz('America/New_York')}
  65     dt = parser.parse(time_data, tzinfos=tzinfos)
  66 
  67     return dt, production
  68 
  69 
  70 def fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=None):
  71     """
  72     Requests the last known production mix (in MW) of a given country
  73     Arguments:
  74     zone_key (optional) -- used in case a parser is able to fetch multiple countries
  75     session (optional)      -- request session passed in order to re-use an existing session
  76     Return:
  77     A dictionary in the form:
  78     {
  79       'zoneKey': 'FR',
  80       'datetime': '2017-01-01T00:00:00Z',
  81       'production': {
  82           'biomass': 0.0,
  83           'coal': 0.0,
  84           'gas': 0.0,
  85           'hydro': 0.0,
  86           'nuclear': null,
  87           'oil': 0.0,
  88           'solar': 0.0,
  89           'wind': 0.0,
  90           'geothermal': 0.0,
  91           'unknown': 0.0
  92       },
  93       'storage': {
  94           'hydro': -10.0,
  95       },
  96       'source': 'mysource.com'
  97     }
  98     """
  99     if target_datetime:
  100         raise NotImplementedError('This parser is not yet able to parse past dates')
  101 
  102     json_data = get_json_data(logger, session=session)
  103     processed_data = data_processer(json_data, logger)
  104 
  105     data = {
  106         'zoneKey': zone_key,
  107         'datetime': processed_data[0],
  108         'production': processed_data[1],
  109         'storage': {},
  110         'source': 'misoenergy.org'
  111     }
  112 
  113     return data
  114 
  115 
  116 if __name__ == '__main__':
  117     print('fetch_production() ->')
  118     print(fetch_production())
  119
  ```
  --- 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/US_MISO.py b/parsers/US_MISO.py
  --- a/parsers/US_MISO.py
  +++ b/parsers/US_MISO.py
  @@ -2,6 +2,7 @@
   
   """Parser for the MISO area of the United States."""
   
  +import logging
   import requests
   from dateutil import parser, tz
   
  @@ -14,6 +15,7 @@
              'Wind': 'wind',
              'Other': 'unknown'}
   
  +wind_forecast_url = 'https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType=getWindForecast&returnType=json'
   
   # To quote the MISO data source;
   # "The category listed as “Other” is the combination of Hydro, Pumped Storage Hydro, Diesel, Demand Response Resources,
  @@ -67,12 +69,14 @@
       return dt, production
   
   
  -def fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=None):
  +def fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=logging.getLogger(__name__)):
       """
       Requests the last known production mix (in MW) of a given country
       Arguments:
       zone_key (optional) -- used in case a parser is able to fetch multiple countries
       session (optional)      -- request session passed in order to re-use an existing session
  +    target_datetime (optional) -- used if parser can fetch data for a specific day
  +    logger (optional) -- handles logging when parser is run as main
       Return:
       A dictionary in the form:
       {
  @@ -96,6 +100,7 @@
         'source': 'mysource.com'
       }
       """
  +
       if target_datetime:
           raise NotImplementedError('This parser is not yet able to parse past dates')
   
  @@ -113,6 +118,48 @@
       return data
   
   
  +def fetch_wind_forecast(zone_key='US-MISO', session=None, target_datetime=None, logger=None):
  +    """
  +    Requests the day ahead wind forecast (in MW) of a given zone
  +    Arguments:
  +    zone_key (optional) -- used in case a parser is able to fetch multiple countries
  +    session (optional)  -- request session passed in order to re-use an existing session
  +    target_datetime (optional) -- used if parser can fetch data for a specific day
  +    logger (optional) -- handles logging when parser is run as main
  +    Return:
  +    A list of dictionaries in the form:
  +    {
  +    'source': 'misoenergy.org',
  +    'production': {'wind': 12932.0},
  +    'datetime': '2019-01-01T00:00:00Z',
  +    'zoneKey': 'US-MISO'
  +    }
  +    """
  +
  +    if target_datetime:
  +        raise NotImplementedError('This parser is not yet able to parse past dates')
  +
  +    s = session or requests.Session()
  +    req = s.get(wind_forecast_url)
  +    raw_json = req.json()
  +    raw_data = raw_json['Forecast']
  +
  +    data = []
  +    for item in raw_data:
  +        dt = parser.parse(item['DateTimeEST']).replace(tzinfo=tz.gettz('America/New_York'))
  +        value = float(item['Value'])
  +
  +        datapoint = {'datetime': dt,
  +                     'production': {'wind': value},
  +                     'source': 'misoenergy.org',
  +                     'zoneKey': zone_key}
  +        data.append(datapoint)
  +
  +    return data
  +
  +
   if __name__ == '__main__':
       print('fetch_production() ->')
       print(fetch_production())
  +    print('fetch_wind_forecast() ->')
  +    print(fetch_wind_forecast())
  
verification_info: {"golden_diff": "diff --git a/parsers/US_MISO.py b/parsers/US_MISO.py\n--- a/parsers/US_MISO.py\n+++ b/parsers/US_MISO.py\n@@ -2,6 +2,7 @@\n \n \"\"\"Parser for the MISO area of the United States.\"\"\"\n \n+import logging\n import requests\n from dateutil import parser, tz\n \n@@ -14,6 +15,7 @@\n            'Wind': 'wind',\n            'Other': 'unknown'}\n \n+wind_forecast_url = 'https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType=getWindForecast&returnType=json'\n \n # To quote the MISO data source;\n # \"The category listed as \u201cOther\u201d is the combination of Hydro, Pumped Storage Hydro, Diesel, Demand Response Resources,\n@@ -67,12 +69,14 @@\n     return dt, production\n \n \n-def fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=None):\n+def fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=logging.getLogger(__name__)):\n     \"\"\"\n     Requests the last known production mix (in MW) of a given country\n     Arguments:\n     zone_key (optional) -- used in case a parser is able to fetch multiple countries\n     session (optional)      -- request session passed in order to re-use an existing session\n+    target_datetime (optional) -- used if parser can fetch data for a specific day\n+    logger (optional) -- handles logging when parser is run as main\n     Return:\n     A dictionary in the form:\n     {\n@@ -96,6 +100,7 @@\n       'source': 'mysource.com'\n     }\n     \"\"\"\n+\n     if target_datetime:\n         raise NotImplementedError('This parser is not yet able to parse past dates')\n \n@@ -113,6 +118,48 @@\n     return data\n \n \n+def fetch_wind_forecast(zone_key='US-MISO', session=None, target_datetime=None, logger=None):\n+    \"\"\"\n+    Requests the day ahead wind forecast (in MW) of a given zone\n+    Arguments:\n+    zone_key (optional) -- used in case a parser is able to fetch multiple countries\n+    session (optional)  -- request session passed in order to re-use an existing session\n+    target_datetime (optional) -- used if parser can fetch data for a specific day\n+    logger (optional) -- handles logging when parser is run as main\n+    Return:\n+    A list of dictionaries in the form:\n+    {\n+    'source': 'misoenergy.org',\n+    'production': {'wind': 12932.0},\n+    'datetime': '2019-01-01T00:00:00Z',\n+    'zoneKey': 'US-MISO'\n+    }\n+    \"\"\"\n+\n+    if target_datetime:\n+        raise NotImplementedError('This parser is not yet able to parse past dates')\n+\n+    s = session or requests.Session()\n+    req = s.get(wind_forecast_url)\n+    raw_json = req.json()\n+    raw_data = raw_json['Forecast']\n+\n+    data = []\n+    for item in raw_data:\n+        dt = parser.parse(item['DateTimeEST']).replace(tzinfo=tz.gettz('America/New_York'))\n+        value = float(item['Value'])\n+\n+        datapoint = {'datetime': dt,\n+                     'production': {'wind': value},\n+                     'source': 'misoenergy.org',\n+                     'zoneKey': zone_key}\n+        data.append(datapoint)\n+\n+    return data\n+\n+\n if __name__ == '__main__':\n     print('fetch_production() ->')\n     print(fetch_production())\n+    print('fetch_wind_forecast() ->')\n+    print(fetch_wind_forecast())\n", "issue": "Add US-MISO day ahead wind & solar forecasts\nBoth Wind Production and Total Load seem available with a day-head forecast from the following webpage https://www.misoenergy.org/markets-and-operations/real-time-displays/\r\n\r\nThese forecasts could be added to the MISO parser \r\n\n", "before_files": [{"content": "#!/usr/bin/env python3\n\n\"\"\"Parser for the MISO area of the United States.\"\"\"\n\nimport requests\nfrom dateutil import parser, tz\n\nmix_url = 'https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType' \\\n          '=getfuelmix&returnType=json'\n\nmapping = {'Coal': 'coal',\n           'Natural Gas': 'gas',\n           'Nuclear': 'nuclear',\n           'Wind': 'wind',\n           'Other': 'unknown'}\n\n\n# To quote the MISO data source;\n# \"The category listed as \u201cOther\u201d is the combination of Hydro, Pumped Storage Hydro, Diesel, Demand Response Resources,\n# External Asynchronous Resources and a varied assortment of solid waste, garbage and wood pulp burners\".\n\n# Timestamp reported by data source is in format 23-Jan-2018 - Interval 11:45 EST\n# Unsure exactly why EST is used, possibly due to operational connections with PJM.\n\n\ndef get_json_data(logger, session=None):\n    \"\"\"Returns 5 minute generation data in json format.\"\"\"\n\n    s = session or requests.session()\n    json_data = s.get(mix_url).json()\n\n    return json_data\n\n\ndef data_processer(json_data, logger):\n    \"\"\"\n    Identifies any unknown fuel types and logs a warning.\n    Returns a tuple containing datetime object and production dictionary.\n    \"\"\"\n\n    generation = json_data['Fuel']['Type']\n\n    production = {}\n    for fuel in generation:\n        try:\n            k = mapping[fuel['CATEGORY']]\n        except KeyError as e:\n            logger.warning(\"Key '{}' is missing from the MISO fuel mapping.\".format(\n                fuel['CATEGORY']))\n            k = 'unknown'\n        v = float(fuel['ACT'])\n        production[k] = production.get(k, 0.0) + v\n\n    # Remove unneeded parts of timestamp to allow datetime parsing.\n    timestamp = json_data['RefId']\n    split_time = timestamp.split(\" \")\n    time_junk = {1, 2}  # set literal\n    useful_time_parts = [v for i, v in enumerate(split_time) if i not in time_junk]\n\n    if useful_time_parts[-1] != 'EST':\n        raise ValueError('Timezone reported for US-MISO has changed.')\n\n    time_data = \" \".join(useful_time_parts)\n    tzinfos = {\"EST\": tz.gettz('America/New_York')}\n    dt = parser.parse(time_data, tzinfos=tzinfos)\n\n    return dt, production\n\n\ndef fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=None):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given country\n    Arguments:\n    zone_key (optional) -- used in case a parser is able to fetch multiple countries\n    session (optional)      -- request session passed in order to re-use an existing session\n    Return:\n    A dictionary in the form:\n    {\n      'zoneKey': '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    if target_datetime:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    json_data = get_json_data(logger, session=session)\n    processed_data = data_processer(json_data, logger)\n\n    data = {\n        'zoneKey': zone_key,\n        'datetime': processed_data[0],\n        'production': processed_data[1],\n        'storage': {},\n        'source': 'misoenergy.org'\n    }\n\n    return data\n\n\nif __name__ == '__main__':\n    print('fetch_production() ->')\n    print(fetch_production())\n", "path": "parsers/US_MISO.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n\"\"\"Parser for the MISO area of the United States.\"\"\"\n\nimport logging\nimport requests\nfrom dateutil import parser, tz\n\nmix_url = 'https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType' \\\n          '=getfuelmix&returnType=json'\n\nmapping = {'Coal': 'coal',\n           'Natural Gas': 'gas',\n           'Nuclear': 'nuclear',\n           'Wind': 'wind',\n           'Other': 'unknown'}\n\nwind_forecast_url = 'https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType=getWindForecast&returnType=json'\n\n# To quote the MISO data source;\n# \"The category listed as \u201cOther\u201d is the combination of Hydro, Pumped Storage Hydro, Diesel, Demand Response Resources,\n# External Asynchronous Resources and a varied assortment of solid waste, garbage and wood pulp burners\".\n\n# Timestamp reported by data source is in format 23-Jan-2018 - Interval 11:45 EST\n# Unsure exactly why EST is used, possibly due to operational connections with PJM.\n\n\ndef get_json_data(logger, session=None):\n    \"\"\"Returns 5 minute generation data in json format.\"\"\"\n\n    s = session or requests.session()\n    json_data = s.get(mix_url).json()\n\n    return json_data\n\n\ndef data_processer(json_data, logger):\n    \"\"\"\n    Identifies any unknown fuel types and logs a warning.\n    Returns a tuple containing datetime object and production dictionary.\n    \"\"\"\n\n    generation = json_data['Fuel']['Type']\n\n    production = {}\n    for fuel in generation:\n        try:\n            k = mapping[fuel['CATEGORY']]\n        except KeyError as e:\n            logger.warning(\"Key '{}' is missing from the MISO fuel mapping.\".format(\n                fuel['CATEGORY']))\n            k = 'unknown'\n        v = float(fuel['ACT'])\n        production[k] = production.get(k, 0.0) + v\n\n    # Remove unneeded parts of timestamp to allow datetime parsing.\n    timestamp = json_data['RefId']\n    split_time = timestamp.split(\" \")\n    time_junk = {1, 2}  # set literal\n    useful_time_parts = [v for i, v in enumerate(split_time) if i not in time_junk]\n\n    if useful_time_parts[-1] != 'EST':\n        raise ValueError('Timezone reported for US-MISO has changed.')\n\n    time_data = \" \".join(useful_time_parts)\n    tzinfos = {\"EST\": tz.gettz('America/New_York')}\n    dt = parser.parse(time_data, tzinfos=tzinfos)\n\n    return dt, production\n\n\ndef fetch_production(zone_key='US-MISO', session=None, target_datetime=None, logger=logging.getLogger(__name__)):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given country\n    Arguments:\n    zone_key (optional) -- used in case a parser is able to fetch multiple countries\n    session (optional)      -- request session passed in order to re-use an existing session\n    target_datetime (optional) -- used if parser can fetch data for a specific day\n    logger (optional) -- handles logging when parser is run as main\n    Return:\n    A dictionary in the form:\n    {\n      'zoneKey': '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    if target_datetime:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    json_data = get_json_data(logger, session=session)\n    processed_data = data_processer(json_data, logger)\n\n    data = {\n        'zoneKey': zone_key,\n        'datetime': processed_data[0],\n        'production': processed_data[1],\n        'storage': {},\n        'source': 'misoenergy.org'\n    }\n\n    return data\n\n\ndef fetch_wind_forecast(zone_key='US-MISO', session=None, target_datetime=None, logger=None):\n    \"\"\"\n    Requests the day ahead wind forecast (in MW) of a given zone\n    Arguments:\n    zone_key (optional) -- used in case a parser is able to fetch multiple countries\n    session (optional)  -- request session passed in order to re-use an existing session\n    target_datetime (optional) -- used if parser can fetch data for a specific day\n    logger (optional) -- handles logging when parser is run as main\n    Return:\n    A list of dictionaries in the form:\n    {\n    'source': 'misoenergy.org',\n    'production': {'wind': 12932.0},\n    'datetime': '2019-01-01T00:00:00Z',\n    'zoneKey': 'US-MISO'\n    }\n    \"\"\"\n\n    if target_datetime:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    s = session or requests.Session()\n    req = s.get(wind_forecast_url)\n    raw_json = req.json()\n    raw_data = raw_json['Forecast']\n\n    data = []\n    for item in raw_data:\n        dt = parser.parse(item['DateTimeEST']).replace(tzinfo=tz.gettz('America/New_York'))\n        value = float(item['Value'])\n\n        datapoint = {'datetime': dt,\n                     'production': {'wind': value},\n                     'source': 'misoenergy.org',\n                     'zoneKey': zone_key}\n        data.append(datapoint)\n\n    return data\n\n\nif __name__ == '__main__':\n    print('fetch_production() ->')\n    print(fetch_production())\n    print('fetch_wind_forecast() ->')\n    print(fetch_wind_forecast())\n", "path": "parsers/US_MISO.py"}]}