Index: translate/storage/test_cpo.py =================================================================== --- translate/storage/test_cpo.py (revision 8224) +++ translate/storage/test_cpo.py (working copy) @@ -72,6 +72,29 @@ unit.addnote("# Double commented comment") assert unit.getnotes() == "# Double commented comment" + def test_context(self): + unit = self.UnitClass("Message") + assert unit.getcontext() == u"" + + unit.setcontext("context message") + assert unit.getcontext() == u"context message" + + unit.setcontext("") + assert unit.getcontext() == u"" + + def test_typecomment(self): + unit = self.UnitClass("Comment") + assert unit.gettypecomments() == [] + + unit.addtypecomment("c-format") + assert unit.hastypecomment("c-format") + assert unit.gettypecomments() == ["c-format"] + + unit.addtypecomment("invalid-format") + assert not unit.hastypecomment("invalid-format") + assert unit.gettypecomments() == ["c-format"] + + class TestCPOFile(test_po.TestPOFile): StoreClass = cpo.pofile def test_msgidcomments(self): Index: translate/storage/cpo.py =================================================================== --- translate/storage/cpo.py (revision 8224) +++ translate/storage/cpo.py (working copy) @@ -120,7 +120,7 @@ gpo.po_filepos_file.restype = STRING gpo.po_message_filepos.restype = c_int gpo.po_message_filepos.argtypes = [c_int, c_int] -gpo.po_message_add_filepos.argtypes = [c_int, STRING, c_int] +gpo.po_message_add_filepos.argtypes = [c_int, STRING, c_size_t] # Message (get methods) gpo.po_message_comments.restype = STRING @@ -140,6 +140,7 @@ gpo.po_message_set_extracted_comments.argtypes = [c_int, STRING] gpo.po_message_set_fuzzy.argtypes = [c_int, c_int] gpo.po_message_set_msgctxt.argtypes = [c_int, STRING] +gpo.po_message_set_format.argtypes = [c_int, STRING, c_int] # Setup the po_xerror_handler xerror_handler = po_xerror_handler() @@ -371,9 +372,34 @@ gpo.po_message_set_comments(self._gpo_message, "") def copy(self): - newpo = self.__class__() - newpo._gpo_message = self._gpo_message - return newpo + """Returns a copy of the this unit that can be used independently. + """ + unit = pounit() + unit.source = self.source + unit.target = self.target + unit.markfuzzy(self.isfuzzy()) + if self.isobsolete(): + unit.makeobsolete() + for location in self.getlocations(): + unit.addlocation(location) + notes = [] + origins = ['translator', 'developer', 'programmer', 'source code'] + for origin in origins: + note = self.getnotes(origin=origin) + if note in notes: + continue + else: + unit.addnote(note, origin=origin) + notes.append(note) + context = gpo.po_message_msgctxt(self._gpo_message) + if context: + unit.setcontext(context) + comments = self._extract_msgidcomments() + if comments: + unit.setmsgidcomment(comments) + for typecomment in self.gettypecomments(): + unit.addtypecomment(typecomment) + return unit def merge(self, otherpo, overwrite=False, comments=True, authoritative=False): """Merges the otherpo (with the same msgid) into this one. @@ -422,6 +448,32 @@ def hastypecomment(self, typecomment): return gpo.po_message_is_format(self._gpo_message, typecomment) + def gettypecomments(self): + """Returns the type comments of a unit, if any. + + @return: a list containing the type comments of the unit + """ + #XXX: brute force + formats = [ + "c", "objc", "sh", "python", "lisp", "elisp", "librep", "scheme", + "smalltalk", "java", "csharp", "awk", "object-pascal", "ycp", "tcl", + "perl", "perl-brace", "php", "gcc-internal", "qt", "kde", "boost", + ] + comments = [] + for format in formats: + format += '-format' + if self.hastypecomment(format): + comments.append(format) + return comments + + def addtypecomment(self, typecomment): + """Adds a type comment to the unit + + @oaram typecomment: the type comment to be added, for example + "c-format". + """ + gpo.po_message_set_format(self._gpo_message, typecomment, 1) + def hasmarkedcomment(self, commentmarker): commentmarker = "(%s)" % commentmarker for comment in self.getnotes("translator").split("\n"): @@ -476,7 +528,8 @@ def __str__(self): pf = pofile() - pf.addunit(self) + unit = self.copy() + pf.addunit(unit) return str(pf) def getlocations(self): @@ -502,9 +555,15 @@ if len(parts) == 2: line = int(parts[1]) else: - line = -1 + # libgettextpo requires a (size_t)(-1) if no file + # location is available + line = c_size_t(-1) gpo.po_message_add_filepos(self._gpo_message, file, line) + def setcontext(self, context): + """Sets the context message""" + gpo.po_message_set_msgctxt(self._gpo_message, context) + def getcontext(self): msgctxt = gpo.po_message_msgctxt(self._gpo_message) msgidcomment = self._extract_msgidcomments() @@ -528,9 +587,15 @@ self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_file, None) def addunit(self, unit): - gpo.po_message_insert(self._gpo_message_iterator, unit._gpo_message) - self.units.append(unit) + unitcopy = unit.copy() + gpo.po_message_insert(self._gpo_message_iterator, unitcopy._gpo_message) + self.units.append(unitcopy) + def addsourceunit(self, source): + self.addunit(self.UnitClass(source)) + unit = self.findunit(source) + return unit + def removeduplicates(self, duplicatestyle="merge"): """make sure each msgid is unique ; merge comments etc from duplicates into original""" msgiddict = {} @@ -664,12 +729,10 @@ newunit = pounit(gpo_message=newmessage) self.units.append(newunit) newmessage = gpo.po_next_message(self._gpo_message_iterator) - self._free_iterator() def __del__(self): # We currently disable this while we still get segmentation faults. # Note that this is definitely leaking memory because of this. - return self._free_iterator() if self._gpo_memory_file is not None: gpo.po_file_free(self._gpo_memory_file) @@ -678,7 +741,6 @@ def _free_iterator(self): # We currently disable this while we still get segmentation faults. # Note that this is definitely leaking memory because of this. - return if self._gpo_message_iterator is not None: gpo.po_message_iterator_free(self._gpo_message_iterator) self._gpo_message_iterator = None