translate.storage.factory

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      elif '<tmx ' in start:
    122          extention = 'tmx'
    123      else:
    124          raise ValueError("Failed to guess file type.")
    125      storefile.seek(0)
    126      return extention
    127
    128 -def _getdummyname(storefile):
    129      """Provides a dummy name for a file object without a name attribute, by guessing the file type."""
    130      return 'dummy.' + _guessextention(storefile)
    131
    132 -def _getname(storefile):
    133      """returns the filename"""
    134      if storefile is None:
    135          raise ValueError("This method cannot magically produce a filename when given None as input.")
    136      if not isinstance(storefile, basestring):
    137          if not hasattr(storefile, "name"):
    138              storefilename = _getdummyname(storefile)
    139          else:
    140              storefilename = storefile.name
    141      else:
    142          storefilename = storefile
    143      return storefilename
    144
    145 -def getclass(storefile, ignore=None, classes=classes, hiddenclasses=hiddenclasses):
    146      """Factory that returns the applicable class for the type of file presented.
    147      Specify ignore to ignore some part at the back of the name (like .gz). """
    148      storefilename = _getname(storefile)
    149      if ignore and storefilename.endswith(ignore):
    150          storefilename = storefilename[:-len(ignore)]
    151      root, ext = os.path.splitext(storefilename)
    152      ext = ext[len(os.path.extsep):].lower()
    153      decomp = None
    154      if ext in decompressclass:
    155          decomp = ext
    156          root, ext = os.path.splitext(root)
    157          ext = ext[len(os.path.extsep):].lower()
    158      if ext in hiddenclasses:
    159          guesserfn = hiddenclasses[ext]
    160          if decomp:
    161              ext = guesserfn(decompressclass[decomp](storefile))
    162          else:
    163              ext = guesserfn(storefile)
    164      try:
    165          storeclass = classes[ext]
    166      except KeyError:
    167          raise ValueError("Unknown filetype (%s)" % storefilename)
    168      return storeclass
    169
    170 -def getobject(storefile, ignore=None, classes=classes, hiddenclasses=hiddenclasses):
    171      """Factory that returns a usable object for the type of file presented.
    172
    173      @type storefile: file or str
    174      @param storefile: File object or file name.
    175
    176      Specify ignore to ignore some part at the back of the name (like .gz).
    177      """
    178
    179      if isinstance(storefile, base.TranslationStore):
    180          return storefile
    181      if isinstance(storefile, basestring):
    182          if os.path.isdir(storefile) or storefile.endswith(os.path.sep):
    183              from translate.storage import directory
    184              return directory.Directory(storefile)
    185      storefilename = _getname(storefile)
    186      storeclass = getclass(storefile, ignore, classes=classes, hiddenclasses=hiddenclasses)
    187      if os.path.exists(storefilename) or not getattr(storefile, "closed", True):
    188          name, ext = os.path.splitext(storefilename)
    189          ext = ext[len(os.path.extsep):].lower()
    190          if ext in decompressclass:
    191              storefile = decompressclass[ext](storefilename)
    192          store = storeclass.parsefile(storefile)
    193      else:
    194          store = storeclass()
    195          store.filename = storefilename
    196      return store
    197
    198 -def supported_files():
    199      """Returns data about all supported files
    200
    201      @return: list of type that include (name, extensions, mimetypes)
    202      @rtype: list
    203      """
    204
    205      supported = {}
    206      for supported_class in classes.itervalues():
    207          name = getattr(supported_class, "Name", None)
    208          if name is None:
    209              continue
    210          extensions = getattr(supported_class, "Extensions", None)
    211          mimetypes = getattr(supported_class, "Mimetypes", None)
    212          if not supported.has_key(name):
    213              supported[name] = (extensions, mimetypes)
    214          else:
    215              supported[name][0].extend(extensions)
    216              supported[name][1].extend(mimetypes)
    217      return [(name, ext_mime[0], ext_mime[1]) for name, ext_mime in supported.iteritems()]
    218