prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  MN parser down
  ## Description
  Mongolia parser is down, but the bot hasn't open an issue. I am opening this one to alert the maintainers.
  It seems this time the parser is down because of a change in the json that was being parsed:
  > raise ParserException(
  parsers.lib.exceptions.ParserException: MN.py Parser: Fetched keys from source dict_keys(['date', 'syssum', 'tpp', 'sumnar', 'sums', 'energyimport', 't']) do not match expected keys dict_values(['date', 'syssum', 'sumnar', 'sums', 'energyimport', 't']).
  
  A new key called tpp (thermal power plants?) has being added. The value of this new key doesn't match the previously calculated unknown production (so tpp plus other keys don't add up to consumption). What should be done to fix this? It seems an unknown source is being added.
  
  By the way, a bit off-topic, but I have noticed that the Mongolia parser outputs global exchange data. We currently get the exchange with Russia from its parser, so we could calculate the exchange with China by substracting the other exchange. Is this possible?
  
  --- 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/MN.py`
  Content:
  ```
  1 #!/usr/bin/env python3
  2 
  3 from datetime import datetime
  4 from logging import Logger, getLogger
  5 from typing import Any
  6 from zoneinfo import ZoneInfo
  7 
  8 from requests import Response, Session
  9 
  10 from electricitymap.contrib.config import ZoneKey
  11 from electricitymap.contrib.lib.models.event_lists import (
  12     ProductionBreakdownList,
  13     TotalConsumptionList,
  14 )
  15 from electricitymap.contrib.lib.models.events import ProductionMix
  16 from parsers.lib.exceptions import ParserException
  17 
  18 NDC_GENERATION = "https://disnews.energy.mn/test/convert.php"
  19 TZ = ZoneInfo("Asia/Ulaanbaatar")  # UTC+8
  20 
  21 # Query fields to web API fields
  22 JSON_QUERY_TO_SRC = {
  23     "time": "date",
  24     "consumptionMW": "syssum",
  25     "solarMW": "sumnar",
  26     "windMW": "sums",
  27     "importMW": "energyimport",  # positive = import
  28     "temperatureC": "t",  # current temperature
  29 }
  30 
  31 
  32 def parse_json(web_json: dict) -> dict[str, Any]:
  33     """
  34     Parse the fetched JSON data to our query format according to JSON_QUERY_TO_SRC.
  35     Example of expected JSON format present at URL:
  36     {"date":"2023-06-27 18:00:00","syssum":"869.37","sumnar":42.34,"sums":119.79,"energyimport":"49.58","t":"17"}
  37     """
  38 
  39     # Validate first if keys in fetched dict match expected keys
  40     if set(JSON_QUERY_TO_SRC.values()) != set(web_json.keys()):
  41         raise ParserException(
  42             parser="MN.py",
  43             message=f"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.",
  44         )
  45 
  46     if None in web_json.values():
  47         raise ParserException(
  48             parser="MN.py",
  49             message=f"Fetched values contain null. Fetched data: {web_json}.",
  50         )
  51 
  52     # Then we can safely parse them
  53     query_data = dict()
  54     for query_key, src_key in JSON_QUERY_TO_SRC.items():
  55         if query_key == "time":
  56             # convert to datetime
  57             query_data[query_key] = datetime.fromisoformat(web_json[src_key]).replace(
  58                 tzinfo=TZ
  59             )
  60         else:
  61             # or convert to float, might also be string
  62             query_data[query_key] = float(web_json[src_key])
  63 
  64     return query_data
  65 
  66 
  67 def query(session: Session) -> dict[str, Any]:
  68     """
  69     Query the JSON endpoint and parse it.
  70     """
  71 
  72     target_response: Response = session.get(NDC_GENERATION)
  73 
  74     if not target_response.ok:
  75         raise ParserException(
  76             parser="MN.py",
  77             message=f"Data request did not succeed: {target_response.status_code}",
  78         )
  79 
  80     # Read as JSON
  81     response_json = target_response.json()
  82     query_result = parse_json(response_json)
  83 
  84     return query_result
  85 
  86 
  87 def fetch_production(
  88     zone_key: ZoneKey,
  89     session: Session = Session(),
  90     target_datetime: datetime | None = None,
  91     logger: Logger = getLogger(__name__),
  92 ):
  93     if target_datetime:
  94         raise NotImplementedError("This parser is not yet able to parse past dates.")
  95 
  96     query_data = query(session)
  97 
  98     # Calculated 'unknown' production from available data (consumption, import, solar, wind).
  99     # 'unknown' consists of 92.8% coal, 5.8% oil and 1.4% hydro as per 2020; sources: IEA and IRENA statistics.
  100     query_data["unknownMW"] = round(
  101         query_data["consumptionMW"]
  102         - query_data["importMW"]
  103         - query_data["solarMW"]
  104         - query_data["windMW"],
  105         13,
  106     )
  107 
  108     prod_mix = ProductionMix(
  109         solar=query_data["solarMW"],
  110         wind=query_data["windMW"],
  111         unknown=query_data["unknownMW"],
  112     )
  113 
  114     prod_breakdown_list = ProductionBreakdownList(logger)
  115     prod_breakdown_list.append(
  116         datetime=query_data["time"],
  117         zoneKey=zone_key,
  118         source="https://ndc.energy.mn/",
  119         production=prod_mix,
  120     )
  121 
  122     return prod_breakdown_list.to_list()
  123 
  124 
  125 def fetch_consumption(
  126     zone_key: ZoneKey,
  127     session: Session = Session(),
  128     target_datetime: datetime | None = None,
  129     logger: Logger = getLogger(__name__),
  130 ):
  131     if target_datetime:
  132         raise NotImplementedError("This parser is not yet able to parse past dates.")
  133 
  134     query_data = query(session)
  135 
  136     consumption_list = TotalConsumptionList(logger)
  137     consumption_list.append(
  138         datetime=query_data["time"],
  139         zoneKey=zone_key,
  140         consumption=query_data["consumptionMW"],
  141         source="https://ndc.energy.mn/",
  142     )
  143 
  144     return consumption_list.to_list()
  145 
  146 
  147 if __name__ == "__main__":
  148     print("fetch_production() ->")
  149     print(fetch_production(ZoneKey("MN")))
  150     print("fetch_consumption() ->")
  151     print(fetch_consumption(ZoneKey("MN")))
  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/MN.py b/parsers/MN.py
  --- a/parsers/MN.py
  +++ b/parsers/MN.py
  @@ -29,18 +29,18 @@
   }
   
   
  -def parse_json(web_json: dict) -> dict[str, Any]:
  +def parse_json(web_json: dict, logger: Logger, zone_key: ZoneKey) -> dict[str, Any]:
       """
       Parse the fetched JSON data to our query format according to JSON_QUERY_TO_SRC.
       Example of expected JSON format present at URL:
  -    {"date":"2023-06-27 18:00:00","syssum":"869.37","sumnar":42.34,"sums":119.79,"energyimport":"49.58","t":"17"}
  +    {"date":"2023-06-27 18:00:00","syssum":"869.37","sumnar":42.34,"sums":119.79,"energyimport":"49.58"}
       """
   
       # Validate first if keys in fetched dict match expected keys
       if set(JSON_QUERY_TO_SRC.values()) != set(web_json.keys()):
  -        raise ParserException(
  -            parser="MN.py",
  -            message=f"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.",
  +        logger.error(
  +            msg=f"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.",
  +            extra={"zone_key": zone_key, "parser": "MN.py"},
           )
   
       if None in web_json.values():
  @@ -52,7 +52,7 @@
       # Then we can safely parse them
       query_data = dict()
       for query_key, src_key in JSON_QUERY_TO_SRC.items():
  -        if query_key == "time":
  +        if "time" in query_key:
               # convert to datetime
               query_data[query_key] = datetime.fromisoformat(web_json[src_key]).replace(
                   tzinfo=TZ
  @@ -64,7 +64,7 @@
       return query_data
   
   
  -def query(session: Session) -> dict[str, Any]:
  +def query(session: Session, logger: Logger, zone_key: ZoneKey) -> dict[str, Any]:
       """
       Query the JSON endpoint and parse it.
       """
  @@ -79,7 +79,7 @@
   
       # Read as JSON
       response_json = target_response.json()
  -    query_result = parse_json(response_json)
  +    query_result = parse_json(response_json, logger, zone_key)
   
       return query_result
   
  @@ -93,11 +93,11 @@
       if target_datetime:
           raise NotImplementedError("This parser is not yet able to parse past dates.")
   
  -    query_data = query(session)
  +    query_data = query(session, logger, zone_key)
   
  -    # Calculated 'unknown' production from available data (consumption, import, solar, wind).
  +    # Calculated 'unknown' production from available data (consumption, import, solar, wind, tpp).
       # 'unknown' consists of 92.8% coal, 5.8% oil and 1.4% hydro as per 2020; sources: IEA and IRENA statistics.
  -    query_data["unknownMW"] = round(
  +    query_data["leftoverMW"] = round(
           query_data["consumptionMW"]
           - query_data["importMW"]
           - query_data["solarMW"]
  @@ -105,11 +105,10 @@
           13,
       )
   
  -    prod_mix = ProductionMix(
  -        solar=query_data["solarMW"],
  -        wind=query_data["windMW"],
  -        unknown=query_data["unknownMW"],
  -    )
  +    prod_mix = ProductionMix()
  +    prod_mix.add_value("solar", query_data["solarMW"])
  +    prod_mix.add_value("wind", query_data["windMW"])
  +    prod_mix.add_value("unknown", query_data["leftoverMW"])
   
       prod_breakdown_list = ProductionBreakdownList(logger)
       prod_breakdown_list.append(
  @@ -131,7 +130,7 @@
       if target_datetime:
           raise NotImplementedError("This parser is not yet able to parse past dates.")
   
  -    query_data = query(session)
  +    query_data = query(session, logger, zone_key)
   
       consumption_list = TotalConsumptionList(logger)
       consumption_list.append(
  
verification_info: {"golden_diff": "diff --git a/parsers/MN.py b/parsers/MN.py\n--- a/parsers/MN.py\n+++ b/parsers/MN.py\n@@ -29,18 +29,18 @@\n }\n \n \n-def parse_json(web_json: dict) -> dict[str, Any]:\n+def parse_json(web_json: dict, logger: Logger, zone_key: ZoneKey) -> dict[str, Any]:\n     \"\"\"\n     Parse the fetched JSON data to our query format according to JSON_QUERY_TO_SRC.\n     Example of expected JSON format present at URL:\n-    {\"date\":\"2023-06-27 18:00:00\",\"syssum\":\"869.37\",\"sumnar\":42.34,\"sums\":119.79,\"energyimport\":\"49.58\",\"t\":\"17\"}\n+    {\"date\":\"2023-06-27 18:00:00\",\"syssum\":\"869.37\",\"sumnar\":42.34,\"sums\":119.79,\"energyimport\":\"49.58\"}\n     \"\"\"\n \n     # Validate first if keys in fetched dict match expected keys\n     if set(JSON_QUERY_TO_SRC.values()) != set(web_json.keys()):\n-        raise ParserException(\n-            parser=\"MN.py\",\n-            message=f\"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.\",\n+        logger.error(\n+            msg=f\"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.\",\n+            extra={\"zone_key\": zone_key, \"parser\": \"MN.py\"},\n         )\n \n     if None in web_json.values():\n@@ -52,7 +52,7 @@\n     # Then we can safely parse them\n     query_data = dict()\n     for query_key, src_key in JSON_QUERY_TO_SRC.items():\n-        if query_key == \"time\":\n+        if \"time\" in query_key:\n             # convert to datetime\n             query_data[query_key] = datetime.fromisoformat(web_json[src_key]).replace(\n                 tzinfo=TZ\n@@ -64,7 +64,7 @@\n     return query_data\n \n \n-def query(session: Session) -> dict[str, Any]:\n+def query(session: Session, logger: Logger, zone_key: ZoneKey) -> dict[str, Any]:\n     \"\"\"\n     Query the JSON endpoint and parse it.\n     \"\"\"\n@@ -79,7 +79,7 @@\n \n     # Read as JSON\n     response_json = target_response.json()\n-    query_result = parse_json(response_json)\n+    query_result = parse_json(response_json, logger, zone_key)\n \n     return query_result\n \n@@ -93,11 +93,11 @@\n     if target_datetime:\n         raise NotImplementedError(\"This parser is not yet able to parse past dates.\")\n \n-    query_data = query(session)\n+    query_data = query(session, logger, zone_key)\n \n-    # Calculated 'unknown' production from available data (consumption, import, solar, wind).\n+    # Calculated 'unknown' production from available data (consumption, import, solar, wind, tpp).\n     # 'unknown' consists of 92.8% coal, 5.8% oil and 1.4% hydro as per 2020; sources: IEA and IRENA statistics.\n-    query_data[\"unknownMW\"] = round(\n+    query_data[\"leftoverMW\"] = round(\n         query_data[\"consumptionMW\"]\n         - query_data[\"importMW\"]\n         - query_data[\"solarMW\"]\n@@ -105,11 +105,10 @@\n         13,\n     )\n \n-    prod_mix = ProductionMix(\n-        solar=query_data[\"solarMW\"],\n-        wind=query_data[\"windMW\"],\n-        unknown=query_data[\"unknownMW\"],\n-    )\n+    prod_mix = ProductionMix()\n+    prod_mix.add_value(\"solar\", query_data[\"solarMW\"])\n+    prod_mix.add_value(\"wind\", query_data[\"windMW\"])\n+    prod_mix.add_value(\"unknown\", query_data[\"leftoverMW\"])\n \n     prod_breakdown_list = ProductionBreakdownList(logger)\n     prod_breakdown_list.append(\n@@ -131,7 +130,7 @@\n     if target_datetime:\n         raise NotImplementedError(\"This parser is not yet able to parse past dates.\")\n \n-    query_data = query(session)\n+    query_data = query(session, logger, zone_key)\n \n     consumption_list = TotalConsumptionList(logger)\n     consumption_list.append(\n", "issue": "MN parser down\n## Description\r\nMongolia parser is down, but the bot hasn't open an issue. I am opening this one to alert the maintainers.\r\nIt seems this time the parser is down because of a change in the json that was being parsed:\r\n> raise ParserException(\r\nparsers.lib.exceptions.ParserException: MN.py Parser: Fetched keys from source dict_keys(['date', 'syssum', 'tpp', 'sumnar', 'sums', 'energyimport', 't']) do not match expected keys dict_values(['date', 'syssum', 'sumnar', 'sums', 'energyimport', 't']).\r\n\r\nA new key called tpp (thermal power plants?) has being added. The value of this new key doesn't match the previously calculated unknown production (so tpp plus other keys don't add up to consumption). What should be done to fix this? It seems an unknown source is being added.\r\n\r\nBy the way, a bit off-topic, but I have noticed that the Mongolia parser outputs global exchange data. We currently get the exchange with Russia from its parser, so we could calculate the exchange with China by substracting the other exchange. Is this possible?\n", "before_files": [{"content": "#!/usr/bin/env python3\n\nfrom datetime import datetime\nfrom logging import Logger, getLogger\nfrom typing import Any\nfrom zoneinfo import ZoneInfo\n\nfrom requests import Response, Session\n\nfrom electricitymap.contrib.config import ZoneKey\nfrom electricitymap.contrib.lib.models.event_lists import (\n    ProductionBreakdownList,\n    TotalConsumptionList,\n)\nfrom electricitymap.contrib.lib.models.events import ProductionMix\nfrom parsers.lib.exceptions import ParserException\n\nNDC_GENERATION = \"https://disnews.energy.mn/test/convert.php\"\nTZ = ZoneInfo(\"Asia/Ulaanbaatar\")  # UTC+8\n\n# Query fields to web API fields\nJSON_QUERY_TO_SRC = {\n    \"time\": \"date\",\n    \"consumptionMW\": \"syssum\",\n    \"solarMW\": \"sumnar\",\n    \"windMW\": \"sums\",\n    \"importMW\": \"energyimport\",  # positive = import\n    \"temperatureC\": \"t\",  # current temperature\n}\n\n\ndef parse_json(web_json: dict) -> dict[str, Any]:\n    \"\"\"\n    Parse the fetched JSON data to our query format according to JSON_QUERY_TO_SRC.\n    Example of expected JSON format present at URL:\n    {\"date\":\"2023-06-27 18:00:00\",\"syssum\":\"869.37\",\"sumnar\":42.34,\"sums\":119.79,\"energyimport\":\"49.58\",\"t\":\"17\"}\n    \"\"\"\n\n    # Validate first if keys in fetched dict match expected keys\n    if set(JSON_QUERY_TO_SRC.values()) != set(web_json.keys()):\n        raise ParserException(\n            parser=\"MN.py\",\n            message=f\"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.\",\n        )\n\n    if None in web_json.values():\n        raise ParserException(\n            parser=\"MN.py\",\n            message=f\"Fetched values contain null. Fetched data: {web_json}.\",\n        )\n\n    # Then we can safely parse them\n    query_data = dict()\n    for query_key, src_key in JSON_QUERY_TO_SRC.items():\n        if query_key == \"time\":\n            # convert to datetime\n            query_data[query_key] = datetime.fromisoformat(web_json[src_key]).replace(\n                tzinfo=TZ\n            )\n        else:\n            # or convert to float, might also be string\n            query_data[query_key] = float(web_json[src_key])\n\n    return query_data\n\n\ndef query(session: Session) -> dict[str, Any]:\n    \"\"\"\n    Query the JSON endpoint and parse it.\n    \"\"\"\n\n    target_response: Response = session.get(NDC_GENERATION)\n\n    if not target_response.ok:\n        raise ParserException(\n            parser=\"MN.py\",\n            message=f\"Data request did not succeed: {target_response.status_code}\",\n        )\n\n    # Read as JSON\n    response_json = target_response.json()\n    query_result = parse_json(response_json)\n\n    return query_result\n\n\ndef fetch_production(\n    zone_key: ZoneKey,\n    session: Session = Session(),\n    target_datetime: datetime | None = None,\n    logger: Logger = getLogger(__name__),\n):\n    if target_datetime:\n        raise NotImplementedError(\"This parser is not yet able to parse past dates.\")\n\n    query_data = query(session)\n\n    # Calculated 'unknown' production from available data (consumption, import, solar, wind).\n    # 'unknown' consists of 92.8% coal, 5.8% oil and 1.4% hydro as per 2020; sources: IEA and IRENA statistics.\n    query_data[\"unknownMW\"] = round(\n        query_data[\"consumptionMW\"]\n        - query_data[\"importMW\"]\n        - query_data[\"solarMW\"]\n        - query_data[\"windMW\"],\n        13,\n    )\n\n    prod_mix = ProductionMix(\n        solar=query_data[\"solarMW\"],\n        wind=query_data[\"windMW\"],\n        unknown=query_data[\"unknownMW\"],\n    )\n\n    prod_breakdown_list = ProductionBreakdownList(logger)\n    prod_breakdown_list.append(\n        datetime=query_data[\"time\"],\n        zoneKey=zone_key,\n        source=\"https://ndc.energy.mn/\",\n        production=prod_mix,\n    )\n\n    return prod_breakdown_list.to_list()\n\n\ndef fetch_consumption(\n    zone_key: ZoneKey,\n    session: Session = Session(),\n    target_datetime: datetime | None = None,\n    logger: Logger = getLogger(__name__),\n):\n    if target_datetime:\n        raise NotImplementedError(\"This parser is not yet able to parse past dates.\")\n\n    query_data = query(session)\n\n    consumption_list = TotalConsumptionList(logger)\n    consumption_list.append(\n        datetime=query_data[\"time\"],\n        zoneKey=zone_key,\n        consumption=query_data[\"consumptionMW\"],\n        source=\"https://ndc.energy.mn/\",\n    )\n\n    return consumption_list.to_list()\n\n\nif __name__ == \"__main__\":\n    print(\"fetch_production() ->\")\n    print(fetch_production(ZoneKey(\"MN\")))\n    print(\"fetch_consumption() ->\")\n    print(fetch_consumption(ZoneKey(\"MN\")))\n", "path": "parsers/MN.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\nfrom datetime import datetime\nfrom logging import Logger, getLogger\nfrom typing import Any\nfrom zoneinfo import ZoneInfo\n\nfrom requests import Response, Session\n\nfrom electricitymap.contrib.config import ZoneKey\nfrom electricitymap.contrib.lib.models.event_lists import (\n    ProductionBreakdownList,\n    TotalConsumptionList,\n)\nfrom electricitymap.contrib.lib.models.events import ProductionMix\nfrom parsers.lib.exceptions import ParserException\n\nNDC_GENERATION = \"https://disnews.energy.mn/test/convert.php\"\nTZ = ZoneInfo(\"Asia/Ulaanbaatar\")  # UTC+8\n\n# Query fields to web API fields\nJSON_QUERY_TO_SRC = {\n    \"time\": \"date\",\n    \"consumptionMW\": \"syssum\",\n    \"solarMW\": \"sumnar\",\n    \"windMW\": \"sums\",\n    \"importMW\": \"energyimport\",  # positive = import\n    \"temperatureC\": \"t\",  # current temperature\n}\n\n\ndef parse_json(web_json: dict, logger: Logger, zone_key: ZoneKey) -> dict[str, Any]:\n    \"\"\"\n    Parse the fetched JSON data to our query format according to JSON_QUERY_TO_SRC.\n    Example of expected JSON format present at URL:\n    {\"date\":\"2023-06-27 18:00:00\",\"syssum\":\"869.37\",\"sumnar\":42.34,\"sums\":119.79,\"energyimport\":\"49.58\"}\n    \"\"\"\n\n    # Validate first if keys in fetched dict match expected keys\n    if set(JSON_QUERY_TO_SRC.values()) != set(web_json.keys()):\n        logger.error(\n            msg=f\"Fetched keys from source {web_json.keys()} do not match expected keys {JSON_QUERY_TO_SRC.values()}.\",\n            extra={\"zone_key\": zone_key, \"parser\": \"MN.py\"},\n        )\n\n    if None in web_json.values():\n        raise ParserException(\n            parser=\"MN.py\",\n            message=f\"Fetched values contain null. Fetched data: {web_json}.\",\n        )\n\n    # Then we can safely parse them\n    query_data = dict()\n    for query_key, src_key in JSON_QUERY_TO_SRC.items():\n        if \"time\" in query_key:\n            # convert to datetime\n            query_data[query_key] = datetime.fromisoformat(web_json[src_key]).replace(\n                tzinfo=TZ\n            )\n        else:\n            # or convert to float, might also be string\n            query_data[query_key] = float(web_json[src_key])\n\n    return query_data\n\n\ndef query(session: Session, logger: Logger, zone_key: ZoneKey) -> dict[str, Any]:\n    \"\"\"\n    Query the JSON endpoint and parse it.\n    \"\"\"\n\n    target_response: Response = session.get(NDC_GENERATION)\n\n    if not target_response.ok:\n        raise ParserException(\n            parser=\"MN.py\",\n            message=f\"Data request did not succeed: {target_response.status_code}\",\n        )\n\n    # Read as JSON\n    response_json = target_response.json()\n    query_result = parse_json(response_json, logger, zone_key)\n\n    return query_result\n\n\ndef fetch_production(\n    zone_key: ZoneKey,\n    session: Session = Session(),\n    target_datetime: datetime | None = None,\n    logger: Logger = getLogger(__name__),\n):\n    if target_datetime:\n        raise NotImplementedError(\"This parser is not yet able to parse past dates.\")\n\n    query_data = query(session, logger, zone_key)\n\n    # Calculated 'unknown' production from available data (consumption, import, solar, wind, tpp).\n    # 'unknown' consists of 92.8% coal, 5.8% oil and 1.4% hydro as per 2020; sources: IEA and IRENA statistics.\n    query_data[\"leftoverMW\"] = round(\n        query_data[\"consumptionMW\"]\n        - query_data[\"importMW\"]\n        - query_data[\"solarMW\"]\n        - query_data[\"windMW\"],\n        13,\n    )\n\n    prod_mix = ProductionMix()\n    prod_mix.add_value(\"solar\", query_data[\"solarMW\"])\n    prod_mix.add_value(\"wind\", query_data[\"windMW\"])\n    prod_mix.add_value(\"unknown\", query_data[\"leftoverMW\"])\n\n    prod_breakdown_list = ProductionBreakdownList(logger)\n    prod_breakdown_list.append(\n        datetime=query_data[\"time\"],\n        zoneKey=zone_key,\n        source=\"https://ndc.energy.mn/\",\n        production=prod_mix,\n    )\n\n    return prod_breakdown_list.to_list()\n\n\ndef fetch_consumption(\n    zone_key: ZoneKey,\n    session: Session = Session(),\n    target_datetime: datetime | None = None,\n    logger: Logger = getLogger(__name__),\n):\n    if target_datetime:\n        raise NotImplementedError(\"This parser is not yet able to parse past dates.\")\n\n    query_data = query(session, logger, zone_key)\n\n    consumption_list = TotalConsumptionList(logger)\n    consumption_list.append(\n        datetime=query_data[\"time\"],\n        zoneKey=zone_key,\n        consumption=query_data[\"consumptionMW\"],\n        source=\"https://ndc.energy.mn/\",\n    )\n\n    return consumption_list.to_list()\n\n\nif __name__ == \"__main__\":\n    print(\"fetch_production() ->\")\n    print(fetch_production(ZoneKey(\"MN\")))\n    print(\"fetch_consumption() ->\")\n    print(fetch_consumption(ZoneKey(\"MN\")))\n", "path": "parsers/MN.py"}]}