2 # -*- coding: utf-8 -*-
4 # Copyright 2006 Zuza Software Foundation
6 # This file is part of translate.
8 # translate is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 """factory methods to build real storage objects that conform to base.py"""
25 from gzip
import GzipFile
27 # bz2 is not available on python 2.3
28 from bz2
import BZ2File
33 from translate
.storage
import base
34 from translate
.storage
import csvl10n
35 from translate
.storage
import mo
36 from translate
.storage
import po
37 from translate
.storage
import qm
38 from translate
.storage
import wordfast
39 #Let's try to import the XML formats carefully. They might fail if the user
40 #doesn't have lxml installed. Let's try to continue gracefully, but print an
43 #Although poxliff is unused in this module, it is referenced in test_factory
44 from translate
.storage
import poxliff
45 from translate
.storage
import tbx
46 from translate
.storage
import tmx
47 from translate
.storage
import xliff
49 except ImportError, e
:
50 print >> sys
.stderr
, str(e
)
54 #TODO: Monolingual formats (with template?)
57 "csv": csvl10n
.csvfile
,
58 "po": po
.pofile
, "pot": po
.pofile
,
59 "mo": mo
.mofile
, "gmo": mo
.mofile
,
61 "_wftm": wordfast
.WordfastTMFile
,
63 """Dictionary of file extensions and their associated class.
65 _ext is a pseudo extension, that is their is no real extension by that name."""
71 "xliff": xliff
.xlifffile
, "xlf": xliff
.xlifffile
,
78 decompressclass
['bz2'] = BZ2File
80 def _examine_txt(storefile
):
81 """Determine the true filetype for a .txt file"""
82 if isinstance(storefile
, basestring
) and os
.path
.exists(storefile
):
83 storefile
= open(storefile
)
85 start
= storefile
.read(600).strip()
86 except AttributeError:
87 raise ValueError("Need to read object to determine type")
88 # Some encoding magic for Wordfast
89 if wordfast
.TAB_UTF16
in start
.split("\n")[0]:
92 encoding
= 'iso-8859-1'
93 start
= start
.decode(encoding
).encode('utf-8')
94 if '%Wordfast TM' in start
:
95 pseudo_extension
= '_wftm'
97 raise ValueError("Failed to guess file type.")
99 return pseudo_extension
101 hiddenclasses
= {"txt": _examine_txt
}
103 def _guessextention(storefile
):
104 """Guesses the type of a file object by looking at the first few characters.
105 The return value is a file extention ."""
106 start
= storefile
.read(300).strip()
107 if '<xliff ' in start
:
109 elif 'msgid "' in start
:
111 elif '%Wordfast TM' in start
:
114 raise ValueError("Failed to guess file type.")
118 def _getdummyname(storefile
):
119 """Provides a dummy name for a file object without a name attribute, by guessing the file type."""
120 return 'dummy.' + _guessextention(storefile
)
122 def _getname(storefile
):
123 """returns the filename"""
124 if storefile
is None:
125 raise ValueError("This method cannot magically produce a filename when given None as input.")
126 if not isinstance(storefile
, basestring
):
127 if not hasattr(storefile
, "name"):
128 storefilename
= _getdummyname(storefile
)
130 storefilename
= storefile
.name
132 storefilename
= storefile
135 def getclass(storefile
, ignore
=None):
136 """Factory that returns the applicable class for the type of file presented.
137 Specify ignore to ignore some part at the back of the name (like .gz). """
138 storefilename
= _getname(storefile
)
139 if ignore
and storefilename
.endswith(ignore
):
140 storefilename
= storefilename
[:-len(ignore
)]
141 root
, ext
= os
.path
.splitext(storefilename
)
142 ext
= ext
[len(os
.path
.extsep
):].lower()
144 if ext
in decompressclass
:
146 root
, ext
= os
.path
.splitext(root
)
147 ext
= ext
[len(os
.path
.extsep
):].lower()
148 if ext
in hiddenclasses
:
149 guesserfn
= hiddenclasses
[ext
]
151 ext
= guesserfn(decompressclass
[decomp
](storefile
))
153 ext
= guesserfn(storefile
)
155 storeclass
= classes
[ext
]
157 raise ValueError("Unknown filetype (%s)" % storefilename
)
160 def getobject(storefile
, ignore
=None):
161 """Factory that returns a usable object for the type of file presented.
163 @type storefile: file or str
164 @param storefile: File object or file name.
166 Specify ignore to ignore some part at the back of the name (like .gz).
169 if isinstance(storefile
, base
.TranslationStore
):
171 if isinstance(storefile
, basestring
):
172 if os
.path
.isdir(storefile
) or storefile
.endswith(os
.path
.sep
):
173 from translate
.storage
import directory
174 return directory
.Directory(storefile
)
175 storefilename
= _getname(storefile
)
176 storeclass
= getclass(storefile
, ignore
)
177 if os
.path
.exists(storefilename
) or not getattr(storefile
, "closed", True):
178 name
, ext
= os
.path
.splitext(storefilename
)
179 ext
= ext
[len(os
.path
.extsep
):].lower()
180 if ext
in decompressclass
:
181 storefile
= decompressclass
[ext
](storefilename
)
182 store
= storeclass
.parsefile(storefile
)