GithubHelp home page GithubHelp logo

Comments (13)

mewwts avatar mewwts commented on August 22, 2024

Hi Chris!
Thanks for your input. You could call prune() and/or to_dict() before shipping it off to a module that doesn't handle the addict instances well.

Now, here's the problem we're facing with returning something but a Dict. In addict the key feature, for me at least, is the fact that you can create nested dictionaries using attributes.

>>> a = Dict()
>>> a.b.c.d.e = 2
>>> a
{'a': {'b': {'c': {'d': {'e': 2}}}}} 

This would not be possible (with the current implementation at least) if we were returning something else than an addict-instance, since when a unknown key is specified, we do not know if the intent was to set a value or getting one!

Does this sound OK to you?

from addict.

sabhiram avatar sabhiram commented on August 22, 2024

We can always expose another member function. Perhaps something to the effect of:

def get(self, key, default_value = None):
    ...

@carmstrong - How do you envision the specifying of said default value? Would it be dict wide? or unique to each key?

Perhaps when the dict is created we can tell it how to initialize default values for various types.

from addict.

carmstrong avatar carmstrong commented on August 22, 2024

Perhaps when the dict is created we can tell it how to initialize default values for various types.

Exactly! A dict-wide default would work just swell.

Your proposal is exactly what I'm envisioning. I really want to use Dict(), but I need default values to be sane Python. Using to_dict() isn't really possible for me because going this route in the first place was to avoid getting a KeyError when a key didn't exist.

from addict.

sabhiram avatar sabhiram commented on August 22, 2024

Hmm, I thought about this a bit more today. Here is another issue, as it stands today: we can legally do this with a Dict:

prop = Dict(a=2, b={'a': 2}, c=[{'a':2}])

So if we would try to set "str" to "DEFAULT" like so:

prop = Dict(a=2, b={'a': 2}, c=[{'a':2}], str="DEFAULT")

The code would just set a key called "str" to "DEFAULT" :)

from addict.

mewwts avatar mewwts commented on August 22, 2024

Well for what it's whort @sabhiram, you can use get today, as it belongs to the dict. So to get a default-value back, like you would with a normal dict-instance, you could simply do

>>>> my_dict.get('my_nonexistent_key', None)
None

Also, it is trivial to to chance the constructor signature to something like

def __init__(*args, default=None, **kwargs):

(The syntax might be off. I know it's different in 2.7 and 3.4)

@carmstrong, would you mind writing out an example for how you use this with mongoengine and when they fail using it? It would be useful to see.

from addict.

carmstrong avatar carmstrong commented on August 22, 2024

would you mind writing out an example for how you use this with mongoengine and when they fail using it? It would be useful to see.

Sure. So my issue is that I'm using xmltodict to convert a large XML payload to a dict. I then create a new dict with addict: Dict(xml). This works great, because I'm accessing deep member properties of the dict when I'm not sure their parent (or grandparent) even exists. For example:

my_dict.Result.Pet.Cat.Name

works great using addict, because if any of those sub-Dicts doesn't exist, I just get a {} back. With a regular dict, I'd get a KeyError which I don't want to have to try/except on every single call to the dict (there are dozens in this file). However, when using this with mongoengine, it doesn't know how to handle an empty Dict. Here's an example of how I'm using everything together:

    parsed = xmltodict.parse(xml)
    res = Dict(parsed)
    result = MyModel()

    errors = []
    for error in res.Results.Error:
      errors.append(ProcessingError(
        error_id = error['@id'],
        code = error.ErrorCode,
        message = error.ErrorMessage
      ))
    result.processing_errors = errors

In this example, ProcessingError is a mongoengine model:

class ProcessingError(EmbeddedDocument):
  error_id = IntField()
  code = StringField()
  message = StringField()

I'm getting an error when mongoengine tries to cast the error_id to an int, because in this case it's not provided, and is {}. mongoengine has no idea what a Dict is.

I hope that makes sense! Very much appreciate the replies.

from addict.

mewwts avatar mewwts commented on August 22, 2024

I'm away this weekend, so my responses might be few and short. Hope it wont hinder your progress!
Could this problem, for now, be bypassed by doing

errors = []
for error in res.Results.Error:
    errors.append(ProcessingError(
        error_id = error.get('@id', None),
        code = error.get('ErrorCode', None),
        message = error.get('ErrorMessage', None)
    ))

or am I wrong? Have a great weekend, and thanks for using, and contributing to addict!

from addict.

carmstrong avatar carmstrong commented on August 22, 2024

Could this problem, for now, be bypassed

You're right! I couldn't do that before I started using addict because some sub-dict may not exist and throw a KeyError, but now that I'm using a Dict I can just use .get on the final dict's key. Thanks for the idea!

from addict.

mewwts avatar mewwts commented on August 22, 2024

Great, @carmstrong!
Do you find that this is a good enough solution so that we may consider to close this issue?

from addict.

carmstrong avatar carmstrong commented on August 22, 2024

Do you find that this is a good enough solution so that we may consider to close this issue?

I still think it'd be nice to have a default method so I could just set it once on the parent Dict creation rather than the 100 or so times I'm accessing a sub-Dict, but I suppose that's up to you guys.

from addict.

mewwts avatar mewwts commented on August 22, 2024

Alright, @carmstrong, your usecase is a bit different from my typical one, and I see where you're coming from. I'll leave this open. I think it might be a candidate feature for future releases.

from addict.

perpetual-hydrofoil avatar perpetual-hydrofoil commented on August 22, 2024

It'd be interesting to allow the Dict() constructor to accept a param that would allow any arbitrary class (or perhaps a function that'd return some value or object) to serve as a default for unset values.

from addict.

mewwts avatar mewwts commented on August 22, 2024

Closing this as there has been no activity for a long time.

from addict.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.