Package translate :: Package storage :: Module factory
[hide private]
[frames] | no frames]

Source Code for Module translate.storage.factory

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # Copyright 2006 Zuza Software Foundation 
  5  # 
  6  # This file is part of translate. 
  7  # 
  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. 
 12  # 
 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. 
 17  # 
 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 
 21   
 22  """factory methods to build real storage objects that conform to base.py""" 
 23   
 24  import os 
 25  from gzip import GzipFile 
 26  try: 
 27      # bz2 is not available on python 2.3 
 28      from bz2 import BZ2File 
 29  except ImportError: 
 30      BZ2File = None 
 31  import sys 
 32   
 33  from translate.storage import base 
 34  from translate.storage import catkeys 
 35  from translate.storage import csvl10n 
 36  from translate.storage import mo 
 37  from translate.storage import omegat 
 38  from translate.storage import po 
 39  from translate.storage import qm 
 40  try: 
 41      # trados uses BeutifulSoup which might not be available 
 42      from translate.storage import trados 
 43  except ImportError: 
 44      trados = None 
 45  from translate.storage import utx 
 46  from translate.storage import wordfast 
 47  #Let's try to import the XML formats carefully. They might fail if the user 
 48  #doesn't have lxml installed. Let's try to continue gracefully, but print an 
 49  #informative warning. 
 50  try: 
 51      #Although poxliff is unused in this module, it is referenced in test_factory 
 52      from translate.storage import poxliff 
 53      from translate.storage import qph 
 54      from translate.storage import tbx 
 55      from translate.storage import tmx 
 56      from translate.storage import ts2 as ts 
 57      from translate.storage import xliff 
 58      support_xml = True 
 59  except ImportError, e: 
 60      print >> sys.stderr, str(e) 
 61      support_xml = False 
 62   
 63   
 64  #TODO: Monolingual formats (with template?) 
 65   
 66  classes = { 
 67             "csv": csvl10n.csvfile, 
 68             "tab": omegat.OmegaTFileTab, "utf8": omegat.OmegaTFile, 
 69             "po": po.pofile, "pot": po.pofile, 
 70             "mo": mo.mofile, "gmo": mo.mofile, 
 71             "qm": qm.qmfile, 
 72             "utx": utx.UtxFile, 
 73             "_wftm": wordfast.WordfastTMFile, 
 74             "catkeys": catkeys.CatkeysFile, 
 75            } 
 76  """Dictionary of file extensions and their associated class. 
 77   
 78  _ext is a pseudo extension, that is their is no real extension by that name.""" 
 79  if trados: 
 80      classes["_trados_txt_tm"] = trados.TradosTxtTmFile 
 81   
 82  if support_xml: 
 83      classes.update({ 
 84             "qph": qph.QphFile, 
 85             "tbx": tbx.tbxfile, 
 86             "tmx": tmx.tmxfile, 
 87             "ts": ts.tsfile, 
 88             "xliff": xliff.xlifffile, "xlf": xliff.xlifffile, 
 89             "sdlxliff": xliff.xlifffile, 
 90      }) 
 91   
 92  decompressclass = { 
 93      'gz': GzipFile, 
 94  } 
 95  if BZ2File: 
 96      decompressclass['bz2'] = BZ2File 
 97   
 98   
99 -def _examine_txt(storefile):
100 """Determine the true filetype for a .txt file""" 101 if isinstance(storefile, basestring) and os.path.exists(storefile): 102 storefile = open(storefile) 103 try: 104 start = storefile.read(600).strip() 105 except AttributeError: 106 raise ValueError("Need to read object to determine type") 107 # Some encoding magic for Wordfast 108 if wordfast.TAB_UTF16 in start.split("\n")[0]: 109 encoding = 'utf-16' 110 else: 111 encoding = 'iso-8859-1' 112 start = start.decode(encoding).encode('utf-8') 113 if '%Wordfast TM' in start: 114 pseudo_extension = '_wftm' 115 elif '<RTF Preamble>' in start: 116 pseudo_extension = '_trados_txt_tm' 117 else: 118 raise ValueError("Failed to guess file type.") 119 storefile.seek(0) 120 return pseudo_extension
121 122 hiddenclasses = {"txt": _examine_txt} 123 124
125 -def _guessextention(storefile):
126 """Guesses the type of a file object by looking at the first few characters. 127 The return value is a file extention .""" 128 start = storefile.read(300).strip() 129 if '<xliff ' in start: 130 extention = 'xlf' 131 elif 'msgid "' in start: 132 extention = 'po' 133 elif '%Wordfast TM' in start: 134 extention = 'txt' 135 elif '<!DOCTYPE TS>' in start: 136 extention = 'ts' 137 elif '<tmx ' in start: 138 extention = 'tmx' 139 elif '#UTX' in start: 140 extention = 'utx' 141 else: 142 raise ValueError("Failed to guess file type.") 143 storefile.seek(0) 144 return extention
145 146
147 -def _getdummyname(storefile):
148 """Provides a dummy name for a file object without a name attribute, by guessing the file type.""" 149 return 'dummy.' + _guessextention(storefile)
150 151
152 -def _getname(storefile):
153 """returns the filename""" 154 if storefile is None: 155 raise ValueError("This method cannot magically produce a filename when given None as input.") 156 if not isinstance(storefile, basestring): 157 if not hasattr(storefile, "name"): 158 storefilename = _getdummyname(storefile) 159 else: 160 storefilename = storefile.name 161 else: 162 storefilename = storefile 163 return storefilename
164 165
166 -def getclass(storefile, ignore=None, classes=classes, hiddenclasses=hiddenclasses):
167 """Factory that returns the applicable class for the type of file presented. 168 Specify ignore to ignore some part at the back of the name (like .gz). """ 169 storefilename = _getname(storefile) 170 if ignore and storefilename.endswith(ignore): 171 storefilename = storefilename[:-len(ignore)] 172 root, ext = os.path.splitext(storefilename) 173 ext = ext[len(os.path.extsep):].lower() 174 decomp = None 175 if ext in decompressclass: 176 decomp = ext 177 root, ext = os.path.splitext(root) 178 ext = ext[len(os.path.extsep):].lower() 179 if ext in hiddenclasses: 180 guesserfn = hiddenclasses[ext] 181 if decomp: 182 ext = guesserfn(decompressclass[decomp](storefile)) 183 else: 184 ext = guesserfn(storefile) 185 try: 186 storeclass = classes[ext] 187 except KeyError: 188 raise ValueError("Unknown filetype (%s)" % storefilename) 189 return storeclass
190 191
192 -def getobject(storefile, ignore=None, classes=classes, hiddenclasses=hiddenclasses):
193 """Factory that returns a usable object for the type of file presented. 194 195 @type storefile: file or str 196 @param storefile: File object or file name. 197 198 Specify ignore to ignore some part at the back of the name (like .gz). 199 """ 200 201 if isinstance(storefile, base.TranslationStore): 202 return storefile 203 if isinstance(storefile, basestring): 204 if os.path.isdir(storefile) or storefile.endswith(os.path.sep): 205 from translate.storage import directory 206 return directory.Directory(storefile) 207 storefilename = _getname(storefile) 208 storeclass = getclass(storefile, ignore, classes=classes, hiddenclasses=hiddenclasses) 209 if os.path.exists(storefilename) or not getattr(storefile, "closed", True): 210 name, ext = os.path.splitext(storefilename) 211 ext = ext[len(os.path.extsep):].lower() 212 if ext in decompressclass: 213 storefile = decompressclass[ext](storefilename) 214 store = storeclass.parsefile(storefile) 215 else: 216 store = storeclass() 217 store.filename = storefilename 218 return store
219 220
221 -def supported_files():
222 """Returns data about all supported files 223 224 @return: list of type that include (name, extensions, mimetypes) 225 @rtype: list 226 """ 227 228 supported = {} 229 for supported_class in classes.itervalues(): 230 name = getattr(supported_class, "Name", None) 231 if name is None: 232 continue 233 extensions = getattr(supported_class, "Extensions", None) 234 mimetypes = getattr(supported_class, "Mimetypes", None) 235 if not name in supported: 236 supported[name] = (extensions, mimetypes) 237 else: 238 supported[name][0].extend(extensions) 239 supported[name][1].extend(mimetypes) 240 return [(name, ext_mime[0], ext_mime[1]) for name, ext_mime in supported.iteritems()]
241