We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Restore access to India-Gujarat (IN-GJ) wind and solar data
Hey everyone,

looks like SLDCGUJ has also removed the access to real-time data websites for wind and solar, just like they did for the conventional real-time data.
The solution should be really simple: We can use the same link which still gives access to that ["print" page](http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php). It has wind and solar generation on the right side, too ;)

![image](https://user-images.githubusercontent.com/25743609/43044321-0939e890-8da4-11e8-868d-51a54a1a5b60.png)

Greetings, Alex

--- 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/IN_GJ.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 import re
4 import collections
5 from operator import itemgetter
6 import arrow
7 import requests
8 import itertools
9 from .lib import zonekey, web, IN
10 from .lib.validation import validate
11 from logging import getLogger
12 
13 
14 station_map = {
15      "coal": ["Ukai(1-5)+Ukai6",
16              "Wanakbori",
17              "Gandhinagar",
18              "Sikka(3-4)",
19              "KLTPS(1-3)+KLTPS4",
20              "SLPP(I+II)",
21              "Akrimota",
22              "TPAECo",
23              "EPGL(I+II)",
24              "Adani(I+II+III)",
25              "BECL(I+II)",
26              "CGPL"],
27     "hydro": ["Ukai(Hydro)",
28               "Kadana(Hydro)",
29               "SSP(RBPH)"],
30     "gas": ["Utran(Gas)(II)",
31             "Dhuvaran(Gas)(I)+(II)+(III)",
32             "GIPCL(I)+(II)",
33             "GSEG(I+II)",
34             "GPPC",
35             "CLPI",
36             "KAWAS",
37             "Sugen+Unosgn",
38             "JHANOR"],
39     "nuclear": ["KAPP"]
40 }
41 
42 
43 def split_and_sum(expression):
44     """
45     Avoid using literal_eval for simple addition expressions.
46     Returns sum of all positive numbers.
47     """
48 
49     split_vals = expression.split('+')
50     float_vals = [float(v) for v in split_vals]
51     total = sum([v for v in float_vals if v > 0.0])
52 
53     return total
54 
55 
56 def fetch_data(zone_key, session=None, logger=None):
57     session = session or requests.session()
58 
59     values = collections.Counter()
60     zonekey.assert_zone_key(zone_key, 'IN-GJ')
61 
62     solar_html = web.get_response_soup(
63         zone_key, 'https://www.sldcguj.com/RealTimeData/GujSolar.php', session)
64     wind_html = web.get_response_soup(
65         zone_key, 'https://www.sldcguj.com/RealTimeData/wind.php', session)
66 
67     values['date'] =  arrow.get(
68         solar_html.find_all('tr')[0].text.split('\t')[-1].strip()
69         + ' Asia/Kolkata', 'D-MM-YYYY H:mm:ss ZZZ').datetime
70     values['solar'] = split_and_sum(
71         solar_html.find_all('tr')[-1].find_all('td')[-1].text.strip())
72     values['wind'] = split_and_sum(
73         wind_html.find_all('tr')[-1].find_all('td')[-1].text.strip())
74 
75     cookies_params = {
76         'ASPSESSIONIDSUQQQTRD': 'ODMNNHADJFGCMLFFGFEMOGBL',
77         'PHPSESSID': 'a301jk6p1p8d50dduflceeg6l1'
78     }
79 
80     rows = web.get_response_soup(
81         zone_key,
82         'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php',
83         session).find_all('tr')
84 
85     for row in rows:
86         elements = row.find_all('td')
87         if len(elements) > 3:  # will find production rows
88             v1, v2 = (re.sub(r'\s+', r'', x.text)
89                       for x in itemgetter(*[0, 3])(elements))
90             energy_type = [k for k, v in station_map.items() if v1 in v]
91             if len(energy_type) > 0:
92                 v2 = split_and_sum(v2)
93                 values[energy_type[0]] += v2
94             else:
95                 if 'StationName' in (v1, v2):  # meta data row
96                     continue
97                 elif 'DSMRate' in v2:  # demand side management
98                     continue
99                 else:
100                     try:
101                         logger.warning(
102                             'Unknown fuel for station name: {}'.format(v1),
103                             extra={'key': zone_key})
104                         v2 = split_and_sum(v2)
105                         values['unknown'] += v2
106                     except ValueError as e:
107                         # handle float failures
108                         logger.warning(
109                             "couldn't convert {} to float".format(v2),
110                             extra={'key': zone_key})
111                         continue
112         elif len(elements) == 3:  # will find consumption row
113             v1, v2 = (re.sub(r'\s+', r'', x.text)
114                       for x in itemgetter(*[0, 2])(elements))
115             if v1 == 'GujaratCatered':
116                 values['total consumption'] = split_and_sum(v2.split('MW')[0])
117         elif len(elements) == 1:
118             # CGPL/KAPP/KAWAS/JHANOR plants have a different html structure.
119             plant_name = re.sub(r'\s+', r'', elements[0].text)
120             known_plants = itertools.chain.from_iterable(station_map.values())
121 
122             if plant_name in known_plants:
123                 energy_type = [k for k, v in station_map.items() if plant_name in v][0]
124                 generation_tag = row.find_all_next("td")[3]
125                 val = float(re.sub(r'\s+', r'', generation_tag.text))
126                 if val > 0:
127                     values[energy_type] += val
128             else:
129                 if plant_name and plant_name != 'GMR':
130                     # GMR is outside Gujarat, sometimes plant_name is ''
131                     logger.warning(
132                         'Unknown fuel for station name: {}'.format(plant_name),
133                         extra={'key': zone_key})
134 
135     return values
136 
137 
138 def fetch_production(zone_key='IN-GJ', session=None, target_datetime=None,
139                      logger=getLogger('IN-GJ')):
140     """
141     Requests the last known production mix (in MW) of a given country
142     Arguments:
143     zone_key: specifies which zone to get
144     session: request session passed in order to re-use an existing session
145     target_datetime: the datetime for which we want production data. If not provided, we should
146       default it to now. The provided target_datetime is timezone-aware in UTC.
147     logger: an instance of a `logging.Logger`; all raised exceptions are also logged automatically
148     Return:
149     A list of dictionaries in the form:
150     {
151       'zoneKey': 'FR',
152       'datetime': '2017-01-01T00:00:00Z',
153       'production': {
154           'biomass': 0.0,
155           'coal': 0.0,
156           'gas': 0.0,
157           'hydro': 0.0,
158           'nuclear': null,
159           'oil': 0.0,
160           'solar': 0.0,
161           'wind': 0.0,
162           'geothermal': 0.0,
163           'unknown': 0.0
164       },
165       'storage': {
166           'hydro': -10.0,
167       },
168       'source': 'mysource.com'
169     }
170     """
171     session = session or requests.session()
172     if target_datetime:
173         raise NotImplementedError(
174             'This parser is not yet able to parse past dates')
175 
176     value_map = fetch_data(zone_key, session, logger=logger)
177 
178     data = {
179         'zoneKey': zone_key,
180         'datetime': value_map['date'],
181         'production': {
182             'biomass': None,
183             'coal': value_map.get('coal', 0),
184             'gas': value_map.get('gas', 0),
185             'hydro': value_map.get('hydro', 0),
186             'nuclear': value_map.get('nuclear', 0),
187             'oil': None,
188             'solar': value_map.get('solar', 0),
189             'wind': value_map.get('wind', 0),
190             'geothermal': None,
191             'unknown': value_map.get('unknown', 0)
192         },
193         'storage': {
194             'hydro': None
195         },
196         'source': 'sldcguj.com',
197     }
198 
199     valid_data = validate(data, logger, remove_negative=True, floor=7000)
200 
201     return valid_data
202 
203 
204 def fetch_consumption(zone_key='IN-GJ', session=None, target_datetime=None,
205                       logger=getLogger('IN-GJ')):
206     """
207     Method to get consumption data of Gujarat
208     :param zone_key:
209     :param session:
210     :return:
211     """
212     session = session or requests.session()
213     if target_datetime:
214         raise NotImplementedError(
215             'This parser is not yet able to parse past dates')
216 
217     value_map = fetch_data(zone_key, session, logger=logger)
218 
219     data = {
220         'zoneKey': zone_key,
221         'datetime': value_map['date'],
222         'consumption': value_map['total consumption'],
223         'source': 'sldcguj.com'
224     }
225 
226     return data
227 
228 
229 if __name__ == '__main__':
230     session = requests.Session()
231     print(fetch_production('IN-GJ', session))
232     print(fetch_consumption('IN-GJ', session))
233
```
--- 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/IN_GJ.py b/parsers/IN_GJ.py
--- a/parsers/IN_GJ.py
+++ b/parsers/IN_GJ.py
@@ -10,6 +10,7 @@
 from .lib.validation import validate
 from logging import getLogger
 
+SLDCGUJ_URL = 'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php'
 
 station_map = {
      "coal": ["Ukai(1-5)+Ukai6",
@@ -59,29 +60,23 @@
     values = collections.Counter()
     zonekey.assert_zone_key(zone_key, 'IN-GJ')
 
-    solar_html = web.get_response_soup(
-        zone_key, 'https://www.sldcguj.com/RealTimeData/GujSolar.php', session)
-    wind_html = web.get_response_soup(
-        zone_key, 'https://www.sldcguj.com/RealTimeData/wind.php', session)
-
-    values['date'] =  arrow.get(
-        solar_html.find_all('tr')[0].text.split('\t')[-1].strip()
-        + ' Asia/Kolkata', 'D-MM-YYYY H:mm:ss ZZZ').datetime
-    values['solar'] = split_and_sum(
-        solar_html.find_all('tr')[-1].find_all('td')[-1].text.strip())
-    values['wind'] = split_and_sum(
-        wind_html.find_all('tr')[-1].find_all('td')[-1].text.strip())
-
     cookies_params = {
         'ASPSESSIONIDSUQQQTRD': 'ODMNNHADJFGCMLFFGFEMOGBL',
         'PHPSESSID': 'a301jk6p1p8d50dduflceeg6l1'
     }
 
-    rows = web.get_response_soup(
-        zone_key,
-        'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php',
-        session).find_all('tr')
+    soup = web.get_response_soup(zone_key, SLDCGUJ_URL, session)
+    rows = soup.find_all('tr')
+    cells = [c.text.strip() for c in soup.find_all('td')]
 
+    # get wind and solar values
+    values['date'] = arrow.get(cells[1], 'DD-MM-YYYY HH:mm:ss').replace(
+        tzinfo='Asia/Kolkata')
+    [wind_solar_index] = [i for i, c in enumerate(cells) if c == '(Wind+Solar) Generation']
+    value = cells[wind_solar_index + 1]
+    values['wind'], values['solar'] = [int(v) for v in value.split(' + ')]
+
+    # get other production values
     for row in rows:
         elements = row.find_all('td')
         if len(elements) > 3:  # will find production rows
@@ -177,7 +172,7 @@
 
     data = {
         'zoneKey': zone_key,
-        'datetime': value_map['date'],
+        'datetime': value_map['date'].datetime,
         'production': {
             'biomass': None,
             'coal': value_map.get('coal', 0),

{"golden_diff": "diff --git a/parsers/IN_GJ.py b/parsers/IN_GJ.py\n--- a/parsers/IN_GJ.py\n+++ b/parsers/IN_GJ.py\n@@ -10,6 +10,7 @@\n from .lib.validation import validate\n from logging import getLogger\n \n+SLDCGUJ_URL = 'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php'\n \n station_map = {\n      \"coal\": [\"Ukai(1-5)+Ukai6\",\n@@ -59,29 +60,23 @@\n     values = collections.Counter()\n     zonekey.assert_zone_key(zone_key, 'IN-GJ')\n \n-    solar_html = web.get_response_soup(\n-        zone_key, 'https://www.sldcguj.com/RealTimeData/GujSolar.php', session)\n-    wind_html = web.get_response_soup(\n-        zone_key, 'https://www.sldcguj.com/RealTimeData/wind.php', session)\n-\n-    values['date'] =  arrow.get(\n-        solar_html.find_all('tr')[0].text.split('\\t')[-1].strip()\n-        + ' Asia/Kolkata', 'D-MM-YYYY H:mm:ss ZZZ').datetime\n-    values['solar'] = split_and_sum(\n-        solar_html.find_all('tr')[-1].find_all('td')[-1].text.strip())\n-    values['wind'] = split_and_sum(\n-        wind_html.find_all('tr')[-1].find_all('td')[-1].text.strip())\n-\n     cookies_params = {\n         'ASPSESSIONIDSUQQQTRD': 'ODMNNHADJFGCMLFFGFEMOGBL',\n         'PHPSESSID': 'a301jk6p1p8d50dduflceeg6l1'\n     }\n \n-    rows = web.get_response_soup(\n-        zone_key,\n-        'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php',\n-        session).find_all('tr')\n+    soup = web.get_response_soup(zone_key, SLDCGUJ_URL, session)\n+    rows = soup.find_all('tr')\n+    cells = [c.text.strip() for c in soup.find_all('td')]\n \n+    # get wind and solar values\n+    values['date'] = arrow.get(cells[1], 'DD-MM-YYYY HH:mm:ss').replace(\n+        tzinfo='Asia/Kolkata')\n+    [wind_solar_index] = [i for i, c in enumerate(cells) if c == '(Wind+Solar) Generation']\n+    value = cells[wind_solar_index + 1]\n+    values['wind'], values['solar'] = [int(v) for v in value.split(' + ')]\n+\n+    # get other production values\n     for row in rows:\n         elements = row.find_all('td')\n         if len(elements) > 3:  # will find production rows\n@@ -177,7 +172,7 @@\n \n     data = {\n         'zoneKey': zone_key,\n-        'datetime': value_map['date'],\n+        'datetime': value_map['date'].datetime,\n         'production': {\n             'biomass': None,\n             'coal': value_map.get('coal', 0),\n", "issue": "Restore access to India-Gujarat (IN-GJ) wind and solar data\nHey everyone,\r\n\r\nlooks like SLDCGUJ has also removed the access to real-time data websites for wind and solar, just like they did for the conventional real-time data.\r\nThe solution should be really simple: We can use the same link which still gives access to that [\"print\" page](http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php). It has wind and solar generation on the right side, too ;)\r\n\r\n![image](https://user-images.githubusercontent.com/25743609/43044321-0939e890-8da4-11e8-868d-51a54a1a5b60.png)\r\n\r\nGreetings, Alex\n", "before_files": [{"content": "#!/usr/bin/env python3\n\nimport re\nimport collections\nfrom operator import itemgetter\nimport arrow\nimport requests\nimport itertools\nfrom .lib import zonekey, web, IN\nfrom .lib.validation import validate\nfrom logging import getLogger\n\n\nstation_map = {\n     \"coal\": [\"Ukai(1-5)+Ukai6\",\n             \"Wanakbori\",\n             \"Gandhinagar\",\n             \"Sikka(3-4)\",\n             \"KLTPS(1-3)+KLTPS4\",\n             \"SLPP(I+II)\",\n             \"Akrimota\",\n             \"TPAECo\",\n             \"EPGL(I+II)\",\n             \"Adani(I+II+III)\",\n             \"BECL(I+II)\",\n             \"CGPL\"],\n    \"hydro\": [\"Ukai(Hydro)\",\n              \"Kadana(Hydro)\",\n              \"SSP(RBPH)\"],\n    \"gas\": [\"Utran(Gas)(II)\",\n            \"Dhuvaran(Gas)(I)+(II)+(III)\",\n            \"GIPCL(I)+(II)\",\n            \"GSEG(I+II)\",\n            \"GPPC\",\n            \"CLPI\",\n            \"KAWAS\",\n            \"Sugen+Unosgn\",\n            \"JHANOR\"],\n    \"nuclear\": [\"KAPP\"]\n}\n\n\ndef split_and_sum(expression):\n    \"\"\"\n    Avoid using literal_eval for simple addition expressions.\n    Returns sum of all positive numbers.\n    \"\"\"\n\n    split_vals = expression.split('+')\n    float_vals = [float(v) for v in split_vals]\n    total = sum([v for v in float_vals if v > 0.0])\n\n    return total\n\n\ndef fetch_data(zone_key, session=None, logger=None):\n    session = session or requests.session()\n\n    values = collections.Counter()\n    zonekey.assert_zone_key(zone_key, 'IN-GJ')\n\n    solar_html = web.get_response_soup(\n        zone_key, 'https://www.sldcguj.com/RealTimeData/GujSolar.php', session)\n    wind_html = web.get_response_soup(\n        zone_key, 'https://www.sldcguj.com/RealTimeData/wind.php', session)\n\n    values['date'] =  arrow.get(\n        solar_html.find_all('tr')[0].text.split('\\t')[-1].strip()\n        + ' Asia/Kolkata', 'D-MM-YYYY H:mm:ss ZZZ').datetime\n    values['solar'] = split_and_sum(\n        solar_html.find_all('tr')[-1].find_all('td')[-1].text.strip())\n    values['wind'] = split_and_sum(\n        wind_html.find_all('tr')[-1].find_all('td')[-1].text.strip())\n\n    cookies_params = {\n        'ASPSESSIONIDSUQQQTRD': 'ODMNNHADJFGCMLFFGFEMOGBL',\n        'PHPSESSID': 'a301jk6p1p8d50dduflceeg6l1'\n    }\n\n    rows = web.get_response_soup(\n        zone_key,\n        'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php',\n        session).find_all('tr')\n\n    for row in rows:\n        elements = row.find_all('td')\n        if len(elements) > 3:  # will find production rows\n            v1, v2 = (re.sub(r'\\s+', r'', x.text)\n                      for x in itemgetter(*[0, 3])(elements))\n            energy_type = [k for k, v in station_map.items() if v1 in v]\n            if len(energy_type) > 0:\n                v2 = split_and_sum(v2)\n                values[energy_type[0]] += v2\n            else:\n                if 'StationName' in (v1, v2):  # meta data row\n                    continue\n                elif 'DSMRate' in v2:  # demand side management\n                    continue\n                else:\n                    try:\n                        logger.warning(\n                            'Unknown fuel for station name: {}'.format(v1),\n                            extra={'key': zone_key})\n                        v2 = split_and_sum(v2)\n                        values['unknown'] += v2\n                    except ValueError as e:\n                        # handle float failures\n                        logger.warning(\n                            \"couldn't convert {} to float\".format(v2),\n                            extra={'key': zone_key})\n                        continue\n        elif len(elements) == 3:  # will find consumption row\n            v1, v2 = (re.sub(r'\\s+', r'', x.text)\n                      for x in itemgetter(*[0, 2])(elements))\n            if v1 == 'GujaratCatered':\n                values['total consumption'] = split_and_sum(v2.split('MW')[0])\n        elif len(elements) == 1:\n            # CGPL/KAPP/KAWAS/JHANOR plants have a different html structure.\n            plant_name = re.sub(r'\\s+', r'', elements[0].text)\n            known_plants = itertools.chain.from_iterable(station_map.values())\n\n            if plant_name in known_plants:\n                energy_type = [k for k, v in station_map.items() if plant_name in v][0]\n                generation_tag = row.find_all_next(\"td\")[3]\n                val = float(re.sub(r'\\s+', r'', generation_tag.text))\n                if val > 0:\n                    values[energy_type] += val\n            else:\n                if plant_name and plant_name != 'GMR':\n                    # GMR is outside Gujarat, sometimes plant_name is ''\n                    logger.warning(\n                        'Unknown fuel for station name: {}'.format(plant_name),\n                        extra={'key': zone_key})\n\n    return values\n\n\ndef fetch_production(zone_key='IN-GJ', session=None, target_datetime=None,\n                     logger=getLogger('IN-GJ')):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given country\n    Arguments:\n    zone_key: specifies which zone to get\n    session: request session passed in order to re-use an existing session\n    target_datetime: the datetime for which we want production data. If not provided, we should\n      default it to now. The provided target_datetime is timezone-aware in UTC.\n    logger: an instance of a `logging.Logger`; all raised exceptions are also logged automatically\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    session = session or requests.session()\n    if target_datetime:\n        raise NotImplementedError(\n            'This parser is not yet able to parse past dates')\n\n    value_map = fetch_data(zone_key, session, logger=logger)\n\n    data = {\n        'zoneKey': zone_key,\n        'datetime': value_map['date'],\n        'production': {\n            'biomass': None,\n            'coal': value_map.get('coal', 0),\n            'gas': value_map.get('gas', 0),\n            'hydro': value_map.get('hydro', 0),\n            'nuclear': value_map.get('nuclear', 0),\n            'oil': None,\n            'solar': value_map.get('solar', 0),\n            'wind': value_map.get('wind', 0),\n            'geothermal': None,\n            'unknown': value_map.get('unknown', 0)\n        },\n        'storage': {\n            'hydro': None\n        },\n        'source': 'sldcguj.com',\n    }\n\n    valid_data = validate(data, logger, remove_negative=True, floor=7000)\n\n    return valid_data\n\n\ndef fetch_consumption(zone_key='IN-GJ', session=None, target_datetime=None,\n                      logger=getLogger('IN-GJ')):\n    \"\"\"\n    Method to get consumption data of Gujarat\n    :param zone_key:\n    :param session:\n    :return:\n    \"\"\"\n    session = session or requests.session()\n    if target_datetime:\n        raise NotImplementedError(\n            'This parser is not yet able to parse past dates')\n\n    value_map = fetch_data(zone_key, session, logger=logger)\n\n    data = {\n        'zoneKey': zone_key,\n        'datetime': value_map['date'],\n        'consumption': value_map['total consumption'],\n        'source': 'sldcguj.com'\n    }\n\n    return data\n\n\nif __name__ == '__main__':\n    session = requests.Session()\n    print(fetch_production('IN-GJ', session))\n    print(fetch_consumption('IN-GJ', session))\n", "path": "parsers/IN_GJ.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\nimport re\nimport collections\nfrom operator import itemgetter\nimport arrow\nimport requests\nimport itertools\nfrom .lib import zonekey, web, IN\nfrom .lib.validation import validate\nfrom logging import getLogger\n\nSLDCGUJ_URL = 'http://www.sldcguj.com/RealTimeData/PrintPage.php?page=realtimedemand.php'\n\nstation_map = {\n     \"coal\": [\"Ukai(1-5)+Ukai6\",\n             \"Wanakbori\",\n             \"Gandhinagar\",\n             \"Sikka(3-4)\",\n             \"KLTPS(1-3)+KLTPS4\",\n             \"SLPP(I+II)\",\n             \"Akrimota\",\n             \"TPAECo\",\n             \"EPGL(I+II)\",\n             \"Adani(I+II+III)\",\n             \"BECL(I+II)\",\n             \"CGPL\"],\n    \"hydro\": [\"Ukai(Hydro)\",\n              \"Kadana(Hydro)\",\n              \"SSP(RBPH)\"],\n    \"gas\": [\"Utran(Gas)(II)\",\n            \"Dhuvaran(Gas)(I)+(II)+(III)\",\n            \"GIPCL(I)+(II)\",\n            \"GSEG(I+II)\",\n            \"GPPC\",\n            \"CLPI\",\n            \"KAWAS\",\n            \"Sugen+Unosgn\",\n            \"JHANOR\"],\n    \"nuclear\": [\"KAPP\"]\n}\n\n\ndef split_and_sum(expression):\n    \"\"\"\n    Avoid using literal_eval for simple addition expressions.\n    Returns sum of all positive numbers.\n    \"\"\"\n\n    split_vals = expression.split('+')\n    float_vals = [float(v) for v in split_vals]\n    total = sum([v for v in float_vals if v > 0.0])\n\n    return total\n\n\ndef fetch_data(zone_key, session=None, logger=None):\n    session = session or requests.session()\n\n    values = collections.Counter()\n    zonekey.assert_zone_key(zone_key, 'IN-GJ')\n\n    cookies_params = {\n        'ASPSESSIONIDSUQQQTRD': 'ODMNNHADJFGCMLFFGFEMOGBL',\n        'PHPSESSID': 'a301jk6p1p8d50dduflceeg6l1'\n    }\n\n    soup = web.get_response_soup(zone_key, SLDCGUJ_URL, session)\n    rows = soup.find_all('tr')\n    cells = [c.text.strip() for c in soup.find_all('td')]\n\n    # get wind and solar values\n    values['date'] = arrow.get(cells[1], 'DD-MM-YYYY HH:mm:ss').replace(\n        tzinfo='Asia/Kolkata')\n    [wind_solar_index] = [i for i, c in enumerate(cells) if c == '(Wind+Solar) Generation']\n    value = cells[wind_solar_index + 1]\n    values['wind'], values['solar'] = [int(v) for v in value.split(' + ')]\n\n    # get other production values\n    for row in rows:\n        elements = row.find_all('td')\n        if len(elements) > 3:  # will find production rows\n            v1, v2 = (re.sub(r'\\s+', r'', x.text)\n                      for x in itemgetter(*[0, 3])(elements))\n            energy_type = [k for k, v in station_map.items() if v1 in v]\n            if len(energy_type) > 0:\n                v2 = split_and_sum(v2)\n                values[energy_type[0]] += v2\n            else:\n                if 'StationName' in (v1, v2):  # meta data row\n                    continue\n                elif 'DSMRate' in v2:  # demand side management\n                    continue\n                else:\n                    try:\n                        logger.warning(\n                            'Unknown fuel for station name: {}'.format(v1),\n                            extra={'key': zone_key})\n                        v2 = split_and_sum(v2)\n                        values['unknown'] += v2\n                    except ValueError as e:\n                        # handle float failures\n                        logger.warning(\n                            \"couldn't convert {} to float\".format(v2),\n                            extra={'key': zone_key})\n                        continue\n        elif len(elements) == 3:  # will find consumption row\n            v1, v2 = (re.sub(r'\\s+', r'', x.text)\n                      for x in itemgetter(*[0, 2])(elements))\n            if v1 == 'GujaratCatered':\n                values['total consumption'] = split_and_sum(v2.split('MW')[0])\n        elif len(elements) == 1:\n            # CGPL/KAPP/KAWAS/JHANOR plants have a different html structure.\n            plant_name = re.sub(r'\\s+', r'', elements[0].text)\n            known_plants = itertools.chain.from_iterable(station_map.values())\n\n            if plant_name in known_plants:\n                energy_type = [k for k, v in station_map.items() if plant_name in v][0]\n                generation_tag = row.find_all_next(\"td\")[3]\n                val = float(re.sub(r'\\s+', r'', generation_tag.text))\n                if val > 0:\n                    values[energy_type] += val\n            else:\n                if plant_name and plant_name != 'GMR':\n                    # GMR is outside Gujarat, sometimes plant_name is ''\n                    logger.warning(\n                        'Unknown fuel for station name: {}'.format(plant_name),\n                        extra={'key': zone_key})\n\n    return values\n\n\ndef fetch_production(zone_key='IN-GJ', session=None, target_datetime=None,\n                     logger=getLogger('IN-GJ')):\n    \"\"\"\n    Requests the last known production mix (in MW) of a given country\n    Arguments:\n    zone_key: specifies which zone to get\n    session: request session passed in order to re-use an existing session\n    target_datetime: the datetime for which we want production data. If not provided, we should\n      default it to now. The provided target_datetime is timezone-aware in UTC.\n    logger: an instance of a `logging.Logger`; all raised exceptions are also logged automatically\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    session = session or requests.session()\n    if target_datetime:\n        raise NotImplementedError(\n            'This parser is not yet able to parse past dates')\n\n    value_map = fetch_data(zone_key, session, logger=logger)\n\n    data = {\n        'zoneKey': zone_key,\n        'datetime': value_map['date'].datetime,\n        'production': {\n            'biomass': None,\n            'coal': value_map.get('coal', 0),\n            'gas': value_map.get('gas', 0),\n            'hydro': value_map.get('hydro', 0),\n            'nuclear': value_map.get('nuclear', 0),\n            'oil': None,\n            'solar': value_map.get('solar', 0),\n            'wind': value_map.get('wind', 0),\n            'geothermal': None,\n            'unknown': value_map.get('unknown', 0)\n        },\n        'storage': {\n            'hydro': None\n        },\n        'source': 'sldcguj.com',\n    }\n\n    valid_data = validate(data, logger, remove_negative=True, floor=7000)\n\n    return valid_data\n\n\ndef fetch_consumption(zone_key='IN-GJ', session=None, target_datetime=None,\n                      logger=getLogger('IN-GJ')):\n    \"\"\"\n    Method to get consumption data of Gujarat\n    :param zone_key:\n    :param session:\n    :return:\n    \"\"\"\n    session = session or requests.session()\n    if target_datetime:\n        raise NotImplementedError(\n            'This parser is not yet able to parse past dates')\n\n    value_map = fetch_data(zone_key, session, logger=logger)\n\n    data = {\n        'zoneKey': zone_key,\n        'datetime': value_map['date'],\n        'consumption': value_map['total consumption'],\n        'source': 'sldcguj.com'\n    }\n\n    return data\n\n\nif __name__ == '__main__':\n    session = requests.Session()\n    print(fetch_production('IN-GJ', session))\n    print(fetch_consumption('IN-GJ', session))\n", "path": "parsers/IN_GJ.py"}]}