diff options
Diffstat (limited to 'minidinstall')
| -rw-r--r-- | minidinstall/ChangeFile.py | 77 | ||||
| -rw-r--r-- | minidinstall/DebianSigVerifier.py | 13 | ||||
| -rw-r--r-- | minidinstall/Dnotify.py | 49 | ||||
| -rwxr-xr-x | minidinstall/DpkgControl.py | 124 | ||||
| -rw-r--r-- | minidinstall/DpkgDatalist.py | 31 | ||||
| -rw-r--r-- | minidinstall/GPGSigVerifier.py | 25 | ||||
| -rw-r--r-- | minidinstall/OrderedDict.py | 11 | ||||
| -rwxr-xr-x | minidinstall/SafeWriteFile.py | 12 | ||||
| -rwxr-xr-x | minidinstall/SignedFile.py | 32 | ||||
| -rw-r--r-- | minidinstall/mail.py | 24 | ||||
| -rw-r--r-- | minidinstall/misc.py | 30 | ||||
| -rw-r--r-- | minidinstall/tweet.py | 17 |
12 files changed, 192 insertions, 253 deletions
diff --git a/minidinstall/ChangeFile.py b/minidinstall/ChangeFile.py index 3b0cf48..4a65af6 100644 --- a/minidinstall/ChangeFile.py +++ b/minidinstall/ChangeFile.py @@ -1,8 +1,8 @@ -# ChangeFile +# ChangeFile -*- mode: python; coding: utf-8 -*- # A class which represents a Debian change file. -# Copyright 2002 Colin Walters <walters@gnu.org> +# Copyright (c) 2002 Colin Walters <walters@gnu.org> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -18,11 +18,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os, re, sys, string, stat -import threading, queue +import os, re, stat import logging -from minidinstall import DpkgControl, SignedFile -from minidinstall import misc +from .DpkgControl import * +from .SignedFile import * +from . import misc class ChangeFileException(Exception): def __init__(self, value): @@ -30,19 +30,19 @@ class ChangeFileException(Exception): def __str__(self): return repr(self._value) -class ChangeFile(DpkgControl.DpkgParagraph): - md5_re = r'^(?P<md5>[0-9a-f]{32})[ \t]+(?P<size>\d+)[ \t]+(?P<section>[-/a-zA-Z0-9]+)[ \t]+(?P<priority>[-a-zA-Z0-9]+)[ \t]+(?P<file>[0-9a-zA-Z][-+:.,=~0-9a-zA-Z_]+)$' - sha1_re = r'^(?P<sha1>[0-9a-f]{40})[ \t]+(?P<size>\d+)[ \t]+(?P<file>[0-9a-zA-Z][-+:.,=~0-9a-zA-Z_]+)$' - sha256_re = r'^(?P<sha256>[0-9a-f]{64})[ \t]+(?P<size>\d+)[ \t]+(?P<file>[0-9a-zA-Z][-+:.,=~0-9a-zA-Z_]+)$' +class ChangeFile(DpkgParagraph): + md5_re = r'^(?P<hashsum>[0-9a-f]{32})[ \t]+(?P<size>\d+)[ \t]+(?P<section>[-/a-zA-Z0-9]+)[ \t]+(?P<priority>[-a-zA-Z0-9]+)[ \t]+(?P<file>[0-9a-zA-Z][-+:.,=~0-9a-zA-Z_]+)$' + sha1_re = r'^(?P<hashsum>[0-9a-f]{40})[ \t]+(?P<size>\d+)[ \t]+(?P<file>[0-9a-zA-Z][-+:.,=~0-9a-zA-Z_]+)$' + sha256_re = r'^(?P<hashsum>[0-9a-f]{64})[ \t]+(?P<size>\d+)[ \t]+(?P<file>[0-9a-zA-Z][-+:.,=~0-9a-zA-Z_]+)$' def __init__(self): - DpkgControl.DpkgParagraph.__init__(self) + DpkgParagraph.__init__(self) self._logger = logging.getLogger("mini-dinstall") self._file = '' def load_from_file(self, filename): self._file = filename - f = SignedFile.SignedFile(open(self._file)) + f = SignedFile(open(self._file)) self.load(f) f.close() @@ -52,57 +52,50 @@ class ChangeFile(DpkgControl.DpkgParagraph): def _get_checksum_from_changes(self): """ extract checksums and size from changes file """ output = {} - hashes = { 'md5': ['files', re.compile(self.md5_re)], - 'sha1': ['checksums-sha1', re.compile(self.sha1_re)], - 'sha256': ['checksums-sha256', re.compile(self.sha256_re)] - } - hashes_checked = hashes.copy() + hashes = { + 'md5': ['files', re.compile(self.md5_re)], + 'sha1': ['checksums-sha1', re.compile(self.sha1_re)], + 'sha256': ['checksums-sha256', re.compile(self.sha256_re)] + } - try: - self['files'] - except KeyError: + if 'files' not in self: return [] - for hash in hashes: - try: - self[hashes[hash][0]] - except KeyError: + for (hash, (field, regex)) in list(hashes.items()): + if field not in self: self._logger.warn("Can't find %s checksum in changes file '%s'" % (hash, os.path.basename(self._file))) - hashes_checked.pop(hash) - - for hash in hashes_checked: + continue output[hash] = [] - for line in self[hashes[hash][0]]: - if line == '': + for line in self[field].splitlines(): + if not line: continue - match = hashes[hash][1].match(line) - if (match is None): - raise ChangeFileException("Couldn't parse file entry \"%s\" in Files field of .changes" % (line,)) - output[hash].append([match.group(hash), match.group('size'), match.group('file') ]) + match = regex.match(line) + if not match: + raise ChangeFileException("Couldn't parse file entry \"%s\" in %s field of .changes" % (line, self.trueFieldCasing[field])) + output[hash].append([match.group('hashsum'), match.group('size'), match.group('file')]) return output def verify(self, sourcedir): """ verify size and hash values from changes file """ checksum = self._get_checksum_from_changes() - for hash in list(checksum.keys()): - for (hashsum, size, filename) in checksum[hash]: + for (hash, value) in list(checksum.items()): + for (hashsum, size, filename) in value: self._verify_file_integrity(os.path.join(sourcedir, filename), int(size), hash, hashsum) - def _verify_file_integrity(self, filename, expected_size, hash, expected_hashsum): """ check uploaded file integrity """ - self._logger.debug('Checking integrity of %s' % (filename,)) + self._logger.debug('Checking integrity of %s' % filename) try: statbuf = os.stat(filename) if not stat.S_ISREG(statbuf[stat.ST_MODE]): - raise ChangeFileException("%s is not a regular file" % (filename,)) + raise ChangeFileException("%s is not a regular file" % filename) size = statbuf[stat.ST_SIZE] except OSError as e: - raise ChangeFileException("Can't stat %s: %s" % (filename,e.strerror)) + raise ChangeFileException("Can't stat %s: %s" % (filename, e.strerror)) if size != expected_size: - raise ChangeFileException("File size for %s does not match that specified in .dsc" % (filename,)) - if (misc.get_file_sum(self, hash, filename) != expected_hashsum): - raise ChangeFileException("%ssum for %s does not match that specified in .dsc" % (hash, filename,)) + raise ChangeFileException("File size for %s does not match that specified in .dsc" % filename) + if misc.get_file_sum(self, hash, filename) != expected_hashsum: + raise ChangeFileException("%ssum for %s does not match that specified in .dsc" % (hash, filename)) self._logger.debug('Verified %ssum %s and size %s for %s' % (hash, expected_hashsum, expected_size, filename)) # vim:ts=4:sw=4:et: diff --git a/minidinstall/DebianSigVerifier.py b/minidinstall/DebianSigVerifier.py index d441a58..17a6ec2 100644 --- a/minidinstall/DebianSigVerifier.py +++ b/minidinstall/DebianSigVerifier.py @@ -2,7 +2,7 @@ # A class for verifying signed files, using Debian keys -# Copyright © 2002 Colin Walters <walters@gnu.org> +# Copyright (c) 2002 Colin Walters <walters@gnu.org> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -18,18 +18,19 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os, re, sys, string, stat, logging -from minidinstall.GPGSigVerifier import GPGSigVerifier +import os +from .GPGSigVerifier import * class DebianSigVerifier(GPGSigVerifier): _dpkg_ring = '/etc/dpkg/local-keyring.gpg' + def __init__(self, keyrings=None, extra_keyrings=None): - if keyrings is None: + if not keyrings: keyrings = ['/usr/share/keyrings/debian-keyring.gpg', '/usr/share/keyrings/debian-keyring.pgp'] if os.access(self._dpkg_ring, os.R_OK): keyrings.append(self._dpkg_ring) - if not extra_keyrings is None: - keyrings += extra_keyrings + if extra_keyrings: + keyrings.extend(extra_keyrings) GPGSigVerifier.__init__(self, keyrings) # vim:ts=4:sw=4:et: diff --git a/minidinstall/Dnotify.py b/minidinstall/Dnotify.py index 18606e1..cdc2c48 100644 --- a/minidinstall/Dnotify.py +++ b/minidinstall/Dnotify.py @@ -2,7 +2,7 @@ # A simple FAM-like beast in Python -# Copyright © 2002 Colin Walters <walters@gnu.org> +# Copyright (c) 2002 Colin Walters <walters@gnu.org> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -18,9 +18,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os, re, sys, string, stat, threading, queue, time +import os, stat, threading, queue, time import logging -from minidinstall import misc +from . import misc class DnotifyException(Exception): def __init__(self, value): @@ -29,7 +29,7 @@ class DnotifyException(Exception): return repr(self._value) class DirectoryNotifierFactory: - def create(self, dirs, use_dnotify=1, poll_time=30, logger=None, cancel_event=None): + def create(self, dirs, use_dnotify=False, poll_time=30, logger=None, cancel_event=None): if use_dnotify and os.access('/usr/bin/dnotify', os.X_OK): if logger: logger.debug("Using dnotify directory notifier") @@ -47,11 +47,11 @@ class DirectoryNotifier: def __init__(self, dirs, logger, cancel_event=None): self._cwd = os.getcwd() self._dirs = dirs - if cancel_event is None: + if not cancel_event: self._cancel_event = threading.Event() else: self._cancel_event = cancel_event - if logger is None: + if not logger: self._logger = logging.getLogger("Dnotify") self._logger.addFilter(DnotifyNullLoggingFilter()) else: @@ -62,13 +62,13 @@ class DirectoryNotifier: class DirectoryNotifierAsyncWrapper(threading.Thread): def __init__(self, dnotify, queue, logger=None, name=None): - if not name is None: + if name: threading.Thread.__init__(self, name=name) else: threading.Thread.__init__(self) self._eventqueue = queue self._dnotify = dnotify - if logger is None: + if not logger: self._logger = logging.getLogger("Dnotify") self._logger.addFilter(DnotifyNullLoggingFilter()) else: @@ -78,7 +78,7 @@ class DirectoryNotifierAsyncWrapper(threading.Thread): self._cancel_event.set() def run(self): - self._logger.info('Created new thread (%s) for async directory notification' % (self.getName())) + self._logger.info('Created new thread (%s) for async directory notification' % self.getName()) while not self._dnotify.cancelled(): dir = self._dnotify.poll() self._eventqueue.put(dir) @@ -97,7 +97,7 @@ class MtimeDirectoryNotifier(DirectoryNotifier): timeout_time = None if timeout: timeout_time = time.time() + timeout - while self._changed == []: + while not self._changed: if timeout_time and time.time() > timeout_time: return None self._logger.debug('Polling...') @@ -105,16 +105,15 @@ class MtimeDirectoryNotifier(DirectoryNotifier): oldtime = self._dirmap[dir] mtime = os.stat(os.path.join(self._cwd, dir))[stat.ST_MTIME] if oldtime < mtime: - self._logger.debug('Directory "%s" has changed' % (dir,)) + self._logger.debug('Directory "%s" has changed' % dir) self._changed.append(dir) self._dirmap[dir] = mtime - if self._changed == []: + if not self._changed: for x in range(self._polltime): if self._cancel_event.isSet(): return None time.sleep(1) - ret = self._changed[0] - self._changed = self._changed[1:] + ret = self._changed.pop(0) return ret class DnotifyDirectoryNotifier(DirectoryNotifier): @@ -127,11 +126,11 @@ class DnotifyDirectoryNotifier(DirectoryNotifier): def poll(self, timeout=None): # delete duplicates i = self._queue.qsize() - self._logger.debug('Queue size: %d', (i,)) + self._logger.debug('Queue size: %d' % i) set = {} - while i > 0: + while i: dir = self._queue_get(timeout) - if dir is None: + if not dir: # We shouldn't have to do this; no one else is reading # from the queue. But we do it just to be safe. for key in list(set.keys()): @@ -142,11 +141,11 @@ class DnotifyDirectoryNotifier(DirectoryNotifier): for key in list(set.keys()): self._queue.put(key) i = self._queue.qsize() - self._logger.debug('Queue size (after duplicate filter): %d', (i,)) + self._logger.debug('Queue size (after duplicate filter): %d' % i) return self._queue_get(timeout) def _queue_get(self, timeout): - if timeout is None: + if not timeout: return self._queue.get() timeout_time = time.time() + timeout while True: @@ -179,21 +178,21 @@ class DnotifyThread(threading.Thread): os.close(outfd) stdout = os.fdopen(infd) c = 'x' - while c != '': + while c: curline = '' c = stdout.read(1) - while c != '' and c != '\0': + while c and c != '\0': curline += c c = stdout.read(1) - if c == '': + if not c: break - self._logger.debug('Directory "%s" changed' % (curline,)) + self._logger.debug('Directory "%s" changed' % curline) self._queue.put(curline) (pid, status) = os.waitpid(pid, 0) - if status is None: + if not status: ecode = 0 else: ecode = os.WEXITSTATUS(status) - raise DnotifyException("dnotify exited with code %s" % (ecode,)) + raise DnotifyException("dnotify exited with code %s" % ecode) # vim:ts=4:sw=4:et: diff --git a/minidinstall/DpkgControl.py b/minidinstall/DpkgControl.py index be08155..02e3567 100755 --- a/minidinstall/DpkgControl.py +++ b/minidinstall/DpkgControl.py @@ -1,7 +1,10 @@ -# DpkgControl.py +#!/usr/bin/python3 +# DpkgControl -*- mode: python; coding: utf-8 -*- # # This module implements control file parsing. # +# Copyright (c) 2001 Adam Heath <doogie@debian.org> +# # DpkgParagraph is a low-level class, that reads/parses a single paragraph # from a file object. # @@ -16,9 +19,7 @@ # To test this, pass it a filetype char, a filename, then, optionally, # the key to a paragraph to display, and if a fourth arg is given, only # show that field. -# -# Copyright 2001 Adam Heath <doogie@debian.org> -# + # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -33,20 +34,15 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import re, string from .DpkgDatalist import * -from minidinstall.SignedFile import * +from .SignedFile import * class DpkgParagraph(DpkgOrderedDatalist): - caseSensitive = 0 trueFieldCasing = {} - def setCaseSensitive( self, value ): self.caseSensitive = value - def load( self, f ): - "Paragraph data from a file object." + """Paragraph data from a file object""" key = None - value = None while True: line = f.readline() if not line: @@ -57,85 +53,53 @@ class DpkgParagraph(DpkgOrderedDatalist): continue else: return - line = line[ :-1 ] if line[ 0 ] != ' ': - key, value = line.split( ":", 1 ) - if value: value = value[ 1: ] - if not self.caseSensitive: - newkey = key.lower() - if key not in self.trueFieldCasing: - self.trueFieldCasing[ newkey ] = key - key = newkey + ( truekey, value ) = line.split( ":", 1 ) + key = truekey.lower() + self.trueFieldCasing[ key ] = truekey + self[ key ] = value.strip() else: - if isinstance( value, list ): - value.append( line[ 1: ] ) - else: - value = [ value, line[ 1: ] ] - self[ key ] = value + self[ key ] += "\n%s" % line.strip() def _storeField( self, f, value, lead = " " ): - if isinstance( value, list ): - value = "\n".join(list(map( lambda v, lead = lead: v and ( lead + v ) or v, value ))) - else: - if value: value = lead + value - f.write( "%s\n" % ( value ) ) + value = "\n".join(list(map( lambda v, lead = lead: lead + v if v else "", value.splitlines() ))) + f.write( "%s\n" % value ) def _store( self, f ): - "Write our paragraph data to a file object" - for key in list(self.keys()): - value = self[ key ] - if key in self.trueFieldCasing: - key = self.trueFieldCasing[ key ] - f.write( "%s:" % key ) + """Write our paragraph data to a file object""" + for ( key, value ) in list(self.items()): + truekey = self.trueFieldCasing[ key ] + f.write( "%s:" % truekey ) self._storeField( f, value ) -class DpkgControl(DpkgOrderedDatalist): - - key = "package" - caseSensitive = 0 - - def setkey( self, key ): self.key = key - def setCaseSensitive( self, value ): self.caseSensitive = value - - def _load_one( self, f ): - p = DpkgParagraph( None ) - p.setCaseSensitive( self.caseSensitive ) - p.load( f ) - return p - - def load( self, f ): +class DpkgControl(DpkgParagraph): + def load( self, f, source = False ): while True: - p = self._load_one( f ) - if not p: break - self[ p[ self.key ] ] = p + para = DpkgParagraph() + para.load( f ) + if not para: + break + if "source" not in para: + self[ para[ "package" ] ] = para + elif source: + self[ "source" ] = para def _store( self, f ): - "Write our control data to a file object" - - for key in list(self.keys()): - self[ key ]._store( f ) - f.write( "\n" ) - -class DpkgSourceControl( DpkgControl ): - source = None - + """Write our control data to a file object""" + keys = list(self.keys()) + while keys: + self[ keys.pop( 0 ) ]._store( f ) + if keys: + f.write( "\n" ) + +class DpkgSourceControl(DpkgControl): def load( self, f ): - f = SignedFile(f) - self.source = self._load_one( f ) - DpkgControl.load( self, f ) - - def __repr__( self ): - return self.source.__repr__() + "\n" + DpkgControl.__repr__( self ) - - def _store( self, f ): - "Write our control data to a file object" - self.source._store( f ) - f.write( "\n" ) - DpkgControl._store( self, f ) + f = SignedFile( f ) + DpkgControl.load( self, f, source = True ) if __name__ == "__main__": import sys - types = { 'p' : DpkgParagraph, 'c' : DpkgControl, 's' : DpkgSourceControl } + types = { 'p': DpkgParagraph, 'c': DpkgControl, 's': DpkgSourceControl } type = sys.argv[ 1 ] if type not in types: print( "Unknown type `%s'!" % type ) @@ -144,11 +108,13 @@ if __name__ == "__main__": data = types[ type ]() data.load( file ) if len( sys.argv ) > 3: - para = data[ sys.argv[ 3 ] ] - if len( sys.argv ) > 4: - para._storeField( sys.stdout, para[ sys.argv[ 4 ] ], "" ) + rargs = sys.argv[ 3: ] + if type != 'p': + data = data[ rargs.pop( 0 ) ] + if rargs: + data._storeField( sys.stdout, data[ rargs[ 0 ].lower() ], "" ) else: - para._store( sys.stdout ) + data._store( sys.stdout ) else: data._store( sys.stdout ) diff --git a/minidinstall/DpkgDatalist.py b/minidinstall/DpkgDatalist.py index 68f9940..e7abbd2 100644 --- a/minidinstall/DpkgDatalist.py +++ b/minidinstall/DpkgDatalist.py @@ -1,10 +1,10 @@ -# DpkgDatalist.py +# DpkgDatalist -*- mode: python; coding: utf-8 -*- # # This module implements DpkgDatalist, an abstract class for storing # a list of objects in a file. Children of this class have to implement # the load and _store methods. # -# Copyright 2001 Wichert Akkerman <wichert@linux.com> +# Copyright (c) 2001 Wichert Akkerman <wichert@linux.com> # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -20,34 +20,31 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os, sys -from collections import UserDict -from collections import OrderedDict -from minidinstall.SafeWriteFile import SafeWriteFile +import sys +from collections import UserDict, OrderedDict +from .SafeWriteFile import SafeWriteFile class DpkgDatalistException(Exception): UNKNOWN = 0 SYNTAXERROR = 1 - def __init__(self, message="", reason=UNKNOWN, file=None, line=None): + def __init__(self, message=None, reason=UNKNOWN, file=None, line=None): self.message=message self.reason=reason self.filename=file self.line=line class _DpkgDatalist: - def __init__(self, fn=""): - '''Initialize a DpkgDatalist object. An optional argument is a - file from which we load values.''' - + def __init__(self, fn=None): + """Initialize a DpkgDatalist object. An optional argument is a + file from which we load values.""" self.filename=fn if self.filename: self.load(self.filename) def store(self, fn=None): - "Store variable data in a file." - - if fn==None: + """Store variable data in a file.""" + if not fn: fn=self.filename # Special case for writing to stdout if not fn: @@ -64,15 +61,13 @@ class _DpkgDatalist: if isinstance(fn, str): vf.close() - class DpkgDatalist(UserDict, _DpkgDatalist): - def __init__(self, fn=""): + def __init__(self, fn=None): UserDict.__init__(self) _DpkgDatalist.__init__(self, fn) - class DpkgOrderedDatalist(OrderedDict, _DpkgDatalist): - def __init__(self, fn=""): + def __init__(self, fn=None): OrderedDict.__init__(self) _DpkgDatalist.__init__(self, fn) diff --git a/minidinstall/GPGSigVerifier.py b/minidinstall/GPGSigVerifier.py index 2e0dee5..0d47379 100644 --- a/minidinstall/GPGSigVerifier.py +++ b/minidinstall/GPGSigVerifier.py @@ -2,7 +2,7 @@ # A class for verifying signed files -# Copyright © 2002 Colin Walters <walters@gnu.org> +# Copyright (c) 2002 Colin Walters <walters@gnu.org> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -18,8 +18,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os, re, sys, string, stat -from minidinstall import misc +import os +from . import misc class GPGSigVerifierException(Exception): def __init__(self, value): @@ -40,10 +40,10 @@ class GPGSigVerificationFailure(Exception): class GPGSigVerifier: def __init__(self, keyrings, gpgv=None): self._keyrings = keyrings - if gpgv is None: + if not gpgv: gpgv = '/usr/bin/gpgv' if not os.access(gpgv, os.X_OK): - raise GPGSigVerifierException("Couldn't execute \"%s\"" % (gpgv,)) + raise GPGSigVerifierException("Couldn't execute \"%s\"" % gpgv) self._gpgv = gpgv def verify(self, filename, sigfilename=None): @@ -53,25 +53,24 @@ class GPGSigVerifier: os.close(stdin) misc.dup2(stdout, 1) misc.dup2(stdout, 2) - args = [] + args = [self._gpgv] for keyring in self._keyrings: - args.append('--keyring') - args.append(keyring) + args.extend(['--keyring', keyring]) if sigfilename: args.append(sigfilename) - args = [self._gpgv] + args + [filename] + args.append(filename) os.execv(self._gpgv, args) os.exit(1) os.close(stdout) output = os.fdopen(stdin).readlines() (pid, status) = os.waitpid(pid, 0) - if not (status is None or (os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0)): + if status or (not os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0): if os.WIFEXITED(status): - msg = "gpgv exited with error code %d" % (os.WEXITSTATUS(status),) + msg = "gpgv exited with error code %d" % os.WEXITSTATUS(status) elif os.WIFSTOPPED(status): - msg = "gpgv stopped unexpectedly with signal %d" % (os.WSTOPSIG(status),) + msg = "gpgv stopped unexpectedly with signal %d" % os.WSTOPSIG(status) elif os.WIFSIGNALED(status): - msg = "gpgv died with signal %d" % (os.WTERMSIG(status),) + msg = "gpgv died with signal %d" % os.WTERMSIG(status) raise GPGSigVerificationFailure(msg, output) return output diff --git a/minidinstall/OrderedDict.py b/minidinstall/OrderedDict.py index 7c842b0..dab57db 100644 --- a/minidinstall/OrderedDict.py +++ b/minidinstall/OrderedDict.py @@ -1,10 +1,10 @@ -# OrderedDict.py +# OrderedDict -*- mode: python; coding: utf-8 -*- # # This class functions almost exactly like UserDict. However, when using # the sequence methods, it returns items in the same order in which they # were added, instead of some random order. # -# Copyright 2001 Adam Heath <doogie@debian.org> +# Copyright (c) 2001 Adam Heath <doogie@debian.org> # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ class OrderedDict(UserDict): def __init__(self, dict=None): UserDict.__init__(self) self.__order=[] - if dict is not None and dict.__class__ is not None: + if dict and dict.__class__: self.update(dict) def __cmp__(self, dict): @@ -57,8 +57,7 @@ class OrderedDict(UserDict): def copy(self): if self.__class__ is OrderedDict: return OrderedDict(self) - import copy - return copy.copy(self) + return self.copy() def keys(self): return self.__order @@ -70,7 +69,7 @@ class OrderedDict(UserDict): return list(map(lambda x, self=self: self.__getitem__(x), self.__order)) def update(self, dict): - for k, v in list(dict.items()): + for (k, v) in list(dict.items()): self.__setitem__(k, v) # vim:ts=4:sw=4:et: diff --git a/minidinstall/SafeWriteFile.py b/minidinstall/SafeWriteFile.py index 591c4f0..38262f2 100755 --- a/minidinstall/SafeWriteFile.py +++ b/minidinstall/SafeWriteFile.py @@ -1,11 +1,12 @@ -# SafeWriteFile.py +#!/usr/bin/python3 +# SafeWriteFile -*- mode: python; coding: utf-8 -*- # # This file is a writable file object. It writes to a specified newname, # and when closed, renames the file to the realname. If the object is # deleted, without being closed, this rename isn't done. If abort() is # called, it also disables the rename. # -# Copyright 2001 Adam Heath <doogie@debian.org> +# Copyright (c) 2001 Adam Heath <doogie@debian.org> # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -27,11 +28,9 @@ from os import rename class ObjectNotAllowed(Exception): pass - class InvalidMode(Exception): pass - class SafeWriteFile: def __init__(self, newname, realname, mode="w", bufsize=-1): @@ -47,7 +46,7 @@ class SafeWriteFile: self.fobj=open(newname, mode, bufsize) self.newname=newname self.realname=realname - self.__abort=0 + self.__abort=False def close(self): self.fobj.close() @@ -55,7 +54,7 @@ class SafeWriteFile: rename(self.newname, self.realname) def abort(self): - self.__abort=1 + self.__abort=True def __del__(self): self.abort() @@ -67,7 +66,6 @@ class SafeWriteFile: except: return eval("self.fobj." + attr) - if __name__ == "__main__": import time f=SafeWriteFile("sf.new", "sf.data") diff --git a/minidinstall/SignedFile.py b/minidinstall/SignedFile.py index efc4730..5a1f7f6 100755 --- a/minidinstall/SignedFile.py +++ b/minidinstall/SignedFile.py @@ -1,9 +1,10 @@ +#!/usr/bin/python3 # SignedFile -*- mode: python; coding: utf-8 -*- # SignedFile offers a subset of file object operations, and is # designed to transparently handle files with PGP signatures. -# Copyright © 2002 Colin Walters <walters@gnu.org> +# Copyright (c) 2002 Colin Walters <walters@gnu.org> # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -19,23 +20,22 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import re,string - class SignedFile: _stream = None - _eof = 0 - _signed = 0 + _eof = False + _signed = False _signature = None _signatureversion = None _initline = None + def __init__(self, stream): self._stream = stream line = stream.readline() - if (line == "-----BEGIN PGP SIGNED MESSAGE-----\n"): - self._signed = 1 + if line == "-----BEGIN PGP SIGNED MESSAGE-----\n": + self._signed = True while True: line = stream.readline() - if (len(line) == 0 or line == '\n'): + if not line or line == '\n': break else: self._initline = line @@ -51,13 +51,13 @@ class SignedFile: if not self._signed: return line elif line == "-----BEGIN PGP SIGNATURE-----\n": - self._eof = 1 + self._eof = True self._signature = [] self._signatureversion = self._stream.readline() self._stream.readline() # skip blank line while True: line = self._stream.readline() - if len(line) == 0 or line == "-----END PGP SIGNATURE-----\n": + if not line or line == "-----END PGP SIGNATURE-----\n": break self._signature.append(line) self._signature = ''.join(self._signature) @@ -68,7 +68,7 @@ class SignedFile: ret = [] while True: line = self.readline() - if (line != ''): + if line: ret.append(line) else: break @@ -86,22 +86,22 @@ class SignedFile: def getSignatureVersion(self): return self._signatureversion -if __name__=="__main__": +if __name__ == "__main__": import sys - if len(sys.argv) == 0: + if not sys.argv: print("Need one file as an argument") sys.exit(1) filename = sys.argv[1] - f=SignedFile(open(filename)) + f = SignedFile(open(filename)) if f.getSigned(): print("**** SIGNED ****") else: print("**** NOT SIGNED ****") - lines=f.readlines() + lines = f.readlines() print(lines) if not f.getSigned(): assert(len(lines) == len(actuallines)) else: - print("Signature: %s" % (f.getSignature())) + print("Signature: %s" % f.getSignature()) # vim:ts=4:sw=4:et: diff --git a/minidinstall/mail.py b/minidinstall/mail.py index 50df462..305d822 100644 --- a/minidinstall/mail.py +++ b/minidinstall/mail.py @@ -1,8 +1,8 @@ # mail -*- mode: python; coding: utf-8 -*- -"""Simple mail support for mini-dinstall.""" +# Simple mail support for mini-dinstall. -# Copyright © 2008 Stephan Sürken <absurd@debian.org> +# Copyright (c) 2008 Stephan Sürken <absurd@debian.org> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -21,24 +21,22 @@ import smtplib import email.mime.text import email.utils - import logging def send(smtp_server, smtp_from, smtp_to, body, subject="mini-dinstall mail notice"): """Send email; on error, log and continue.""" - logger = logging.getLogger("mini-dinstall") - try: - # Create a mime body - mime_body = email.mime.text.MIMEText(body, 'plain', 'utf-8') - mime_body['Subject'] = subject - mime_body['From'] = smtp_from - mime_body['To'] = smtp_to - mime_body['Date'] = email.utils.formatdate(localtime=True) - mime_body['Message-ID'] = email.utils.make_msgid() - mime_body.add_header('X-Mini-Dinstall', 'YES') + # Create a mime body + mime_body = email.mime.text.MIMEText(body, 'plain', 'utf-8') + mime_body['Subject'] = subject + mime_body['From'] = smtp_from + mime_body['To'] = smtp_to + mime_body['Date'] = email.utils.formatdate(localtime=True) + mime_body['Message-ID'] = email.utils.make_msgid() + mime_body.add_header('X-Mini-Dinstall', 'YES') + try: # Send via SMTP server smtp = smtplib.SMTP(smtp_server) smtp.sendmail(smtp_from, [smtp_to], mime_body.as_string()) diff --git a/minidinstall/misc.py b/minidinstall/misc.py index 372c450..5f7fb71 100644 --- a/minidinstall/misc.py +++ b/minidinstall/misc.py @@ -2,7 +2,7 @@ # misc tools for mini-dinstall -# Copyright © 2004 Thomas Viehmann <tv@beamnet.de> +# Copyright (c) 2004 Thomas Viehmann <tv@beamnet.de> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -18,26 +18,25 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os, errno, time, string, re, hashlib +import os, errno, time, re, hashlib -def dup2(fd,fd2): +def dup2(fd, fd2): # dup2 with EBUSY retries (cf. dup2(2) and Debian bug #265513) - success = 0 + success = False tries = 0 - while (not success): + while not success: try: - os.dup2(fd,fd2) - success = 1 + os.dup2(fd, fd2) + success = True except OSError as e: - if (e.errno != errno.EBUSY) or (tries >= 3): + if e.errno != errno.EBUSY or tries >= 3: raise - # wait 0-2 seconds befor next try + # wait 0-2 seconds before next try time.sleep(tries) tries += 1 def format_changes(L): """ remove changelog header and all lines with only a dot """ - dotmatch = re.compile('^\.$') L1 = [] @@ -48,16 +47,11 @@ def format_changes(L): def get_file_sum(self, type, filename): """ generate hash sums for file """ - if type == 'md5': - sum = hashlib.md5() - elif type == 'sha1': - sum = hashlib.sha1() - elif type == 'sha256': - sum = hashlib.sha256() + sum = getattr(hashlib, type)() self._logger.debug("Generate %s (python-internal) for %s" % (type, filename)) - f = open(filename,'rb') + f = open(filename, 'rb') buf = f.read(8192) - while buf != '': + while buf: sum.update(buf) buf = f.read(8192) return sum.hexdigest() diff --git a/minidinstall/tweet.py b/minidinstall/tweet.py index 7106085..3a4a4ef 100644 --- a/minidinstall/tweet.py +++ b/minidinstall/tweet.py @@ -1,8 +1,8 @@ -# mail -*- mode: python; coding: utf-8 -*- +# tweet -*- mode: python; coding: utf-8 -*- -"""Simple tweet support for mini-dinstall.""" +# Simple tweet support for mini-dinstall. -# Copyright © 2010 Christopher R. Gabriel <cgabriel@truelite.it> +# Copyright (c) 2010 Christopher R. Gabriel <cgabriel@truelite.it> # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -18,10 +18,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - import logging import urllib.request -import base64 def send(tweet_body, tweet_server, tweet_user, tweet_password): """Send tweet; on error, log and continue.""" @@ -37,8 +35,8 @@ def send(tweet_body, tweet_server, tweet_user, tweet_password): if not post_url: logger.exception("Unknown tweet site") - if not tweet_user or not tweet_password: - logger.exception("Missing username or password for twitting") + if not (tweet_user and tweet_password): + logger.exception("Missing username or password for tweeting") auth_handler = urllib.request.HTTPBasicAuthHandler() auth_handler.add_password(realm=auth_realm, @@ -49,10 +47,9 @@ def send(tweet_body, tweet_server, tweet_user, tweet_password): req = urllib.request.Request(post_url) req.add_data("status=%s" % tweet_body) - handle = None try: handle = m_http_opener.open(req) - a = handle.read() + result = handle.read() logger.info("Tweet sent to %s (%s)" % (tweet_server, tweet_user)) except Exception as e: - logger.exception("Error sending tweet to %s ('%s') via %s: %s: %s", tweet_server, tweet_body, tweet_user, type(e), e.args) + logger.exception("Error sending tweet to %s ('%s') via %s: %s: %s" % (tweet_server, tweet_body, tweet_user, type(e), e.args)) |
