Thread (3 messages) 3 messages, 3 authors, 2024-01-30

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

From: Donald Hunter <donald.hunter@gmail.com>
Date: 2024-01-29 11:29:46
Also in: linux-doc

Alessandro Marcolini [off-list ref] writes:
On 1/27/24 18:18, Donald Hunter wrote:
quoted
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:
If we take the approach of resolving the level from the spec then I
wouldn't use ChainMap. Per the Python docs [1]: "A ChainMap class is
provided for quickly linking a number of mappings so they can be treated
as a single unit."

I think we could instead pass a list of mappings from current to
outermost and then just reference the correct level that was resolved
from the spec.
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?
The more I think about it, the more I agree that using path-like syntax
in the selector is overkill. It makes sense to resolve the selector
level from the spec and then directly access the mappings from the
correct scope level.

[1] https://docs.python.org/3/library/collections.html#collections.ChainMap
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help