Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(84)

Side by Side Diff: translate/storage/cpo.py

Issue 102: Handle typecomments SVN Base: https://translate.svn.sourceforge.net/svnroot/translate/src/trunk/
Patch Set: Created 1 year, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 # 3 #
4 # Copyright 2002-2007 Zuza Software Foundation 4 # Copyright 2002-2007 Zuza Software Foundation
5 # 5 #
6 # This file is part of translate. 6 # This file is part of translate.
7 # 7 #
8 # translate is free software; you can redistribute it and/or modify 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 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 10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version. 11 # (at your option) any later version.
12 # 12 #
13 # translate is distributed in the hope that it will be useful, 13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details. 16 # GNU General Public License for more details.
17 # 17 #
18 # You should have received a copy of the GNU General Public License 18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software 19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 21
22 """Classes that hold units of .po files (pounit) or entire files (pofile). 22 """Classes that hold units of .po files (pounit) or entire files (pofile).
23 23
24 Gettext-style .po (or .pot) files are used in translations for KDE, GNOME and 24 Gettext-style .po (or .pot) files are used in translations for KDE, GNOME and
25 many other projects. 25 many other projects.
26 26
27 This uses libgettextpo from the gettext package. Any version before 0.17 will 27 This uses libgettextpo from the gettext package. Any version before 0.17 will
28 at least cause some subtle bugs or may not work at all. Developers might want 28 at least cause some subtle bugs or may not work at all. Developers might want
29 to have a look at gettext-tools/libgettextpo/gettext-po.h from the gettext 29 to have a look at gettext-tools/libgettextpo/gettext-po.h from the gettext
30 package for the public API of the library. 30 package for the public API of the library.
31 """ 31 """
32 32
33 from translate.misc.multistring import multistring 33 from translate.misc.multistring import multistring
34 from translate.storage import pocommon 34 from translate.storage import pocommon
35 from translate.misc import quote 35 from translate.misc import quote
36 from translate.lang import data 36 from translate.lang import data
37 from ctypes import * 37 from ctypes import *
38 import ctypes.util 38 import ctypes.util
39 try: 39 try:
40 import cStringIO as StringIO 40 import cStringIO as StringIO
41 except ImportError: 41 except ImportError:
42 import StringIO 42 import StringIO
43 import os 43 import os
44 import pypo 44 import pypo
45 import re 45 import re
46 import sys 46 import sys
47 import tempfile 47 import tempfile
48 48
49 lsep = " " 49 lsep = " "
50 """Seperator for #: entries""" 50 """Seperator for #: entries"""
51 51
52 STRING = c_char_p 52 STRING = c_char_p
53 53
54 # Structures 54 # Structures
55 class po_message(Structure): 55 class po_message(Structure):
56 _fields_ = [] 56 _fields_ = []
57 57
58 # Function prototypes 58 # Function prototypes
59 xerror_prototype = CFUNCTYPE(None, c_int, POINTER(po_message), STRING, c_uint, c _uint, c_int, STRING) 59 xerror_prototype = CFUNCTYPE(None, c_int, POINTER(po_message), STRING, c_uint, c _uint, c_int, STRING)
60 xerror2_prototype = CFUNCTYPE(None, c_int, POINTER(po_message), STRING, c_uint, c_uint, c_int, STRING, POINTER(po_message), STRING, c_uint, c_uint, c_int, STRIN G) 60 xerror2_prototype = CFUNCTYPE(None, c_int, POINTER(po_message), STRING, c_uint, c_uint, c_int, STRING, POINTER(po_message), STRING, c_uint, c_uint, c_int, STRIN G)
61 61
62 62
63 # Structures (error handler) 63 # Structures (error handler)
64 class po_xerror_handler(Structure): 64 class po_xerror_handler(Structure):
65 _fields_ = [('xerror', xerror_prototype), 65 _fields_ = [('xerror', xerror_prototype),
66 ('xerror2', xerror2_prototype)] 66 ('xerror2', xerror2_prototype)]
67 67
68 class po_error_handler(Structure): 68 class po_error_handler(Structure):
69 _fields_ = [ 69 _fields_ = [
70 ('error', CFUNCTYPE(None, c_int, c_int, STRING)), 70 ('error', CFUNCTYPE(None, c_int, c_int, STRING)),
71 ('error_at_line', CFUNCTYPE(None, c_int, c_int, STRING, c_uint, STRING)), 71 ('error_at_line', CFUNCTYPE(None, c_int, c_int, STRING, c_uint, STRING)),
72 ('multiline_warning', CFUNCTYPE(None, STRING, STRING)), 72 ('multiline_warning', CFUNCTYPE(None, STRING, STRING)),
73 ('multiline_error', CFUNCTYPE(None, STRING, STRING)), 73 ('multiline_error', CFUNCTYPE(None, STRING, STRING)),
74 ] 74 ]
75 75
76 # Callback functions for po_xerror_handler 76 # Callback functions for po_xerror_handler
77 def xerror_cb(severity, message, filename, lineno, column, multilint_p, message_ text): 77 def xerror_cb(severity, message, filename, lineno, column, multilint_p, message_ text):
78 print >> sys.stderr, "xerror_cb", severity, message, filename, lineno, colum n, multilint_p, message_text 78 print >> sys.stderr, "xerror_cb", severity, message, filename, lineno, colum n, multilint_p, message_text
79 if severity >= 1: 79 if severity >= 1:
80 raise ValueError(message_text) 80 raise ValueError(message_text)
81 81
82 def xerror2_cb(severity, message1, filename1, lineno1, column1, multiline_p1, me ssage_text1, message2, filename2, lineno2, column2, multiline_p2, message_text2) : 82 def xerror2_cb(severity, message1, filename1, lineno1, column1, multiline_p1, me ssage_text1, message2, filename2, lineno2, column2, multiline_p2, message_text2) :
83 print >> sys.stderr, "xerror2_cb", severity, message1, filename1, lineno1, c olumn1, multiline_p1, message_text1, message2, filename2, lineno2, column2, mult iline_p2, message_text2 83 print >> sys.stderr, "xerror2_cb", severity, message1, filename1, lineno1, c olumn1, multiline_p1, message_text1, message2, filename2, lineno2, column2, mult iline_p2, message_text2
84 if severity >= 1: 84 if severity >= 1:
85 raise ValueError(message_text1) 85 raise ValueError(message_text1)
86 86
87 87
88 88
89 # Load libgettextpo 89 # Load libgettextpo
90 gpo = None 90 gpo = None
91 # 'gettextpo' is recognised on Unix, while only 'libgettextpo' is recognised on 91 # 'gettextpo' is recognised on Unix, while only 'libgettextpo' is recognised on
92 # windows. Therefore we test both. 92 # windows. Therefore we test both.
93 names = ['gettextpo', 'libgettextpo'] 93 names = ['gettextpo', 'libgettextpo']
94 for name in names: 94 for name in names:
95 lib_location = ctypes.util.find_library(name) 95 lib_location = ctypes.util.find_library(name)
96 if lib_location: 96 if lib_location:
97 gpo = cdll.LoadLibrary(lib_location) 97 gpo = cdll.LoadLibrary(lib_location)
98 if gpo: 98 if gpo:
99 break 99 break
100 else: 100 else:
101 # Now we are getting desperate, so let's guess a unix type DLL that might 101 # Now we are getting desperate, so let's guess a unix type DLL that might
102 # be in LD_LIBRARY_PATH or loaded with LD_PRELOAD 102 # be in LD_LIBRARY_PATH or loaded with LD_PRELOAD
103 try: 103 try:
104 gpo = cdll.LoadLibrary('libgettextpo.so') 104 gpo = cdll.LoadLibrary('libgettextpo.so')
105 except OSError, e: 105 except OSError, e:
106 raise ImportError("gettext PO library not found") 106 raise ImportError("gettext PO library not found")
107 107
108 # Setup return and paramater types 108 # Setup return and paramater types
109 # File access 109 # File access
110 gpo.po_file_read_v3.argtypes = [STRING, POINTER(po_xerror_handler)] 110 gpo.po_file_read_v3.argtypes = [STRING, POINTER(po_xerror_handler)]
111 gpo.po_file_write_v2.argtypes = [c_int, STRING, POINTER(po_xerror_handler)] 111 gpo.po_file_write_v2.argtypes = [c_int, STRING, POINTER(po_xerror_handler)]
112 gpo.po_file_write_v2.retype = c_int 112 gpo.po_file_write_v2.retype = c_int
113 113
114 # Header 114 # Header
115 gpo.po_file_domain_header.restype = STRING 115 gpo.po_file_domain_header.restype = STRING
116 gpo.po_header_field.restype = STRING 116 gpo.po_header_field.restype = STRING
117 gpo.po_header_field.argtypes = [STRING, STRING] 117 gpo.po_header_field.argtypes = [STRING, STRING]
118 118
119 # Locations (filepos) 119 # Locations (filepos)
120 gpo.po_filepos_file.restype = STRING 120 gpo.po_filepos_file.restype = STRING
121 gpo.po_message_filepos.restype = c_int 121 gpo.po_message_filepos.restype = c_int
122 gpo.po_message_filepos.argtypes = [c_int, c_int] 122 gpo.po_message_filepos.argtypes = [c_int, c_int]
123 gpo.po_message_add_filepos.argtypes = [c_int, STRING, c_int] 123 gpo.po_message_add_filepos.argtypes = [c_int, STRING, c_int]
124 124
125 # Message (get methods) 125 # Message (get methods)
126 gpo.po_message_comments.restype = STRING 126 gpo.po_message_comments.restype = STRING
127 gpo.po_message_extracted_comments.restype = STRING 127 gpo.po_message_extracted_comments.restype = STRING
128 gpo.po_message_prev_msgctxt.restype = STRING 128 gpo.po_message_prev_msgctxt.restype = STRING
129 gpo.po_message_prev_msgid.restype = STRING 129 gpo.po_message_prev_msgid.restype = STRING
130 gpo.po_message_prev_msgid_plural.restype = STRING 130 gpo.po_message_prev_msgid_plural.restype = STRING
131 gpo.po_message_is_format.restype = c_int 131 gpo.po_message_is_format.restype = c_int
132 gpo.po_message_msgctxt.restype = STRING 132 gpo.po_message_msgctxt.restype = STRING
133 gpo.po_message_msgid.restype = STRING 133 gpo.po_message_msgid.restype = STRING
134 gpo.po_message_msgid_plural.restype = STRING 134 gpo.po_message_msgid_plural.restype = STRING
135 gpo.po_message_msgstr.restype = STRING 135 gpo.po_message_msgstr.restype = STRING
136 gpo.po_message_msgstr_plural.restype = STRING 136 gpo.po_message_msgstr_plural.restype = STRING
137 gpo.po_message_set_format.argtypes = [c_int, STRING, c_int]
138 gpo.po_format_list.restype = POINTER(STRING)
137 139
138 # Message (set methods) 140 # Message (set methods)
139 gpo.po_message_set_comments.argtypes = [c_int, STRING] 141 gpo.po_message_set_comments.argtypes = [c_int, STRING]
140 gpo.po_message_set_extracted_comments.argtypes = [c_int, STRING] 142 gpo.po_message_set_extracted_comments.argtypes = [c_int, STRING]
141 gpo.po_message_set_fuzzy.argtypes = [c_int, c_int] 143 gpo.po_message_set_fuzzy.argtypes = [c_int, c_int]
142 gpo.po_message_set_msgctxt.argtypes = [c_int, STRING] 144 gpo.po_message_set_msgctxt.argtypes = [c_int, STRING]
143 145
144 # Setup the po_xerror_handler 146 # Setup the po_xerror_handler
145 xerror_handler = po_xerror_handler() 147 xerror_handler = po_xerror_handler()
146 xerror_handler.xerror = xerror_prototype(xerror_cb) 148 xerror_handler.xerror = xerror_prototype(xerror_cb)
147 xerror_handler.xerror2 = xerror2_prototype(xerror2_cb) 149 xerror_handler.xerror2 = xerror2_prototype(xerror2_cb)
148 150
149 def escapeforpo(text): 151 def escapeforpo(text):
150 return pypo.escapeforpo(text) 152 return pypo.escapeforpo(text)
151 153
152 def quoteforpo(text): 154 def quoteforpo(text):
153 return pypo.quoteforpo(text) 155 return pypo.quoteforpo(text)
154 156
155 def unquotefrompo(postr): 157 def unquotefrompo(postr):
156 return pypo.unquotefrompo(postr) 158 return pypo.unquotefrompo(postr)
157 159
158 def encodingToUse(encoding): 160 def encodingToUse(encoding):
159 return pypo.encodingToUse(encoding) 161 return pypo.encodingToUse(encoding)
160 162
161 def get_libgettextpo_version(): 163 def get_libgettextpo_version():
162 """Returns the libgettextpo version 164 """Returns the libgettextpo version
163 165
164 @rtype: three-value tuple 166 @rtype: three-value tuple
165 @return: libgettextpo version in the following format:: 167 @return: libgettextpo version in the following format::
166 (major version, minor version, subminor version) 168 (major version, minor version, subminor version)
167 """ 169 """
168 libversion = c_long.in_dll(gpo, 'libgettextpo_version') 170 libversion = c_long.in_dll(gpo, 'libgettextpo_version')
169 major = libversion.value >> 16 171 major = libversion.value >> 16
170 minor = libversion.value >> 8 172 minor = libversion.value >> 8
171 subminor = libversion.value - (major << 16) - (minor << 8) 173 subminor = libversion.value - (major << 16) - (minor << 8)
172 return major, minor, subminor 174 return major, minor, subminor
173 175
174 176
175 class pounit(pocommon.pounit): 177 class pounit(pocommon.pounit):
176 def __init__(self, source=None, encoding='utf-8', gpo_message=None): 178 def __init__(self, source=None, encoding='utf-8', gpo_message=None):
177 self._encoding = encoding 179 self._encoding = encoding
178 if not gpo_message: 180 if not gpo_message:
179 self._gpo_message = gpo.po_message_create() 181 self._gpo_message = gpo.po_message_create()
180 if source or source == "": 182 if source or source == "":
181 self.source = source 183 self.source = source
182 self.target = "" 184 self.target = ""
183 elif gpo_message: 185 elif gpo_message:
184 self._gpo_message = gpo_message 186 self._gpo_message = gpo_message
185 187
186 def setmsgidcomment(self, msgidcomment): 188 def setmsgidcomment(self, msgidcomment):
(...skipping 187 matching lines...) Show 10 above Show 10 below
374 newpo = self.__class__() 376 newpo = self.__class__()
375 newpo._gpo_message = self._gpo_message 377 newpo._gpo_message = self._gpo_message
376 return newpo 378 return newpo
377 379
378 def merge(self, otherpo, overwrite=False, comments=True, authoritative=False ): 380 def merge(self, otherpo, overwrite=False, comments=True, authoritative=False ):
379 """Merges the otherpo (with the same msgid) into this one. 381 """Merges the otherpo (with the same msgid) into this one.
380 382
381 Overwrite non-blank self.msgstr only if overwrite is True 383 Overwrite non-blank self.msgstr only if overwrite is True
382 merge comments only if comments is True 384 merge comments only if comments is True
383 385
384 """ 386 """
385 387
386 if not isinstance(otherpo, pounit): 388 if not isinstance(otherpo, pounit):
387 super(pounit, self).merge(otherpo, overwrite, comments) 389 super(pounit, self).merge(otherpo, overwrite, comments)
388 return 390 return
389 if comments: 391 if comments:
390 self.addnote(otherpo.getnotes("translator"), origin="translator", po sition="merge") 392 self.addnote(otherpo.getnotes("translator"), origin="translator", po sition="merge")
391 # FIXME mergelists(self.typecomments, otherpo.typecomments) 393 # FIXME mergelists(self.typecomments, otherpo.typecomments)
392 if not authoritative: 394 if not authoritative:
393 # We don't bring across otherpo.automaticcomments as we consider ourself 395 # We don't bring across otherpo.automaticcomments as we consider ourself
394 # to be the the authority. Same applies to otherpo.msgidcomment s 396 # to be the the authority. Same applies to otherpo.msgidcomment s
395 self.addnote(otherpo.getnotes("developer"), origin="developer", position="merge") 397 self.addnote(otherpo.getnotes("developer"), origin="developer", position="merge")
396 self.msgidcomment = otherpo._extract_msgidcomments() or None 398 self.msgidcomment = otherpo._extract_msgidcomments() or None
397 self.addlocations(otherpo.getlocations()) 399 self.addlocations(otherpo.getlocations())
398 if not self.istranslated() or overwrite: 400 if not self.istranslated() or overwrite:
399 # Remove kde-style comments from the translation (if any). 401 # Remove kde-style comments from the translation (if any).
400 if self._extract_msgidcomments(otherpo.target): 402 if self._extract_msgidcomments(otherpo.target):
401 otherpo.target = otherpo.target.replace('_: ' + otherpo._extract _msgidcomments()+ '\n', '') 403 otherpo.target = otherpo.target.replace('_: ' + otherpo._extract _msgidcomments()+ '\n', '')
402 self.target = otherpo.target 404 self.target = otherpo.target
403 if self.source != otherpo.source: 405 if self.source != otherpo.source:
404 self.markfuzzy() 406 self.markfuzzy()
405 else: 407 else:
406 self.markfuzzy(otherpo.isfuzzy()) 408 self.markfuzzy(otherpo.isfuzzy())
407 elif not otherpo.istranslated(): 409 elif not otherpo.istranslated():
408 if self.source != otherpo.source: 410 if self.source != otherpo.source:
409 self.markfuzzy() 411 self.markfuzzy()
410 else: 412 else:
411 if self.target != otherpo.target: 413 if self.target != otherpo.target:
412 self.markfuzzy() 414 self.markfuzzy()
413 415
414 def isheader(self): 416 def isheader(self):
415 #return self.source == u"" and self.target != u"" 417 #return self.source == u"" and self.target != u""
416 # we really want to make sure that there is no msgidcomment or msgctxt 418 # we really want to make sure that there is no msgidcomment or msgctxt
417 return self.getid() == "" and len(self.target) > 0 419 return self.getid() == "" and len(self.target) > 0
418 420
419 def isblank(self): 421 def isblank(self):
420 return len(self.source) == 0 and len(self.target) == 0 422 return len(self.source) == 0 and len(self.target) == 0
421 423
422 def hastypecomment(self, typecomment): 424 def hastypecomment(self, typecomment):
423 return gpo.po_message_is_format(self._gpo_message, typecomment) 425 return gpo.po_message_is_format(self._gpo_message, typecomment)
426
427 def _get_available_typecomments(self):
428 """Returns a list of all the type comments available"""
429 formats = gpo.po_format_list()
430 typecomments = []
431 for format in formats:
432 if format is None:
433 break
434 else:
435 typecomments.append(format)
436 return typecomments
437
438 def gettypecomments(self):
439 """Returns a list of the unit type comments
440
441 @returns: a list of the typecomments or an empty list if the unit not
442 have type comments.
443 """
444 comments = []
445 for typecomment in self._get_available_typecomments():
446 if self.hastypecomment(typecomment):
447 comments.append(typecomment)
448 return comments
449
450 def addtypecomment(self, typecomment):
451 """Adds a type comment to the unit
452
453 @param typecomment: the type comment to be added, for example
454 "c-format"
455 """
456 if typecomment not in self._get_available_typecomments():
457 raise ValueError("Invalid typecomment: %s" % typecomment)
458
459 gpo.po_message_set_format(self._gpo_message, typecomment, 1)
424 460
425 def hasmarkedcomment(self, commentmarker): 461 def hasmarkedcomment(self, commentmarker):
426 commentmarker = "(%s)" % commentmarker 462 commentmarker = "(%s)" % commentmarker
427 for comment in self.getnotes("translator").split("\n"): 463 for comment in self.getnotes("translator").split("\n"):
428 if comment.startswith(commentmarker): 464 if comment.startswith(commentmarker):
429 return True 465 return True
430 return False 466 return False
431 467
432 def istranslated(self): 468 def istranslated(self):
433 return super(pounit, self).istranslated() and not self.isobsolete() 469 return super(pounit, self).istranslated() and not self.isobsolete()
434 470
435 def istranslatable(self): 471 def istranslatable(self):
436 return not (self.isheader() or self.isblank() or self.isobsolete()) 472 return not (self.isheader() or self.isblank() or self.isobsolete())
437 473
438 def isfuzzy(self): 474 def isfuzzy(self):
439 return gpo.po_message_is_fuzzy(self._gpo_message) 475 return gpo.po_message_is_fuzzy(self._gpo_message)
440 476
441 def markfuzzy(self, present=True): 477 def markfuzzy(self, present=True):
442 gpo.po_message_set_fuzzy(self._gpo_message, present) 478 gpo.po_message_set_fuzzy(self._gpo_message, present)
443 479
444 def isreview(self): 480 def isreview(self):
445 return self.hasmarkedcomment("review") or self.hasmarkedcomment("pofilte r") 481 return self.hasmarkedcomment("review") or self.hasmarkedcomment("pofilte r")
446 482
447 def isobsolete(self): 483 def isobsolete(self):
448 return gpo.po_message_is_obsolete(self._gpo_message) 484 return gpo.po_message_is_obsolete(self._gpo_message)
449 485
450 def makeobsolete(self): 486 def makeobsolete(self):
451 # FIXME: libgettexpo currently does not reset other data, we probably wa nt to do that 487 # FIXME: libgettexpo currently does not reset other data, we probably wa nt to do that
452 # but a better solution would be for libgettextpo to output correct data on serialisation 488 # but a better solution would be for libgettextpo to output correct data on serialisation
453 gpo.po_message_set_obsolete(self._gpo_message, True) 489 gpo.po_message_set_obsolete(self._gpo_message, True)
454 490
455 def resurrect(self): 491 def resurrect(self):
456 gpo.po_message_set_obsolete(self._gpo_message, False) 492 gpo.po_message_set_obsolete(self._gpo_message, False)
457 493
458 def hasplural(self): 494 def hasplural(self):
459 return gpo.po_message_msgid_plural(self._gpo_message) is not None 495 return gpo.po_message_msgid_plural(self._gpo_message) is not None
460 496
461 def _extract_msgidcomments(self, text=None): 497 def _extract_msgidcomments(self, text=None):
462 """Extract KDE style msgid comments from the unit. 498 """Extract KDE style msgid comments from the unit.
463 499
464 @rtype: String 500 @rtype: String
465 @return: Returns the extracted msgidcomments found in this unit's msgid. 501 @return: Returns the extracted msgidcomments found in this unit's msgid.
466 502
467 """ 503 """
468 504
469 if not text: 505 if not text:
470 text = gpo.po_message_msgid(self._gpo_message) 506 text = gpo.po_message_msgid(self._gpo_message)
471 if text: 507 if text:
472 msgidcomment = re.search("_: (.*)\n", text) 508 msgidcomment = re.search("_: (.*)\n", text)
473 if msgidcomment: 509 if msgidcomment:
(...skipping 162 matching lines...) Show 10 above Show 10 below
636 posrc = input.read() 672 posrc = input.read()
637 input.close() 673 input.close()
638 input = posrc 674 input = posrc
639 675
640 needtmpfile = not os.path.isfile(input) 676 needtmpfile = not os.path.isfile(input)
641 if needtmpfile: 677 if needtmpfile:
642 # This is not a file - we write the string to a temporary file 678 # This is not a file - we write the string to a temporary file
643 fd, fname = tempfile.mkstemp(prefix='translate', suffix='.po') 679 fd, fname = tempfile.mkstemp(prefix='translate', suffix='.po')
644 os.write(fd, input) 680 os.write(fd, input)
645 input = fname 681 input = fname
646 os.close(fd) 682 os.close(fd)
647 683
648 self._gpo_memory_file = gpo.po_file_read_v3(input, xerror_handler) 684 self._gpo_memory_file = gpo.po_file_read_v3(input, xerror_handler)
649 if self._gpo_memory_file is None: 685 if self._gpo_memory_file is None:
650 print >> sys.stderr, "Error:" 686 print >> sys.stderr, "Error:"
651 687
652 if needtmpfile: 688 if needtmpfile:
653 os.remove(input) 689 os.remove(input)
654 690
655 # Handle xerrors here 691 # Handle xerrors here
656 self._header = gpo.po_file_domain_header(self._gpo_memory_file, None) 692 self._header = gpo.po_file_domain_header(self._gpo_memory_file, None)
657 if self._header: 693 if self._header:
658 charset = gpo.po_header_field(self._header, "Content-Type") 694 charset = gpo.po_header_field(self._header, "Content-Type")
659 if charset: 695 if charset:
660 charset = re.search("charset=([^\\s]+)", charset).group(1) 696 charset = re.search("charset=([^\\s]+)", charset).group(1)
661 self._encoding = encodingToUse(charset) 697 self._encoding = encodingToUse(charset)
662 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_fi le, None) 698 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_fi le, None)
663 newmessage = gpo.po_next_message(self._gpo_message_iterator) 699 newmessage = gpo.po_next_message(self._gpo_message_iterator)
664 while newmessage: 700 while newmessage:
665 newunit = pounit(gpo_message=newmessage) 701 newunit = pounit(gpo_message=newmessage)
666 self.addunit(newunit, new=False) 702 self.addunit(newunit, new=False)
667 newmessage = gpo.po_next_message(self._gpo_message_iterator) 703 newmessage = gpo.po_next_message(self._gpo_message_iterator)
668 self._free_iterator() 704 self._free_iterator()
669 705
670 def __del__(self): 706 def __del__(self):
671 # We currently disable this while we still get segmentation faults. 707 # We currently disable this while we still get segmentation faults.
672 # Note that this is definitely leaking memory because of this. 708 # Note that this is definitely leaking memory because of this.
673 return 709 return
674 self._free_iterator() 710 self._free_iterator()
675 if self._gpo_memory_file is not None: 711 if self._gpo_memory_file is not None:
676 gpo.po_file_free(self._gpo_memory_file) 712 gpo.po_file_free(self._gpo_memory_file)
677 self._gpo_memory_file = None 713 self._gpo_memory_file = None
678 714
679 def _free_iterator(self): 715 def _free_iterator(self):
680 # We currently disable this while we still get segmentation faults. 716 # We currently disable this while we still get segmentation faults.
681 # Note that this is definitely leaking memory because of this. 717 # Note that this is definitely leaking memory because of this.
682 return 718 return
683 if self._gpo_message_iterator is not None: 719 if self._gpo_message_iterator is not None:
684 gpo.po_message_iterator_free(self._gpo_message_iterator) 720 gpo.po_message_iterator_free(self._gpo_message_iterator)
685 self._gpo_message_iterator = None 721 self._gpo_message_iterator = None
OLDNEW

Powered by Google App Engine
This is Rietveld r159