Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use DotMap with exec? #56

Open
frdfsnlght opened this issue Nov 10, 2019 · 7 comments
Open

Can't use DotMap with exec? #56

frdfsnlght opened this issue Nov 10, 2019 · 7 comments

Comments

@frdfsnlght
Copy link

Here's some sample code:

from dotmap import DotMap

code = 'print("hello")'
g = {}
l = DotMap()
exec(code, g, l)

And it's output (using python 3.7.3 on Raspbian):

Traceback (most recent call last):
  File "dotmaptest.py", line 7, in <module>
    exec(code, g, l)
  File "<string>", line 1, in <module>
TypeError: 'DotMap' object is not callable

Any idea why I can't use a DotMap as the "locals" parameter? Using a standard dictionary works, of course. I can't seem to find any obvious answer, but maybe I'm missing something.

@drgrib
Copy link
Owner

drgrib commented Nov 10, 2019

Strange. The locals argument in exec() is supposed to accept a mapping object and as far as I know, DotMap is one. But maybe I'm wrong about that.

In the meanwhile, a usable, if slightly cumbersome, workaround is

from dotmap import DotMap

code = 'print("hello")'
g = {}
l = DotMap()
exec(code, g, l.toDict())

@frdfsnlght
Copy link
Author

That's about where I've arrived as well. However, I don't think it will work for my use case. Correct me if I'm wrong, but changes made the dictionary (in the code being exec'ed) that result from l.toDict() won't propagate back to the DotMap? Maybe I could just create a new DotMap from the changed dictionary, but I get worried about all the conversions back and forth taking up "too much time". I don't know what "too much time" means for my situation, but I'm trying to keep the part of the code that needs to do the exec as fast as possible.

You're findings on the requirements of the local parameter to the exec function are also what I found and caused me to scratch my head. Looking at the DotMap code (and since it inherits from dict) it looks like it satisfies the requirements. I don't understand what's going on. Maybe the python source needs to be consulted?

@drgrib
Copy link
Owner

drgrib commented Nov 10, 2019

Yes, if you need the code in the exec call to update the values in the locals DotMap, then the toDict solution won't work.

Checking the exec source code is probably the next step, though not one that I personally have the bandwidth to explore.

@frdfsnlght
Copy link
Author

Well, I just spent some time looking at the python source for exec and following it to the best of my abilities and I'm no closer to understanding what's wrong.

Adding DotMap to my project was just a nice feature to have but unnecessary. I'll probably have to drop it unless I can think of some other clever solution. I have a bunch more development to do anyway.

Thanks.

@MaxOstrowski
Copy link

Just encountered the same problem. Any new insights on this issue ? Thanks a lot.

@drgrib
Copy link
Owner

drgrib commented Jan 24, 2023

No new insights. Full disclosure, I support DotMap as much as I can in my spare time using my past experience in Python and general programming and algorithms knowledge. But I don't even use Python for active development anymore, let alone DotMap specifically. So involved Python-specific debugging like this is way out of scope for my personal attention.

@MaxOstrowski
Copy link

This code

from dotmap import DotMap

#x = {}
x = DotMap()
exec("print(42)", {}, x)

fails with the DotMap with the Error:
TypeError: 'DotMap' object is not callable
Other instructions, like

from dotmap import DotMap

#x = {}
x = DotMap()
exec("a=42", {}, x)

work fine. The problem is the function call to print. In fact, this is true for any other function call, like:
exec("list([])", {}, x)
DotMap seems to try to generate "list" or "print" as an entry to the dictionary.
Edit:
Using DotMap(_dynamic=False) makes the code work again.

I think this should be fine for my current usecase, maybe it helps others, and maybe it helps to identify where the bug is ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants