Search code examples
pythondictionarymethodssuperself

Extending dictionary with cascading methods


I am extending the dict class in python:

import jmespath
import json

class superDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    
    def prettyPrint(self):
        print(self.pprettyPrint())
    
    def pprettyPrint(self):
        return json.dumps(self, indent=4, sort_keys=True, default=str)
    
    def search(self, pattern):
        return jmespath.search(pattern, self)
    
   ...

I would like to be able to do:

regDict = {"key": "value"}
super = superDict(regDict)
super.search('patern').prettyPrint()

the problem I have here is that jmespath can return a list, so I cannot do:

    def search(self, pattern):
        return superDict(jmespath.search(pattern, self))

Next idea would be creating a prettyprint class that superDict would inherit from and could also be used in the return of search:

class superDict(dict, prettyprint):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    ...

    def search(self, pattern):
        return prettyprint(jmespath.search(pattern, self))

class prettyprint: ???

But I can't figure out what the prettyprint class would look like for this to work. I basically can't think of an elegant way to do this. Maybe some logic in init around the arg type would be simpler?


Solution

  • I ended up using new

    class extensions:
        def prettyPrint(self):
            print(self.pprettyPrint())
            return self
        
        def pprettyPrint(self):
            return json.dumps(self, indent=4, sort_keys=True, default=str)
        
        def search(self, pattern):
            return exJSON(jmespath.search(pattern, self))
    
    class exList(list, extensions):
        def prettyTable(self, headers):
            x = PrettyTable()
            x.field_names = headers
            for row in self:
                x.add_row(row.values())
            x.align = "l"
            print(x)
            return self
    
    class exDict(dict, extensions):
        pass
            
    class exStr(str, extensions):
        pass
    
    class exJSON:
        def __new__(self, obj):
            if type(obj) is dict:
                return exDict(obj)
            if type(obj) is list:
                return exList(obj)
            if type(obj) is str:
                return exStr(obj)
            else:
                return obj