diff options
25 files changed, 79 insertions, 36 deletions
diff --git a/HACKING.rst b/HACKING.rst index 307d7477c9..b29361a8d1 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -211,6 +211,25 @@ Example:: LOG.error(msg % {"s_id": "1234", "m_key": "imageId"}) +Python 3.x compatibility +------------------------ +Nova code should stay Python 3.x compatible. That means all Python 2.x-only +constructs should be avoided. An example is + + except x,y: + +Use + + except x as y: + +instead. Other Python 3.x compatility issues, like e.g. print operator +can be avoided in new code by using + + from __future__ import print_function + +at the top of your module. + + Creating Unit Tests ------------------- For every new feature, unit tests should be created that both test and diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index dfe015456f..12ea5f6152 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -251,7 +251,7 @@ class EC2KeystoneAuth(wsgi.Middleware): project_name = result['access']['token']['tenant'].get('name') roles = [role['name'] for role in result['access']['user']['roles']] - except (AttributeError, KeyError), e: + except (AttributeError, KeyError) as e: LOG.exception(_("Keystone failure: %s") % e) msg = _("Failure communicating with keystone") return ec2_error(req, request_id, "Unauthorized", msg) diff --git a/nova/api/openstack/compute/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py index 3452136c03..10a3182947 100644 --- a/nova/api/openstack/compute/contrib/admin_actions.py +++ b/nova/api/openstack/compute/contrib/admin_actions.py @@ -123,7 +123,7 @@ class AdminActionsController(wsgi.Controller): except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'migrate') - except Exception, e: + except Exception as e: LOG.exception(_("Error in migrate %s"), e) raise exc.HTTPBadRequest() return webob.Response(status_int=202) diff --git a/nova/api/openstack/compute/contrib/attach_interfaces.py b/nova/api/openstack/compute/contrib/attach_interfaces.py index dfaa284fa9..ec565a0d12 100644 --- a/nova/api/openstack/compute/contrib/attach_interfaces.py +++ b/nova/api/openstack/compute/contrib/attach_interfaces.py @@ -102,13 +102,13 @@ class InterfaceAttachmentController(object): LOG.audit(_("Attach interface"), instance=instance) network_info = self.compute_api.attach_interface(context, instance, network_id, port_id, req_ip) - except exception.NotFound, e: + except exception.NotFound as e: LOG.exception(e) raise exc.HTTPNotFound() except NotImplementedError: msg = _("Network driver does not support this function.") raise webob.exc.HTTPNotImplemented(explanation=msg) - except exception.InterfaceAttachFailed, e: + except exception.InterfaceAttachFailed as e: LOG.exception(e) msg = _("Failed to attach interface") raise webob.exc.HTTPInternalServerError(explanation=msg) diff --git a/nova/api/openstack/compute/contrib/flavor_access.py b/nova/api/openstack/compute/contrib/flavor_access.py index 566eb64727..47d7e07e28 100644 --- a/nova/api/openstack/compute/contrib/flavor_access.py +++ b/nova/api/openstack/compute/contrib/flavor_access.py @@ -191,7 +191,7 @@ class FlavorActionController(wsgi.Controller): try: flavors.remove_instance_type_access(id, tenant, context) - except exception.FlavorAccessNotFound, e: + except exception.FlavorAccessNotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) return _marshall_flavor_access(id) diff --git a/nova/api/openstack/compute/contrib/flavormanage.py b/nova/api/openstack/compute/contrib/flavormanage.py index 086c541dcc..8dc942f18a 100644 --- a/nova/api/openstack/compute/contrib/flavormanage.py +++ b/nova/api/openstack/compute/contrib/flavormanage.py @@ -42,7 +42,7 @@ class FlavorManageController(wsgi.Controller): try: flavor = flavors.get_instance_type_by_flavor_id( id, read_deleted="no") - except exception.NotFound, e: + except exception.NotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) flavors.destroy(flavor['name']) diff --git a/nova/cmd/baremetal_deploy_helper.py b/nova/cmd/baremetal_deploy_helper.py index 765af8f31a..d63d06ee9d 100644 --- a/nova/cmd/baremetal_deploy_helper.py +++ b/nova/cmd/baremetal_deploy_helper.py @@ -201,7 +201,7 @@ def deploy(address, port, iqn, lun, image_path, pxe_config_path, login_iscsi(address, port, iqn) try: root_uuid = work_on_disk(dev, root_mb, swap_mb, image_path) - except processutils.ProcessExecutionError, err: + except processutils.ProcessExecutionError as err: # Log output if there was a error LOG.error("Cmd : %s" % err.cmd) LOG.error("StdOut : %s" % err.stdout) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f9a1cc94dc..8a2ddf8770 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1774,7 +1774,7 @@ class ComputeManager(manager.SchedulerDependentManager): reboot_type, block_device_info=block_device_info, bad_volumes_callback=bad_volumes_callback) - except Exception, exc: + except Exception as exc: LOG.error(_('Cannot reboot instance: %(exc)s'), locals(), context=context, instance=instance) compute_utils.add_instance_fault_from_exc(context, @@ -4114,7 +4114,7 @@ class ComputeManager(manager.SchedulerDependentManager): reservations=None): try: yield - except exception.InstanceFaultRollback, error: + except exception.InstanceFaultRollback as error: self._quota_rollback(context, reservations) msg = _("Setting instance back to ACTIVE after: %s") LOG.info(msg % error, instance_uuid=instance_uuid) @@ -4122,7 +4122,7 @@ class ComputeManager(manager.SchedulerDependentManager): vm_state=vm_states.ACTIVE, task_state=None) raise error.inner_exception - except Exception, error: + except Exception as error: with excutils.save_and_reraise_exception(): self._quota_rollback(context, reservations) msg = _('%s. Setting instance vm_state to ERROR') diff --git a/nova/console/xvp.py b/nova/console/xvp.py index be3a41c1dc..b281014990 100644 --- a/nova/console/xvp.py +++ b/nova/console/xvp.py @@ -143,7 +143,7 @@ class XVPConsoleProxy(object): '-p', CONF.console_xvp_pid, '-c', CONF.console_xvp_conf, '-l', CONF.console_xvp_log) - except processutils.ProcessExecutionError, err: + except processutils.ProcessExecutionError as err: LOG.error(_('Error starting xvp: %s') % err) def _xvp_restart(self): diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 18aa185ab8..d3f53dc275 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3739,7 +3739,7 @@ def instance_type_create(context, values): if 'flavorid' in e.columns: raise exception.InstanceTypeIdExists(flavor_id=values['flavorid']) raise exception.InstanceTypeExists(name=values['name']) - except Exception, e: + except Exception as e: raise db_exc.DBError(e) return _dict_with_extra_specs(instance_type_ref) @@ -4505,7 +4505,7 @@ def s3_image_create(context, image_uuid): s3_image_ref = models.S3Image() s3_image_ref.update({'uuid': image_uuid}) s3_image_ref.save() - except Exception, e: + except Exception as e: raise db_exc.DBError(e) return s3_image_ref diff --git a/nova/exception.py b/nova/exception.py index 94394d5f75..bbe5442f1d 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -73,7 +73,7 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, # contain confidential information. try: return f(self, context, *args, **kw) - except Exception, e: + except Exception as e: with excutils.save_and_reraise_exception(): if notifier: payload = dict(exception=e) diff --git a/nova/hacking/checks.py b/nova/hacking/checks.py index 49fbf15f41..89ad7c554e 100644 --- a/nova/hacking/checks.py +++ b/nova/hacking/checks.py @@ -27,5 +27,29 @@ def import_no_db_in_virt(logical_line, filename): yield (0, "N307: nova.db import not allowed in nova/virt/*") +def except_python3x_compatible(logical_line, filename): + """Check for except statements to be Python 3.x compatible + + As of Python 3.x, the construct "except x,y:" has been removed. + + N308 + """ + + def is_old_style_except(logical_line): + # Should match: + # except ProcessExecutionError, exn: + # Should not match: + # except UncodeError: + # except (x,y): + return (',' in logical_line + and ')' not in logical_line.rpartition(',')[2]) + + if ("except " in logical_line + and logical_line.endswith(':') + and is_old_style_except(logical_line)): + yield(0, "N308: Python 3.x incompatible 'except x,y:' construct") + + def factory(register): register(import_no_db_in_virt) + register(except_python3x_compatible) diff --git a/nova/image/s3.py b/nova/image/s3.py index f08cbcdcbd..4a5660a6c3 100644 --- a/nova/image/s3.py +++ b/nova/image/s3.py @@ -392,14 +392,14 @@ class S3ImageService(object): key = self.cert_rpcapi.decrypt_text(elevated, project_id=context.project_id, text=base64.b64encode(encrypted_key)) - except Exception, exc: + except Exception as exc: msg = _('Failed to decrypt private key: %s') % exc raise exception.NovaException(msg) try: iv = self.cert_rpcapi.decrypt_text(elevated, project_id=context.project_id, text=base64.b64encode(encrypted_iv)) - except Exception, exc: + except Exception as exc: raise exception.NovaException(_('Failed to decrypt initialization ' 'vector: %s') % exc) @@ -410,7 +410,7 @@ class S3ImageService(object): '-K', '%s' % (key,), '-iv', '%s' % (iv,), '-out', '%s' % (decrypted_filename,)) - except processutils.ProcessExecutionError, exc: + except processutils.ProcessExecutionError as exc: raise exception.NovaException(_('Failed to decrypt image file ' '%(image_file)s: %(err)s') % {'image_file': encrypted_filename, diff --git a/nova/openstack/common/processutils.py b/nova/openstack/common/processutils.py index de6179602c..87d89b490a 100644 --- a/nova/openstack/common/processutils.py +++ b/nova/openstack/common/processutils.py @@ -203,7 +203,7 @@ def trycmd(*args, **kwargs): try: out, err = execute(*args, **kwargs) failed = False - except ProcessExecutionError, exn: + except ProcessExecutionError as exn: out, err = '', str(exn) failed = True diff --git a/nova/scheduler/scheduler_options.py b/nova/scheduler/scheduler_options.py index f7aa911550..bae470d1b1 100644 --- a/nova/scheduler/scheduler_options.py +++ b/nova/scheduler/scheduler_options.py @@ -66,7 +66,7 @@ class SchedulerOptions(object): """Get the last modified datetime. Broken out for testing.""" try: return os.path.getmtime(filename) - except os.error, e: + except os.error as e: with excutils.save_and_reraise_exception(): LOG.exception(_("Could not stat scheduler options file " "%(filename)s: '%(e)s'"), locals()) @@ -75,7 +75,7 @@ class SchedulerOptions(object): """Decode the JSON file. Broken out for testing.""" try: return json.load(handle) - except ValueError, e: + except ValueError as e: LOG.exception(_("Could not decode scheduler options: " "'%(e)s'") % locals()) return {} diff --git a/nova/tests/api/openstack/compute/test_limits.py b/nova/tests/api/openstack/compute/test_limits.py index e51601e315..79bb97d2a2 100644 --- a/nova/tests/api/openstack/compute/test_limits.py +++ b/nova/tests/api/openstack/compute/test_limits.py @@ -462,7 +462,7 @@ class ParseLimitsTest(BaseLimitTestSuite): '(PUT, /foo*, /foo.*, 10, hour);' '(POST, /bar*, /bar.*, 5, second);' '(Say, /derp*, /derp.*, 1, day)') - except ValueError, e: + except ValueError as e: assert False, str(e) # Make sure the number of returned limits are correct diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index 949f54512b..3c3ac6c6cd 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -309,7 +309,7 @@ class ApiEc2TestCase(test.TestCase): try: self.ec2.create_key_pair('test') - except boto_exc.EC2ResponseError, e: + except boto_exc.EC2ResponseError as e: if e.code == 'InvalidKeyPair.Duplicate': pass else: diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py index 00cfdbf6c8..9baf9eb6a5 100644 --- a/nova/tests/test_migrations.py +++ b/nova/tests/test_migrations.py @@ -219,7 +219,7 @@ class BaseMigrationTestCase(test.TestCase): for key, value in defaults.items(): self.test_databases[key] = value self.snake_walk = cp.getboolean('walk_style', 'snake_walk') - except ConfigParser.ParsingError, e: + except ConfigParser.ParsingError as e: self.fail("Failed to read test_migrations.conf config " "file. Got error: %s" % e) else: diff --git a/nova/tests/test_notifications.py b/nova/tests/test_notifications.py index 71b85b3757..988ce983d4 100644 --- a/nova/tests/test_notifications.py +++ b/nova/tests/test_notifications.py @@ -99,7 +99,7 @@ class NotificationsTestCase(test.TestCase): try: # Get a real exception with a call stack. raise test.TestingException("junk") - except test.TestingException, e: + except test.TestingException as e: exception = e notifications.send_api_fault("http://example.com/foo", 500, exception) diff --git a/nova/tests/virt/libvirt/test_fakelibvirt.py b/nova/tests/virt/libvirt/test_fakelibvirt.py index 52183ab5fc..8fa2ffc63f 100644 --- a/nova/tests/virt/libvirt/test_fakelibvirt.py +++ b/nova/tests/virt/libvirt/test_fakelibvirt.py @@ -136,7 +136,7 @@ class FakeLibvirtTests(test.TestCase): conn = self.get_openAuth_curry_func()('qemu:///system') try: getattr(conn, xmlfunc_name)("this is not valid </xml>", *args) - except libvirt.libvirtError, e: + except libvirt.libvirtError as e: self.assertEqual(e.get_error_code(), libvirt.VIR_ERR_XML_DETAIL) self.assertEqual(e.get_error_domain(), libvirt.VIR_FROM_DOMAIN) return @@ -242,7 +242,7 @@ class FakeLibvirtTests(test.TestCase): dom_id = conn.listDomainsID()[0] try: conn.lookupByID(dom_id + 1) - except libvirt.libvirtError, e: + except libvirt.libvirtError as e: self.assertEqual(e.get_error_code(), libvirt.VIR_ERR_NO_DOMAIN) self.assertEqual(e.get_error_domain(), libvirt.VIR_FROM_QEMU) return @@ -315,7 +315,7 @@ class FakeLibvirtTests(test.TestCase): nwfilter.undefine() try: conn.nwfilterLookupByName('nova-instance-instance-789320334') - except libvirt.libvirtError, e: + except libvirt.libvirtError as e: self.assertEqual(e.get_error_code(), libvirt.VIR_ERR_NO_NWFILTER) self.assertEqual(e.get_error_domain(), libvirt.VIR_FROM_NWFILTER) return diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py index 6b70fe1c69..d246c32b75 100644 --- a/nova/tests/virt/libvirt/test_libvirt.py +++ b/nova/tests/virt/libvirt/test_libvirt.py @@ -2153,7 +2153,7 @@ class LibvirtConnTestCase(test.TestCase): conn.ensure_filtering_rules_for_instance(instance_ref, network_info, time_module=fake_timer) - except exception.NovaException, e: + except exception.NovaException as e: msg = ('The firewall filter for %s does not exist' % instance_ref['name']) c1 = (0 <= str(e).find(msg)) diff --git a/nova/utils.py b/nova/utils.py index 97551e8eb9..de843dff49 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -927,7 +927,7 @@ def tempdir(**kwargs): finally: try: shutil.rmtree(tmpdir) - except OSError, e: + except OSError as e: LOG.error(_('Could not remove tmpdir: %s'), str(e)) @@ -1007,7 +1007,7 @@ def last_bytes(file_like_object, num): try: file_like_object.seek(-num, os.SEEK_END) - except IOError, e: + except IOError as e: if e.errno == 22: file_like_object.seek(0, os.SEEK_SET) else: @@ -1074,7 +1074,7 @@ class ExceptionHelper(object): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) - except rpc_common.ClientException, e: + except rpc_common.ClientException as e: raise (e._exc_info[1], None, e._exc_info[2]) return wrapper diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 332f3b88cc..e178d08fd8 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -877,7 +877,7 @@ class VMOps(object): new_vdi_ref, new_vdi_uuid = create_copy_vdi_and_resize( undo_mgr, old_vdi_ref) transfer_vhd_to_dest(new_vdi_ref, new_vdi_uuid) - except Exception, error: + except Exception as error: msg = _("_migrate_disk_resizing_down failed. " "Restoring orig vm due_to: %{exception}.") LOG.exception(msg, instance=instance) diff --git a/smoketests/base.py b/smoketests/base.py index c90da102c8..1ecb5a92ed 100644 --- a/smoketests/base.py +++ b/smoketests/base.py @@ -98,7 +98,7 @@ class SmokeTestCase(unittest.TestCase): try: conn = self.connect_ssh(ip, key_name) conn.close() - except Exception, e: + except Exception as e: time.sleep(wait) else: return True diff --git a/tools/conf/extract_opts.py b/tools/conf/extract_opts.py index 89f335d9b4..deb49f7a91 100644 --- a/tools/conf/extract_opts.py +++ b/tools/conf/extract_opts.py @@ -104,12 +104,12 @@ def _import_module(mod_str): return sys.modules[mod_str[4:]] else: return importutils.import_module(mod_str) - except (ValueError, AttributeError), err: + except (ValueError, AttributeError) as err: return None - except ImportError, ie: + except ImportError as ie: sys.stderr.write("%s\n" % str(ie)) return None - except Exception, e: + except Exception as e: return None |