diff --git a/.pylintrc b/.pylintrc index 5e1d5fc..689b0e6 100644 --- a/.pylintrc +++ b/.pylintrc @@ -13,6 +13,7 @@ extension-pkg-whitelist=lxml.etree disable= bad-continuation, raising-format-tuple, + raise-missing-from, import-outside-toplevel, inconsistent-return-statements, duplicate-code, diff --git a/qubesadmin/app.py b/qubesadmin/app.py index 7de88f9..6c5d2a0 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -167,7 +167,7 @@ class QubesBase(qubesadmin.base.PropertyHolder): cache_enabled = False def __init__(self): - super(QubesBase, self).__init__(self, 'admin.property.', 'dom0') + super().__init__(self, 'admin.property.', 'dom0') self.domains = VMCollection(self) self.labels = qubesadmin.base.WrapperObjectsCollection( self, 'admin.label.List', qubesadmin.label.Label) @@ -454,19 +454,19 @@ class QubesBase(qubesadmin.base.PropertyHolder): ['qvm-appmenus', '--init', '--update', '--source', src_vm.name, dst_vm.name] subprocess.check_output(appmenus_cmd, stderr=subprocess.STDOUT) - except OSError: + except OSError as e: # this file needs to be python 2.7 compatible, # so no FileNotFoundError self.log.error('Failed to clone appmenus, qvm-appmenus missing') if not ignore_errors: raise qubesadmin.exc.QubesException( - 'Failed to clone appmenus') + 'Failed to clone appmenus') from e except subprocess.CalledProcessError as e: self.log.error('Failed to clone appmenus: %s', e.output.decode()) if not ignore_errors: raise qubesadmin.exc.QubesException( - 'Failed to clone appmenus') + 'Failed to clone appmenus') from e except qubesadmin.exc.QubesException: if not ignore_errors: diff --git a/qubesadmin/backup/core2.py b/qubesadmin/backup/core2.py index 251154d..f9ae32b 100644 --- a/qubesadmin/backup/core2.py +++ b/qubesadmin/backup/core2.py @@ -38,7 +38,7 @@ class Core2VM(qubesadmin.backup.BackupVM): '''VM object''' # pylint: disable=too-few-public-methods def __init__(self): - super(Core2VM, self).__init__() + super().__init__() self.backup_content = False @property @@ -148,7 +148,7 @@ class Core2Qubes(qubesadmin.backup.BackupApp): raise ValueError("store path required") self.qid_map = {} self.log = logging.getLogger('qubesadmin.backup.core2') - super(Core2Qubes, self).__init__(store) + super().__init__(store) def load_globals(self, element): '''Load global settings diff --git a/qubesadmin/backup/core3.py b/qubesadmin/backup/core3.py index 626b414..c464a07 100644 --- a/qubesadmin/backup/core3.py +++ b/qubesadmin/backup/core3.py @@ -57,7 +57,7 @@ class Core3Qubes(qubesadmin.backup.BackupApp): raise ValueError("store path required") self.log = logging.getLogger('qubesadmin.backup.core3') self.labels = {} - super(Core3Qubes, self).__init__(store) + super().__init__(store) @staticmethod def get_property(xml_obj, prop): diff --git a/qubesadmin/backup/restore.py b/qubesadmin/backup/restore.py index 0ff47f9..890fb96 100644 --- a/qubesadmin/backup/restore.py +++ b/qubesadmin/backup/restore.py @@ -82,7 +82,7 @@ _tar_file_size_re = re.compile(r"^[^ ]+ [^ ]+/[^ ]+ *([0-9]+) .*") class BackupCanceledError(QubesException): '''Exception raised when backup/restore was cancelled''' def __init__(self, msg, tmpdir=None): - super(BackupCanceledError, self).__init__(msg) + super().__init__(msg) self.tmpdir = tmpdir def init_supported_hmac_and_crypto(): @@ -361,7 +361,7 @@ class ExtractWorker3(Process): :param bool verify_only: only verify data integrity, do not extract :param dict handlers: handlers for actual data ''' - super(ExtractWorker3, self).__init__() + super().__init__() #: queue with files to extract self.queue = queue #: paths on the queue are relative to this dir @@ -904,14 +904,14 @@ class BackupRestore(object): USERNAME_MISMATCH = object() def __init__(self, vm, subdir=None): - super(BackupRestore.Dom0ToRestore, self).__init__(vm) + super().__init__(vm) if subdir: self.subdir = subdir self.username = os.path.basename(subdir) def __init__(self, app, backup_location, backup_vm, passphrase, location_is_service=False, force_compression_filter=None): - super(BackupRestore, self).__init__() + super().__init__() #: qubes.Qubes instance self.app = app diff --git a/qubesadmin/base.py b/qubesadmin/base.py index ccb08cf..c4c3b7b 100644 --- a/qubesadmin/base.py +++ b/qubesadmin/base.py @@ -345,7 +345,7 @@ class PropertyHolder(object): def __setattr__(self, key, value): if key.startswith('_') or key in self._local_properties(): - return super(PropertyHolder, self).__setattr__(key, value) + return super().__setattr__(key, value) if value is qubesadmin.DEFAULT: try: self.qubesd_call( @@ -371,7 +371,7 @@ class PropertyHolder(object): def __delattr__(self, name): if name.startswith('_') or name in self._local_properties(): - return super(PropertyHolder, self).__delattr__(name) + return super().__delattr__(name) try: self.qubesd_call( self._method_dest, diff --git a/qubesadmin/devices.py b/qubesadmin/devices.py index 4efcab7..5a7b665 100644 --- a/qubesadmin/devices.py +++ b/qubesadmin/devices.py @@ -115,7 +115,7 @@ class UnknownDevice(DeviceInfo): **kwargs): if description is None: description = "Unknown device" - super(UnknownDevice, self).__init__(backend_domain, devclass, ident, + super().__init__(backend_domain, devclass, ident, description, **kwargs) @@ -295,7 +295,7 @@ class DeviceManager(dict): """ def __init__(self, vm): - super(DeviceManager, self).__init__() + super().__init__() self._vm = vm def __missing__(self, key): diff --git a/qubesadmin/exc.py b/qubesadmin/exc.py index f55ceba..5021f22 100644 --- a/qubesadmin/exc.py +++ b/qubesadmin/exc.py @@ -25,7 +25,7 @@ class QubesException(Exception): '''Base exception for all Qubes-related errors.''' def __init__(self, message_format, *args, **kwargs): # TODO: handle translations - super(QubesException, self).__init__( + super().__init__( message_format % tuple(int(d) if d.isdigit() else d for d in args), **kwargs) @@ -164,7 +164,7 @@ class DeviceAlreadyAttached(QubesException, KeyError): class BackupRestoreError(QubesException): '''Restoring a backup failed''' def __init__(self, msg, backup_log=None): - super(BackupRestoreError, self).__init__(msg) + super().__init__(msg) self.backup_log = backup_log # pylint: disable=too-many-ancestors @@ -177,8 +177,7 @@ class QubesPropertyAccessError(QubesDaemonAccessError, AttributeError): '''Failed to read/write property value, cause is unknown (insufficient permissions, no such property, invalid value, other)''' def __init__(self, prop): - super(QubesPropertyAccessError, self).__init__( - 'Failed to access \'%s\' property' % prop) + super().__init__('Failed to access \'%s\' property' % prop) # legacy name QubesDaemonNoResponseError = QubesDaemonAccessError diff --git a/qubesadmin/features.py b/qubesadmin/features.py index e7a9cee..3522043 100644 --- a/qubesadmin/features.py +++ b/qubesadmin/features.py @@ -35,7 +35,7 @@ class Features(object): # pylint: disable=too-few-public-methods def __init__(self, vm): - super(Features, self).__init__() + super().__init__() self.vm = vm def __delitem__(self, key): diff --git a/qubesadmin/firewall.py b/qubesadmin/firewall.py index 45f08b1..8af5a70 100644 --- a/qubesadmin/firewall.py +++ b/qubesadmin/firewall.py @@ -53,7 +53,7 @@ class RuleChoice(RuleOption): '''Base class for multiple-choices rule elements''' # pylint: disable=abstract-method def __init__(self, value): - super(RuleChoice, self).__init__(value) + super().__init__(value) self.allowed_values = \ [v for k, v in self.__class__.__dict__.items() if not k.startswith('__') and isinstance(v, str) and @@ -148,7 +148,7 @@ class DstHost(RuleOption): except socket.error: raise ValueError('Invalid IP address: ' + host) - super(DstHost, self).__init__(value) + super().__init__(value) @property def rule(self): @@ -175,7 +175,7 @@ class DstPorts(RuleOption): raise ValueError('Ports out of range') if self.range[0] > self.range[1]: raise ValueError('Invalid port range') - super(DstPorts, self).__init__( + super().__init__( str(self.range[0]) if self.range[0] == self.range[1] else '{!s}-{!s}'.format(*self.range)) @@ -188,7 +188,7 @@ class DstPorts(RuleOption): class IcmpType(RuleOption): '''ICMP packet type''' def __init__(self, value): - super(IcmpType, self).__init__(value) + super().__init__(value) value = int(value) if value < 0 or value > 255: raise ValueError('ICMP type out of range') @@ -212,7 +212,7 @@ class SpecialTarget(RuleChoice): class Expire(RuleOption): '''Rule expire time''' def __init__(self, value): - super(Expire, self).__init__(value) + super().__init__(value) self.datetime = datetime.datetime.utcfromtimestamp(int(value)) @property diff --git a/qubesadmin/label.py b/qubesadmin/label.py index bd2645d..74a3b98 100644 --- a/qubesadmin/label.py +++ b/qubesadmin/label.py @@ -46,7 +46,7 @@ class Label(object): qubesd_response = self.app.qubesd_call( 'dom0', 'admin.label.Get', self._name, None) except qubesadmin.exc.QubesDaemonNoResponseError: - raise AttributeError + raise qubesadmin.exc.QubesPropertyAccessError('label.color') self._color = qubesd_response.decode() return self._color @@ -63,13 +63,13 @@ class Label(object): @property def index(self): - '''color specification as in HTML (``#abcdef``)''' + '''label numeric identifier''' if self._index is None: try: qubesd_response = self.app.qubesd_call( 'dom0', 'admin.label.Index', self._name, None) except qubesadmin.exc.QubesDaemonNoResponseError: - raise AttributeError + raise qubesadmin.exc.QubesPropertyAccessError('label.index') self._index = int(qubesd_response.decode()) return self._index diff --git a/qubesadmin/spinner.py b/qubesadmin/spinner.py index 58e6758..7d4b3d5 100644 --- a/qubesadmin/spinner.py +++ b/qubesadmin/spinner.py @@ -91,7 +91,7 @@ class QubesSpinner(AbstractSpinner): This spinner uses standard ASCII control characters''' def __init__(self, *args, **kwargs): - super(QubesSpinner, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.hidelen = 0 self.cub1 = '\b' @@ -120,7 +120,7 @@ class QubesSpinnerEnterpriseEdition(QubesSpinner): if charset is None: charset = ENTERPRISE_CHARSET if self.stream_isatty else '.' - super(QubesSpinnerEnterpriseEdition, self).__init__(stream, charset) + super().__init__(stream, charset) if self.stream_isatty: try: diff --git a/qubesadmin/tags.py b/qubesadmin/tags.py index 37c09e9..fc0f579 100644 --- a/qubesadmin/tags.py +++ b/qubesadmin/tags.py @@ -31,7 +31,7 @@ class Tags(object): # pylint: disable=too-few-public-methods def __init__(self, vm): - super(Tags, self).__init__() + super().__init__() self.vm = vm def remove(self, elem): diff --git a/qubesadmin/tools/__init__.py b/qubesadmin/tools/__init__.py index 595e817..ade58ad 100644 --- a/qubesadmin/tools/__init__.py +++ b/qubesadmin/tools/__init__.py @@ -62,7 +62,7 @@ class PropertyAction(argparse.Action): metavar='NAME=VALUE', required=False, help='set property to a value'): - super(PropertyAction, self).__init__(option_strings, 'properties', + super().__init__(option_strings, 'properties', metavar=metavar, default={}, help=help) def __call__(self, parser, namespace, values, option_string=None): @@ -99,7 +99,7 @@ class SinglePropertyAction(argparse.Action): if const is not None: nargs = 0 - super(SinglePropertyAction, self).__init__(option_strings, 'properties', + super().__init__(option_strings, 'properties', metavar=metavar, help=help, default={}, const=const, nargs=nargs) @@ -141,7 +141,7 @@ class VmNameAction(QubesAction): nargs, "Passed unexpected value {!s} as {!s} nargs ".format( nargs, dest)) - super(VmNameAction, self).__init__(option_strings, dest=dest, help=help, + super().__init__(option_strings, dest=dest, help=help, nargs=nargs, **kwargs) def __call__(self, parser, namespace, values, option_string=None): @@ -200,11 +200,11 @@ class RunningVmNameAction(VmNameAction): raise argparse.ArgumentError( nargs, "Passed unexpected value {!s} as {!s} nargs ".format( nargs, dest)) - super(RunningVmNameAction, self).__init__( + super().__init__( option_strings, dest=dest, help=help, nargs=nargs, **kwargs) def parse_qubes_app(self, parser, namespace): - super(RunningVmNameAction, self).parse_qubes_app(parser, namespace) + super().parse_qubes_app(parser, namespace) for vm in namespace.domains: if not vm.is_running(): parser.error_runtime("domain {!r} is not running".format( @@ -220,7 +220,7 @@ class VolumeAction(QubesAction): def __init__(self, help='A pool & volume id combination', required=True, **kwargs): # pylint: disable=redefined-builtin - super(VolumeAction, self).__init__(help=help, required=required, + super().__init__(help=help, required=required, **kwargs) def __call__(self, parser, namespace, values, option_string=None): @@ -261,7 +261,7 @@ class VMVolumeAction(QubesAction): def __init__(self, help='A pool & volume id combination', required=True, **kwargs): # pylint: disable=redefined-builtin - super(VMVolumeAction, self).__init__(help=help, required=required, + super().__init__(help=help, required=required, **kwargs) def __call__(self, parser, namespace, values, option_string=None): @@ -339,7 +339,7 @@ class QubesArgumentParser(argparse.ArgumentParser): def __init__(self, vmname_nargs=None, **kwargs): - super(QubesArgumentParser, self).__init__(add_help=False, **kwargs) + super().__init__(add_help=False, **kwargs) self._vmname_nargs = vmname_nargs @@ -370,7 +370,7 @@ class QubesArgumentParser(argparse.ArgumentParser): # pylint: disable=arguments-differ,signature-differs # hack for tests app = kwargs.pop('app', None) - namespace = super(QubesArgumentParser, self).parse_args(*args, **kwargs) + namespace = super().parse_args(*args, **kwargs) self.set_qubes_verbosity(namespace) if app is not None: @@ -472,8 +472,7 @@ class AliasedSubParsersAction(argparse._SubParsersAction): dest = name if aliases: dest += ' (%s)' % ','.join(aliases) - super(AliasedSubParsersAction._AliasedPseudoAction, self).\ - __init__(option_strings=[], dest=dest, help=help) + super().__init__(option_strings=[], dest=dest, help=help) def __call__(self, parser, namespace, values, option_string=None): pass @@ -485,8 +484,7 @@ class AliasedSubParsersAction(argparse._SubParsersAction): else: aliases = [] - local_parser = super(AliasedSubParsersAction, self).add_parser( - name, **kwargs) + local_parser = super().add_parser(name, **kwargs) # Make the aliases work. for alias in aliases: @@ -532,7 +530,7 @@ class VmNameGroup(argparse._MutuallyExclusiveGroup): def __init__(self, container, required, vm_action=VmNameAction, help=None): # pylint: disable=redefined-builtin - super(VmNameGroup, self).__init__(container, required=required) + super().__init__(container, required=required) if not help: help = 'perform the action on all qubes' self.add_argument('--all', action='store_true', dest='all_domains', diff --git a/qubesadmin/tools/qvm_device.py b/qubesadmin/tools/qvm_device.py index c74f7de..a200f71 100644 --- a/qubesadmin/tools/qvm_device.py +++ b/qubesadmin/tools/qvm_device.py @@ -163,7 +163,7 @@ class DeviceAction(qubesadmin.tools.QubesAction): required=True, allow_unknown=False, **kwargs): # pylint: disable=redefined-builtin self.allow_unknown = allow_unknown - super(DeviceAction, self).__init__(help=help, required=required, + super().__init__(help=help, required=required, **kwargs) def __call__(self, parser, namespace, values, option_string=None): diff --git a/qubesadmin/tools/qvm_ls.py b/qubesadmin/tools/qvm_ls.py index e3a8270..5f235f0 100644 --- a/qubesadmin/tools/qvm_ls.py +++ b/qubesadmin/tools/qvm_ls.py @@ -141,9 +141,7 @@ class PropertyColumn(Column): def __init__(self, name): ls_head = name.replace('_', '-').upper() - super(PropertyColumn, self).__init__( - head=ls_head, - attr=name) + super().__init__(head=ls_head, attr=name) def __repr__(self): return '{}(head={!r}'.format( @@ -201,9 +199,7 @@ class FlagsColumn(Column): # pylint: disable=no-self-use def __init__(self): - super(FlagsColumn, self).__init__( - head='FLAGS', - doc=self.__class__.__doc__) + super().__init__(head='FLAGS', doc=self.__class__.__doc__) @flag(1) @@ -505,7 +501,7 @@ class _HelpColumnsAction(argparse.Action): dest=argparse.SUPPRESS, default=argparse.SUPPRESS, help='list all available columns with short descriptions and exit'): - super(_HelpColumnsAction, self).__init__( + super().__init__( option_strings=option_strings, dest=dest, default=default, @@ -536,7 +532,7 @@ class _HelpFormatsAction(argparse.Action): dest=argparse.SUPPRESS, default=argparse.SUPPRESS, help='list all available formats with their definitions and exit'): - super(_HelpFormatsAction, self).__init__( + super().__init__( option_strings=option_strings, dest=dest, default=default, diff --git a/qubesadmin/tools/qvm_pool_legacy.py b/qubesadmin/tools/qvm_pool_legacy.py index 6b90b0c..d396898 100644 --- a/qubesadmin/tools/qvm_pool_legacy.py +++ b/qubesadmin/tools/qvm_pool_legacy.py @@ -36,11 +36,11 @@ class _Info(qubesadmin.tools.PoolsAction): def __init__(self, option_strings, help='print pool info and exit', **kwargs): # pylint: disable=redefined-builtin - super(_Info, self).__init__(option_strings, help=help, **kwargs) + super().__init__(option_strings, help=help, **kwargs) def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, 'command', 'info') - super(_Info, self).__call__(parser, namespace, values, option_string) + super().__call__(parser, namespace, values, option_string) def pool_info(pool): @@ -62,11 +62,11 @@ class _Remove(argparse.Action): ''' Action for argument parser that removes a pool ''' def __init__(self, option_strings, dest=None, default=None, metavar=None): - super(_Remove, self).__init__(option_strings=option_strings, - dest=dest, - metavar=metavar, - default=default, - help='remove pool') + super().__init__(option_strings=option_strings, + dest=dest, + metavar=metavar, + default=default, + help='remove pool') def __call__(self, parser, namespace, name, option_string=None): setattr(namespace, 'command', 'remove') @@ -77,12 +77,12 @@ class _Add(argparse.Action): ''' Action for argument parser that adds a pool. ''' def __init__(self, option_strings, dest=None, default=None, metavar=None): - super(_Add, self).__init__(option_strings=option_strings, - dest=dest, - metavar=metavar, - default=default, - nargs=2, - help='add pool') + super().__init__(option_strings=option_strings, + dest=dest, + metavar=metavar, + default=default, + nargs=2, + help='add pool') def __call__(self, parser, namespace, values, option_string=None): name, driver = values @@ -95,23 +95,23 @@ class _Set(qubesadmin.tools.PoolsAction): ''' Action for argument parser that sets pool options. ''' def __init__(self, option_strings, dest=None, default=None, metavar=None): - super(_Set, self).__init__(option_strings=option_strings, - dest=dest, - metavar=metavar, - default=default, - help='modify pool (use -o to specify ' - 'modifications)') + super().__init__(option_strings=option_strings, + dest=dest, + metavar=metavar, + default=default, + help='modify pool (use -o to specify ' + 'modifications)') def __call__(self, parser, namespace, name, option_string=None): setattr(namespace, 'command', 'set') - super(_Set, self).__call__(parser, namespace, name, option_string) + super().__call__(parser, namespace, name, option_string) class _Options(argparse.Action): ''' Action for argument parser that parsers options. ''' def __init__(self, option_strings, dest, default, metavar='options'): - super(_Options, self).__init__( + super().__init__( option_strings=option_strings, dest=dest, metavar=metavar, diff --git a/qubesadmin/tools/qvm_start.py b/qubesadmin/tools/qvm_start.py index 260d713..c750235 100644 --- a/qubesadmin/tools/qvm_start.py +++ b/qubesadmin/tools/qvm_start.py @@ -42,7 +42,7 @@ class DriveAction(argparse.Action): metavar='IMAGE', required=False, help='Attach drive'): - super(DriveAction, self).__init__(option_strings, dest, + super().__init__(option_strings, dest, metavar=metavar, help=help) self.prefix = prefix diff --git a/qubesadmin/vm/__init__.py b/qubesadmin/vm/__init__.py index 2cbcaeb..530c8a8 100644 --- a/qubesadmin/vm/__init__.py +++ b/qubesadmin/vm/__init__.py @@ -53,7 +53,7 @@ class QubesVM(qubesadmin.base.PropertyHolder): firewall = None def __init__(self, app, name, klass=None, power_state=None): - super(QubesVM, self).__init__(app, 'admin.vm.property.', name) + super().__init__(app, 'admin.vm.property.', name) self._volumes = None self._klass = klass self._power_state_cache = power_state @@ -373,7 +373,7 @@ class QubesVM(qubesadmin.base.PropertyHolder): # use cached value if available if self._klass is None: # pylint: disable=no-member - self._klass = super(QubesVM, self).klass + self._klass = super().klass return self._klass class DispVMWrapper(QubesVM): @@ -398,7 +398,7 @@ class DispVMWrapper(QubesVM): # Service call may wait for session start, give it more time # than default 5s kwargs['connect_timeout'] = self.qrexec_timeout - return super(DispVMWrapper, self).run_service(service, **kwargs) + return super().run_service(service, **kwargs) def cleanup(self): '''Cleanup after DispVM usage'''