]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Removes the use of mutables as default args
authorGary Kotton <gkotton@vmware.com>
Thu, 29 Oct 2015 14:40:05 +0000 (07:40 -0700)
committerGary Kotton <gkotton@vmware.com>
Thu, 29 Oct 2015 14:57:31 +0000 (07:57 -0700)
Passing mutable objects as default args is a known Python pitfall.
We'd better avoid this. This commit changes mutable default args with
None, then use 'arg = arg or {}', 'arg = arg or []'. For unit code which
doesn't use the args , just set with None. This commit also adds hacking
check.

This code was taken from commit 0bea84ac20fe498bd08f7212a0017196c8cb0812
in Nova.

Change-Id: I36d07cade687690dc02a8f6cc3d70f5d00caf112
Co-Authored-By: ChangBo Guo(gcb) <glongwave@gmail.com>
17 files changed:
HACKING.rst
neutron/agent/linux/interface.py
neutron/agent/linux/iptables_firewall.py
neutron/api/api_common.py
neutron/api/extensions.py
neutron/hacking/checks.py
neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py
neutron/tests/unit/agent/linux/test_interface.py
neutron/tests/unit/api/test_extensions.py
neutron/tests/unit/api/v2/test_base.py
neutron/tests/unit/db/test_db_base_plugin_v2.py
neutron/tests/unit/extension_stubs.py
neutron/tests/unit/extensions/test_dns.py
neutron/tests/unit/extensions/test_l3.py
neutron/tests/unit/extensions/test_securitygroup.py
neutron/tests/unit/hacking/test_checks.py
neutron/tests/unit/plugins/ml2/drivers/freescale/test_mechanism_fslsdn.py

index 6b9df25901cf0ff1c76eb83d9a119ebe523b8782..0eade2778f6e56c325b6884ff3fff9507b034019 100644 (file)
@@ -18,6 +18,7 @@ Neutron Specific Commandments
 - [N326] Python 3: do not use basestring.
 - [N327] Python 3: do not use dict.iteritems.
 - [N328] Detect wrong usage with assertEqual
+- [N329] Method's default argument shouldn't be mutable
 
 Creating Unit Tests
 -------------------
index bcdf06c59e5bc17090bcf494a807240f911881b7..ad235be89431de5fa08bcef07d2b1965b8dca9f2 100644 (file)
@@ -105,8 +105,7 @@ class LinuxInterfaceDriver(object):
         return False
 
     def init_l3(self, device_name, ip_cidrs, namespace=None,
-                preserve_ips=[],
-                clean_connections=False):
+                preserve_ips=None, clean_connections=False):
         """Set the L3 settings for the interface using data from the port.
 
         ip_cidrs: list of 'X.X.X.X/YY' strings
@@ -114,6 +113,7 @@ class LinuxInterfaceDriver(object):
         clean_connections: Boolean to indicate if we should cleanup connections
           associated to removed ips
         """
+        preserve_ips = preserve_ips or []
         device = ip_lib.IPDevice(device_name, namespace=namespace)
 
         # The LLA generated by the operating system is not known to
index 2770e084276ad6870530cb0038c5df3b8e3b4022..4165ed7a69b18ccfa9ef02eb4956ad99b552c767 100644 (file)
@@ -128,7 +128,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
                     self.devices_with_udpated_sg_members[sg_id].append(device)
 
     def security_group_updated(self, action_type, sec_group_ids,
-                               device_ids=[]):
+                               device_ids=None):
+        device_ids = device_ids or []
         if action_type == 'sg_rule':
             self.updated_rule_sg_ids.update(sec_group_ids)
         elif action_type == 'sg_member':
index 5b7032092cc16c88367244ea458a3425d046d151..659e1ee1aa5c739aa5c304c3d7704f56d5bc22d3 100644 (file)
@@ -29,7 +29,7 @@ from neutron.i18n import _LW
 LOG = logging.getLogger(__name__)
 
 
-def get_filters(request, attr_info, skips=[]):
+def get_filters(request, attr_info, skips=None):
     """Extracts the filters from the request string.
 
     Returns a dict of lists for the filters:
@@ -37,6 +37,7 @@ def get_filters(request, attr_info, skips=[]):
     becomes:
     {'check': [u'a', u'b'], 'name': [u'Bob']}
     """
+    skips = skips or []
     res = {}
     for key, values in six.iteritems(request.GET.dict_of_lists()):
         if key in skips:
index 442dfc9aa67cbe3030c31e8277d9e3dc697683ae..f5fb29b2edc74942613fa32652e1d4128764e2ad 100644 (file)
@@ -641,7 +641,10 @@ class ResourceExtension(object):
     """Add top level resources to the OpenStack API in Neutron."""
 
     def __init__(self, collection, controller, parent=None, path_prefix="",
-                 collection_actions={}, member_actions={}, attr_map={}):
+                 collection_actions=None, member_actions=None, attr_map=None):
+        collection_actions = collection_actions or {}
+        member_actions = member_actions or {}
+        attr_map = attr_map or {}
         self.collection = collection
         self.controller = controller
         self.parent = parent
index 383c64e9f1e0fcaac955ea1d042ec899499ee13c..a1d2ae4f39454fb70b5e82ced5f6ada0dcddf4f5 100644 (file)
@@ -38,6 +38,7 @@ _all_log_levels = {
     'exception': '_LE',
 }
 _all_hints = set(_all_log_levels.values())
+mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])")
 
 
 def _regex_for_level(level, hint):
@@ -186,6 +187,12 @@ def check_asserttrue(logical_line, filename):
             yield (0, msg)
 
 
+def no_mutable_default_args(logical_line):
+    msg = "N329: Method's default argument shouldn't be mutable!"
+    if mutable_default_args.match(logical_line):
+        yield (0, msg)
+
+
 def factory(register):
     register(validate_log_translations)
     register(use_jsonutils)
@@ -197,3 +204,4 @@ def factory(register):
     register(check_no_basestring)
     register(check_python3_no_iteritems)
     register(check_asserttrue)
+    register(no_mutable_default_args)
index 1918b4950541ee7d1bc0874a4c8a229a56b32669..4815a0ac89a2b49956f2e2a0c053312ef3bb07bb 100644 (file)
@@ -155,7 +155,8 @@ class SriovNicSwitchAgent(object):
         mgr.initialize(connection, 'sriov')
         return mgr
 
-    def setup_eswitch_mgr(self, device_mappings, exclude_devices={}):
+    def setup_eswitch_mgr(self, device_mappings, exclude_devices=None):
+        exclude_devices = exclude_devices or {}
         self.eswitch_mgr = esm.ESwitchManager()
         self.eswitch_mgr.discover_devices(device_mappings, exclude_devices)
 
index 130abf1853a0249d1c977548f9be5d88300361d4..86f542ae1ef9b61ea4e570b02db22a9ac53a84e3 100644 (file)
@@ -361,9 +361,9 @@ class TestOVSInterfaceDriver(TestBase):
                                          'aa:bb:cc:dd:ee:ff',
                                          internal=True)
 
-    def _test_plug(self, additional_expectation=[], bridge=None,
+    def _test_plug(self, additional_expectation=None, bridge=None,
                    namespace=None):
-
+        additional_expectation = additional_expectation or []
         if not bridge:
             bridge = 'br-int'
 
index c8fea09c9870ddb756a7f9c6074999d96f97934f..60efe6db637100da28deeb8703b7fc8c88e2728e 100644 (file)
@@ -51,7 +51,8 @@ extensions_path = ':'.join(neutron.tests.unit.extensions.__path__)
 
 class ExtensionsTestApp(base_wsgi.Router):
 
-    def __init__(self, options={}):
+    def __init__(self, options=None):
+        options = options or {}
         mapper = routes.Mapper()
         controller = ext_stubs.StubBaseAppController()
         mapper.resource("dummy_resource", "/dummy_resources",
index 8507df9f91f272ed439839ed26521bf1d742b211..2e062014f3b7c4b2b47ce9fc66dac63416d8b4ab 100644 (file)
@@ -146,7 +146,8 @@ class APIv2TestCase(APIv2TestBase):
         fields.extend(policy_attrs)
         return fields
 
-    def _get_collection_kwargs(self, skipargs=[], **kwargs):
+    def _get_collection_kwargs(self, skipargs=None, **kwargs):
+        skipargs = skipargs or []
         args_list = ['filters', 'fields', 'sorts', 'limit', 'marker',
                      'page_reverse']
         args_dict = dict(
index 6d57248dc44a4fe8c958dcfca388013a340ea24b..588c7509f5c1e7233bba6476ba973f6c32d22388 100644 (file)
@@ -1220,7 +1220,9 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s
             self, expected_status=webob.exc.HTTPOk.code,
             expected_error='StateInvalid', subnet=None,
             device_owner=DEVICE_OWNER_COMPUTE, updated_fixed_ips=None,
-            host_arg={}, arg_list=[]):
+            host_arg=None, arg_list=None):
+        host_arg = host_arg or {}
+        arg_list = arg_list or []
         with self.port(device_owner=device_owner, subnet=subnet,
                        arg_list=arg_list, **host_arg) as port:
             self.assertIn('mac_address', port['port'])
index f98d2149186fda91f9016e944f55c6baa545975a..b2a0748af00c73910f2597d04a1cfb0388527357 100644 (file)
@@ -39,7 +39,8 @@ class StubExtension(object):
 
 class StubPlugin(object):
 
-    def __init__(self, supported_extensions=[]):
+    def __init__(self, supported_extensions=None):
+        supported_extensions = supported_extensions or []
         self.supported_extension_aliases = supported_extensions
 
 
index 683cb65b0b0b1970c40b1fb44ec5b8d139210e28..48f799055bbd3c1008a052a0efd7b2b9e98f3854 100644 (file)
@@ -151,9 +151,12 @@ class DnsExtensionTestCase(test_db_base_plugin_v2.TestNetworksV2):
             self._verify_dns_assigment(res['port'],
                                        ips_list=['10.0.0.2'])
 
-    def _verify_dns_assigment(self, port, ips_list=[], exp_ips_ipv4=0,
-                              exp_ips_ipv6=0, ipv4_cidrs=[], ipv6_cidrs=[],
+    def _verify_dns_assigment(self, port, ips_list=None, exp_ips_ipv4=0,
+                              exp_ips_ipv6=0, ipv4_cidrs=None, ipv6_cidrs=None,
                               dns_name=''):
+        ips_list = ips_list or []
+        ipv4_cidrs = ipv4_cidrs or []
+        ipv6_cidrs = ipv6_cidrs or []
         self.assertEqual(port['dns_name'], dns_name)
         dns_assignment = port['dns_assignment']
         if ips_list:
index bfe0f13037e406beab031eda4d63fd216fe8ee75..77183081787b54a55a6bdcca858d29aab884996e 100644 (file)
@@ -353,7 +353,8 @@ class L3NatTestCaseMixin(object):
 
     def _add_external_gateway_to_router(self, router_id, network_id,
                                         expected_code=exc.HTTPOk.code,
-                                        neutron_context=None, ext_ips=[]):
+                                        neutron_context=None, ext_ips=None):
+        ext_ips = ext_ips or []
         body = {'router':
                 {'external_gateway_info': {'network_id': network_id}}}
         if ext_ips:
index 9ce50f2de0a5cce9c944b891172538d3115f2a2c..bf9be380dec1fe728473a06903f88c8605225354 100644 (file)
@@ -213,8 +213,9 @@ class SecurityGroupTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
                                                                    network)
 
     def get_ports(self, context, filters=None, fields=None,
-                  sorts=[], limit=None, marker=None,
+                  sorts=None, limit=None, marker=None,
                   page_reverse=False):
+        sorts = sorts or []
         neutron_lports = super(SecurityGroupTestPlugin, self).get_ports(
             context, filters, sorts=sorts, limit=limit, marker=marker,
             page_reverse=page_reverse)
index d6e1d5f8db639cfe16545cae14d4090b88b0f28e..97193bf28a922acf1976a79a01446c341f139915 100644 (file)
@@ -177,3 +177,16 @@ class HackingTestCase(base.BaseTestCase):
         self.assertEqual(
             0, len(list(checks.check_asserttrue(pass_code,
                                             "neutron/tests/test_assert.py"))))
+
+    def test_no_mutable_default_args(self):
+        self.assertEqual(1, len(list(checks.no_mutable_default_args(
+            " def fake_suds_context(calls={}):"))))
+
+        self.assertEqual(1, len(list(checks.no_mutable_default_args(
+            "def get_info_from_bdm(virt_type, bdm, mapping=[])"))))
+
+        self.assertEqual(0, len(list(checks.no_mutable_default_args(
+            "defined = []"))))
+
+        self.assertEqual(0, len(list(checks.no_mutable_default_args(
+            "defined, undefined = [], {}"))))
index f4ac15f3010f7e892757b5cc9a0be5969a5621bf..a34f5eaf363be71ca8a6e242e1a8a4acf5007696 100644 (file)
@@ -221,7 +221,8 @@ class TestFslSdnMechanismDriver(base.BaseTestCase):
         return FakeContext(subnet)
 
     def _get_port_context(self, tenant_id, net_id, port_id,
-                          fixed_ips=[]):
+                          fixed_ips=None):
+        fixed_ips = fixed_ips or []
         # sample data for testing purpose only
         port = {'device_id': '1234',
                 'name': 'FakePort',