prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  FR: key coal has negative value -9.0
  ```
  invalid point: {'zoneKey': 'FR', 'datetime': datetime.datetime(2018, 10, 9, 11, 15, tzinfo=tzoffset(None, 7200)), 'production': {'nuclear': 41740.0, 'coal': -9.0, 'gas': 4057.0, 'oil': 188.0, 'wind': 1158.0, 'solar': 2762.0, 'biomass': 861.0, 'hydro': 3366.0}, 'storage': {'hydro': -1024.0}, 'source': 'opendata.reseaux-energies.fr', 'schemaVersion': 1}, reason:FR: key coal has negative value -9.0
  ```
  
  Probably a good idea to set small negative values to 0
  
  --- 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/FR.py`
  Content:
  ```
  1 #!/usr/bin/env python3
  2 
  3 import arrow
  4 import json
  5 import logging
  6 import os
  7 import math
  8 
  9 import pandas as pd
  10 import requests
  11 import xml.etree.ElementTree as ET
  12 
  13 API_ENDPOINT = 'https://opendata.reseaux-energies.fr/api/records/1.0/search/'
  14 
  15 MAP_GENERATION = {
  16     'nucleaire': 'nuclear',
  17     'charbon': 'coal',
  18     'gaz': 'gas',
  19     'fioul': 'oil',
  20     'eolien': 'wind',
  21     'solaire': 'solar',
  22     'bioenergies': 'biomass'
  23 }
  24 
  25 MAP_HYDRO = [
  26     'hydraulique_fil_eau_eclusee',
  27     'hydraulique_lacs',
  28     'hydraulique_step_turbinage',
  29     'pompage'
  30 ]
  31 
  32 def is_not_nan_and_truthy(v):
  33     if isinstance(v, float) and math.isnan(v):
  34         return False
  35     return bool(v)
  36 
  37 
  38 def fetch_production(zone_key='FR', session=None, target_datetime=None,
  39                      logger=logging.getLogger(__name__)):
  40     if target_datetime:
  41         to = arrow.get(target_datetime, 'Europe/Paris')
  42     else:
  43         to = arrow.now(tz='Europe/Paris')
  44 
  45     # setup request
  46     r = session or requests.session()
  47     formatted_from = to.shift(days=-1).format('YYYY-MM-DDTHH:mm')
  48     formatted_to = to.format('YYYY-MM-DDTHH:mm')
  49 
  50     params = {
  51         'dataset': 'eco2mix-national-tr',
  52         'q': 'date_heure >= {} AND date_heure <= {}'.format(
  53             formatted_from, formatted_to),
  54         'timezone': 'Europe/Paris',
  55         'rows': 100
  56     }
  57 
  58     if 'RESEAUX_ENERGIES_TOKEN' not in os.environ:
  59         raise Exception(
  60             'No RESEAUX_ENERGIES_TOKEN found! Please add it into secrets.env!')
  61     params['apikey'] = os.environ['RESEAUX_ENERGIES_TOKEN']
  62 
  63     # make request and create dataframe with response
  64     response = r.get(API_ENDPOINT, params=params)
  65     data = json.loads(response.content)
  66     data = [d['fields'] for d in data['records']]
  67     df = pd.DataFrame(data)
  68 
  69     # filter out desired columns and convert values to float
  70     value_columns = list(MAP_GENERATION.keys()) + MAP_HYDRO
  71     df = df[['date_heure'] + value_columns]
  72     df[value_columns] = df[value_columns].astype(float)
  73 
  74     datapoints = list()
  75     for row in df.iterrows():
  76         production = dict()
  77         for key, value in MAP_GENERATION.items():
  78             production[value] = row[1][key]
  79 
  80         # Hydro is a special case!
  81         production['hydro'] = row[1]['hydraulique_lacs'] + row[1]['hydraulique_fil_eau_eclusee']
  82         storage = {
  83             'hydro': row[1]['pompage'] * -1 + row[1]['hydraulique_step_turbinage'] * -1
  84         }
  85 
  86         # if all production values are null, ignore datapoint
  87         if not any([is_not_nan_and_truthy(v)
  88                     for k, v in production.items()]):
  89             continue
  90 
  91         datapoints.append({
  92             'zoneKey': zone_key,
  93             'datetime': arrow.get(row[1]['date_heure']).datetime,
  94             'production': production,
  95             'storage': storage,
  96             'source': 'opendata.reseaux-energies.fr'
  97         })
  98 
  99     return datapoints
  100 
  101 
  102 def fetch_price(zone_key, session=None, target_datetime=None,
  103                 logger=logging.getLogger(__name__)):
  104     if target_datetime:
  105         now = arrow.get(target_datetime, tz='Europe/Paris')
  106     else:
  107         now = arrow.now(tz='Europe/Paris')
  108 
  109     r = session or requests.session()
  110     formatted_from = now.shift(days=-1).format('DD/MM/YYYY')
  111     formatted_to = now.format('DD/MM/YYYY')
  112 
  113     url = 'http://www.rte-france.com/getEco2MixXml.php?type=donneesMarche&da' \
  114           'teDeb={}&dateFin={}&mode=NORM'.format(formatted_from, formatted_to)
  115     response = r.get(url)
  116     obj = ET.fromstring(response.content)
  117     datas = {}
  118 
  119     for donnesMarche in obj:
  120         if donnesMarche.tag != 'donneesMarche':
  121             continue
  122 
  123         start_date = arrow.get(arrow.get(donnesMarche.attrib['date']).datetime, 'Europe/Paris')
  124 
  125         for item in donnesMarche:
  126             if item.get('granularite') != 'Global':
  127                 continue
  128             country_c = item.get('perimetre')
  129             if zone_key != country_c:
  130                 continue
  131             value = None
  132             for value in item:
  133                 if value.text == 'ND':
  134                     continue
  135                 period = int(value.attrib['periode'])
  136                 datetime = start_date.replace(hours=+period).datetime
  137                 if not datetime in datas:
  138                     datas[datetime] = {
  139                         'zoneKey': zone_key,
  140                         'currency': 'EUR',
  141                         'datetime': datetime,
  142                         'source': 'rte-france.com',
  143                     }
  144                 data = datas[datetime]
  145                 data['price'] = float(value.text)
  146 
  147     return list(datas.values())
  148 
  149 
  150 if __name__ == '__main__':
  151     print(fetch_production())
  152
  ```
  --- 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/FR.py b/parsers/FR.py
  --- a/parsers/FR.py
  +++ b/parsers/FR.py
  @@ -75,7 +75,12 @@
       for row in df.iterrows():
           production = dict()
           for key, value in MAP_GENERATION.items():
  -            production[value] = row[1][key]
  +             # Set small negative values to 0
  +            if row[1][key] < 0 and row[1][key] > -50:
  +                logger.warning('Setting small value of %s (%s) to 0.' % (key, value))
  +                production[value] = 0
  +            else:
  +                production[value] = row[1][key]
   
           # Hydro is a special case!
           production['hydro'] = row[1]['hydraulique_lacs'] + row[1]['hydraulique_fil_eau_eclusee']
  
verification_info: {"golden_diff": "diff --git a/parsers/FR.py b/parsers/FR.py\n--- a/parsers/FR.py\n+++ b/parsers/FR.py\n@@ -75,7 +75,12 @@\n     for row in df.iterrows():\n         production = dict()\n         for key, value in MAP_GENERATION.items():\n-            production[value] = row[1][key]\n+             # Set small negative values to 0\n+            if row[1][key] < 0 and row[1][key] > -50:\n+                logger.warning('Setting small value of %s (%s) to 0.' % (key, value))\n+                production[value] = 0\n+            else:\n+                production[value] = row[1][key]\n \n         # Hydro is a special case!\n         production['hydro'] = row[1]['hydraulique_lacs'] + row[1]['hydraulique_fil_eau_eclusee']\n", "issue": "FR: key coal has negative value -9.0\n```\r\ninvalid point: {'zoneKey': 'FR', 'datetime': datetime.datetime(2018, 10, 9, 11, 15, tzinfo=tzoffset(None, 7200)), 'production': {'nuclear': 41740.0, 'coal': -9.0, 'gas': 4057.0, 'oil': 188.0, 'wind': 1158.0, 'solar': 2762.0, 'biomass': 861.0, 'hydro': 3366.0}, 'storage': {'hydro': -1024.0}, 'source': 'opendata.reseaux-energies.fr', 'schemaVersion': 1}, reason:FR: key coal has negative value -9.0\r\n```\r\n\r\nProbably a good idea to set small negative values to 0\n", "before_files": [{"content": "#!/usr/bin/env python3\n\nimport arrow\nimport json\nimport logging\nimport os\nimport math\n\nimport pandas as pd\nimport requests\nimport xml.etree.ElementTree as ET\n\nAPI_ENDPOINT = 'https://opendata.reseaux-energies.fr/api/records/1.0/search/'\n\nMAP_GENERATION = {\n    'nucleaire': 'nuclear',\n    'charbon': 'coal',\n    'gaz': 'gas',\n    'fioul': 'oil',\n    'eolien': 'wind',\n    'solaire': 'solar',\n    'bioenergies': 'biomass'\n}\n\nMAP_HYDRO = [\n    'hydraulique_fil_eau_eclusee',\n    'hydraulique_lacs',\n    'hydraulique_step_turbinage',\n    'pompage'\n]\n\ndef is_not_nan_and_truthy(v):\n    if isinstance(v, float) and math.isnan(v):\n        return False\n    return bool(v)\n\n\ndef fetch_production(zone_key='FR', session=None, target_datetime=None,\n                     logger=logging.getLogger(__name__)):\n    if target_datetime:\n        to = arrow.get(target_datetime, 'Europe/Paris')\n    else:\n        to = arrow.now(tz='Europe/Paris')\n\n    # setup request\n    r = session or requests.session()\n    formatted_from = to.shift(days=-1).format('YYYY-MM-DDTHH:mm')\n    formatted_to = to.format('YYYY-MM-DDTHH:mm')\n\n    params = {\n        'dataset': 'eco2mix-national-tr',\n        'q': 'date_heure >= {} AND date_heure <= {}'.format(\n            formatted_from, formatted_to),\n        'timezone': 'Europe/Paris',\n        'rows': 100\n    }\n\n    if 'RESEAUX_ENERGIES_TOKEN' not in os.environ:\n        raise Exception(\n            'No RESEAUX_ENERGIES_TOKEN found! Please add it into secrets.env!')\n    params['apikey'] = os.environ['RESEAUX_ENERGIES_TOKEN']\n\n    # make request and create dataframe with response\n    response = r.get(API_ENDPOINT, params=params)\n    data = json.loads(response.content)\n    data = [d['fields'] for d in data['records']]\n    df = pd.DataFrame(data)\n\n    # filter out desired columns and convert values to float\n    value_columns = list(MAP_GENERATION.keys()) + MAP_HYDRO\n    df = df[['date_heure'] + value_columns]\n    df[value_columns] = df[value_columns].astype(float)\n\n    datapoints = list()\n    for row in df.iterrows():\n        production = dict()\n        for key, value in MAP_GENERATION.items():\n            production[value] = row[1][key]\n\n        # Hydro is a special case!\n        production['hydro'] = row[1]['hydraulique_lacs'] + row[1]['hydraulique_fil_eau_eclusee']\n        storage = {\n            'hydro': row[1]['pompage'] * -1 + row[1]['hydraulique_step_turbinage'] * -1\n        }\n\n        # if all production values are null, ignore datapoint\n        if not any([is_not_nan_and_truthy(v)\n                    for k, v in production.items()]):\n            continue\n\n        datapoints.append({\n            'zoneKey': zone_key,\n            'datetime': arrow.get(row[1]['date_heure']).datetime,\n            'production': production,\n            'storage': storage,\n            'source': 'opendata.reseaux-energies.fr'\n        })\n\n    return datapoints\n\n\ndef fetch_price(zone_key, session=None, target_datetime=None,\n                logger=logging.getLogger(__name__)):\n    if target_datetime:\n        now = arrow.get(target_datetime, tz='Europe/Paris')\n    else:\n        now = arrow.now(tz='Europe/Paris')\n\n    r = session or requests.session()\n    formatted_from = now.shift(days=-1).format('DD/MM/YYYY')\n    formatted_to = now.format('DD/MM/YYYY')\n\n    url = 'http://www.rte-france.com/getEco2MixXml.php?type=donneesMarche&da' \\\n          'teDeb={}&dateFin={}&mode=NORM'.format(formatted_from, formatted_to)\n    response = r.get(url)\n    obj = ET.fromstring(response.content)\n    datas = {}\n\n    for donnesMarche in obj:\n        if donnesMarche.tag != 'donneesMarche':\n            continue\n\n        start_date = arrow.get(arrow.get(donnesMarche.attrib['date']).datetime, 'Europe/Paris')\n\n        for item in donnesMarche:\n            if item.get('granularite') != 'Global':\n                continue\n            country_c = item.get('perimetre')\n            if zone_key != country_c:\n                continue\n            value = None\n            for value in item:\n                if value.text == 'ND':\n                    continue\n                period = int(value.attrib['periode'])\n                datetime = start_date.replace(hours=+period).datetime\n                if not datetime in datas:\n                    datas[datetime] = {\n                        'zoneKey': zone_key,\n                        'currency': 'EUR',\n                        'datetime': datetime,\n                        'source': 'rte-france.com',\n                    }\n                data = datas[datetime]\n                data['price'] = float(value.text)\n\n    return list(datas.values())\n\n\nif __name__ == '__main__':\n    print(fetch_production())\n", "path": "parsers/FR.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\nimport arrow\nimport json\nimport logging\nimport os\nimport math\n\nimport pandas as pd\nimport requests\nimport xml.etree.ElementTree as ET\n\nAPI_ENDPOINT = 'https://opendata.reseaux-energies.fr/api/records/1.0/search/'\n\nMAP_GENERATION = {\n    'nucleaire': 'nuclear',\n    'charbon': 'coal',\n    'gaz': 'gas',\n    'fioul': 'oil',\n    'eolien': 'wind',\n    'solaire': 'solar',\n    'bioenergies': 'biomass'\n}\n\nMAP_HYDRO = [\n    'hydraulique_fil_eau_eclusee',\n    'hydraulique_lacs',\n    'hydraulique_step_turbinage',\n    'pompage'\n]\n\ndef is_not_nan_and_truthy(v):\n    if isinstance(v, float) and math.isnan(v):\n        return False\n    return bool(v)\n\n\ndef fetch_production(zone_key='FR', session=None, target_datetime=None,\n                     logger=logging.getLogger(__name__)):\n    if target_datetime:\n        to = arrow.get(target_datetime, 'Europe/Paris')\n    else:\n        to = arrow.now(tz='Europe/Paris')\n\n    # setup request\n    r = session or requests.session()\n    formatted_from = to.shift(days=-1).format('YYYY-MM-DDTHH:mm')\n    formatted_to = to.format('YYYY-MM-DDTHH:mm')\n\n    params = {\n        'dataset': 'eco2mix-national-tr',\n        'q': 'date_heure >= {} AND date_heure <= {}'.format(\n            formatted_from, formatted_to),\n        'timezone': 'Europe/Paris',\n        'rows': 100\n    }\n\n    if 'RESEAUX_ENERGIES_TOKEN' not in os.environ:\n        raise Exception(\n            'No RESEAUX_ENERGIES_TOKEN found! Please add it into secrets.env!')\n    params['apikey'] = os.environ['RESEAUX_ENERGIES_TOKEN']\n\n    # make request and create dataframe with response\n    response = r.get(API_ENDPOINT, params=params)\n    data = json.loads(response.content)\n    data = [d['fields'] for d in data['records']]\n    df = pd.DataFrame(data)\n\n    # filter out desired columns and convert values to float\n    value_columns = list(MAP_GENERATION.keys()) + MAP_HYDRO\n    df = df[['date_heure'] + value_columns]\n    df[value_columns] = df[value_columns].astype(float)\n\n    datapoints = list()\n    for row in df.iterrows():\n        production = dict()\n        for key, value in MAP_GENERATION.items():\n             # Set small negative values to 0\n            if row[1][key] < 0 and row[1][key] > -50:\n                logger.warning('Setting small value of %s (%s) to 0.' % (key, value))\n                production[value] = 0\n            else:\n                production[value] = row[1][key]\n\n        # Hydro is a special case!\n        production['hydro'] = row[1]['hydraulique_lacs'] + row[1]['hydraulique_fil_eau_eclusee']\n        storage = {\n            'hydro': row[1]['pompage'] * -1 + row[1]['hydraulique_step_turbinage'] * -1\n        }\n\n        # if all production values are null, ignore datapoint\n        if not any([is_not_nan_and_truthy(v)\n                    for k, v in production.items()]):\n            continue\n\n        datapoints.append({\n            'zoneKey': zone_key,\n            'datetime': arrow.get(row[1]['date_heure']).datetime,\n            'production': production,\n            'storage': storage,\n            'source': 'opendata.reseaux-energies.fr'\n        })\n\n    return datapoints\n\n\ndef fetch_price(zone_key, session=None, target_datetime=None,\n                logger=logging.getLogger(__name__)):\n    if target_datetime:\n        now = arrow.get(target_datetime, tz='Europe/Paris')\n    else:\n        now = arrow.now(tz='Europe/Paris')\n\n    r = session or requests.session()\n    formatted_from = now.shift(days=-1).format('DD/MM/YYYY')\n    formatted_to = now.format('DD/MM/YYYY')\n\n    url = 'http://www.rte-france.com/getEco2MixXml.php?type=donneesMarche&da' \\\n          'teDeb={}&dateFin={}&mode=NORM'.format(formatted_from, formatted_to)\n    response = r.get(url)\n    obj = ET.fromstring(response.content)\n    datas = {}\n\n    for donnesMarche in obj:\n        if donnesMarche.tag != 'donneesMarche':\n            continue\n\n        start_date = arrow.get(arrow.get(donnesMarche.attrib['date']).datetime, 'Europe/Paris')\n\n        for item in donnesMarche:\n            if item.get('granularite') != 'Global':\n                continue\n            country_c = item.get('perimetre')\n            if zone_key != country_c:\n                continue\n            value = None\n            for value in item:\n                if value.text == 'ND':\n                    continue\n                period = int(value.attrib['periode'])\n                datetime = start_date.replace(hours=+period).datetime\n                if not datetime in datas:\n                    datas[datetime] = {\n                        'zoneKey': zone_key,\n                        'currency': 'EUR',\n                        'datetime': datetime,\n                        'source': 'rte-france.com',\n                    }\n                data = datas[datetime]\n                data['price'] = float(value.text)\n\n    return list(datas.values())\n\n\nif __name__ == '__main__':\n    print(fetch_production())\n", "path": "parsers/FR.py"}]}