| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
| 3 # | 3 # |
| 4 # Copyright 2006-2008 Zuza Software Foundation | 4 # Copyright 2006-2008 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 """Base classes for storage interfaces. | 22 """Base classes for storage interfaces. |
| 23 | 23 |
| 24 @organization: Zuza Software Foundation | 24 @organization: Zuza Software Foundation |
| 25 @copyright: 2006-2007 Zuza Software Foundation | 25 @copyright: 2006-2007 Zuza Software Foundation |
| 26 @license: U{GPL <http://www.fsf.org/licensing/licenses/gpl.html>} | 26 @license: U{GPL <http://www.fsf.org/licensing/licenses/gpl.html>} |
| 27 """ | 27 """ |
| 28 | 28 |
| 29 try: | 29 try: |
| 30 import cPickle as pickle | 30 import cPickle as pickle |
| 31 except: | 31 except: |
| 32 import pickle | 32 import pickle |
| 33 from exceptions import NotImplementedError | 33 from exceptions import NotImplementedError |
| 34 | 34 |
| 35 def force_override(method, baseclass): | 35 def force_override(method, baseclass): |
| 36 """Forces derived classes to override method.""" | 36 """Forces derived classes to override method.""" |
| 37 | 37 |
| 38 if type(method.im_self) == type(baseclass): | 38 if type(method.im_self) == type(baseclass): |
| 39 # then this is a classmethod and im_self is the actual class | 39 # then this is a classmethod and im_self is the actual class |
| 40 actualclass = method.im_self | 40 actualclass = method.im_self |
| 41 else: | 41 else: |
| 42 actualclass = method.im_class | 42 actualclass = method.im_class |
| 43 if actualclass != baseclass: | 43 if actualclass != baseclass: |
| 44 raise NotImplementedError("%s does not reimplement %s as required by %s"
% (actualclass.__name__, method.__name__, baseclass.__name__)) | 44 raise NotImplementedError("%s does not reimplement %s as required by %s"
% (actualclass.__name__, method.__name__, baseclass.__name__)) |
| 45 | 45 |
| 46 class ParseError(Exception): | 46 class ParseError(Exception): |
| 47 pass | 47 pass |
| 48 | 48 |
| 49 class TranslationUnit(object): | 49 class TranslationUnit(object): |
| 50 """Base class for translation units. | 50 """Base class for translation units. |
| (...skipping 198 matching lines...) Show 10 above Show 10 below |
| 249 | 249 |
| 250 def markfuzzy(self, value=True): | 250 def markfuzzy(self, value=True): |
| 251 """Marks the unit as fuzzy or not.""" | 251 """Marks the unit as fuzzy or not.""" |
| 252 pass | 252 pass |
| 253 | 253 |
| 254 def isheader(self): | 254 def isheader(self): |
| 255 """Indicates whether this unit is a header.""" | 255 """Indicates whether this unit is a header.""" |
| 256 | 256 |
| 257 return False | 257 return False |
| 258 | 258 |
| 259 def isreview(self): | 259 def isreview(self): |
| 260 """Indicates whether this unit needs review.""" | 260 """Indicates whether this unit needs review.""" |
| 261 return False | 261 return False |
| 262 | 262 |
| 263 | 263 |
| 264 def isblank(self): | 264 def isblank(self): |
| 265 """Used to see if this unit has no source or target string. | 265 """Used to see if this unit has no source or target string. |
| 266 | 266 |
| 267 @note: This is probably used more to find translatable units, | 267 @note: This is probably used more to find translatable units, |
| 268 and we might want to move in that direction rather and get rid of this. | 268 and we might want to move in that direction rather and get rid of this. |
| 269 | 269 |
| 270 """ | 270 """ |
| 271 | 271 |
| 272 return not (self.source or self.target) | 272 return not (self.source or self.target) |
| 273 | 273 |
| 274 def hasplural(self): | 274 def hasplural(self): |
| 275 """Tells whether or not this specific unit has plural strings.""" | 275 """Tells whether or not this specific unit has plural strings.""" |
| 276 | 276 |
| 277 #TODO: Reconsider | 277 #TODO: Reconsider |
| 278 return False | 278 return False |
| 279 | 279 |
| 280 def getsourcelanguage(self): | 280 def getsourcelanguage(self): |
| 281 return getattr(self._store, "sourcelanguage", "en") | 281 return getattr(self._store, "sourcelanguage", "en") |
| 282 | 282 |
| 283 def gettargetlanguage(self): | 283 def gettargetlanguage(self): |
| 284 return getattr(self._store, "targetlanguage", None) | 284 return getattr(self._store, "targetlanguage", None) |
| 285 | 285 |
| 286 def merge(self, otherunit, overwrite=False, comments=True): | 286 def merge(self, otherunit, overwrite=False, comments=True): |
| 287 """Do basic format agnostic merging.""" | 287 """Do basic format agnostic merging.""" |
| 288 | 288 |
| 289 if self.target == "" or overwrite: | 289 if self.target == "" or overwrite: |
| 290 self.target = otherunit.target | 290 self.target = otherunit.target |
| 291 | 291 |
| 292 def unit_iter(self): | 292 def unit_iter(self): |
| 293 """Iterator that only returns this unit.""" | 293 """Iterator that only returns this unit.""" |
| 294 yield self | 294 yield self |
| 295 | 295 |
| 296 def getunits(self): | 296 def getunits(self): |
| 297 """This unit in a list.""" | 297 """This unit in a list.""" |
| 298 return [self] | 298 return [self] |
| 299 |
| 300 def setprev_source(self, source): |
| 301 """Sets the previous source message for this unit""" |
| 302 pass |
| 303 |
| 304 def getprev_source(self): |
| 305 """Gets the previous source message for this unit""" |
| 306 pass |
| 307 |
| 308 prev_source = property(getprev_source, setprev_source) |
| 309 |
| 310 def setprev_context(self, context): |
| 311 """Sets the previous context of this unit""" |
| 312 pass |
| 313 |
| 314 def getprev_context(self): |
| 315 """Gets the previous context of this unit""" |
| 316 pass |
| 317 |
| 318 prev_context = property(getprev_context, setprev_context) |
| 319 |
| 320 def set_as_previous(self): |
| 321 """Sets this unit as a previous unit message""" |
| 322 if self.isfuzzy(): |
| 323 return |
| 324 self.setprev_context(self.getcontext()) |
| 325 self.setprev_source(self.source) |
| 326 self.markfuzzy() |
| 299 | 327 |
| 300 def buildfromunit(cls, unit): | 328 def buildfromunit(cls, unit): |
| 301 """Build a native unit from a foreign unit, preserving as much | 329 """Build a native unit from a foreign unit, preserving as much |
| 302 information as possible.""" | 330 information as possible.""" |
| 303 | 331 |
| 304 if type(unit) == cls and hasattr(unit, "copy") and callable(unit.copy): | 332 if type(unit) == cls and hasattr(unit, "copy") and callable(unit.copy): |
| 305 return unit.copy() | 333 return unit.copy() |
| 306 newunit = cls(unit.source) | 334 newunit = cls(unit.source) |
| 307 newunit.target = unit.target | 335 newunit.target = unit.target |
| 308 newunit.markfuzzy(unit.isfuzzy()) | 336 newunit.markfuzzy(unit.isfuzzy()) |
| 309 locations = unit.getlocations() | 337 locations = unit.getlocations() |
| 310 if locations: | 338 if locations: |
| 311 newunit.addlocations(locations) | 339 newunit.addlocations(locations) |
| 312 notes = unit.getnotes() | 340 notes = unit.getnotes() |
| 313 if notes: | 341 if notes: |
| 314 newunit.addnote(notes) | 342 newunit.addnote(notes) |
| 315 return newunit | 343 return newunit |
| 316 buildfromunit = classmethod(buildfromunit) | 344 buildfromunit = classmethod(buildfromunit) |
| 317 | 345 |
| 318 class TranslationStore(object): | 346 class TranslationStore(object): |
| 319 """Base class for stores for multiple translation units of type UnitClass.""
" | 347 """Base class for stores for multiple translation units of type UnitClass.""
" |
| 320 | 348 |
| 321 UnitClass = TranslationUnit | 349 UnitClass = TranslationUnit |
| 322 Mimetypes = None | 350 Mimetypes = None |
| 323 Extensions = None | 351 Extensions = None |
| 324 | 352 |
| 325 def __init__(self, unitclass=None): | 353 def __init__(self, unitclass=None): |
| 326 """Constructs a blank TranslationStore.""" | 354 """Constructs a blank TranslationStore.""" |
| 327 | 355 |
| 328 self.units = [] | 356 self.units = [] |
| 329 self.filepath = None | 357 self.filepath = None |
| 330 self.translator = "" | 358 self.translator = "" |
| 331 self.date = "" | 359 self.date = "" |
| 332 self.sourcelanguage = None | 360 self.sourcelanguage = None |
| 333 self.targetlanguage = None | 361 self.targetlanguage = None |
| 334 if unitclass: | 362 if unitclass: |
| 335 self.UnitClass = unitclass | 363 self.UnitClass = unitclass |
| 336 super(TranslationStore, self).__init__() | 364 super(TranslationStore, self).__init__() |
| 337 | 365 |
| 338 def setsourcelanguage(self, sourcelanguage): | 366 def setsourcelanguage(self, sourcelanguage): |
| 339 """Sets the source language for this store""" | 367 """Sets the source language for this store""" |
| 340 self.sourcelanguage = sourcelanguage | 368 self.sourcelanguage = sourcelanguage |
| 341 | 369 |
| 342 def settargetlanguage(self, targetlanguage): | 370 def settargetlanguage(self, targetlanguage): |
| 343 """Sets the target language for this store""" | 371 """Sets the target language for this store""" |
| 344 self.targetlanguage = targetlanguage | 372 self.targetlanguage = targetlanguage |
| 345 | 373 |
| 346 def unit_iter(self): | 374 def unit_iter(self): |
| 347 """Iterator over all the units in this store.""" | 375 """Iterator over all the units in this store.""" |
| 348 for unit in self.units: | 376 for unit in self.units: |
| (...skipping 111 matching lines...) Show 10 above Show 10 below |
| 460 return newstore | 488 return newstore |
| 461 parsestring = classmethod(parsestring) | 489 parsestring = classmethod(parsestring) |
| 462 | 490 |
| 463 def parse(self, data): | 491 def parse(self, data): |
| 464 """parser to process the given source string""" | 492 """parser to process the given source string""" |
| 465 self.units = pickle.loads(data).units | 493 self.units = pickle.loads(data).units |
| 466 | 494 |
| 467 def savefile(self, storefile): | 495 def savefile(self, storefile): |
| 468 """Writes the string representation to the given file (or filename).""" | 496 """Writes the string representation to the given file (or filename).""" |
| 469 if isinstance(storefile, basestring): | 497 if isinstance(storefile, basestring): |
| 470 storefile = open(storefile, "w") | 498 storefile = open(storefile, "w") |
| 471 self.fileobj = storefile | 499 self.fileobj = storefile |
| 472 self._assignname() | 500 self._assignname() |
| 473 storestring = str(self) | 501 storestring = str(self) |
| 474 storefile.write(storestring) | 502 storefile.write(storestring) |
| 475 storefile.close() | 503 storefile.close() |
| 476 | 504 |
| 477 def save(self): | 505 def save(self): |
| 478 """Save to the file that data was originally read from, if available.""" | 506 """Save to the file that data was originally read from, if available.""" |
| 479 fileobj = getattr(self, "fileobj", None) | 507 fileobj = getattr(self, "fileobj", None) |
| 480 if not fileobj: | 508 if not fileobj: |
| 481 filename = getattr(self, "filename", None) | 509 filename = getattr(self, "filename", None) |
| 482 if filename: | 510 if filename: |
| 483 fileobj = file(filename, "w") | 511 fileobj = file(filename, "w") |
| 484 else: | 512 else: |
| 485 fileobj.close() | 513 fileobj.close() |
| 486 filename = getattr(fileobj, "name", getattr(fileobj, "filename", Non
e)) | 514 filename = getattr(fileobj, "name", getattr(fileobj, "filename", Non
e)) |
| 487 if not filename: | 515 if not filename: |
| 488 raise ValueError("No file or filename to save to") | 516 raise ValueError("No file or filename to save to") |
| 489 fileobj = fileobj.__class__(filename, "w") | 517 fileobj = fileobj.__class__(filename, "w") |
| 490 self.savefile(fileobj) | 518 self.savefile(fileobj) |
| 491 | 519 |
| 492 def parsefile(cls, storefile): | 520 def parsefile(cls, storefile): |
| 493 """Reads the given file (or opens the given filename) and parses back to
an object.""" | 521 """Reads the given file (or opens the given filename) and parses back to
an object.""" |
| 494 | 522 |
| 495 if isinstance(storefile, basestring): | 523 if isinstance(storefile, basestring): |
| 496 storefile = open(storefile, "r") | 524 storefile = open(storefile, "r") |
| 497 mode = getattr(storefile, "mode", "r") | 525 mode = getattr(storefile, "mode", "r") |
| 498 #For some reason GzipFile returns 1, so we have to test for that here | 526 #For some reason GzipFile returns 1, so we have to test for that here |
| 499 if mode == 1 or "r" in mode: | 527 if mode == 1 or "r" in mode: |
| 500 storestring = storefile.read() | 528 storestring = storefile.read() |
| 501 storefile.close() | 529 storefile.close() |
| 502 else: | 530 else: |
| 503 storestring = "" | 531 storestring = "" |
| 504 newstore = cls.parsestring(storestring) | 532 newstore = cls.parsestring(storestring) |
| 505 newstore.fileobj = storefile | 533 newstore.fileobj = storefile |
| 506 newstore._assignname() | 534 newstore._assignname() |
| 507 return newstore | 535 return newstore |
| 508 parsefile = classmethod(parsefile) | 536 parsefile = classmethod(parsefile) |
| 509 | 537 |
| OLD | NEW |