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

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

Issue 101: Add setcontext method in PO storage classes 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"""
(...skipping 406 matching lines...) Show 10 above Show 10 below
457 457
458 def hasplural(self): 458 def hasplural(self):
459 return gpo.po_message_msgid_plural(self._gpo_message) is not None 459 return gpo.po_message_msgid_plural(self._gpo_message) is not None
460 460
461 def _extract_msgidcomments(self, text=None): 461 def _extract_msgidcomments(self, text=None):
462 """Extract KDE style msgid comments from the unit. 462 """Extract KDE style msgid comments from the unit.
463 463
464 @rtype: String 464 @rtype: String
465 @return: Returns the extracted msgidcomments found in this unit's msgid. 465 @return: Returns the extracted msgidcomments found in this unit's msgid.
466 466
467 """ 467 """
468 468
469 if not text: 469 if not text:
470 text = gpo.po_message_msgid(self._gpo_message) 470 text = gpo.po_message_msgid(self._gpo_message)
471 if text: 471 if text:
472 msgidcomment = re.search("_: (.*)\n", text) 472 msgidcomment = re.search("_: (.*)\n", text)
473 if msgidcomment: 473 if msgidcomment:
474 return msgidcomment.group(1).decode(self._encoding) 474 return msgidcomment.group(1).decode(self._encoding)
475 return u"" 475 return u""
476 476
477 def __str__(self): 477 def __str__(self):
478 pf = pofile() 478 pf = pofile()
479 pf.addunit(self) 479 pf.addunit(self)
480 return str(pf) 480 return str(pf)
481 481
482 def getlocations(self): 482 def getlocations(self):
483 locations = [] 483 locations = []
484 i = 0 484 i = 0
485 location = gpo.po_message_filepos(self._gpo_message, i) 485 location = gpo.po_message_filepos(self._gpo_message, i)
486 while location: 486 while location:
487 locname = gpo.po_filepos_file(location) 487 locname = gpo.po_filepos_file(location)
488 locline = gpo.po_filepos_start_line(location) 488 locline = gpo.po_filepos_start_line(location)
489 if locline == -1: 489 if locline == -1:
490 locstring = locname 490 locstring = locname
491 else: 491 else:
492 locstring = locname + ":" + str(locline) 492 locstring = locname + ":" + str(locline)
493 locations.append(locstring) 493 locations.append(locstring)
494 i += 1 494 i += 1
495 location = gpo.po_message_filepos(self._gpo_message, i) 495 location = gpo.po_message_filepos(self._gpo_message, i)
496 return locations 496 return locations
497 497
498 def addlocation(self, location): 498 def addlocation(self, location):
499 for loc in location.split(): 499 for loc in location.split():
500 parts = loc.split(":") 500 parts = loc.split(":")
501 file = parts[0] 501 file = parts[0]
502 if len(parts) == 2: 502 if len(parts) == 2:
503 line = int(parts[1]) 503 line = int(parts[1])
504 else: 504 else:
505 line = -1 505 line = -1
506 gpo.po_message_add_filepos(self._gpo_message, file, line) 506 gpo.po_message_add_filepos(self._gpo_message, file, line)
507
508 def setcontext(self, context):
509 """Sets the context message"""
510 gpo.po_message_set_msgctxt(self._gpo_message, context)
507 511
508 def getcontext(self): 512 def getcontext(self):
509 msgctxt = gpo.po_message_msgctxt(self._gpo_message) 513 msgctxt = gpo.po_message_msgctxt(self._gpo_message)
510 msgidcomment = self._extract_msgidcomments() 514 msgidcomment = self._extract_msgidcomments()
511 if msgctxt: 515 if msgctxt:
512 return msgctxt + msgidcomment 516 return msgctxt + msgidcomment
513 else: 517 else:
514 return msgidcomment 518 return msgidcomment
515 519
516 class pofile(pocommon.pofile): 520 class pofile(pocommon.pofile):
517 UnitClass = pounit 521 UnitClass = pounit
518 def __init__(self, inputfile=None, encoding=None, unitclass=pounit): 522 def __init__(self, inputfile=None, encoding=None, unitclass=pounit):
519 self.UnitClass = unitclass 523 self.UnitClass = unitclass
520 pocommon.pofile.__init__(self, unitclass=unitclass) 524 pocommon.pofile.__init__(self, unitclass=unitclass)
521 self._gpo_memory_file = None 525 self._gpo_memory_file = None
522 self._gpo_message_iterator = None 526 self._gpo_message_iterator = None
523 self._encoding = encodingToUse(encoding) 527 self._encoding = encodingToUse(encoding)
524 if inputfile is not None: 528 if inputfile is not None:
525 self.parse(inputfile) 529 self.parse(inputfile)
526 else: 530 else:
527 self._gpo_memory_file = gpo.po_file_create() 531 self._gpo_memory_file = gpo.po_file_create()
528 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memor y_file, None) 532 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memor y_file, None)
529 533
530 def addunit(self, unit): 534 def addunit(self, unit):
531 gpo.po_message_insert(self._gpo_message_iterator, unit._gpo_message) 535 gpo.po_message_insert(self._gpo_message_iterator, unit._gpo_message)
532 self.units.append(unit) 536 self.units.append(unit)
533 537
534 def removeduplicates(self, duplicatestyle="merge"): 538 def removeduplicates(self, duplicatestyle="merge"):
535 """make sure each msgid is unique ; merge comments etc from duplicates i nto original""" 539 """make sure each msgid is unique ; merge comments etc from duplicates i nto original"""
536 msgiddict = {} 540 msgiddict = {}
537 uniqueunits = [] 541 uniqueunits = []
538 # we sometimes need to keep track of what has been marked 542 # we sometimes need to keep track of what has been marked
539 # TODO: this is using a list as the pos aren't hashable, but this is slo w... 543 # TODO: this is using a list as the pos aren't hashable, but this is slo w...
540 markedpos = [] 544 markedpos = []
541 def addcomment(thepo): 545 def addcomment(thepo):
542 thepo.msgidcomment = " ".join(thepo.getlocations()) 546 thepo.msgidcomment = " ".join(thepo.getlocations())
543 markedpos.append(thepo) 547 markedpos.append(thepo)
544 for thepo in self.units: 548 for thepo in self.units:
545 if thepo.isheader(): 549 if thepo.isheader():
546 uniqueunits.append(thepo) 550 uniqueunits.append(thepo)
547 continue 551 continue
548 if duplicatestyle.startswith("msgid_comment"): 552 if duplicatestyle.startswith("msgid_comment"):
549 msgid = thepo._extract_msgidcomments() + thepo.source 553 msgid = thepo._extract_msgidcomments() + thepo.source
550 else: 554 else:
551 msgid = thepo.source 555 msgid = thepo.source
552 if duplicatestyle == "msgid_comment_all": 556 if duplicatestyle == "msgid_comment_all":
553 addcomment(thepo) 557 addcomment(thepo)
554 uniqueunits.append(thepo) 558 uniqueunits.append(thepo)
555 elif msgid in msgiddict: 559 elif msgid in msgiddict:
556 if duplicatestyle == "merge": 560 if duplicatestyle == "merge":
(...skipping 78 matching lines...) Show 10 above Show 10 below
635 posrc = input.read() 639 posrc = input.read()
636 input.close() 640 input.close()
637 input = posrc 641 input = posrc
638 642
639 needtmpfile = not os.path.isfile(input) 643 needtmpfile = not os.path.isfile(input)
640 if needtmpfile: 644 if needtmpfile:
641 # This is not a file - we write the string to a temporary file 645 # This is not a file - we write the string to a temporary file
642 fd, fname = tempfile.mkstemp(prefix='translate', suffix='.po') 646 fd, fname = tempfile.mkstemp(prefix='translate', suffix='.po')
643 os.write(fd, input) 647 os.write(fd, input)
644 input = fname 648 input = fname
645 os.close(fd) 649 os.close(fd)
646 650
647 self._gpo_memory_file = gpo.po_file_read_v3(input, xerror_handler) 651 self._gpo_memory_file = gpo.po_file_read_v3(input, xerror_handler)
648 if self._gpo_memory_file is None: 652 if self._gpo_memory_file is None:
649 print >> sys.stderr, "Error:" 653 print >> sys.stderr, "Error:"
650 654
651 if needtmpfile: 655 if needtmpfile:
652 os.remove(input) 656 os.remove(input)
653 657
654 # Handle xerrors here 658 # Handle xerrors here
655 self._header = gpo.po_file_domain_header(self._gpo_memory_file, None) 659 self._header = gpo.po_file_domain_header(self._gpo_memory_file, None)
656 if self._header: 660 if self._header:
657 charset = gpo.po_header_field(self._header, "Content-Type") 661 charset = gpo.po_header_field(self._header, "Content-Type")
658 if charset: 662 if charset:
659 charset = re.search("charset=([^\\s]+)", charset).group(1) 663 charset = re.search("charset=([^\\s]+)", charset).group(1)
660 self._encoding = encodingToUse(charset) 664 self._encoding = encodingToUse(charset)
661 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_fi le, None) 665 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_fi le, None)
662 newmessage = gpo.po_next_message(self._gpo_message_iterator) 666 newmessage = gpo.po_next_message(self._gpo_message_iterator)
663 while newmessage: 667 while newmessage:
664 newunit = pounit(gpo_message=newmessage) 668 newunit = pounit(gpo_message=newmessage)
665 self.units.append(newunit) 669 self.units.append(newunit)
666 newmessage = gpo.po_next_message(self._gpo_message_iterator) 670 newmessage = gpo.po_next_message(self._gpo_message_iterator)
667 self._free_iterator() 671 self._free_iterator()
668 672
669 def __del__(self): 673 def __del__(self):
670 # We currently disable this while we still get segmentation faults. 674 # We currently disable this while we still get segmentation faults.
671 # Note that this is definitely leaking memory because of this. 675 # Note that this is definitely leaking memory because of this.
672 return 676 return
673 self._free_iterator() 677 self._free_iterator()
674 if self._gpo_memory_file is not None: 678 if self._gpo_memory_file is not None:
675 gpo.po_file_free(self._gpo_memory_file) 679 gpo.po_file_free(self._gpo_memory_file)
676 self._gpo_memory_file = None 680 self._gpo_memory_file = None
677 681
678 def _free_iterator(self): 682 def _free_iterator(self):
679 # We currently disable this while we still get segmentation faults. 683 # We currently disable this while we still get segmentation faults.
680 # Note that this is definitely leaking memory because of this. 684 # Note that this is definitely leaking memory because of this.
681 return 685 return
682 if self._gpo_message_iterator is not None: 686 if self._gpo_message_iterator is not None:
683 gpo.po_message_iterator_free(self._gpo_message_iterator) 687 gpo.po_message_iterator_free(self._gpo_message_iterator)
684 self._gpo_message_iterator = None 688 self._gpo_message_iterator = None
OLDNEW

Powered by Google App Engine
This is Rietveld r159