DictModel generates invalid python attribute names

Bug #1251653 reported by Yves-Gwenael Bourhis
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
neutron
Fix Released
Low
Yves-Gwenael Bourhis

Bug Description

neutron.agent.linux.dhcp.DictModel class generates objects which may have attributes with invalid names.

On an instance of neutron.agent.linux.dhcp.Dnsmasq you have a network attribute which is a DictModel instance, this 'network' DictModel instance has attributes which do not respect the variable naming rules in python.

i.e.:
ipdb> dir(self.network) # 'self' is an instance of neutron.agent.linux.dhcp.Dnsmasq
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_ns_name', 'admin_state_up', 'id', 'name', 'namespace', 'ports', 'provider:network_type', 'provider:physical_network', 'provider:segmentation_id', 'router:external', 'shared', 'status', 'subnets', 'tenant_id']

As you can see, 'network.provider:network_type' is not a valid python attribute name and can only be accessed with getattr, so attribute access (as mentioned in DictModel's doc string) is therefore not guaranteed (attribute access on 'network.provider:network_type' would give a SyntaxError and getattr is compulsory to access it).

Is there a reason why DictModel is not simply a subclass of dict with a __getattr__ method which would call __getitem__ on the dict? This would give attribute access to values "when the keys respect variable names", and dict keys which do not have the proper naming rules would still be accessible via the classical dict key access mechanism.

example:

>>> class DictModelExample(dict):
>>> def __getattr__(self, name):
>>> return self[name]
>>> def __setattr__(self, name, value):
>>> self[name] = value
>>>
>>> d = {'a': 'foo'}
>>> d = DictModelExample(d)
>>> d.a
... 'foo'
>>> d.b = 'bar'
>>> d
... {'a': 'foo', 'b': 'bar'}

off course, we would keep the part in the __init__ method which converts dict values to DictModel.

Tags: l3-ipam-dhcp
description: updated
description: updated
description: updated
description: updated
Revision history for this message
Mark McClain (markmcclain) wrote :

DictModel really needs to go away, but it will probably be J before we should tackle that refactor to using real objects.

Changed in neutron:
importance: Undecided → Low
status: New → Triaged
tags: added: l3-ipam-dhcp
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to neutron (master)

Fix proposed to branch: master
Review: https://review.openstack.org/64696

Changed in neutron:
assignee: nobody → Yves-Gwenael Bourhis (yves-gwenael-bourhis)
status: Triaged → In Progress
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to neutron (master)

Reviewed: https://review.openstack.org/64696
Committed: https://git.openstack.org/cgit/openstack/neutron/commit/?id=89f87c61e7e5c4fa69379e4039ad4b8221142a7c
Submitter: Jenkins
Branch: master

commit 89f87c61e7e5c4fa69379e4039ad4b8221142a7c
Author: Yves-Gwenael Bourhis <email address hidden>
Date: Thu Jan 2 15:19:17 2014 +0100

    Changed DictModel to dict with attribute access

    DictModel is a dict where keys are accessible via attribute access.
    The old version was an object with attributes created from dict keys and many
    attributes where accessible only via getattr because they did not have a valid
    python attribute naming (i.e.: 'provider:network_type' is not a valid
    python variable/attribute name)::

        >>> d.provider:network_type
          File "<stdin>", line 1
            d.provider:network_type
                  ^
        SyntaxError: invalid syntax

    This time we just subclass dict with attribute access to keys.

    So dict keys are accessible via attribute access but remain accessible via key
    access::

        >>> d = DictModel({'foo': 'bar', 'provider:network_type': 'something'})
        >>> d.foo == d['foo']
        ... True
        >>> getattr(d, 'provider:network_type') == d.get('provider:network_type')
        ... True
        >>> getattr(d, 'provider:network_type') == d['provider:network_type']
        ... True

    One of the big advantages when debugging is that now in pdb, pp(d) (where d is
    a DictModel instance) shows a nice dictionary structure, while with the old
    version whe had to perform a "dir(d)" and introspect each attribute...

    Change-Id: I05fad7cd9763f97f61680d45e1b6592a80049541
    Closes-Bug: 1251653

Changed in neutron:
status: In Progress → Fix Committed
Thierry Carrez (ttx)
Changed in neutron:
milestone: none → juno-1
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in neutron:
milestone: juno-1 → 2014.2
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.