We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
sub2po - Can't find headers file
On a fresh install of python 3.8 in a new virtualenv, I get the following error:

```
(ttk) C:\dev\translate-toolkit>sub2po -P "C:\dev\translate-toolkit\DA Launch Trailer.ass" "C:\dev\translate-toolkit\trailer.pot"
processing 1 files...
Failed to read file 'C:\Users\Sim\Envs\ttk\lib\site-packages\data\headers\ass': No such file or directory
sub2po: WARNING: Error processing: input C:\dev\translate-toolkit\DA Launch Trailer.ass, output C:\dev\translate-toolkit\trailer.pot, template None: FileNotFoundError(2, 'No such file or directory')
[###########################################] 100%
```

I suspect there is a package required that I have not installed and did not see in the install docs, but maybe it is something else?

I have installed aeidon; here is my package list:

```
(ttk) C:\dev\translate-toolkit>pip list
Package           Version
----------------- ---------
aeidon            1.7.0
ass               0.5.1
certifi           2020.6.20
chardet           3.0.4
idna              2.10
iniparse          0.5
inotify           0.2.10
lxml              4.6.1
nose              1.3.7
pip               20.2.4
requests          2.24.0
setuptools        50.3.2
six               1.15.0
srt               3.4.1
subtitle          2.1
translate-toolkit 3.1.1
urllib3           1.25.11
wheel             0.35.1
```

FYI, [I had the same error](https://github.com/WeblateOrg/weblate/issues/4732) in a linux environment when trying to do this via Weblate.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `translate/storage/subtitles.py`
Content:
```
1 #
2 # Copyright 2008-2009 Zuza Software Foundation
3 #
4 # This file is part of translate.
5 #
6 # translate is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # translate is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, see <http://www.gnu.org/licenses/>.
18 
19 """Class that manages subtitle files for translation.
20 
21 This class makes use of the subtitle functionality of ``gaupol``.
22 
23 .. seealso:: gaupol/agents/open.py::open_main
24 
25 A patch to gaupol is required to open utf-8 files successfully.
26 """
27 
28 import os
29 from io import StringIO
30 from tempfile import NamedTemporaryFile
31 
32 from translate.storage import base
33 
34 
35 try:
36     from aeidon import Subtitle, documents, newlines
37     from aeidon.encodings import detect
38     from aeidon.files import AdvSubStationAlpha, MicroDVD, SubRip, SubStationAlpha, new
39     from aeidon.util import detect_format as determine
40 except ImportError:
41     try:
42         from gaupol import FormatDeterminer, documents
43         from gaupol.encodings import detect
44         from gaupol.files import (
45             AdvSubStationAlpha,
46             MicroDVD,
47             SubRip,
48             SubStationAlpha,
49             new,
50         )
51         from gaupol.newlines import newlines
52         from gaupol.subtitle import Subtitle
53 
54         _determiner = FormatDeterminer()
55         determine = _determiner.determine
56     except ImportError:
57         raise ImportError("\naeidon or gaupol package required for Subtitle support")
58 
59 
60 class SubtitleUnit(base.TranslationUnit):
61     """A subtitle entry that is translatable"""
62 
63     def __init__(self, source=None, **kwargs):
64         self._start = "00:00:00.000"
65         self._end = "00:00:00.000"
66         self._duration = 0.0
67         if source:
68             self.source = source
69             self.target = source
70         super().__init__(source)
71 
72     def getnotes(self, origin=None):
73         if origin in ["programmer", "developer", "source code", None]:
74             return "visible for %d seconds" % self._duration
75         else:
76             return ""
77 
78     def getlocations(self):
79         return [f"{self._start}-->{self._end}"]
80 
81     def getid(self):
82         return self.getlocations()[0]
83 
84 
85 class SubtitleFile(base.TranslationStore):
86     """A subtitle file"""
87 
88     UnitClass = SubtitleUnit
89 
90     def __init__(self, inputfile=None, **kwargs):
91         """construct an Subtitle file, optionally reading in from inputfile."""
92         super().__init__(**kwargs)
93         self.filename = None
94         self._subtitlefile = None
95         if inputfile is not None:
96             self._parsefile(inputfile)
97 
98     def serialize(self, out):
99         subtitles = []
100         for unit in self.units:
101             subtitle = Subtitle()
102             subtitle.main_text = unit.target or unit.source
103             subtitle.start = unit._start
104             subtitle.end = unit._end
105             subtitles.append(subtitle)
106         # Using transient output might be dropped if/when we have more control
107         # over the open mode of out files.
108         output = StringIO()
109         self._subtitlefile.write_to_file(subtitles, documents.MAIN, output)
110         out.write(output.getvalue().encode(self._subtitlefile.encoding))
111 
112     def _parse(self):
113         try:
114             self.encoding = detect(self.filename)
115             self._format = determine(self.filename, self.encoding)
116             self._subtitlefile = new(self._format, self.filename, self.encoding)
117             for subtitle in self._subtitlefile.read():
118                 newunit = self.addsourceunit(subtitle.main_text)
119                 newunit._start = subtitle.start
120                 newunit._end = subtitle.end
121                 newunit._duration = subtitle.duration_seconds
122         except Exception as e:
123             raise base.ParseError(e)
124 
125     def _parsefile(self, storefile):
126         if hasattr(storefile, "name"):
127             self.filename = storefile.name
128             storefile.close()
129         elif hasattr(storefile, "filename"):
130             self.filename = storefile.filename
131             storefile.close()
132         elif isinstance(storefile, str):
133             self.filename = storefile
134 
135         if self.filename and os.path.exists(self.filename):
136             self._parse()
137         else:
138             self.parse(storefile.read())
139 
140     @classmethod
141     def parsefile(cls, storefile):
142         """parse the given file"""
143         newstore = cls()
144         newstore._parsefile(storefile)
145         return newstore
146 
147     def parse(self, input):
148         if isinstance(input, bytes):
149             # Gaupol does not allow parsing from strings
150             kwargs = {"delete": False}
151             if self.filename:
152                 kwargs["suffix"] = self.filename
153 
154             temp_file = NamedTemporaryFile(**kwargs)
155             temp_file.close()
156 
157             try:
158                 with open(temp_file.name, "wb") as fh:
159                     fh.write(input)
160                 self._parsefile(temp_file.name)
161             finally:
162                 os.unlink(temp_file.name)
163         else:
164             self._parsefile(input)
165 
166 
167 ############# format specific classes ###################
168 
169 # the generic SubtitleFile can adapt to any format, but only the
170 # specilized classes can be used to construct a new file
171 
172 
173 class SubRipFile(SubtitleFile):
174     """specialized class for SubRipFile's only"""
175 
176     Name = "SubRip subtitles file"
177     Extensions = ["srt"]
178 
179     def __init__(self, *args, **kwargs):
180         super().__init__(*args, **kwargs)
181         if self._subtitlefile is None:
182             self._subtitlefile = SubRip(self.filename or "", self.encoding)
183         if self._subtitlefile.newline is None:
184             self._subtitlefile.newline = newlines.UNIX
185 
186 
187 class MicroDVDFile(SubtitleFile):
188     """specialized class for SubRipFile's only"""
189 
190     Name = "MicroDVD subtitles file"
191     Extensions = ["sub"]
192 
193     def __init__(self, *args, **kwargs):
194         super().__init__(*args, **kwargs)
195         if self._subtitlefile is None:
196             self._subtitlefile = MicroDVD(self.filename or "", self.encoding)
197         if self._subtitlefile.newline is None:
198             self._subtitlefile.newline = newlines.UNIX
199 
200 
201 class AdvSubStationAlphaFile(SubtitleFile):
202     """specialized class for SubRipFile's only"""
203 
204     Name = "Advanced Substation Alpha subtitles file"
205     Extensions = ["ass"]
206 
207     def __init__(self, *args, **kwargs):
208         super().__init__(*args, **kwargs)
209         if self._subtitlefile is None:
210             self._subtitlefile = AdvSubStationAlpha(self.filename or "", self.encoding)
211         if self._subtitlefile.newline is None:
212             self._subtitlefile.newline = newlines.UNIX
213 
214 
215 class SubStationAlphaFile(SubtitleFile):
216     """specialized class for SubRipFile's only"""
217 
218     Name = "Substation Alpha subtitles file"
219     Extensions = ["ssa"]
220 
221     def __init__(self, *args, **kwargs):
222         super().__init__(*args, **kwargs)
223         if self._subtitlefile is None:
224             self._subtitlefile = SubStationAlpha(self.filename or "", self.encoding)
225         if self._subtitlefile.newline is None:
226             self._subtitlefile.newline = newlines.UNIX
227
```
--- 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/translate/storage/subtitles.py b/translate/storage/subtitles.py
--- a/translate/storage/subtitles.py
+++ b/translate/storage/subtitles.py
@@ -60,9 +60,11 @@
 class SubtitleUnit(base.TranslationUnit):
     """A subtitle entry that is translatable"""
 
+    init_time = "00:00:00.000"
+
     def __init__(self, source=None, **kwargs):
-        self._start = "00:00:00.000"
-        self._end = "00:00:00.000"
+        self._start = self.init_time
+        self._end = self.init_time
         self._duration = 0.0
         if source:
             self.source = source
@@ -82,6 +84,12 @@
         return self.getlocations()[0]
 
 
+class MicroDVDUnit(SubtitleUnit):
+    """MicroDVD unit, it uses frames instead of time as start/end."""
+
+    init_time = 0
+
+
 class SubtitleFile(base.TranslationStore):
     """A subtitle file"""
 
@@ -189,6 +197,7 @@
 
     Name = "MicroDVD subtitles file"
     Extensions = ["sub"]
+    UnitClass = MicroDVDUnit
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)

{"golden_diff": "diff --git a/translate/storage/subtitles.py b/translate/storage/subtitles.py\n--- a/translate/storage/subtitles.py\n+++ b/translate/storage/subtitles.py\n@@ -60,9 +60,11 @@\n class SubtitleUnit(base.TranslationUnit):\n     \"\"\"A subtitle entry that is translatable\"\"\"\n \n+    init_time = \"00:00:00.000\"\n+\n     def __init__(self, source=None, **kwargs):\n-        self._start = \"00:00:00.000\"\n-        self._end = \"00:00:00.000\"\n+        self._start = self.init_time\n+        self._end = self.init_time\n         self._duration = 0.0\n         if source:\n             self.source = source\n@@ -82,6 +84,12 @@\n         return self.getlocations()[0]\n \n \n+class MicroDVDUnit(SubtitleUnit):\n+    \"\"\"MicroDVD unit, it uses frames instead of time as start/end.\"\"\"\n+\n+    init_time = 0\n+\n+\n class SubtitleFile(base.TranslationStore):\n     \"\"\"A subtitle file\"\"\"\n \n@@ -189,6 +197,7 @@\n \n     Name = \"MicroDVD subtitles file\"\n     Extensions = [\"sub\"]\n+    UnitClass = MicroDVDUnit\n \n     def __init__(self, *args, **kwargs):\n         super().__init__(*args, **kwargs)\n", "issue": "sub2po - Can't find headers file\nOn a fresh install of python 3.8 in a new virtualenv, I get the following error:\r\n\r\n```\r\n(ttk) C:\\dev\\translate-toolkit>sub2po -P \"C:\\dev\\translate-toolkit\\DA Launch Trailer.ass\" \"C:\\dev\\translate-toolkit\\trailer.pot\"\r\nprocessing 1 files...\r\nFailed to read file 'C:\\Users\\Sim\\Envs\\ttk\\lib\\site-packages\\data\\headers\\ass': No such file or directory\r\nsub2po: WARNING: Error processing: input C:\\dev\\translate-toolkit\\DA Launch Trailer.ass, output C:\\dev\\translate-toolkit\\trailer.pot, template None: FileNotFoundError(2, 'No such file or directory')\r\n[###########################################] 100%\r\n```\r\n\r\nI suspect there is a package required that I have not installed and did not see in the install docs, but maybe it is something else?\r\n\r\nI have installed aeidon; here is my package list:\r\n\r\n```\r\n(ttk) C:\\dev\\translate-toolkit>pip list\r\nPackage           Version\r\n----------------- ---------\r\naeidon            1.7.0\r\nass               0.5.1\r\ncertifi           2020.6.20\r\nchardet           3.0.4\r\nidna              2.10\r\niniparse          0.5\r\ninotify           0.2.10\r\nlxml              4.6.1\r\nnose              1.3.7\r\npip               20.2.4\r\nrequests          2.24.0\r\nsetuptools        50.3.2\r\nsix               1.15.0\r\nsrt               3.4.1\r\nsubtitle          2.1\r\ntranslate-toolkit 3.1.1\r\nurllib3           1.25.11\r\nwheel             0.35.1\r\n```\r\n\r\nFYI, [I had the same error](https://github.com/WeblateOrg/weblate/issues/4732) in a linux environment when trying to do this via Weblate.\n", "before_files": [{"content": "#\n# Copyright 2008-2009 Zuza Software Foundation\n#\n# This file is part of translate.\n#\n# translate is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# translate is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Class that manages subtitle files for translation.\n\nThis class makes use of the subtitle functionality of ``gaupol``.\n\n.. seealso:: gaupol/agents/open.py::open_main\n\nA patch to gaupol is required to open utf-8 files successfully.\n\"\"\"\n\nimport os\nfrom io import StringIO\nfrom tempfile import NamedTemporaryFile\n\nfrom translate.storage import base\n\n\ntry:\n    from aeidon import Subtitle, documents, newlines\n    from aeidon.encodings import detect\n    from aeidon.files import AdvSubStationAlpha, MicroDVD, SubRip, SubStationAlpha, new\n    from aeidon.util import detect_format as determine\nexcept ImportError:\n    try:\n        from gaupol import FormatDeterminer, documents\n        from gaupol.encodings import detect\n        from gaupol.files import (\n            AdvSubStationAlpha,\n            MicroDVD,\n            SubRip,\n            SubStationAlpha,\n            new,\n        )\n        from gaupol.newlines import newlines\n        from gaupol.subtitle import Subtitle\n\n        _determiner = FormatDeterminer()\n        determine = _determiner.determine\n    except ImportError:\n        raise ImportError(\"\\naeidon or gaupol package required for Subtitle support\")\n\n\nclass SubtitleUnit(base.TranslationUnit):\n    \"\"\"A subtitle entry that is translatable\"\"\"\n\n    def __init__(self, source=None, **kwargs):\n        self._start = \"00:00:00.000\"\n        self._end = \"00:00:00.000\"\n        self._duration = 0.0\n        if source:\n            self.source = source\n            self.target = source\n        super().__init__(source)\n\n    def getnotes(self, origin=None):\n        if origin in [\"programmer\", \"developer\", \"source code\", None]:\n            return \"visible for %d seconds\" % self._duration\n        else:\n            return \"\"\n\n    def getlocations(self):\n        return [f\"{self._start}-->{self._end}\"]\n\n    def getid(self):\n        return self.getlocations()[0]\n\n\nclass SubtitleFile(base.TranslationStore):\n    \"\"\"A subtitle file\"\"\"\n\n    UnitClass = SubtitleUnit\n\n    def __init__(self, inputfile=None, **kwargs):\n        \"\"\"construct an Subtitle file, optionally reading in from inputfile.\"\"\"\n        super().__init__(**kwargs)\n        self.filename = None\n        self._subtitlefile = None\n        if inputfile is not None:\n            self._parsefile(inputfile)\n\n    def serialize(self, out):\n        subtitles = []\n        for unit in self.units:\n            subtitle = Subtitle()\n            subtitle.main_text = unit.target or unit.source\n            subtitle.start = unit._start\n            subtitle.end = unit._end\n            subtitles.append(subtitle)\n        # Using transient output might be dropped if/when we have more control\n        # over the open mode of out files.\n        output = StringIO()\n        self._subtitlefile.write_to_file(subtitles, documents.MAIN, output)\n        out.write(output.getvalue().encode(self._subtitlefile.encoding))\n\n    def _parse(self):\n        try:\n            self.encoding = detect(self.filename)\n            self._format = determine(self.filename, self.encoding)\n            self._subtitlefile = new(self._format, self.filename, self.encoding)\n            for subtitle in self._subtitlefile.read():\n                newunit = self.addsourceunit(subtitle.main_text)\n                newunit._start = subtitle.start\n                newunit._end = subtitle.end\n                newunit._duration = subtitle.duration_seconds\n        except Exception as e:\n            raise base.ParseError(e)\n\n    def _parsefile(self, storefile):\n        if hasattr(storefile, \"name\"):\n            self.filename = storefile.name\n            storefile.close()\n        elif hasattr(storefile, \"filename\"):\n            self.filename = storefile.filename\n            storefile.close()\n        elif isinstance(storefile, str):\n            self.filename = storefile\n\n        if self.filename and os.path.exists(self.filename):\n            self._parse()\n        else:\n            self.parse(storefile.read())\n\n    @classmethod\n    def parsefile(cls, storefile):\n        \"\"\"parse the given file\"\"\"\n        newstore = cls()\n        newstore._parsefile(storefile)\n        return newstore\n\n    def parse(self, input):\n        if isinstance(input, bytes):\n            # Gaupol does not allow parsing from strings\n            kwargs = {\"delete\": False}\n            if self.filename:\n                kwargs[\"suffix\"] = self.filename\n\n            temp_file = NamedTemporaryFile(**kwargs)\n            temp_file.close()\n\n            try:\n                with open(temp_file.name, \"wb\") as fh:\n                    fh.write(input)\n                self._parsefile(temp_file.name)\n            finally:\n                os.unlink(temp_file.name)\n        else:\n            self._parsefile(input)\n\n\n############# format specific classes ###################\n\n# the generic SubtitleFile can adapt to any format, but only the\n# specilized classes can be used to construct a new file\n\n\nclass SubRipFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"SubRip subtitles file\"\n    Extensions = [\"srt\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = SubRip(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n\n\nclass MicroDVDFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"MicroDVD subtitles file\"\n    Extensions = [\"sub\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = MicroDVD(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n\n\nclass AdvSubStationAlphaFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"Advanced Substation Alpha subtitles file\"\n    Extensions = [\"ass\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = AdvSubStationAlpha(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n\n\nclass SubStationAlphaFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"Substation Alpha subtitles file\"\n    Extensions = [\"ssa\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = SubStationAlpha(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n", "path": "translate/storage/subtitles.py"}], "after_files": [{"content": "#\n# Copyright 2008-2009 Zuza Software Foundation\n#\n# This file is part of translate.\n#\n# translate is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# translate is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Class that manages subtitle files for translation.\n\nThis class makes use of the subtitle functionality of ``gaupol``.\n\n.. seealso:: gaupol/agents/open.py::open_main\n\nA patch to gaupol is required to open utf-8 files successfully.\n\"\"\"\n\nimport os\nfrom io import StringIO\nfrom tempfile import NamedTemporaryFile\n\nfrom translate.storage import base\n\n\ntry:\n    from aeidon import Subtitle, documents, newlines\n    from aeidon.encodings import detect\n    from aeidon.files import AdvSubStationAlpha, MicroDVD, SubRip, SubStationAlpha, new\n    from aeidon.util import detect_format as determine\nexcept ImportError:\n    try:\n        from gaupol import FormatDeterminer, documents\n        from gaupol.encodings import detect\n        from gaupol.files import (\n            AdvSubStationAlpha,\n            MicroDVD,\n            SubRip,\n            SubStationAlpha,\n            new,\n        )\n        from gaupol.newlines import newlines\n        from gaupol.subtitle import Subtitle\n\n        _determiner = FormatDeterminer()\n        determine = _determiner.determine\n    except ImportError:\n        raise ImportError(\"\\naeidon or gaupol package required for Subtitle support\")\n\n\nclass SubtitleUnit(base.TranslationUnit):\n    \"\"\"A subtitle entry that is translatable\"\"\"\n\n    init_time = \"00:00:00.000\"\n\n    def __init__(self, source=None, **kwargs):\n        self._start = self.init_time\n        self._end = self.init_time\n        self._duration = 0.0\n        if source:\n            self.source = source\n            self.target = source\n        super().__init__(source)\n\n    def getnotes(self, origin=None):\n        if origin in [\"programmer\", \"developer\", \"source code\", None]:\n            return \"visible for %d seconds\" % self._duration\n        else:\n            return \"\"\n\n    def getlocations(self):\n        return [f\"{self._start}-->{self._end}\"]\n\n    def getid(self):\n        return self.getlocations()[0]\n\n\nclass MicroDVDUnit(SubtitleUnit):\n    \"\"\"MicroDVD unit, it uses frames instead of time as start/end.\"\"\"\n\n    init_time = 0\n\n\nclass SubtitleFile(base.TranslationStore):\n    \"\"\"A subtitle file\"\"\"\n\n    UnitClass = SubtitleUnit\n\n    def __init__(self, inputfile=None, **kwargs):\n        \"\"\"construct an Subtitle file, optionally reading in from inputfile.\"\"\"\n        super().__init__(**kwargs)\n        self.filename = None\n        self._subtitlefile = None\n        if inputfile is not None:\n            self._parsefile(inputfile)\n\n    def serialize(self, out):\n        subtitles = []\n        for unit in self.units:\n            subtitle = Subtitle()\n            subtitle.main_text = unit.target or unit.source\n            subtitle.start = unit._start\n            subtitle.end = unit._end\n            subtitles.append(subtitle)\n        # Using transient output might be dropped if/when we have more control\n        # over the open mode of out files.\n        output = StringIO()\n        self._subtitlefile.write_to_file(subtitles, documents.MAIN, output)\n        out.write(output.getvalue().encode(self._subtitlefile.encoding))\n\n    def _parse(self):\n        try:\n            self.encoding = detect(self.filename)\n            self._format = determine(self.filename, self.encoding)\n            self._subtitlefile = new(self._format, self.filename, self.encoding)\n            for subtitle in self._subtitlefile.read():\n                newunit = self.addsourceunit(subtitle.main_text)\n                newunit._start = subtitle.start\n                newunit._end = subtitle.end\n                newunit._duration = subtitle.duration_seconds\n        except Exception as e:\n            raise base.ParseError(e)\n\n    def _parsefile(self, storefile):\n        if hasattr(storefile, \"name\"):\n            self.filename = storefile.name\n            storefile.close()\n        elif hasattr(storefile, \"filename\"):\n            self.filename = storefile.filename\n            storefile.close()\n        elif isinstance(storefile, str):\n            self.filename = storefile\n\n        if self.filename and os.path.exists(self.filename):\n            self._parse()\n        else:\n            self.parse(storefile.read())\n\n    @classmethod\n    def parsefile(cls, storefile):\n        \"\"\"parse the given file\"\"\"\n        newstore = cls()\n        newstore._parsefile(storefile)\n        return newstore\n\n    def parse(self, input):\n        if isinstance(input, bytes):\n            # Gaupol does not allow parsing from strings\n            kwargs = {\"delete\": False}\n            if self.filename:\n                kwargs[\"suffix\"] = self.filename\n\n            temp_file = NamedTemporaryFile(**kwargs)\n            temp_file.close()\n\n            try:\n                with open(temp_file.name, \"wb\") as fh:\n                    fh.write(input)\n                self._parsefile(temp_file.name)\n            finally:\n                os.unlink(temp_file.name)\n        else:\n            self._parsefile(input)\n\n\n############# format specific classes ###################\n\n# the generic SubtitleFile can adapt to any format, but only the\n# specilized classes can be used to construct a new file\n\n\nclass SubRipFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"SubRip subtitles file\"\n    Extensions = [\"srt\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = SubRip(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n\n\nclass MicroDVDFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"MicroDVD subtitles file\"\n    Extensions = [\"sub\"]\n    UnitClass = MicroDVDUnit\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = MicroDVD(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n\n\nclass AdvSubStationAlphaFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"Advanced Substation Alpha subtitles file\"\n    Extensions = [\"ass\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = AdvSubStationAlpha(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n\n\nclass SubStationAlphaFile(SubtitleFile):\n    \"\"\"specialized class for SubRipFile's only\"\"\"\n\n    Name = \"Substation Alpha subtitles file\"\n    Extensions = [\"ssa\"]\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self._subtitlefile is None:\n            self._subtitlefile = SubStationAlpha(self.filename or \"\", self.encoding)\n        if self._subtitlefile.newline is None:\n            self._subtitlefile.newline = newlines.UNIX\n", "path": "translate/storage/subtitles.py"}]}