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