jmespath.py
jmespath.py copied to clipboard
Matching against objects derived from base collection types
I would like to use this library to match against values derived like collections.MutableSequence and collections.MutableMapping. For example:
` import collections
import jmespath
class MySequence( collections.MutableSequence ):
def __init__( self, data ):
self.data = data
def __delitem__( self, index ):
del self.data[index]
def __getitem__( self, index ):
return self.data[index]
def __len__( self ):
return len( self.data )
def __setitem__( self, index, value ):
self.data[index] = value
def insert( self, index, value ):
self.data.insert( index, value )
data = [ {"name": "Seattle", "state": "WA"}, {"name": "New York", "state": "NY"}, {"name": "Bellevue", "state": "WA"}, {"name": "Olympia", "state": "WA"} ]
print jmespath.compile( '[0]' ).search( data ) # --> {'state': 'WA', 'name': 'Seattle'} print jmespath.compile( '[0]' ).search( MySequence( data ) ) # --> None ` It seems like this should be doable by changing all instances of isinstance( foo, list ) to isinstance( foo, collections.MutableSequence ), as this will return True for the default list type.
I agree that this would be a great change (and while we're at it, using collections.abc.Sequence
rather than MutableSequence
).
For the time being, though, I've found a suitable workaround by just having my custom collection classes inherit from the python builtin as well as the collections base class. In your example:
class MySequence( collections.MutableSequence, list):
def __init__( self, data ):
self.data = data
def __delitem__( self, index ):
del self.data[index]
def __getitem__( self, index ):
return self.data[index]
def __len__( self ):
return len( self.data )
def __setitem__( self, index, value ):
self.data[index] = value
def insert( self, index, value ):
self.data.insert( index, value )
If the relevant class definitions are in code you can't modify (e.g. someone else's library), and you don't mind doing something gnarly, you can monkey-patch the collections
class before the rest of your imports:
import collections.abc
class CompatibleSequence(collections.abc.MutableSequence, list):
...
collections.abc.MutableSequence = CompatibleSequence
import PackageThatProvidesCollectionsYouWantToNavigateWithJMESPath
Both strategies result in the print statements at the bottom of the example printing the desired output.