We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Need to raise custom exception
https://github.com/networktocode/ntc-templates/blob/923f9afe679f549d14079c4ec962cc913f784550/ntc_templates/parse.py#L38

Currently `parse_output` raises a generic `Exception`; this needs to be changed to a custom exception that can be properly caught by users of the function.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ntc_templates/parse.py`
Content:
```
1 """ntc_templates.parse."""
2 
3 import os
4 
5 # Due to TextFSM library issues on Windows, it is better to not fail on import
6 # Instead fail at runtime (i.e. if method is actually used).
7 try:
8     from textfsm import clitable
9 
10     HAS_CLITABLE = True
11 except ImportError:
12     HAS_CLITABLE = False
13 
14 
15 def _get_template_dir():
16     template_dir = os.environ.get("NTC_TEMPLATES_DIR")
17     if template_dir is None:
18         package_dir = os.path.dirname(__file__)
19         template_dir = os.path.join(package_dir, "templates")
20         if not os.path.isdir(template_dir):
21             project_dir = os.path.dirname(os.path.dirname(os.path.dirname(template_dir)))
22             template_dir = os.path.join(project_dir, "templates")
23 
24     return template_dir
25 
26 
27 def _clitable_to_dict(cli_table):
28     """Convert TextFSM cli_table object to list of dictionaries."""
29     objs = []
30     for row in cli_table:
31         temp_dict = {}
32         for index, element in enumerate(row):
33             temp_dict[cli_table.header[index].lower()] = element
34         objs.append(temp_dict)
35 
36     return objs
37 
38 
39 def parse_output(platform=None, command=None, data=None):
40     """Return the structured data based on the output from a network device."""
41     if not HAS_CLITABLE:
42         msg = """
43 The TextFSM library is not currently supported on Windows. If you are NOT using Windows
44 you should be able to 'pip install textfsm' to fix this issue. If you are using Windows
45 then you will need to install the patch referenced here:
46 
47 https://github.com/google/textfsm/pull/82
48 
49 """
50         raise ImportError(msg)
51 
52     template_dir = _get_template_dir()
53     cli_table = clitable.CliTable("index", template_dir)
54 
55     attrs = {"Command": command, "Platform": platform}
56     try:
57         cli_table.ParseCmd(data, attrs)
58         structured_data = _clitable_to_dict(cli_table)
59     except clitable.CliTableError as err:
60         raise Exception(  # pylint: disable=broad-exception-raised
61             f'Unable to parse command "{command}" on platform {platform} - {str(err)}'
62         ) from err
63         # Invalid or Missing template
64         # module.fail_json(msg='parsing error', error=str(e))
65         # rather than fail, fallback to return raw text
66         # structured_data = [data]
67 
68     return structured_data
69
```
--- 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/ntc_templates/parse.py b/ntc_templates/parse.py
--- a/ntc_templates/parse.py
+++ b/ntc_templates/parse.py
@@ -12,6 +12,10 @@
     HAS_CLITABLE = False
 
 
+class ParsingException(Exception):
+    """Error that is raised when TextFSM hits an `Error` state."""
+
+
 def _get_template_dir():
     template_dir = os.environ.get("NTC_TEMPLATES_DIR")
     if template_dir is None:
@@ -57,9 +61,7 @@
         cli_table.ParseCmd(data, attrs)
         structured_data = _clitable_to_dict(cli_table)
     except clitable.CliTableError as err:
-        raise Exception(  # pylint: disable=broad-exception-raised
-            f'Unable to parse command "{command}" on platform {platform} - {str(err)}'
-        ) from err
+        raise ParsingException(f'Unable to parse command "{command}" on platform {platform} - {str(err)}') from err
         # Invalid or Missing template
         # module.fail_json(msg='parsing error', error=str(e))
         # rather than fail, fallback to return raw text

{"golden_diff": "diff --git a/ntc_templates/parse.py b/ntc_templates/parse.py\n--- a/ntc_templates/parse.py\n+++ b/ntc_templates/parse.py\n@@ -12,6 +12,10 @@\n     HAS_CLITABLE = False\n \n \n+class ParsingException(Exception):\n+    \"\"\"Error that is raised when TextFSM hits an `Error` state.\"\"\"\n+\n+\n def _get_template_dir():\n     template_dir = os.environ.get(\"NTC_TEMPLATES_DIR\")\n     if template_dir is None:\n@@ -57,9 +61,7 @@\n         cli_table.ParseCmd(data, attrs)\n         structured_data = _clitable_to_dict(cli_table)\n     except clitable.CliTableError as err:\n-        raise Exception(  # pylint: disable=broad-exception-raised\n-            f'Unable to parse command \"{command}\" on platform {platform} - {str(err)}'\n-        ) from err\n+        raise ParsingException(f'Unable to parse command \"{command}\" on platform {platform} - {str(err)}') from err\n         # Invalid or Missing template\n         # module.fail_json(msg='parsing error', error=str(e))\n         # rather than fail, fallback to return raw text\n", "issue": "Need to raise custom exception\nhttps://github.com/networktocode/ntc-templates/blob/923f9afe679f549d14079c4ec962cc913f784550/ntc_templates/parse.py#L38\r\n\r\nCurrently `parse_output` raises a generic `Exception`; this needs to be changed to a custom exception that can be properly caught by users of the function.\n", "before_files": [{"content": "\"\"\"ntc_templates.parse.\"\"\"\n\nimport os\n\n# Due to TextFSM library issues on Windows, it is better to not fail on import\n# Instead fail at runtime (i.e. if method is actually used).\ntry:\n    from textfsm import clitable\n\n    HAS_CLITABLE = True\nexcept ImportError:\n    HAS_CLITABLE = False\n\n\ndef _get_template_dir():\n    template_dir = os.environ.get(\"NTC_TEMPLATES_DIR\")\n    if template_dir is None:\n        package_dir = os.path.dirname(__file__)\n        template_dir = os.path.join(package_dir, \"templates\")\n        if not os.path.isdir(template_dir):\n            project_dir = os.path.dirname(os.path.dirname(os.path.dirname(template_dir)))\n            template_dir = os.path.join(project_dir, \"templates\")\n\n    return template_dir\n\n\ndef _clitable_to_dict(cli_table):\n    \"\"\"Convert TextFSM cli_table object to list of dictionaries.\"\"\"\n    objs = []\n    for row in cli_table:\n        temp_dict = {}\n        for index, element in enumerate(row):\n            temp_dict[cli_table.header[index].lower()] = element\n        objs.append(temp_dict)\n\n    return objs\n\n\ndef parse_output(platform=None, command=None, data=None):\n    \"\"\"Return the structured data based on the output from a network device.\"\"\"\n    if not HAS_CLITABLE:\n        msg = \"\"\"\nThe TextFSM library is not currently supported on Windows. If you are NOT using Windows\nyou should be able to 'pip install textfsm' to fix this issue. If you are using Windows\nthen you will need to install the patch referenced here:\n\nhttps://github.com/google/textfsm/pull/82\n\n\"\"\"\n        raise ImportError(msg)\n\n    template_dir = _get_template_dir()\n    cli_table = clitable.CliTable(\"index\", template_dir)\n\n    attrs = {\"Command\": command, \"Platform\": platform}\n    try:\n        cli_table.ParseCmd(data, attrs)\n        structured_data = _clitable_to_dict(cli_table)\n    except clitable.CliTableError as err:\n        raise Exception(  # pylint: disable=broad-exception-raised\n            f'Unable to parse command \"{command}\" on platform {platform} - {str(err)}'\n        ) from err\n        # Invalid or Missing template\n        # module.fail_json(msg='parsing error', error=str(e))\n        # rather than fail, fallback to return raw text\n        # structured_data = [data]\n\n    return structured_data\n", "path": "ntc_templates/parse.py"}], "after_files": [{"content": "\"\"\"ntc_templates.parse.\"\"\"\n\nimport os\n\n# Due to TextFSM library issues on Windows, it is better to not fail on import\n# Instead fail at runtime (i.e. if method is actually used).\ntry:\n    from textfsm import clitable\n\n    HAS_CLITABLE = True\nexcept ImportError:\n    HAS_CLITABLE = False\n\n\nclass ParsingException(Exception):\n    \"\"\"Error that is raised when TextFSM hits an `Error` state.\"\"\"\n\n\ndef _get_template_dir():\n    template_dir = os.environ.get(\"NTC_TEMPLATES_DIR\")\n    if template_dir is None:\n        package_dir = os.path.dirname(__file__)\n        template_dir = os.path.join(package_dir, \"templates\")\n        if not os.path.isdir(template_dir):\n            project_dir = os.path.dirname(os.path.dirname(os.path.dirname(template_dir)))\n            template_dir = os.path.join(project_dir, \"templates\")\n\n    return template_dir\n\n\ndef _clitable_to_dict(cli_table):\n    \"\"\"Convert TextFSM cli_table object to list of dictionaries.\"\"\"\n    objs = []\n    for row in cli_table:\n        temp_dict = {}\n        for index, element in enumerate(row):\n            temp_dict[cli_table.header[index].lower()] = element\n        objs.append(temp_dict)\n\n    return objs\n\n\ndef parse_output(platform=None, command=None, data=None):\n    \"\"\"Return the structured data based on the output from a network device.\"\"\"\n    if not HAS_CLITABLE:\n        msg = \"\"\"\nThe TextFSM library is not currently supported on Windows. If you are NOT using Windows\nyou should be able to 'pip install textfsm' to fix this issue. If you are using Windows\nthen you will need to install the patch referenced here:\n\nhttps://github.com/google/textfsm/pull/82\n\n\"\"\"\n        raise ImportError(msg)\n\n    template_dir = _get_template_dir()\n    cli_table = clitable.CliTable(\"index\", template_dir)\n\n    attrs = {\"Command\": command, \"Platform\": platform}\n    try:\n        cli_table.ParseCmd(data, attrs)\n        structured_data = _clitable_to_dict(cli_table)\n    except clitable.CliTableError as err:\n        raise ParsingException(f'Unable to parse command \"{command}\" on platform {platform} - {str(err)}') from err\n        # Invalid or Missing template\n        # module.fail_json(msg='parsing error', error=str(e))\n        # rather than fail, fallback to return raw text\n        # structured_data = [data]\n\n    return structured_data\n", "path": "ntc_templates/parse.py"}]}