Re: [PATCH net-next v1 02/12] tools/net/ynl: Support sub-messages in nested attribute spaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 1/27/24 18:18, Donald Hunter wrote:
> Jakub Kicinski <kuba@xxxxxxxxxx> writes:
>> Is it possible to check at which "level" of the chainmap the key was
>> found? If so we can also construct a 'chainmap of attr sets' and make
>> sure that the key level == attr set level. I.e. that we got a hit at
>> the first level which declares a key of that name.
>>
>> More crude option - we could construct a list of dicts (the levels
>> within the chainmap) and keys they can't contain. Once we got a hit
>> for a sub-message key at level A, all dicts currently on top of A
>> are not allowed to add that key. Once we're done with the message we
>> scan thru the list and make sure the keys haven't appeared?
>>
>> Another random thought, should we mark the keys which can "descend"
>> somehow? IDK, put a ~ in front?
>>
>> 	selector: ~kind
>>
>> or some other char?
> Okay, so I think the behaviour we need is to either search current scope
> or search the outermost scope. My suggestion would be to replace the
> ChainMap approach with just choosing between current and outermost
> scope. The unusual case is needing to search the outermost scope so
> using a prefix e.g. '/' for that would work.
>
> We can have 'selector: kind' continue to refer to current scope and then
> have 'selector: /kind' refer to the outermost scope.
>
> If we run into a case that requires something other than current or
> outermost then we could add e.g. '../kind' so that the scope to search
> is always explicitly identified.

Wouldn't add different chars in front of the selctor value be confusing?

IMHO the solution of using a ChainMap with levels could be an easier solution. We could just modify the __getitem__() method to output both the value and the level, and the get() method to add the chance to specify a level (in our case the level found in the spec) and error out if the specified level doesn't match with the found one. Something like this:

from collections import ChainMap

class LevelChainMap(ChainMap):
    def __getitem__(self, key):
        for mapping in self.maps:
            try:
                return mapping[key], self.maps[::-1].index(mapping)
            except KeyError:
                pass
        return self.__missing__(key)

    def get(self, key, default=None, level=None):
        val, lvl = self[key] if key in self else (default, None)
        if level:
            if lvl != level:
                raise Exception("Level mismatch")
        return val, lvl

# example usage
c = LevelChainMap({'a':1}, {'inner':{'a':1}}, {'outer': {'inner':{'a':1}}})
print(c.get('a', level=2))
print(c.get('a', level=1)) #raise err

This will leave the spec as it is and will require small changes.

What do you think?





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux