Package translate :: Package storage :: Module properties
[hide private]
[frames] | no frames]

Source Code for Module translate.storage.properties

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  #  
  4  # Copyright 2004-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  """classes that hold units of .properties files (propunit) or entire files 
 23  (propfile) these files are used in translating Mozilla and other software 
 24   
 25  @note: The following {.properties file 
 26  description<http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.Reader)>} 
 27  and {example <http://www.exampledepot.com/egs/java.util/Props.html>} give some 
 28  good references to the .properties specification.  A simple summary of what is 
 29  permissible follows. 
 30   
 31  # a comment 
 32  ! a comment 
 33       
 34  a = a string 
 35  b = a string with escape sequences \t \n \r \\ \" \' \ (space) \u0123 
 36  c = a string with a continuation line \ 
 37      continuation line 
 38  d.e.f = another string 
 39   
 40  """ 
 41   
 42  from translate.storage import base 
 43  from translate.misc import quote 
 44  import re 
 45   
 46  # the rstripeols convert dos <-> unix nicely as well 
 47  # output will be appropriate for the platform 
 48   
 49  eol = "\n" 
 50   
51 -class propunit(base.TranslationUnit):
52 """an element of a properties file i.e. a name and value, and any comments 53 associated"""
54 - def __init__(self, source=""):
55 """construct a blank propunit""" 56 super(propunit, self).__init__(source) 57 self.name = "" 58 self.value = "" 59 self.comments = [] 60 self.source = source
61
62 - def setsource(self, source):
63 """Sets the source AND the target to be equal""" 64 self.value = quote.mozillapropertiesencode(source or "")
65
66 - def getsource(self):
67 value = quote.mozillapropertiesdecode(self.value) 68 value = value.lstrip(" ") 69 rstriped = value.rstrip(" ") 70 if rstriped and rstriped[-1] != "\\": 71 value = rstriped 72 73 value = re.sub("\\\\ ", " ", value) 74 return value
75 76 source = property(getsource, setsource) 77
78 - def settarget(self, target):
79 """Note: this also sets the .source attribute!""" 80 # TODO: shouldn't this just call the .source property? no quoting done here... 81 self.source = target
82
83 - def gettarget(self):
84 return self.source
85 target = property(gettarget, settarget) 86
87 - def __str__(self):
88 """convert to a string. double check that unicode is handled somehow here""" 89 source = self.getoutput() 90 if isinstance(source, unicode): 91 return source.encode(getattr(self, "encoding", "UTF-8")) 92 return source
93
94 - def getoutput(self):
95 """convert the element back into formatted lines for a .properties file""" 96 if self.isblank(): 97 return "".join(self.comments + ["\n"]) 98 else: 99 if "\\u" in self.value: 100 self.value = quote.mozillapropertiesencode(quote.mozillapropertiesdecode(self.value)) 101 return "".join(self.comments + ["%s=%s\n" % (self.name, self.value)])
102
103 - def getlocations(self):
104 return [self.name]
105
106 - def addnote(self, note, origin=None):
107 self.comments.append(note)
108
109 - def getnotes(self, origin=None):
110 return '\n'.join(self.comments)
111
112 - def removenotes(self):
113 self.comments = []
114
115 - def isblank(self):
116 """returns whether this is a blank element, containing only comments...""" 117 return not (self.name or self.value)
118
119 -class propfile(base.TranslationStore):
120 """this class represents a .properties file, made up of propunits""" 121 UnitClass = propunit
122 - def __init__(self, inputfile=None):
123 """construct a propfile, optionally reading in from inputfile""" 124 super(propfile, self).__init__(unitclass = self.UnitClass) 125 self.filename = getattr(inputfile, 'name', '') 126 if inputfile is not None: 127 propsrc = inputfile.read() 128 inputfile.close() 129 self.parse(propsrc)
130
131 - def parse(self, propsrc):
132 """read the source of a properties file in and include them as units""" 133 newunit = propunit() 134 inmultilinevalue = False 135 for line in propsrc.split("\n"): 136 # handle multiline value if we're in one 137 line = quote.rstripeol(line) 138 if inmultilinevalue: 139 newunit.value += line.lstrip() 140 # see if there's more 141 inmultilinevalue = (newunit.value[-1:] == '\\') 142 # if we're still waiting for more... 143 if inmultilinevalue: 144 # strip the backslash 145 newunit.value = newunit.value[:-1] 146 if not inmultilinevalue: 147 # we're finished, add it to the list... 148 self.addunit(newunit) 149 newunit = propunit() 150 # otherwise, this could be a comment 151 elif line.strip()[:1] == '#': 152 # add a comment 153 line = quote.escapecontrols(line) 154 newunit.comments.append(line+"\n") 155 elif not line.strip(): 156 # this is a blank line... 157 if str(newunit).strip(): 158 self.addunit(newunit) 159 newunit = propunit() 160 else: 161 equalspos = line.find('=') 162 # if no equals, just ignore it 163 if equalspos == -1: 164 continue 165 # otherwise, this is a definition 166 else: 167 newunit.name = line[:equalspos].strip() 168 newunit.value = line[equalspos+1:].lstrip() 169 # backslash at end means carry string on to next line 170 if newunit.value[-1:] == '\\': 171 inmultilinevalue = True 172 newunit.value = newunit.value[:-1] 173 else: 174 self.addunit(newunit) 175 newunit = propunit() 176 # see if there is a leftover one... 177 if inmultilinevalue or len(newunit.comments) > 0: 178 self.addunit(newunit)
179
180 - def __str__(self):
181 """convert the units back to lines""" 182 lines = [] 183 for unit in self.units: 184 lines.append(str(unit)) 185 return "".join(lines)
186 187 if __name__ == '__main__': 188 import sys 189 pf = propfile(sys.stdin) 190 sys.stdout.write(str(pf)) 191