We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug] Punctuation restoration works incorrect
### Describe the bug

Punctuation restoration works incorrect.

### To Reproduce

```
from TTS.tts.utils.text.punctuation import Punctuation, _PUNC_IDX, PuncPosition

# original text "...i think i understand."
punctuator = Punctuation()
text = ['', 'i think i understand']
punctuation = [_PUNC_IDX(punc='...', position=PuncPosition.BEGIN), _PUNC_IDX(punc='.', position=PuncPosition.END)]
punctuator.restore(text, punctuation)

# result ["....", "i think i understand"]
```

### Expected behavior

result: `["...i think i understand."]`

### Logs

_No response_

### Environment

```shell
{
    "CUDA": {
        "GPU": [
            "NVIDIA RTX A6000"
        ],
        "available": true,
        "version": "11.8"
    },
    "Packages": {
        "PyTorch_debug": false,
        "PyTorch_version": "2.0.0+cu118",
        "TTS": "0.16.6",
        "numpy": "1.22.0"
    },
    "System": {
        "OS": "Linux",
        "architecture": [
            "64bit",
            ""
        ],
        "processor": "x86_64",
        "python": "3.10.12",
        "version": "#170-Ubuntu SMP Fri Jun 16 13:43:31 UTC 2023"
    }
}
```


### Additional context

_No response_

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `TTS/tts/utils/text/punctuation.py`
Content:
```
1 import collections
2 import re
3 from enum import Enum
4 
5 import six
6 
7 _DEF_PUNCS = ';:,.!?¡¿—…"«»“”'
8 
9 _PUNC_IDX = collections.namedtuple("_punc_index", ["punc", "position"])
10 
11 
12 class PuncPosition(Enum):
13     """Enum for the punctuations positions"""
14 
15     BEGIN = 0
16     END = 1
17     MIDDLE = 2
18     ALONE = 3
19 
20 
21 class Punctuation:
22     """Handle punctuations in text.
23 
24     Just strip punctuations from text or strip and restore them later.
25 
26     Args:
27         puncs (str): The punctuations to be processed. Defaults to `_DEF_PUNCS`.
28 
29     Example:
30         >>> punc = Punctuation()
31         >>> punc.strip("This is. example !")
32         'This is example'
33 
34         >>> text_striped, punc_map = punc.strip_to_restore("This is. example !")
35         >>> ' '.join(text_striped)
36         'This is example'
37 
38         >>> text_restored = punc.restore(text_striped, punc_map)
39         >>> text_restored[0]
40         'This is. example !'
41     """
42 
43     def __init__(self, puncs: str = _DEF_PUNCS):
44         self.puncs = puncs
45 
46     @staticmethod
47     def default_puncs():
48         """Return default set of punctuations."""
49         return _DEF_PUNCS
50 
51     @property
52     def puncs(self):
53         return self._puncs
54 
55     @puncs.setter
56     def puncs(self, value):
57         if not isinstance(value, six.string_types):
58             raise ValueError("[!] Punctuations must be of type str.")
59         self._puncs = "".join(list(dict.fromkeys(list(value))))  # remove duplicates without changing the oreder
60         self.puncs_regular_exp = re.compile(rf"(\s*[{re.escape(self._puncs)}]+\s*)+")
61 
62     def strip(self, text):
63         """Remove all the punctuations by replacing with `space`.
64 
65         Args:
66             text (str): The text to be processed.
67 
68         Example::
69 
70             "This is. example !" -> "This is example "
71         """
72         return re.sub(self.puncs_regular_exp, " ", text).rstrip().lstrip()
73 
74     def strip_to_restore(self, text):
75         """Remove punctuations from text to restore them later.
76 
77         Args:
78             text (str): The text to be processed.
79 
80         Examples ::
81 
82             "This is. example !" -> [["This is", "example"], [".", "!"]]
83 
84         """
85         text, puncs = self._strip_to_restore(text)
86         return text, puncs
87 
88     def _strip_to_restore(self, text):
89         """Auxiliary method for Punctuation.preserve()"""
90         matches = list(re.finditer(self.puncs_regular_exp, text))
91         if not matches:
92             return [text], []
93         # the text is only punctuations
94         if len(matches) == 1 and matches[0].group() == text:
95             return [], [_PUNC_IDX(text, PuncPosition.ALONE)]
96         # build a punctuation map to be used later to restore punctuations
97         puncs = []
98         for match in matches:
99             position = PuncPosition.MIDDLE
100             if match == matches[0] and text.startswith(match.group()):
101                 position = PuncPosition.BEGIN
102             elif match == matches[-1] and text.endswith(match.group()):
103                 position = PuncPosition.END
104             puncs.append(_PUNC_IDX(match.group(), position))
105         # convert str text to a List[str], each item is separated by a punctuation
106         splitted_text = []
107         for idx, punc in enumerate(puncs):
108             split = text.split(punc.punc)
109             prefix, suffix = split[0], punc.punc.join(split[1:])
110             splitted_text.append(prefix)
111             # if the text does not end with a punctuation, add it to the last item
112             if idx == len(puncs) - 1 and len(suffix) > 0:
113                 splitted_text.append(suffix)
114             text = suffix
115         return splitted_text, puncs
116 
117     @classmethod
118     def restore(cls, text, puncs):
119         """Restore punctuation in a text.
120 
121         Args:
122             text (str): The text to be processed.
123             puncs (List[str]): The list of punctuations map to be used for restoring.
124 
125         Examples ::
126 
127             ['This is', 'example'], ['.', '!'] -> "This is. example!"
128 
129         """
130         return cls._restore(text, puncs, 0)
131 
132     @classmethod
133     def _restore(cls, text, puncs, num):  # pylint: disable=too-many-return-statements
134         """Auxiliary method for Punctuation.restore()"""
135         if not puncs:
136             return text
137 
138         # nothing have been phonemized, returns the puncs alone
139         if not text:
140             return ["".join(m.punc for m in puncs)]
141 
142         current = puncs[0]
143 
144         if current.position == PuncPosition.BEGIN:
145             return cls._restore([current.punc + text[0]] + text[1:], puncs[1:], num)
146 
147         if current.position == PuncPosition.END:
148             return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:], num + 1)
149 
150         if current.position == PuncPosition.ALONE:
151             return [current.mark] + cls._restore(text, puncs[1:], num + 1)
152 
153         # POSITION == MIDDLE
154         if len(text) == 1:  # pragma: nocover
155             # a corner case where the final part of an intermediate
156             # mark (I) has not been phonemized
157             return cls._restore([text[0] + current.punc], puncs[1:], num)
158 
159         return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:], num)
160 
161 
162 # if __name__ == "__main__":
163 #     punc = Punctuation()
164 #     text = "This is. This is, example!"
165 
166 #     print(punc.strip(text))
167 
168 #     split_text, puncs = punc.strip_to_restore(text)
169 #     print(split_text, " ---- ", puncs)
170 
171 #     restored_text = punc.restore(split_text, puncs)
172 #     print(restored_text)
173
```
--- 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/TTS/tts/utils/text/punctuation.py b/TTS/tts/utils/text/punctuation.py
--- a/TTS/tts/utils/text/punctuation.py
+++ b/TTS/tts/utils/text/punctuation.py
@@ -15,7 +15,6 @@
     BEGIN = 0
     END = 1
     MIDDLE = 2
-    ALONE = 3
 
 
 class Punctuation:
@@ -92,7 +91,7 @@
             return [text], []
         # the text is only punctuations
         if len(matches) == 1 and matches[0].group() == text:
-            return [], [_PUNC_IDX(text, PuncPosition.ALONE)]
+            return [], [_PUNC_IDX(text, PuncPosition.BEGIN)]
         # build a punctuation map to be used later to restore punctuations
         puncs = []
         for match in matches:
@@ -107,11 +106,14 @@
         for idx, punc in enumerate(puncs):
             split = text.split(punc.punc)
             prefix, suffix = split[0], punc.punc.join(split[1:])
+            text = suffix
+            if prefix == "":
+                # We don't want to insert an empty string in case of initial punctuation
+                continue
             splitted_text.append(prefix)
             # if the text does not end with a punctuation, add it to the last item
             if idx == len(puncs) - 1 and len(suffix) > 0:
                 splitted_text.append(suffix)
-            text = suffix
         return splitted_text, puncs
 
     @classmethod
@@ -127,10 +129,10 @@
             ['This is', 'example'], ['.', '!'] -> "This is. example!"
 
         """
-        return cls._restore(text, puncs, 0)
+        return cls._restore(text, puncs)
 
     @classmethod
-    def _restore(cls, text, puncs, num):  # pylint: disable=too-many-return-statements
+    def _restore(cls, text, puncs):  # pylint: disable=too-many-return-statements
         """Auxiliary method for Punctuation.restore()"""
         if not puncs:
             return text
@@ -142,21 +144,18 @@
         current = puncs[0]
 
         if current.position == PuncPosition.BEGIN:
-            return cls._restore([current.punc + text[0]] + text[1:], puncs[1:], num)
+            return cls._restore([current.punc + text[0]] + text[1:], puncs[1:])
 
         if current.position == PuncPosition.END:
-            return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:], num + 1)
-
-        if current.position == PuncPosition.ALONE:
-            return [current.mark] + cls._restore(text, puncs[1:], num + 1)
+            return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:])
 
         # POSITION == MIDDLE
         if len(text) == 1:  # pragma: nocover
             # a corner case where the final part of an intermediate
             # mark (I) has not been phonemized
-            return cls._restore([text[0] + current.punc], puncs[1:], num)
+            return cls._restore([text[0] + current.punc], puncs[1:])
 
-        return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:], num)
+        return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:])
 
 
 # if __name__ == "__main__":

{"golden_diff": "diff --git a/TTS/tts/utils/text/punctuation.py b/TTS/tts/utils/text/punctuation.py\n--- a/TTS/tts/utils/text/punctuation.py\n+++ b/TTS/tts/utils/text/punctuation.py\n@@ -15,7 +15,6 @@\n     BEGIN = 0\n     END = 1\n     MIDDLE = 2\n-    ALONE = 3\n \n \n class Punctuation:\n@@ -92,7 +91,7 @@\n             return [text], []\n         # the text is only punctuations\n         if len(matches) == 1 and matches[0].group() == text:\n-            return [], [_PUNC_IDX(text, PuncPosition.ALONE)]\n+            return [], [_PUNC_IDX(text, PuncPosition.BEGIN)]\n         # build a punctuation map to be used later to restore punctuations\n         puncs = []\n         for match in matches:\n@@ -107,11 +106,14 @@\n         for idx, punc in enumerate(puncs):\n             split = text.split(punc.punc)\n             prefix, suffix = split[0], punc.punc.join(split[1:])\n+            text = suffix\n+            if prefix == \"\":\n+                # We don't want to insert an empty string in case of initial punctuation\n+                continue\n             splitted_text.append(prefix)\n             # if the text does not end with a punctuation, add it to the last item\n             if idx == len(puncs) - 1 and len(suffix) > 0:\n                 splitted_text.append(suffix)\n-            text = suffix\n         return splitted_text, puncs\n \n     @classmethod\n@@ -127,10 +129,10 @@\n             ['This is', 'example'], ['.', '!'] -> \"This is. example!\"\n \n         \"\"\"\n-        return cls._restore(text, puncs, 0)\n+        return cls._restore(text, puncs)\n \n     @classmethod\n-    def _restore(cls, text, puncs, num):  # pylint: disable=too-many-return-statements\n+    def _restore(cls, text, puncs):  # pylint: disable=too-many-return-statements\n         \"\"\"Auxiliary method for Punctuation.restore()\"\"\"\n         if not puncs:\n             return text\n@@ -142,21 +144,18 @@\n         current = puncs[0]\n \n         if current.position == PuncPosition.BEGIN:\n-            return cls._restore([current.punc + text[0]] + text[1:], puncs[1:], num)\n+            return cls._restore([current.punc + text[0]] + text[1:], puncs[1:])\n \n         if current.position == PuncPosition.END:\n-            return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:], num + 1)\n-\n-        if current.position == PuncPosition.ALONE:\n-            return [current.mark] + cls._restore(text, puncs[1:], num + 1)\n+            return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:])\n \n         # POSITION == MIDDLE\n         if len(text) == 1:  # pragma: nocover\n             # a corner case where the final part of an intermediate\n             # mark (I) has not been phonemized\n-            return cls._restore([text[0] + current.punc], puncs[1:], num)\n+            return cls._restore([text[0] + current.punc], puncs[1:])\n \n-        return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:], num)\n+        return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:])\n \n \n # if __name__ == \"__main__\":\n", "issue": "[Bug] Punctuation restoration works incorrect\n### Describe the bug\n\nPunctuation restoration works incorrect.\n\n### To Reproduce\n\n```\r\nfrom TTS.tts.utils.text.punctuation import Punctuation, _PUNC_IDX, PuncPosition\r\n\r\n# original text \"...i think i understand.\"\r\npunctuator = Punctuation()\r\ntext = ['', 'i think i understand']\r\npunctuation = [_PUNC_IDX(punc='...', position=PuncPosition.BEGIN), _PUNC_IDX(punc='.', position=PuncPosition.END)]\r\npunctuator.restore(text, punctuation)\r\n\r\n# result [\"....\", \"i think i understand\"]\r\n```\n\n### Expected behavior\n\nresult: `[\"...i think i understand.\"]`\n\n### Logs\n\n_No response_\n\n### Environment\n\n```shell\n{\r\n    \"CUDA\": {\r\n        \"GPU\": [\r\n            \"NVIDIA RTX A6000\"\r\n        ],\r\n        \"available\": true,\r\n        \"version\": \"11.8\"\r\n    },\r\n    \"Packages\": {\r\n        \"PyTorch_debug\": false,\r\n        \"PyTorch_version\": \"2.0.0+cu118\",\r\n        \"TTS\": \"0.16.6\",\r\n        \"numpy\": \"1.22.0\"\r\n    },\r\n    \"System\": {\r\n        \"OS\": \"Linux\",\r\n        \"architecture\": [\r\n            \"64bit\",\r\n            \"\"\r\n        ],\r\n        \"processor\": \"x86_64\",\r\n        \"python\": \"3.10.12\",\r\n        \"version\": \"#170-Ubuntu SMP Fri Jun 16 13:43:31 UTC 2023\"\r\n    }\r\n}\n```\n\n\n### Additional context\n\n_No response_\n", "before_files": [{"content": "import collections\nimport re\nfrom enum import Enum\n\nimport six\n\n_DEF_PUNCS = ';:,.!?\u00a1\u00bf\u2014\u2026\"\u00ab\u00bb\u201c\u201d'\n\n_PUNC_IDX = collections.namedtuple(\"_punc_index\", [\"punc\", \"position\"])\n\n\nclass PuncPosition(Enum):\n    \"\"\"Enum for the punctuations positions\"\"\"\n\n    BEGIN = 0\n    END = 1\n    MIDDLE = 2\n    ALONE = 3\n\n\nclass Punctuation:\n    \"\"\"Handle punctuations in text.\n\n    Just strip punctuations from text or strip and restore them later.\n\n    Args:\n        puncs (str): The punctuations to be processed. Defaults to `_DEF_PUNCS`.\n\n    Example:\n        >>> punc = Punctuation()\n        >>> punc.strip(\"This is. example !\")\n        'This is example'\n\n        >>> text_striped, punc_map = punc.strip_to_restore(\"This is. example !\")\n        >>> ' '.join(text_striped)\n        'This is example'\n\n        >>> text_restored = punc.restore(text_striped, punc_map)\n        >>> text_restored[0]\n        'This is. example !'\n    \"\"\"\n\n    def __init__(self, puncs: str = _DEF_PUNCS):\n        self.puncs = puncs\n\n    @staticmethod\n    def default_puncs():\n        \"\"\"Return default set of punctuations.\"\"\"\n        return _DEF_PUNCS\n\n    @property\n    def puncs(self):\n        return self._puncs\n\n    @puncs.setter\n    def puncs(self, value):\n        if not isinstance(value, six.string_types):\n            raise ValueError(\"[!] Punctuations must be of type str.\")\n        self._puncs = \"\".join(list(dict.fromkeys(list(value))))  # remove duplicates without changing the oreder\n        self.puncs_regular_exp = re.compile(rf\"(\\s*[{re.escape(self._puncs)}]+\\s*)+\")\n\n    def strip(self, text):\n        \"\"\"Remove all the punctuations by replacing with `space`.\n\n        Args:\n            text (str): The text to be processed.\n\n        Example::\n\n            \"This is. example !\" -> \"This is example \"\n        \"\"\"\n        return re.sub(self.puncs_regular_exp, \" \", text).rstrip().lstrip()\n\n    def strip_to_restore(self, text):\n        \"\"\"Remove punctuations from text to restore them later.\n\n        Args:\n            text (str): The text to be processed.\n\n        Examples ::\n\n            \"This is. example !\" -> [[\"This is\", \"example\"], [\".\", \"!\"]]\n\n        \"\"\"\n        text, puncs = self._strip_to_restore(text)\n        return text, puncs\n\n    def _strip_to_restore(self, text):\n        \"\"\"Auxiliary method for Punctuation.preserve()\"\"\"\n        matches = list(re.finditer(self.puncs_regular_exp, text))\n        if not matches:\n            return [text], []\n        # the text is only punctuations\n        if len(matches) == 1 and matches[0].group() == text:\n            return [], [_PUNC_IDX(text, PuncPosition.ALONE)]\n        # build a punctuation map to be used later to restore punctuations\n        puncs = []\n        for match in matches:\n            position = PuncPosition.MIDDLE\n            if match == matches[0] and text.startswith(match.group()):\n                position = PuncPosition.BEGIN\n            elif match == matches[-1] and text.endswith(match.group()):\n                position = PuncPosition.END\n            puncs.append(_PUNC_IDX(match.group(), position))\n        # convert str text to a List[str], each item is separated by a punctuation\n        splitted_text = []\n        for idx, punc in enumerate(puncs):\n            split = text.split(punc.punc)\n            prefix, suffix = split[0], punc.punc.join(split[1:])\n            splitted_text.append(prefix)\n            # if the text does not end with a punctuation, add it to the last item\n            if idx == len(puncs) - 1 and len(suffix) > 0:\n                splitted_text.append(suffix)\n            text = suffix\n        return splitted_text, puncs\n\n    @classmethod\n    def restore(cls, text, puncs):\n        \"\"\"Restore punctuation in a text.\n\n        Args:\n            text (str): The text to be processed.\n            puncs (List[str]): The list of punctuations map to be used for restoring.\n\n        Examples ::\n\n            ['This is', 'example'], ['.', '!'] -> \"This is. example!\"\n\n        \"\"\"\n        return cls._restore(text, puncs, 0)\n\n    @classmethod\n    def _restore(cls, text, puncs, num):  # pylint: disable=too-many-return-statements\n        \"\"\"Auxiliary method for Punctuation.restore()\"\"\"\n        if not puncs:\n            return text\n\n        # nothing have been phonemized, returns the puncs alone\n        if not text:\n            return [\"\".join(m.punc for m in puncs)]\n\n        current = puncs[0]\n\n        if current.position == PuncPosition.BEGIN:\n            return cls._restore([current.punc + text[0]] + text[1:], puncs[1:], num)\n\n        if current.position == PuncPosition.END:\n            return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:], num + 1)\n\n        if current.position == PuncPosition.ALONE:\n            return [current.mark] + cls._restore(text, puncs[1:], num + 1)\n\n        # POSITION == MIDDLE\n        if len(text) == 1:  # pragma: nocover\n            # a corner case where the final part of an intermediate\n            # mark (I) has not been phonemized\n            return cls._restore([text[0] + current.punc], puncs[1:], num)\n\n        return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:], num)\n\n\n# if __name__ == \"__main__\":\n#     punc = Punctuation()\n#     text = \"This is. This is, example!\"\n\n#     print(punc.strip(text))\n\n#     split_text, puncs = punc.strip_to_restore(text)\n#     print(split_text, \" ---- \", puncs)\n\n#     restored_text = punc.restore(split_text, puncs)\n#     print(restored_text)\n", "path": "TTS/tts/utils/text/punctuation.py"}], "after_files": [{"content": "import collections\nimport re\nfrom enum import Enum\n\nimport six\n\n_DEF_PUNCS = ';:,.!?\u00a1\u00bf\u2014\u2026\"\u00ab\u00bb\u201c\u201d'\n\n_PUNC_IDX = collections.namedtuple(\"_punc_index\", [\"punc\", \"position\"])\n\n\nclass PuncPosition(Enum):\n    \"\"\"Enum for the punctuations positions\"\"\"\n\n    BEGIN = 0\n    END = 1\n    MIDDLE = 2\n\n\nclass Punctuation:\n    \"\"\"Handle punctuations in text.\n\n    Just strip punctuations from text or strip and restore them later.\n\n    Args:\n        puncs (str): The punctuations to be processed. Defaults to `_DEF_PUNCS`.\n\n    Example:\n        >>> punc = Punctuation()\n        >>> punc.strip(\"This is. example !\")\n        'This is example'\n\n        >>> text_striped, punc_map = punc.strip_to_restore(\"This is. example !\")\n        >>> ' '.join(text_striped)\n        'This is example'\n\n        >>> text_restored = punc.restore(text_striped, punc_map)\n        >>> text_restored[0]\n        'This is. example !'\n    \"\"\"\n\n    def __init__(self, puncs: str = _DEF_PUNCS):\n        self.puncs = puncs\n\n    @staticmethod\n    def default_puncs():\n        \"\"\"Return default set of punctuations.\"\"\"\n        return _DEF_PUNCS\n\n    @property\n    def puncs(self):\n        return self._puncs\n\n    @puncs.setter\n    def puncs(self, value):\n        if not isinstance(value, six.string_types):\n            raise ValueError(\"[!] Punctuations must be of type str.\")\n        self._puncs = \"\".join(list(dict.fromkeys(list(value))))  # remove duplicates without changing the oreder\n        self.puncs_regular_exp = re.compile(rf\"(\\s*[{re.escape(self._puncs)}]+\\s*)+\")\n\n    def strip(self, text):\n        \"\"\"Remove all the punctuations by replacing with `space`.\n\n        Args:\n            text (str): The text to be processed.\n\n        Example::\n\n            \"This is. example !\" -> \"This is example \"\n        \"\"\"\n        return re.sub(self.puncs_regular_exp, \" \", text).rstrip().lstrip()\n\n    def strip_to_restore(self, text):\n        \"\"\"Remove punctuations from text to restore them later.\n\n        Args:\n            text (str): The text to be processed.\n\n        Examples ::\n\n            \"This is. example !\" -> [[\"This is\", \"example\"], [\".\", \"!\"]]\n\n        \"\"\"\n        text, puncs = self._strip_to_restore(text)\n        return text, puncs\n\n    def _strip_to_restore(self, text):\n        \"\"\"Auxiliary method for Punctuation.preserve()\"\"\"\n        matches = list(re.finditer(self.puncs_regular_exp, text))\n        if not matches:\n            return [text], []\n        # the text is only punctuations\n        if len(matches) == 1 and matches[0].group() == text:\n            return [], [_PUNC_IDX(text, PuncPosition.BEGIN)]\n        # build a punctuation map to be used later to restore punctuations\n        puncs = []\n        for match in matches:\n            position = PuncPosition.MIDDLE\n            if match == matches[0] and text.startswith(match.group()):\n                position = PuncPosition.BEGIN\n            elif match == matches[-1] and text.endswith(match.group()):\n                position = PuncPosition.END\n            puncs.append(_PUNC_IDX(match.group(), position))\n        # convert str text to a List[str], each item is separated by a punctuation\n        splitted_text = []\n        for idx, punc in enumerate(puncs):\n            split = text.split(punc.punc)\n            prefix, suffix = split[0], punc.punc.join(split[1:])\n            text = suffix\n            if prefix == \"\":\n                # We don't want to insert an empty string in case of initial punctuation\n                continue\n            splitted_text.append(prefix)\n            # if the text does not end with a punctuation, add it to the last item\n            if idx == len(puncs) - 1 and len(suffix) > 0:\n                splitted_text.append(suffix)\n        return splitted_text, puncs\n\n    @classmethod\n    def restore(cls, text, puncs):\n        \"\"\"Restore punctuation in a text.\n\n        Args:\n            text (str): The text to be processed.\n            puncs (List[str]): The list of punctuations map to be used for restoring.\n\n        Examples ::\n\n            ['This is', 'example'], ['.', '!'] -> \"This is. example!\"\n\n        \"\"\"\n        return cls._restore(text, puncs)\n\n    @classmethod\n    def _restore(cls, text, puncs):  # pylint: disable=too-many-return-statements\n        \"\"\"Auxiliary method for Punctuation.restore()\"\"\"\n        if not puncs:\n            return text\n\n        # nothing have been phonemized, returns the puncs alone\n        if not text:\n            return [\"\".join(m.punc for m in puncs)]\n\n        current = puncs[0]\n\n        if current.position == PuncPosition.BEGIN:\n            return cls._restore([current.punc + text[0]] + text[1:], puncs[1:])\n\n        if current.position == PuncPosition.END:\n            return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:])\n\n        # POSITION == MIDDLE\n        if len(text) == 1:  # pragma: nocover\n            # a corner case where the final part of an intermediate\n            # mark (I) has not been phonemized\n            return cls._restore([text[0] + current.punc], puncs[1:])\n\n        return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:])\n\n\n# if __name__ == \"__main__\":\n#     punc = Punctuation()\n#     text = \"This is. This is, example!\"\n\n#     print(punc.strip(text))\n\n#     split_text, puncs = punc.strip_to_restore(text)\n#     print(split_text, \" ---- \", puncs)\n\n#     restored_text = punc.restore(split_text, puncs)\n#     print(restored_text)\n", "path": "TTS/tts/utils/text/punctuation.py"}]}