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