We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
US-IPC is occasionally missing a key
```
Traceback (most recent call last):
  File "/home/feeder/lib/fetch_data.py", line 130, in launch_parsers
    **parser_kwargs)
  File "/home/electricitymap/parsers/US_IPC.py", line 129, in fetch_production
    processed_data = data_processer(raw_data, logger)
  File "/home/electricitymap/parsers/US_IPC.py", line 83, in data_processer
    production.pop(key)
KeyError: 'Net Purchases'
```

--- 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_IPC.py`
Content:
```
1 #!usr/bin/env python3
2 
3 """Parser for the Idaho Power Comapny area of the United States."""
4 
5 from dateutil import parser, tz
6 from itertools import groupby
7 from logging import getLogger
8 import requests
9 
10 
11 # NOTE No pumped storage yet but future ideas can be found at the following url.
12 # https://docs.idahopower.com/pdfs/AboutUs/PlanningForFuture/irp/IRP.pdf
13 
14 # Renewable energy (PURPA) is likely bought with credits from outside the Utility
15 # area and not supplied to customers. For that reason those types are commented out. 
16 
17 PRODUCTION_URL = 'https://api.idahopower.com/Energy/Api/V1/GenerationAndDemand/Subset'
18 
19 GENERATION_MAPPING = {'Non-Utility Geothermal': 'geothermal',
20                       'Hydro': 'hydro',
21                       'Coal': 'coal',
22                       'Diesel': 'oil',
23                       'PURPA/Non-Utility Wind': 'wind',
24                       'Natural Gas': 'gas',
25                       'PURPA/Non-Utility Solar': 'solar'
26                       #'PURPA Other': 'biomass'
27                       }
28 
29 TIMEZONE = tz.gettz("America/Boise")
30 
31 
32 def get_data(session=None):
33     """Returns a list of dictionaries."""
34 
35     s = session or requests.Session()
36 
37     req = requests.get(PRODUCTION_URL)
38     json_data = req.json()
39     raw_data = json_data['list']
40 
41     return raw_data
42 
43 
44 def timestamp_converter(timestamp):
45     """Converts a str timestamp into an aware datetime object."""
46 
47     dt_naive = parser.parse(timestamp)
48     dt_aware = dt_naive.replace(tzinfo=TIMEZONE)
49 
50     return dt_aware
51 
52 
53 def data_processer(raw_data, logger):
54     """
55     Groups dictionaries by datetime key.
56     Removes unneeded keys and logs any new ones.
57     Returns a list of tuples containing (datetime object, dictionary).
58     """
59 
60     dt_key = lambda x: x['datetime']
61     grouped = groupby(raw_data, dt_key)
62 
63     keys_to_ignore = {'Load', 'Net Purchases', 'Inadvertent', 'PURPA Other'}
64     known_keys = GENERATION_MAPPING.keys() | keys_to_ignore
65 
66     unmapped = set()
67     parsed_data = []
68     for group in grouped:
69         dt = timestamp_converter(group[0])
70         generation = group[1]
71 
72         production = {}
73         for gen_type in generation:
74             production[gen_type['name']] = float(gen_type['data'])
75 
76         current_keys = production.keys() | set()
77         unknown_keys = current_keys - known_keys
78         unmapped = unmapped | unknown_keys
79 
80         keys_to_remove = keys_to_ignore | unknown_keys
81 
82         for key in keys_to_remove:
83             production.pop(key)
84 
85         production = {GENERATION_MAPPING[k]: v for k, v in production.items()}
86 
87         parsed_data.append((dt, production))
88 
89     for key in unmapped:
90         logger.warning('Key \'{}\' in US-IPC is not mapped to type.'.format(key), extra={'key': 'US-IPC'})
91 
92     return parsed_data
93 
94 
95 def fetch_production(zone_key = 'US-IPC', session=None, target_datetime=None, logger=getLogger(__name__)):
96     """
97     Requests the last known production mix (in MW) of a given zone
98     Arguments:
99     zone_key (optional) -- used in case a parser is able to fetch multiple zones
100     session (optional) -- request session passed in order to re-use an existing session
101     Return:
102     A list of dictionaries in the form:
103     {
104       'zoneKey': 'FR',
105       'datetime': '2017-01-01T00:00:00Z',
106       'production': {
107           'biomass': 0.0,
108           'coal': 0.0,
109           'gas': 0.0,
110           'hydro': 0.0,
111           'nuclear': null,
112           'oil': 0.0,
113           'solar': 0.0,
114           'wind': 0.0,
115           'geothermal': 0.0,
116           'unknown': 0.0
117       },
118       'storage': {
119           'hydro': -10.0,
120       },
121       'source': 'mysource.com'
122     }
123     """
124 
125     if target_datetime is not None:
126         raise NotImplementedError('This parser is not yet able to parse past dates')
127 
128     raw_data = get_data(session=session)
129     processed_data = data_processer(raw_data, logger)
130 
131     production_data = []
132     for item in processed_data:
133         datapoint = {
134           'zoneKey': zone_key,
135           'datetime': item[0],
136           'production': item[1],
137           'storage': {},
138           'source': 'idahopower.com'
139         }
140 
141         production_data.append(datapoint)
142 
143     return production_data
144 
145 
146 if __name__ == '__main__':
147     """Main method, never used by the Electricity Map backend, but handy for testing."""
148 
149     print('fetch_production() ->')
150     print(fetch_production())
151
```
--- 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/US_IPC.py b/parsers/US_IPC.py
--- a/parsers/US_IPC.py
+++ b/parsers/US_IPC.py
@@ -12,7 +12,7 @@
 # https://docs.idahopower.com/pdfs/AboutUs/PlanningForFuture/irp/IRP.pdf
 
 # Renewable energy (PURPA) is likely bought with credits from outside the Utility
-# area and not supplied to customers. For that reason those types are commented out. 
+# area and not supplied to customers. For that reason those types are commented out.
 
 PRODUCTION_URL = 'https://api.idahopower.com/Energy/Api/V1/GenerationAndDemand/Subset'
 
@@ -80,7 +80,7 @@
         keys_to_remove = keys_to_ignore | unknown_keys
 
         for key in keys_to_remove:
-            production.pop(key)
+            production.pop(key, None)
 
         production = {GENERATION_MAPPING[k]: v for k, v in production.items()}

{"golden_diff": "diff --git a/parsers/US_IPC.py b/parsers/US_IPC.py\n--- a/parsers/US_IPC.py\n+++ b/parsers/US_IPC.py\n@@ -12,7 +12,7 @@\n # https://docs.idahopower.com/pdfs/AboutUs/PlanningForFuture/irp/IRP.pdf\n \n # Renewable energy (PURPA) is likely bought with credits from outside the Utility\n-# area and not supplied to customers. For that reason those types are commented out. \n+# area and not supplied to customers. For that reason those types are commented out.\n \n PRODUCTION_URL = 'https://api.idahopower.com/Energy/Api/V1/GenerationAndDemand/Subset'\n \n@@ -80,7 +80,7 @@\n         keys_to_remove = keys_to_ignore | unknown_keys\n \n         for key in keys_to_remove:\n-            production.pop(key)\n+            production.pop(key, None)\n \n         production = {GENERATION_MAPPING[k]: v for k, v in production.items()}\n", "issue": "US-IPC is occasionally missing a key\n```\r\nTraceback (most recent call last):\r\n  File \"/home/feeder/lib/fetch_data.py\", line 130, in launch_parsers\r\n    **parser_kwargs)\r\n  File \"/home/electricitymap/parsers/US_IPC.py\", line 129, in fetch_production\r\n    processed_data = data_processer(raw_data, logger)\r\n  File \"/home/electricitymap/parsers/US_IPC.py\", line 83, in data_processer\r\n    production.pop(key)\r\nKeyError: 'Net Purchases'\r\n```\n", "before_files": [{"content": "#!usr/bin/env python3\n\n\"\"\"Parser for the Idaho Power Comapny area of the United States.\"\"\"\n\nfrom dateutil import parser, tz\nfrom itertools import groupby\nfrom logging import getLogger\nimport requests\n\n\n# NOTE No pumped storage yet but future ideas can be found at the following url.\n# https://docs.idahopower.com/pdfs/AboutUs/PlanningForFuture/irp/IRP.pdf\n\n# Renewable energy (PURPA) is likely bought with credits from outside the Utility\n# area and not supplied to customers. For that reason those types are commented out. \n\nPRODUCTION_URL = 'https://api.idahopower.com/Energy/Api/V1/GenerationAndDemand/Subset'\n\nGENERATION_MAPPING = {'Non-Utility Geothermal': 'geothermal',\n                      'Hydro': 'hydro',\n                      'Coal': 'coal',\n                      'Diesel': 'oil',\n                      'PURPA/Non-Utility Wind': 'wind',\n                      'Natural Gas': 'gas',\n                      'PURPA/Non-Utility Solar': 'solar'\n                      #'PURPA Other': 'biomass'\n                      }\n\nTIMEZONE = tz.gettz(\"America/Boise\")\n\n\ndef get_data(session=None):\n    \"\"\"Returns a list of dictionaries.\"\"\"\n\n    s = session or requests.Session()\n\n    req = requests.get(PRODUCTION_URL)\n    json_data = req.json()\n    raw_data = json_data['list']\n\n    return raw_data\n\n\ndef timestamp_converter(timestamp):\n    \"\"\"Converts a str timestamp into an aware datetime object.\"\"\"\n\n    dt_naive = parser.parse(timestamp)\n    dt_aware = dt_naive.replace(tzinfo=TIMEZONE)\n\n    return dt_aware\n\n\ndef data_processer(raw_data, logger):\n    \"\"\"\n    Groups dictionaries by datetime key.\n    Removes unneeded keys and logs any new ones.\n    Returns a list of tuples containing (datetime object, dictionary).\n    \"\"\"\n\n    dt_key = lambda x: x['datetime']\n    grouped = groupby(raw_data, dt_key)\n\n    keys_to_ignore = {'Load', 'Net Purchases', 'Inadvertent', 'PURPA Other'}\n    known_keys = GENERATION_MAPPING.keys() | keys_to_ignore\n\n    unmapped = set()\n    parsed_data = []\n    for group in grouped:\n        dt = timestamp_converter(group[0])\n        generation = group[1]\n\n        production = {}\n        for gen_type in generation:\n            production[gen_type['name']] = float(gen_type['data'])\n\n        current_keys = production.keys() | set()\n        unknown_keys = current_keys - known_keys\n        unmapped = unmapped | unknown_keys\n\n        keys_to_remove = keys_to_ignore | unknown_keys\n\n        for key in keys_to_remove:\n            production.pop(key)\n\n        production = {GENERATION_MAPPING[k]: v for k, v in production.items()}\n\n        parsed_data.append((dt, production))\n\n    for key in unmapped:\n        logger.warning('Key \\'{}\\' in US-IPC is not mapped to type.'.format(key), extra={'key': 'US-IPC'})\n\n    return parsed_data\n\n\ndef fetch_production(zone_key = 'US-IPC', session=None, target_datetime=None, logger=getLogger(__name__)):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given zone\n    Arguments:\n    zone_key (optional) -- used in case a parser is able to fetch multiple zones\n    session (optional) -- request session passed in order to re-use an existing session\n    Return:\n    A list of dictionaries 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 is not None:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    raw_data = get_data(session=session)\n    processed_data = data_processer(raw_data, logger)\n\n    production_data = []\n    for item in processed_data:\n        datapoint = {\n          'zoneKey': zone_key,\n          'datetime': item[0],\n          'production': item[1],\n          'storage': {},\n          'source': 'idahopower.com'\n        }\n\n        production_data.append(datapoint)\n\n    return production_data\n\n\nif __name__ == '__main__':\n    \"\"\"Main method, never used by the Electricity Map backend, but handy for testing.\"\"\"\n\n    print('fetch_production() ->')\n    print(fetch_production())\n", "path": "parsers/US_IPC.py"}], "after_files": [{"content": "#!usr/bin/env python3\n\n\"\"\"Parser for the Idaho Power Comapny area of the United States.\"\"\"\n\nfrom dateutil import parser, tz\nfrom itertools import groupby\nfrom logging import getLogger\nimport requests\n\n\n# NOTE No pumped storage yet but future ideas can be found at the following url.\n# https://docs.idahopower.com/pdfs/AboutUs/PlanningForFuture/irp/IRP.pdf\n\n# Renewable energy (PURPA) is likely bought with credits from outside the Utility\n# area and not supplied to customers. For that reason those types are commented out.\n\nPRODUCTION_URL = 'https://api.idahopower.com/Energy/Api/V1/GenerationAndDemand/Subset'\n\nGENERATION_MAPPING = {'Non-Utility Geothermal': 'geothermal',\n                      'Hydro': 'hydro',\n                      'Coal': 'coal',\n                      'Diesel': 'oil',\n                      'PURPA/Non-Utility Wind': 'wind',\n                      'Natural Gas': 'gas',\n                      'PURPA/Non-Utility Solar': 'solar'\n                      #'PURPA Other': 'biomass'\n                      }\n\nTIMEZONE = tz.gettz(\"America/Boise\")\n\n\ndef get_data(session=None):\n    \"\"\"Returns a list of dictionaries.\"\"\"\n\n    s = session or requests.Session()\n\n    req = requests.get(PRODUCTION_URL)\n    json_data = req.json()\n    raw_data = json_data['list']\n\n    return raw_data\n\n\ndef timestamp_converter(timestamp):\n    \"\"\"Converts a str timestamp into an aware datetime object.\"\"\"\n\n    dt_naive = parser.parse(timestamp)\n    dt_aware = dt_naive.replace(tzinfo=TIMEZONE)\n\n    return dt_aware\n\n\ndef data_processer(raw_data, logger):\n    \"\"\"\n    Groups dictionaries by datetime key.\n    Removes unneeded keys and logs any new ones.\n    Returns a list of tuples containing (datetime object, dictionary).\n    \"\"\"\n\n    dt_key = lambda x: x['datetime']\n    grouped = groupby(raw_data, dt_key)\n\n    keys_to_ignore = {'Load', 'Net Purchases', 'Inadvertent', 'PURPA Other'}\n    known_keys = GENERATION_MAPPING.keys() | keys_to_ignore\n\n    unmapped = set()\n    parsed_data = []\n    for group in grouped:\n        dt = timestamp_converter(group[0])\n        generation = group[1]\n\n        production = {}\n        for gen_type in generation:\n            production[gen_type['name']] = float(gen_type['data'])\n\n        current_keys = production.keys() | set()\n        unknown_keys = current_keys - known_keys\n        unmapped = unmapped | unknown_keys\n\n        keys_to_remove = keys_to_ignore | unknown_keys\n\n        for key in keys_to_remove:\n            production.pop(key, None)\n\n        production = {GENERATION_MAPPING[k]: v for k, v in production.items()}\n\n        parsed_data.append((dt, production))\n\n    for key in unmapped:\n        logger.warning('Key \\'{}\\' in US-IPC is not mapped to type.'.format(key), extra={'key': 'US-IPC'})\n\n    return parsed_data\n\n\ndef fetch_production(zone_key = 'US-IPC', session=None, target_datetime=None, logger=getLogger(__name__)):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given zone\n    Arguments:\n    zone_key (optional) -- used in case a parser is able to fetch multiple zones\n    session (optional) -- request session passed in order to re-use an existing session\n    Return:\n    A list of dictionaries 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 is not None:\n        raise NotImplementedError('This parser is not yet able to parse past dates')\n\n    raw_data = get_data(session=session)\n    processed_data = data_processer(raw_data, logger)\n\n    production_data = []\n    for item in processed_data:\n        datapoint = {\n          'zoneKey': zone_key,\n          'datetime': item[0],\n          'production': item[1],\n          'storage': {},\n          'source': 'idahopower.com'\n        }\n\n        production_data.append(datapoint)\n\n    return production_data\n\n\nif __name__ == '__main__':\n    \"\"\"Main method, never used by the Electricity Map backend, but handy for testing.\"\"\"\n\n    print('fetch_production() ->')\n    print(fetch_production())\n", "path": "parsers/US_IPC.py"}]}