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