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