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