#!/usr/bin/python # vim:fileencoding=iso-8859-2 from time import strftime from optparse import OptionParser from os import path, popen, rename import locale, os, sre, sys __version__ = '0.1.1' loc = locale.getpreferredencoding() if loc != 'ISO-8859-2': def N_(message): '''Aha! We're gonna convert messages too.''' return message.decode('iso-8859-2').encode(loc) else: def N_(message): '''Nope, we're on Bart's box probably ;]''' return message def warn(message): '''Speeks to stderr.''' try: sys.stderr.write('%s\n' % message) except: pass class RecodeSpec: '''Handles various operations performed on files and data.''' def __init__(self, filename): '''Aaaa, init ;]''' self.spec = filename self.regexp = sre.compile('%changelog.*\n', sre.I) self.Date = strftime('%a %b %d %Y') def read_spec(self): '''This one reads spec (or not).''' try: fh = open(self.spec, 'r') try: data = fh.read() return data finally: fh.close() except IOError, error: warn('%s: %s' % (self.spec, error[1])) return False def write_old_spec(self, data, from_what): '''Writes original spec using filename "spec.encoding.index"''' if from_what == 'from_utf': encoding = 'UTF-8' if from_what == 'from_iso': encoding = 'ISO-8859-2' i = 9 fileout = ('%s.%s' % (self.spec, encoding)) while i > 0: if path.exists('%s.%d' % (fileout, i)): try: rename('%s.%d' % (fileout, i), '%s.%d' % (fileout, i+1)) except OSError or IOError, error: warn('%s: %s' % (self.spec, error[1])) pass i -= 1 try: fh = open('%s.1' % fileout, 'w') fh.truncate() try: fh.write(data) return True finally: fh.close() except OSError or IOError, error: warn('%s: %s' % (self.spec, error[1])) return False def write_new_spec(self, newdata): '''New file is comming!''' try: fh = open(self.spec, 'w') fh.truncate() try: fh.write(newdata) return True finally: fh.close() except IOError, error: warn('%s: %s' % (self.spec, error[1])) return False def update_changelog(self, data, to_what): '''This one is pretty usefull (or not). Adds to %changelog current date, packager's name and e-mail and message "Converted to $encoding.''' try: packager = popen('rpm -E %packager').read() except: pass if packager.find('%packager') != -1: warn(N_('Warnung: Brak pola %packager w ~/.rpmmacros')) packager = '\n' if to_what == 'to_utf': encoding = 'UTF-8' if to_what == 'to_iso': encoding = 'ISO-8859-2' string = ('%s %s- Spec converted to %s' % (self.Date, packager, encoding)) match = sre.search(self.regexp, data, 1) if match != None: newdata = sre.sub(self.regexp, ('%%changelog\n* %s\n\n' % string), data, 1) return (None, newdata) else: return (None, False) def to_utf(self, data): '''Converts from ISO to UTF.''' try: newdata = data.decode('iso-8859-2').encode('utf8') return (True, newdata) except UnicodeError, error: return (False, error[2], data[error[3]]) def to_iso(self, data): '''Converts from UTF to ISO.''' try: newdata = data.decode('utf8').encode('iso-8859-2') return (True, newdata) except UnicodeError, error: return (False, error[2], data[error[2]]) def main(): '''Main proc, main code is at the bottom. Nothing interesting but don't remove it.''' usage = (N_('sconv [-chisuv|--usage] spec [spec] ...')) version = (N_('sconv, wersja %s Copyright (C) 2005 Bart Kreska\n') % __version__) description = (N_('sconv - konwerter speców UTF-8 <==> ISO-8859-2')) parser = OptionParser(usage=usage, version=False, add_help_option=False, description=description) parser.add_option('-c', '--changelog', help=N_('Aktualizuje sekcję %changelog'), action='store_true', default=False) parser.add_option('-h', '--help', help=N_('Wyświetla tę pomoc i kończy'), action='store_true', default=False) parser.add_option('-i', '--to-iso', help=N_('Konwertuje plik UTF-8 na ISO-8859-2'), action='store_true', default=False) parser.add_option('-s', '--stdout', help=N_('Nie zapisuje plików, drukuje na STDOUT'), action='store_true', default=False) parser.add_option('-u', '--to-utf', '--to-utf8', help=N_('Konwertuje plik ISO-8859-2 na UTF-8'), action='store_true', default=False) parser.add_option('-v', '--version', help=N_('Wyświetla wersję programu i kończy'), action='store_true', default=False) parser.add_option('--usage', help=N_('Wyświetla skróconą pomoc i kończy'), action='store_true', default=False) (options, args) = parser.parse_args() if not sys.argv[1:]: parser.print_usage() sys.exit(2) if options.version: print version sys.exit(0) if options.help: parser.print_help() sys.exit(0) if options.usage: parser.print_usage() sys.exit(0) if options.to_iso and options.to_utf: warn(N_('Prrrr, albo -i albo -u')) sys.exit(2) if options.to_iso and not args or options.to_utf and not args: warn(N_('Ej no mistrzu, podaj jakiś plik może, hę?')) sys.exit(2) if not options.to_iso and not options.to_utf: parser.print_usage() sys.exit(2) for arg in args: spec = RecodeSpec(arg) data = spec.read_spec() if data and options.to_utf: recoded = spec.to_utf(data) if recoded[0] == False: warn(N_('Error: ISO ==> UTF: Niedozwolony znak na pozycji %s: %s') \ % (recoded[1], recoded[2])) else: if options.changelog: recoded = spec.update_changelog(recoded[1], 'to_utf') if options.stdout: sys.stdout.write(recoded[1]) else: if spec.write_old_spec(data, 'from_iso'): spec.write_new_spec(recoded[1]) if data and options.to_iso: recoded = spec.to_iso(data) if recoded[0] == False: warn(N_('Error: UTF ==> ISO: Niedozwolony znak na pozycji %s: %s') \ % (recoded[1], recoded[2])) else: if options.changelog: recoded = spec.update_changelog(recoded[1], 'to_iso') if options.stdout: sys.stdout.write(recoded[1]) else: if spec.write_old_spec(data, 'from_utf'): spec.write_new_spec(recoded[1]) if __name__ == '__main__': main()