cdgriffith / Box

Python dictionaries with advanced dot notation access
https://github.com/cdgriffith/Box/wiki
MIT License
2.53k stars 103 forks source link

Add a way to view the last made request to the box (and sub box) objects. #15

Closed chavenor closed 4 years ago

chavenor commented 7 years ago
from box import Box

class test(object):
    def __init__(self, **kwargs):
        d = Box({
        'item':'value', 
        'item2': self.ok
        })
        self.d = d 

    def ok(self, **kwargs):
        print "test"
        print kwargs.keys()
        for key in kwargs.keys():
            print kwargs[key]
        return 

data={
    'test':'value',
    'test1':'value1'
}

t = test()
print t.d.item2(**data)

From t.d.item2 how do I get that path while in the 'ok' function.

Thanks!

cdgriffith commented 7 years ago

Not positive what you mean by that path, but if you mean which keys are the parent of the ok function, I would guess the only way is to traverse down to it (like you would have to do for a stadard dict.)

It might be possible with how the upcoming box version works to add something that could have a Box object detect if it is a child of another Box. Is that the feature you are asking for?

chavenor commented 7 years ago

Yes what you are describing is what I'm looking to do. The parent child feature should work as long as I can get all the way back to the original key.

Doing so would allow me to create a dynamic endpoint that I can extend by simply changing what's in the dict as all the settings, validation and so on could be pulled in along with the call without having to inconvenience the end user/coder.

Perhaps initiate the box with a parameter to turn this feature on? track_tree=True

Below is another example.

from box import Box

class API(object):
    def __init__(self, **kwargs):
        endpoints = Box( { 'domains' : {
                'list': {
                    'go': self.build,
                    'path': '{account_id}/domains',
                    'request_type': 'get',
                    'required_fields' : ['username', 'password', 'account_id'],
                    'input_fields': [],
                    'filters': ['name_like', 'registrant_id'],
                    'sorting': ['id', 'name', 'expires_on'],
                    'action': [],
                    'success_status': 200,
                    'success_message': 'Domains listed.',      }  }})
        self.endpoints = endpoints

    def build(self, **kwargs):
        # HERE #
        key_path = 'dotted path for the api.endpoints.domains.list.go(**data) function'.split('.')
        settings = endpoints[key_path[1]][key_path[2]][key_path[3]] #or the endpoints.domains.list key path.
        Do stuff with settings...
        # HERE #
        print kwargs['username']
        print kwargs['password']
        return 

data={
    'username':'chavenor',
    'password':'secret'
}

api = API()
print api.endpoints.domains.list.go(**data)
chavenor commented 7 years ago

What is your target date for your next release and what can I do to help you get there with this feature? Money, favors, karma, testing, caffeine?

cdgriffith commented 7 years ago

I never say no to caffeine, lol, but the big thing is testing (really more just trying it out in other projects / console and see what breaks). I hope to release Tuesday, baring no big issues found from other reviews I will be getting tomorrow. Please poke it as much as you want and add new issues for anything.

To grab latest: pip install git+https://github.com/cdgriffith/Box.git@development

Super short version of why this might be possible is there is now a semi heritage state by default for the new DefaultBox. (However won't be able to use as is.) So again might (and IMO should) be possible to do something like that.

I'm going to update title of this and propose to add a property to Box (and potentially BoxList if necessary) box_heritage.

Potential usage:

bx = Box(a={"b": {"c": "d"}))

bx.a.b.box_heritage
# "a.b"

(Just a note, this feature probably won't make it into Tuesdays release, but after that is out the door this is next item to tackle)

Also, Thanks for the wonderful idea! I really do think that has a lot of potential! You'll be making it into the AUTHORS file for the release at least 😄

chavenor commented 7 years ago

Not sure if that use case will work for me as you still needed to add the full path to call the box_heritage to get what you already know.

I'm trying to determine the last request key path made to the box so I could call it in another function almost like a heritage history -- not even sure this is even possible.

cdgriffith commented 7 years ago

Ouh, a last request made. I will move above info to another issue and rename again. Because that, good sir, is also a brilliant idea, and might be possible!

cdgriffith commented 7 years ago

Would usage like this fulfill your need? (Testing in heritage branch, names not final at all. Thinking of maybe .box_last_action)

In [1]: from box import Box

In [2]: hearth = Box.from_json(filename="test//data//hearthstone_cards.json", tracker_box=True)

In [3]: hearth.The_Jade_Lotus.name.frFR
Out[3]: 'Le Lotus de jade'

In [4]: hearth.box_track()
Out[4]: ['The Jade Lotus', 'name', 'frFR']

In [5]: hearth.Corruption.artist
Out[5]: 'Wayne Reynolds'

In [6]: hearth.box_track()
Out[6]: ['Corruption', 'artist']
chavenor commented 7 years ago

Perfect! That should work! Awesome!

chavenor commented 7 years ago

@cdgriffith just wanted to followup with on this. Is this available in the newest release?

Thanks!

cdgriffith commented 7 years ago

Hi @chavenor sorry for late reply. It is not in the current 3.0 release, was planing on the next one 3.1.

Doing some testing it seems it may be best for it to be it's own subclass of Box. As the additional logic checks to even figure out if we should store history can make a noticeable difference on large samples.

So ATM I am trying to see how to either cut those times down or if it's better to just be it's own class.

chavenor commented 7 years ago

It's own class prob makes the most sense. Performance is king. Is there a branch or tag that this new feature would live in so I don't have to bug ya. ;)

Thanks!

Casey

cdgriffith commented 7 years ago

Working on it in https://github.com/cdgriffith/Box/tree/heritage branch currently.

Very much a work in progress, (like right now it doesn't work for the first time box_history is called). Please feel free to poke and prod and give feedback. (also not sold on names yet, just easier to spell Tracker than Heritage IMO)

from box import TrackerBox, Box
a = TrackerBox({'a': {'b': {'c': 'd'}}})
a.a.b.c
Out[18]: 'd'
a.box_history()
Out[19]: ['a']
a.a.b.c
Out[20]: 'd'
a.box_history()
Out[21]:  ['a', 'b', 'c']
chavenor commented 7 years ago

I'll take a look when I grab some time. Thanks for you efforts on this.

cdgriffith commented 4 years ago

Hi @chavenor, as an update with the new version of Box 4, it works in an entirely new method that doesn't keep the hierarchy at all anymore, so this is no longer a realistic possibility.

If anyone else is interested in making something like this, it is probably easier to start from UserDict and apply it to that than with Box.