« no previous file
|
no next file »
Index: pootlefile.py
===================================================================
--- pootlefile.py (revision 7756)
+++ pootlefile.py (working copy)
@@ -230,401 +230,423 @@
assignitems.extend(actionitems)
return assignitems
-class pootlebase(object):
- pass
-
-class pootlefile(pootlebase):
- """this represents a pootle-managed file and its associated files"""
- x_generator = "Pootle %s" % __version__.ver
- def __init__(self, project=None, pofilename=None):
- if pofilename:
- self.__class__.__bases__ = (factory.getclass(pofilename),)
- super(pootlefile, self).__init__()
- self.pofilename = pofilename
- if project is None:
- from Pootle import projects
- self.project = projects.DummyProject(None)
- self.checker = None
- self.filename = self.pofilename
- else:
- self.project = project
- self.checker = self.project.checker
- self.filename = os.path.join(self.project.podir, self.pofilename)
-
- self.lockedfile = LockedFile(self.filename)
- # we delay parsing until it is required
- self.pomtime = None
- self.assigns = None
-
- self.pendingfilename = self.filename + os.extsep + "pending"
- self.pendingfile = None
- self.statistics = statistics.pootlestatistics(self)
- self.tmfilename = self.filename + os.extsep + "tm"
- # we delay parsing until it is required
- self.pomtime = None
- self.tracker = timecache.timecache(20*60)
-
- def parsestring(cls, storestring):
- newstore = cls()
- newstore.parse(storestring)
- return newstore
- parsestring = classmethod(parsestring)
-
- def parsefile(cls, storefile):
- """Reads the given file (or opens the given filename) and parses back to an object"""
- if isinstance(storefile, basestring):
- storefile = open(storefile, "r")
- if "r" in getattr(storefile, "mode", "r"):
- storestring = storefile.read()
- else:
- storestring = ""
- return cls.parsestring(storestring)
- parsefile = classmethod(parsefile)
-
- def getheaderplural(self):
- """returns values for nplural and plural values. It tries to see if the
- file has it specified (in a po header or similar)."""
- try:
- return super(pootlefile, self).getheaderplural()
- except AttributeError:
- return None, None
-
- def updateheaderplural(self, *args, **kwargs):
- """updates the file header. If there is an updateheader function in the
- underlying store it will be delegated there."""
- try:
- super(pootlefile, self).updateheaderplural(*args, **kwargs)
- except AttributeError:
- pass
-
- def updateheader(self, **kwargs):
- """updates the file header. If there is an updateheader function in the
- underlying store it will be delegated there."""
- try:
- super(pootlefile, self).updateheader(**kwargs)
- except AttributeError:
- pass
-
- def readpendingfile(self):
- """reads and parses the pending file corresponding to this file"""
- if os.path.exists(self.pendingfilename):
- inputfile = open(self.pendingfilename, "r")
- self.pendingfile = factory.getobject(inputfile, ignore=".pending")
- else:
- self.pendingfile = po.pofile()
-
- def savependingfile(self):
- """saves changes to disk..."""
- output = str(self.pendingfile)
- outputfile = open(self.pendingfilename, "w")
- outputfile.write(output)
- outputfile.close()
-
- def readtmfile(self):
- """reads and parses the tm file corresponding to this file"""
- if os.path.exists(self.tmfilename):
- tmmtime = statistics.getmodtime(self.tmfilename)
- if tmmtime == getattr(self, "tmmtime", None):
+def make_class(base_class):
+ class pootlefile(base_class):
+ """this represents a pootle-managed file and its associated files"""
+ x_generator = "Pootle %s" % __version__.ver
+ def __init__(self, project=None, pofilename=None):
+ if pofilename:
+ self.__class__.__bases__ = (factory.getclass(pofilename),)
+ super(pootlefile, self).__init__()
+ self.pofilename = pofilename
+ if project is None:
+ from Pootle import projects
+ self.project = projects.DummyProject(None)
+ self.checker = None
+ self.filename = self.pofilename
+ else:
+ self.project = project
+ self.checker = self.project.checker
+ self.filename = os.path.join(self.project.podir, self.pofilename)
+
+ self.lockedfile = LockedFile(self.filename)
+ # we delay parsing until it is required
+ self.pomtime = None
+ self.assigns = None
+
+ self.pendingfilename = self.filename + os.extsep + "pending"
+ self.pendingfile = None
+ self.statistics = statistics.pootlestatistics(self)
+ self.tmfilename = self.filename + os.extsep + "tm"
+ # we delay parsing until it is required
+ self.pomtime = None
+ self.tracker = timecache.timecache(20*60)
+
+ def parsestring(cls, storestring):
+ newstore = cls()
+ newstore.parse(storestring)
+ return newstore
+ parsestring = classmethod(parsestring)
+
+ def parsefile(cls, storefile):
+ """Reads the given file (or opens the given filename) and parses back to an object"""
+ if isinstance(storefile, basestring):
+ storefile = open(storefile, "r")
+ if "r" in getattr(storefile, "mode", "r"):
+ storestring = storefile.read()
+ else:
+ storestring = ""
+ return cls.parsestring(storestring)
+ parsefile = classmethod(parsefile)
+
+ def getheaderplural(self):
+ """returns values for nplural and plural values. It tries to see if the
+ file has it specified (in a po header or similar)."""
+ try:
+ return super(pootlefile, self).getheaderplural()
+ except AttributeError:
+ return None, None
+
+ def updateheaderplural(self, *args, **kwargs):
+ """updates the file header. If there is an updateheader function in the
+ underlying store it will be delegated there."""
+ try:
+ super(pootlefile, self).updateheaderplural(*args, **kwargs)
+ except AttributeError:
+ pass
+
+ def updateheader(self, **kwargs):
+ """updates the file header. If there is an updateheader function in the
+ underlying store it will be delegated there."""
+ try:
+ super(pootlefile, self).updateheader(**kwargs)
+ except AttributeError:
+ pass
+
+ def readpendingfile(self):
+ """reads and parses the pending file corresponding to this file"""
+ if os.path.exists(self.pendingfilename):
+ inputfile = open(self.pendingfilename, "r")
+ self.pendingfile = factory.getobject(inputfile, ignore=".pending")
+ else:
+ self.pendingfile = po.pofile()
+
+ def savependingfile(self):
+ """saves changes to disk..."""
+ output = str(self.pendingfile)
+ outputfile = open(self.pendingfilename, "w")
+ outputfile.write(output)
+ outputfile.close()
+
+ def readtmfile(self):
+ """reads and parses the tm file corresponding to this file"""
+ if os.path.exists(self.tmfilename):
+ tmmtime = statistics.getmodtime(self.tmfilename)
+ if tmmtime == getattr(self, "tmmtime", None):
+ return
+ inputfile = open(self.tmfilename, "r")
+ self.tmmtime, self.tmfile = tmmtime, factory.getobject(inputfile, ignore=".tm")
+ else:
+ self.tmfile = po.pofile()
+
+ def getsuggestions(self, item):
+ """find all the suggestion items submitted for the given item"""
+ unit = self.getitem(item)
+ if isinstance(unit, xliff.xliffunit):
+ return unit.getalttrans()
+
+ locations = unit.getlocations()
+ self.readpendingfile()
+ # TODO: review the matching method
+ suggestpos = [suggestpo for suggestpo in self.pendingfile.units if suggestpo.getlocations() == locations]
+ return suggestpos
+
+ def addsuggestion(self, item, suggtarget, username):
+ """adds a new suggestion for the given item"""
+ unit = self.getitem(item)
+ if isinstance(unit, xliff.xliffunit):
+ if isinstance(suggtarget, list) and (len(suggtarget) > 0):
+ suggtarget = suggtarget[0]
+ unit.addalttrans(suggtarget, origin=username)
+ self.statistics.reclassifyunit(item)
+ self.savepofile()
return
- inputfile = open(self.tmfilename, "r")
- self.tmmtime, self.tmfile = tmmtime, factory.getobject(inputfile, ignore=".tm")
- else:
- self.tmfile = po.pofile()
-
- def getsuggestions(self, item):
- """find all the suggestion items submitted for the given item"""
- unit = self.getitem(item)
- if isinstance(unit, xliff.xliffunit):
- return unit.getalttrans()
-
- locations = unit.getlocations()
- self.readpendingfile()
- # TODO: review the matching method
- suggestpos = [suggestpo for suggestpo in self.pendingfile.units if suggestpo.getlocations() == locations]
- return suggestpos
-
- def addsuggestion(self, item, suggtarget, username):
- """adds a new suggestion for the given item"""
- unit = self.getitem(item)
- if isinstance(unit, xliff.xliffunit):
- if isinstance(suggtarget, list) and (len(suggtarget) > 0):
- suggtarget = suggtarget[0]
- unit.addalttrans(suggtarget, origin=username)
+
+ self.readpendingfile()
+ newpo = unit.copy()
+ if username is not None:
+ newpo.msgidcomments.append('"_: suggested by %s\\n"' % username)
+ newpo.target = suggtarget
+ newpo.markfuzzy(False)
+ self.pendingfile.addunit(newpo)
+ self.savependingfile()
self.statistics.reclassifyunit(item)
+
+ def deletesuggestion(self, item, suggitem):
+ """removes the suggestion from the pending file"""
+ unit = self.getitem(item)
+ if hasattr(unit, "xmlelement"):
+ suggestions = self.getsuggestions(item)
+ unit.delalttrans(suggestions[suggitem])
+ self.savepofile()
+ else:
+ self.readpendingfile()
+ locations = unit.getlocations()
+ # TODO: remove the suggestion in a less brutal manner
+ pendingitems = [pendingitem for pendingitem, suggestpo in enumerate(self.pendingfile.units) if suggestpo.getlocations() == locations]
+ pendingitem = pendingitems[suggitem]
+ del self.pendingfile.units[pendingitem]
+ self.savependingfile()
+ self.statistics.reclassifyunit(item)
+
+ def getsuggester(self, item, suggitem):
+ """returns who suggested the given item's suggitem if recorded, else None"""
+ unit = self.getsuggestions(item)[suggitem]
+ if hasattr(unit, "xmlelement"):
+ return unit.xmlelement.get("origin")
+
+ for msgidcomment in unit.msgidcomments:
+ if msgidcomment.find("suggested by ") != -1:
+ suggestedby = po.unquotefrompo([msgidcomment]).replace("_:", "", 1).replace("suggested by ", "", 1).strip()
+ return suggestedby
+ return None
+
+ def gettmsuggestions(self, item):
+ """find all the tmsuggestion items submitted for the given item"""
+ self.readtmfile()
+ unit = self.getitem(item)
+ locations = unit.getlocations()
+ # TODO: review the matching method
+ # Can't simply use the location index, because we want multiple matches
+ suggestpos = [suggestpo for suggestpo in self.tmfile.units if suggestpo.getlocations() == locations]
+ return suggestpos
+
+ def track(self, item, message):
+ """sets the tracker message for the given item"""
+ self.tracker[item] = message
+
+ def readpofile(self):
+ """reads and parses the main file"""
+ # make sure encoding is reset so it is read from the file
+ self.encoding = None
+ self.units = []
+ pomtime, filecontents = self.lockedfile.getcontents()
+ # note: we rely on this not resetting the filename, which we set earlier, when given a string
+ self.parse(filecontents)
+ self.pomtime = pomtime
+
+ def savepofile(self):
+ """saves changes to the main file to disk..."""
+ output = str(self)
+ self.pomtime = self.lockedfile.writecontents(output)
+
+ def pofreshen(self):
+ """makes sure we have a freshly parsed pofile"""
+ try:
+ if self.pomtime != self.lockedfile.readmodtime():
+ self.readpofile()
+ except OSError, e:
+ # If this exception is not triggered by a bad
+ # symlink, then we have a missing file on our hands...
+ if not os.path.islink(self.filename):
+ # ...and thus we rescan our files to get rid of the missing filename
+ self.project.scanpofiles()
+ else:
+ print "%s is a broken symlink" % (self.filename,)
+
+ def getoutput(self):
+ """returns pofile output"""
+ self.pofreshen()
+ return super(pootlefile, self).getoutput()
+
+ def updateunit(self, item, newvalues, userprefs, languageprefs):
+ """updates a translation with a new target value"""
+ self.pofreshen()
+ unit = self.getitem(item)
+
+ if newvalues.has_key("target"):
+ unit.target = newvalues["target"]
+ if newvalues.has_key("fuzzy"):
+ unit.markfuzzy(newvalues["fuzzy"])
+ if newvalues.has_key("translator_comments"):
+ unit.removenotes()
+ if newvalues["translator_comments"]:
+ unit.addnote(newvalues["translator_comments"])
+
+ po_revision_date = time.strftime("%Y-%m-%d %H:%M") + tzstring()
+ headerupdates = {"PO_Revision_Date": po_revision_date, "X_Generator": self.x_generator}
+ if userprefs:
+ if getattr(userprefs, "name", None) and getattr(userprefs, "email", None):
+ headerupdates["Last_Translator"] = "%s <%s>" % (userprefs.name, userprefs.email)
+ # XXX: If we needed to add a header, the index value in item will be one out after
+ # adding the header.
+ # TODO: remove once we force the PO class to always output headers
+ force_recache = False
+ if not self.header():
+ force_recache = True
+ self.updateheader(add=True, **headerupdates)
+ if languageprefs:
+ nplurals = getattr(languageprefs, "nplurals", None)
+ pluralequation = getattr(languageprefs, "pluralequation", None)
+ if nplurals and pluralequation:
+ self.updateheaderplural(nplurals, pluralequation)
self.savepofile()
- return
-
- self.readpendingfile()
- newpo = unit.copy()
- if username is not None:
- newpo.msgidcomments.append('"_: suggested by %s\\n"' % username)
- newpo.target = suggtarget
- newpo.markfuzzy(False)
- self.pendingfile.addunit(newpo)
- self.savependingfile()
- self.statistics.reclassifyunit(item)
-
- def deletesuggestion(self, item, suggitem):
- """removes the suggestion from the pending file"""
- unit = self.getitem(item)
- if hasattr(unit, "xmlelement"):
- suggestions = self.getsuggestions(item)
- unit.delalttrans(suggestions[suggitem])
- self.savepofile()
- else:
- self.readpendingfile()
- locations = unit.getlocations()
- # TODO: remove the suggestion in a less brutal manner
- pendingitems = [pendingitem for pendingitem, suggestpo in enumerate(self.pendingfile.units) if suggestpo.getlocations() == locations]
- pendingitem = pendingitems[suggitem]
- del self.pendingfile.units[pendingitem]
- self.savependingfile()
- self.statistics.reclassifyunit(item)
-
- def getsuggester(self, item, suggitem):
- """returns who suggested the given item's suggitem if recorded, else None"""
- unit = self.getsuggestions(item)[suggitem]
- if hasattr(unit, "xmlelement"):
- return unit.xmlelement.get("origin")
-
- for msgidcomment in unit.msgidcomments:
- if msgidcomment.find("suggested by ") != -1:
- suggestedby = po.unquotefrompo([msgidcomment]).replace("_:", "", 1).replace("suggested by ", "", 1).strip()
- return suggestedby
- return None
-
- def gettmsuggestions(self, item):
- """find all the tmsuggestion items submitted for the given item"""
- self.readtmfile()
- unit = self.getitem(item)
- locations = unit.getlocations()
- # TODO: review the matching method
- # Can't simply use the location index, because we want multiple matches
- suggestpos = [suggestpo for suggestpo in self.tmfile.units if suggestpo.getlocations() == locations]
- return suggestpos
-
- def track(self, item, message):
- """sets the tracker message for the given item"""
- self.tracker[item] = message
-
- def readpofile(self):
- """reads and parses the main file"""
- # make sure encoding is reset so it is read from the file
- self.encoding = None
- self.units = []
- pomtime, filecontents = self.lockedfile.getcontents()
- # note: we rely on this not resetting the filename, which we set earlier, when given a string
- self.parse(filecontents)
- self.pomtime = pomtime
-
- def savepofile(self):
- """saves changes to the main file to disk..."""
- output = str(self)
- self.pomtime = self.lockedfile.writecontents(output)
-
- def pofreshen(self):
- """makes sure we have a freshly parsed pofile"""
- try:
- if self.pomtime != self.lockedfile.readmodtime():
- self.readpofile()
- except OSError, e:
- # If this exception is not triggered by a bad
- # symlink, then we have a missing file on our hands...
- if not os.path.islink(self.filename):
- # ...and thus we rescan our files to get rid of the missing filename
- self.project.scanpofiles()
- else:
- print "%s is a broken symlink" % (self.filename,)
-
- def getoutput(self):
- """returns pofile output"""
- self.pofreshen()
- return super(pootlefile, self).getoutput()
-
- def updateunit(self, item, newvalues, userprefs, languageprefs):
- """updates a translation with a new target value"""
- self.pofreshen()
- unit = self.getitem(item)
-
- if newvalues.has_key("target"):
- unit.target = newvalues["target"]
- if newvalues.has_key("fuzzy"):
- unit.markfuzzy(newvalues["fuzzy"])
- if newvalues.has_key("translator_comments"):
- unit.removenotes()
- if newvalues["translator_comments"]:
- unit.addnote(newvalues["translator_comments"])
-
- po_revision_date = time.strftime("%Y-%m-%d %H:%M") + tzstring()
- headerupdates = {"PO_Revision_Date": po_revision_date, "X_Generator": self.x_generator}
- if userprefs:
- if getattr(userprefs, "name", None) and getattr(userprefs, "email", None):
- headerupdates["Last_Translator"] = "%s <%s>" % (userprefs.name, userprefs.email)
- # XXX: If we needed to add a header, the index value in item will be one out after
- # adding the header.
- # TODO: remove once we force the PO class to always output headers
- force_recache = False
- if not self.header():
- force_recache = True
- self.updateheader(add=True, **headerupdates)
- if languageprefs:
- nplurals = getattr(languageprefs, "nplurals", None)
- pluralequation = getattr(languageprefs, "pluralequation", None)
- if nplurals and pluralequation:
- self.updateheaderplural(nplurals, pluralequation)
- self.savepofile()
- if force_recache:
- self.statistics.purge_totals()
- self.statistics.reclassifyunit(item)
-
- def getitem(self, item):
- """Returns a single unit based on the item number."""
- return self.units[self.statistics.getstats()["total"][item]]
-
- def iteritems(self, search, lastitem=None):
- """iterates through the items in this pofile starting after the given lastitem, using the given search"""
- # update stats if required
- translatables = self.statistics.getstats()["total"]
- if lastitem is None:
- minitem = 0
- else:
- minitem = lastitem + 1
- maxitem = len(translatables)
- validitems = range(minitem, maxitem)
- if search.assignedto or search.assignedaction:
- assignitems = self.getassigns().finditems(search)
- validitems = [item for item in validitems if item in assignitems]
- # loop through, filtering on matchnames if required
- for item in validitems:
- if not search.matchnames:
- yield item
- for name in search.matchnames:
- if translatables[item] in self.statistics.getstats()[name]:
+ if force_recache:
+ self.statistics.purge_totals()
+ self.statistics.reclassifyunit(item)
+
+ def getitem(self, item):
+ """Returns a single unit based on the item number."""
+ return self.units[self.statistics.getstats()["total"][item]]
+
+ def iteritems(self, search, lastitem=None):
+ """iterates through the items in this pofile starting after the given lastitem, using the given search"""
+ # update stats if required
+ translatables = self.statistics.getstats()["total"]
+ if lastitem is None:
+ minitem = 0
+ else:
+ minitem = lastitem + 1
+ maxitem = len(translatables)
+ validitems = range(minitem, maxitem)
+ if search.assignedto or search.assignedaction:
+ assignitems = self.getassigns().finditems(search)
+ validitems = [item for item in validitems if item in assignitems]
+ # loop through, filtering on matchnames if required
+ for item in validitems:
+ if not search.matchnames:
yield item
-
- def matchitems(self, newfile, uselocations=False):
- """matches up corresponding items in this pofile with the given newfile, and returns tuples of matching poitems (None if no match found)"""
- if not hasattr(self, "sourceindex"):
- self.makeindex()
- if not hasattr(newfile, "sourceindex"):
- newfile.makeindex()
- matches = []
- for newpo in newfile.units:
- if newpo.isheader():
- continue
- foundid = False
- if uselocations:
- newlocations = newpo.getlocations()
- mergedlocations = []
- for location in newlocations:
- if location in mergedlocations:
- continue
- if location in self.locationindex:
- oldpo = self.locationindex[location]
- if oldpo is not None:
- foundid = True
- matches.append((oldpo, newpo))
- mergedlocations.append(location)
+ for name in search.matchnames:
+ if translatables[item] in self.statistics.getstats()[name]:
+ yield item
+
+ def matchitems(self, newfile, uselocations=False):
+ """matches up corresponding items in this pofile with the given newfile, and returns tuples of matching poitems (None if no match found)"""
+ if not hasattr(self, "sourceindex"):
+ self.makeindex()
+ if not hasattr(newfile, "sourceindex"):
+ newfile.makeindex()
+ matches = []
+ for newpo in newfile.units:
+ if newpo.isheader():
+ continue
+ foundid = False
+ if uselocations:
+ newlocations = newpo.getlocations()
+ mergedlocations = []
+ for location in newlocations:
+ if location in mergedlocations:
continue
- if not foundid:
- # We can't use the multistring, because it might contain more than two
- # entries in a PO xliff file. Rather use the singular.
- source = unicode(newpo.source)
- if source in self.sourceindex:
- oldpo = self.sourceindex[source]
- matches.append((oldpo, newpo))
- else:
- matches.append((None, newpo))
- # find items that have been removed
- matcheditems = [oldpo for oldpo, newpo in matches if oldpo]
- for oldpo in self.units:
- if not oldpo in matcheditems:
- matches.append((oldpo, None))
- return matches
-
- def getassigns(self):
- if self.assigns is None:
- self.assigns = pootleassigns(self)
- return self.assigns
-
- def mergeitem(self, oldpo, newpo, username, suggest=False):
- """merges any changes from newpo into oldpo"""
- unchanged = oldpo.target == newpo.target
- if not suggest and (not oldpo.target or not newpo.target or oldpo.isheader() or newpo.isheader() or unchanged):
- oldpo.merge(newpo)
- else:
- for item in self.statistics.getstats()["total"]:
- matchpo = self.units[item]
- if matchpo == oldpo:
- strings = getattr(newpo.target, "strings", [newpo.target])
- self.addsuggestion(item, strings, username)
- return
- raise KeyError("Could not find item for merge")
-
- def mergefile(self, newfile, username, allownewstrings=True, suggestions=False):
- """make sure each msgid is unique ; merge comments etc from duplicates into original"""
- self.makeindex()
- matches = self.matchitems(newfile)
- for oldpo, newpo in matches:
- if suggestions:
- if oldpo and newpo:
- self.mergeitem(oldpo, newpo, username, suggest=True)
- continue
-
- if oldpo is None:
- if allownewstrings:
- if isinstance(newpo, po.pounit):
- self.addunit(newpo)
+ if location in self.locationindex:
+ oldpo = self.locationindex[location]
+ if oldpo is not None:
+ foundid = True
+ matches.append((oldpo, newpo))
+ mergedlocations.append(location)
+ continue
+ if not foundid:
+ # We can't use the multistring, because it might contain more than two
+ # entries in a PO xliff file. Rather use the singular.
+ source = unicode(newpo.source)
+ if source in self.sourceindex:
+ oldpo = self.sourceindex[source]
+ matches.append((oldpo, newpo))
else:
- self.addunit(self.UnitClass.buildfromunit(newpo))
- elif newpo is None:
- # TODO: mark the old one as obsolete
- pass
+ matches.append((None, newpo))
+ # find items that have been removed
+ matcheditems = [oldpo for oldpo, newpo in matches if oldpo]
+ for oldpo in self.units:
+ if not oldpo in matcheditems:
+ matches.append((oldpo, None))
+ return matches
+
+ def getassigns(self):
+ if self.assigns is None:
+ self.assigns = pootleassigns(self)
+ return self.assigns
+
+ def mergeitem(self, oldpo, newpo, username, suggest=False):
+ """merges any changes from newpo into oldpo"""
+ unchanged = oldpo.target == newpo.target
+ if not suggest and (not oldpo.target or not newpo.target or oldpo.isheader() or newpo.isheader() or unchanged):
+ oldpo.merge(newpo)
else:
- self.mergeitem(oldpo, newpo, username)
- # we invariably want to get the ids (source locations) from the newpo
- if hasattr(newpo, "sourcecomments"):
- oldpo.sourcecomments = newpo.sourcecomments
-
- if not isinstance(newfile, po.pofile) or suggestions:
- #TODO: We don't support updating the header yet.
+ for item in self.statistics.getstats()["total"]:
+ matchpo = self.units[item]
+ if matchpo == oldpo:
+ strings = getattr(newpo.target, "strings", [newpo.target])
+ self.addsuggestion(item, strings, username)
+ return
+ raise KeyError("Could not find item for merge")
+
+ def mergefile(self, newfile, username, allownewstrings=True, suggestions=False):
+ """make sure each msgid is unique ; merge comments etc from duplicates into original"""
+ self.makeindex()
+ matches = self.matchitems(newfile)
+ for oldpo, newpo in matches:
+ if suggestions:
+ if oldpo and newpo:
+ self.mergeitem(oldpo, newpo, username, suggest=True)
+ continue
+
+ if oldpo is None:
+ if allownewstrings:
+ if isinstance(newpo, po.pounit):
+ self.addunit(newpo)
+ else:
+ self.addunit(self.UnitClass.buildfromunit(newpo))
+ elif newpo is None:
+ # TODO: mark the old one as obsolete
+ pass
+ else:
+ self.mergeitem(oldpo, newpo, username)
+ # we invariably want to get the ids (source locations) from the newpo
+ if hasattr(newpo, "sourcecomments"):
+ oldpo.sourcecomments = newpo.sourcecomments
+
+ if not isinstance(newfile, po.pofile) or suggestions:
+ #TODO: We don't support updating the header yet.
+ self.savepofile()
+ # the easiest way to recalculate everything
+ self.readpofile()
+ return
+
+ #Let's update selected header entries. Only the ones listed below, and ones
+ #that are empty in self can be updated. The check in header_order is just
+ #a basic sanity check so that people don't insert garbage.
+ updatekeys = ['Content-Type',
+ 'POT-Creation-Date',
+ 'Last-Translator',
+ 'Project-Id-Version',
+ 'PO-Revision-Date',
+ 'Language-Team']
+ headerstoaccept = {}
+ ownheader = self.parseheader()
+ for (key, value) in newfile.parseheader().items():
+ if key in updatekeys or (not key in ownheader or not ownheader[key]) and key in po.pofile.header_order:
+ headerstoaccept[key] = value
+ self.updateheader(add=True, **headerstoaccept)
+
+ #Now update the comments above the header:
+ header = self.header()
+ newheader = newfile.header()
+ if header is None and not newheader is None:
+ header = self.UnitClass("", encoding=self.encoding)
+ header.target = ""
+ if header:
+ header._initallcomments(blankall=True)
+ if newheader:
+ for i in range(len(header.allcomments)):
+ header.allcomments[i].extend(newheader.allcomments[i])
+
self.savepofile()
# the easiest way to recalculate everything
self.readpofile()
- return
+ return pootlefile
- #Let's update selected header entries. Only the ones listed below, and ones
- #that are empty in self can be updated. The check in header_order is just
- #a basic sanity check so that people don't insert garbage.
- updatekeys = ['Content-Type',
- 'POT-Creation-Date',
- 'Last-Translator',
- 'Project-Id-Version',
- 'PO-Revision-Date',
- 'Language-Team']
- headerstoaccept = {}
- ownheader = self.parseheader()
- for (key, value) in newfile.parseheader().items():
- if key in updatekeys or (not key in ownheader or not ownheader[key]) and key in po.pofile.header_order:
- headerstoaccept[key] = value
- self.updateheader(add=True, **headerstoaccept)
-
- #Now update the comments above the header:
- header = self.header()
- newheader = newfile.header()
- if header is None and not newheader is None:
- header = self.UnitClass("", encoding=self.encoding)
- header.target = ""
- if header:
- header._initallcomments(blankall=True)
- if newheader:
- for i in range(len(header.allcomments)):
- header.allcomments[i].extend(newheader.allcomments[i])
-
- self.savepofile()
- # the easiest way to recalculate everything
- self.readpofile()
+_pootlefile_classes = {}
+# We want to extend the functionality of translation stores with some
+# Pootle-specific functionality, but we still want them to act like
+# translation stores. The clean way to do this, is to store a reference
+# to a translation store inside a "pootlefile" class and to delegate
+# if needed to the store. This was done initially through __getattr__
+# and __setattr__, although it proved to be rather slow (which made
+# a difference for large sets of translation files). This is now
+# achieved through inheritance. When we have to load a translation file,
+# we get hold of its corresponding translation store class. Then we
+# see whether there is a class which contains pootlefile functionality
+# and which derives from the translation store class. If there isn't
+# we invoke make_class to create such a class. Then we return an
+# instance of this class to the user.
+def pootlefile(project=None, pofilename=None):
+ po_class = po.pofile
+ if pofilename != None:
+ po_class = factory.getclass(pofilename)
+ if po_class not in _pootlefile_classes:
+ _pootlefile_classes[po_class] = make_class(po_class)
+ return _pootlefile_classes[po_class](project, pofilename)
+
class Search:
"""an object containing all the searching information"""
def __init__(self, dirfilter=None, matchnames=[], assignedto=None, assignedaction=None, searchtext=None):
« no previous file
|
no next file »