lupa icon indicating copy to clipboard operation
lupa copied to clipboard

add nested dict support

Open synodriver opened this issue 2 years ago • 3 comments

Closes https://github.com/scoder/lupa/issues/199

synodriver avatar Apr 02 '22 05:04 synodriver

By the way, I've fixed some compiler warnings on msvc about type convertion from Py_ssize_t to int.

synodriver avatar Apr 02 '22 05:04 synodriver

Wow the ci fails somehow. Maybe lua should build first and link python extension against lua.dll or liblua.so. See my github action's script

synodriver avatar Apr 02 '22 05:04 synodriver

Conflicts are resolved now.

synodriver avatar Aug 14 '22 08:08 synodriver

Rather than requiring users to think about a hard depth limit for their data structures, what do you think about keeping a dict of mapped objects (by original object ID) and reusing already mapped object references? That way, we could really map recursive structures 1:1 without the risk to run into infinite loops while mapping.

scoder avatar Jan 02 '24 16:01 scoder

Rather than requiring users to think about a hard depth limit for their data structures, what do you think about keeping a dict of mapped objects (by original object ID) and reusing already mapped object references? That way, we could really map recursive structures 1:1 without the risk to run into infinite loops while mapping.

Great idea, I've implemented it in the latest commit.

synodriver avatar Jan 04 '24 11:01 synodriver

I've extracted the logic from LuaRuntime.table_from() in the master branch to make it reusable for the recursive container mappings. Could you please adapt your code? Most of the changes in py_to_lua can probably be avoided now.

scoder avatar Jan 06 '24 10:01 scoder

Most of the changes in py_to_lua can probably be avoided now.

I'm afraid not because py_to_lua_table still make calls to py_to_lua

synodriver avatar Jan 06 '24 10:01 synodriver

Most of the changes in py_to_lua can probably be avoided now.

I'm afraid not because py_to_lua_table still make calls to py_to_lua

Sorry, I just meant the additions, not the flags etc. Both functions need to call each other, but you can avoid the dict/list mappings in py_to_lua now.

scoder avatar Jan 06 '24 10:01 scoder

avoid the dict/list mappings in py_to_lua now.

Could you please give me some advice about that? Perhaps I misunderstood your idea, but I think there might be dict in dict, so we have to check them in py_to_lua again.

synodriver avatar Jan 06 '24 11:01 synodriver

avoid the dict/list mappings in py_to_lua now.

Could you please give me some advice about that? Perhaps I misunderstood your idea, but I think there might be dict in dict, so we have to check them in py_to_lua again.

I think it mostly boils down to something like this:

     elif recursive and isinstance(o, (list, dict, Sequence, Mapping)):
        # check existing mapped_objs cache, then failing that:
        table = py_to_lua_table([o], recursive=True)
        # update cache

scoder avatar Jan 06 '24 11:01 scoder

Finally... I made it, looks better now.

synodriver avatar Jan 06 '24 15:01 synodriver

Iet me explaint what I found these days. There is a bug in master branch which can not pass your testcase.

lua.table_from(1)

will always end up with an error: int is not iterable. At the same time, there might be some gc problem with cpython itself, in the loop test there are some lua tables can't match the corresponding pyobject, but when I test them in a individual test, the problem just disappear, making it very hard to debug.

synodriver avatar Feb 12 '24 06:02 synodriver

There is a bug in master branch which can not pass your testcase.

lua.table_from(1)

That's not a bug. The method expects one or more iterables or mappings as arguments, not plain values. I.e., you can write lua.from_table([1], [2], [3,4,5]), but not lua.from_table(1,2,3,4,5). That's also what the docstring says, at least as I read it.

Edit: BTW, it's a good thing that we currently reject simple arguments. There's negative precedence with Python's builtin min and max functions, which accept either a single iterable or multiple simple values as arguments to compare. The problem is that a single argument becomes ambiguous. You cannot say max(5), because it gives you the irritating error message "5 is not iterable", whereas max(5,6) just works and does what you expected, without needing any kind of obvious iteration. In lua.table_from(), at least you get this error message for whatever simple (non-iterable) arguments you pass.

scoder avatar Feb 20 '24 08:02 scoder

Thanks for your help with the nested data structure generator, it looks better now. The last thing to do is figure out a way to compare them without encountering strange garbage collection bugs in CPython.....

synodriver avatar Feb 20 '24 14:02 synodriver

Thanks for all the work on this. I think it's good enough to be released in Lupa 2.1.

scoder avatar Feb 21 '24 09:02 scoder