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

Decode tuples per abi #2799

Merged
merged 35 commits into from
Feb 13, 2023
Merged

Decode tuples per abi #2799

merged 35 commits into from
Feb 13, 2023

Conversation

pacrob
Copy link
Contributor

@pacrob pacrob commented Jan 27, 2023

What was wrong?

Named objects can already be passed to contracts where tuples are expected as input, but there is no way to decode outputs as named objects despite having the names available in the ABI.

Original PR #1353
Related to Issue #1267

How was it fixed?

A decode_tuples option is added when instantiating a Contract. When set, tuples returned from a contract function call will be a new NamedTuple of the name ABIDecodedNamedTuple. NamedTuples are compatible wherever regular tuples are used, but fields can be accessed with tuple_name.key syntax. I set the NamedTuple option rename=True to handle restricted field names, rather than add a custom renaming scheme as in the original PR. More info on NamedTuples.

Contract event data was previously returned as an AttributeDict with any nested info as unnamed tuples. It is now AttributeDicts all the way down.

Todo:

Cute Animal Picture

image

@pacrob pacrob force-pushed the decode-tuples-per-abi branch 3 times, most recently from 8eb0fbb to 5942fa5 Compare January 27, 2023 23:51
@pacrob pacrob changed the title Decode tuples per abi [WIP] Decode tuples per abi Jan 27, 2023
@pacrob pacrob force-pushed the decode-tuples-per-abi branch 2 times, most recently from 7355d85 to faa5801 Compare January 31, 2023 21:39
Copy link
Collaborator

@kclowes kclowes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked through this on a pretty high level, and it's looking good to me. I left some nits, and then a few thoughts I had are:

  • Do we need to pass decode_tuples to ContractEvents as well?
  • Can we also add a test to the contract caller tests to make sure that's working okay?
  • I think I'm okay with the rename option, since if you are opting in to this functionality, you should have some idea of how namedtuples work, but I'm curious to get feedback from @fselmo here too. I think originally we had talked about returning a regular tuple as a fallback if there were fields that aren't allowed as namedtuple field names.
  • It might be nice to give banteg some credit here, either by cherry-picking a PR or two, or maybe by tagging him in the notes when you merge or something.

docs/web3.contract.rst Outdated Show resolved Hide resolved
tests/core/contracts/test_contract_call_interface.py Outdated Show resolved Hide resolved
web3/contract/base_contract.py Outdated Show resolved Hide resolved
web3/contract/utils.py Outdated Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@fselmo fselmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a first pass. This looks great. I don't think I like the internal renaming of keywords to _0, _1, _2... etc. I wonder if we can come up with a better solution there? 🤔

If we kept track of them somehow and remapped them to from_, class_, etc... would that be better? I haven't looked but is that an option in namedtuple?

If this seems like the best approach I think I'm OK with it since this is just an enhancement / nice-to-have flag. But ideally, and for a better user experience, I would like to know what those fields were called by having the name from the key in one way or another.

Thoughts?

docs/web3.contract.rst Outdated Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/contract/base_contract.py Outdated Show resolved Hide resolved
@fselmo
Copy link
Collaborator

fselmo commented Feb 2, 2023

* I think I'm okay with the `rename` option, since if you are opting in to this functionality, you should have some idea of how `namedtuples` work, but I'm curious to get feedback from @fselmo here too. I think originally we had talked about returning a regular tuple as a fallback if there were fields that aren't allowed as namedtuple field names.

Yeah I had some thoughts on this here. Not sure what the best approach is but I'd like to have a better UX than just _0, _1, etc... worst case, I don't think I'm against just inherent namedtuple handling.

* It might be nice to give banteg some credit here, either by cherry-picking a PR or two, or maybe by tagging him in the notes when you merge or something.

Agreed!

@pacrob pacrob force-pushed the decode-tuples-per-abi branch 2 times, most recently from 88b269f to bcad18b Compare February 2, 2023 18:35
@pacrob
Copy link
Contributor Author

pacrob commented Feb 2, 2023

I chose to go with namedtuple's rename=True for predictability. They have a set of rules for renaming that we can point to and say "this is how it behaves". If a user has previous experience with namedtuples, they would be expecting this renaming pattern. If we roll our own renaming scheme, we need to explain it in detail and still run the risk of missing edge cases.

Regarding returning just a plain tuple instead: I feel it would be more confusing, having set decode_tuples=True, to just get a plain tuple back with no explanation. If the user sees a ABIDecodedNamedTuple with renamed fields, they at least know they set the flag correctly and can do more research.

@pacrob pacrob force-pushed the decode-tuples-per-abi branch 5 times, most recently from 0695e4d to 4a408be Compare February 6, 2023 23:43
web3/_utils/abi.py Outdated Show resolved Hide resolved
@pacrob pacrob changed the title [WIP] Decode tuples per abi Decode tuples per abi Feb 10, 2023
Copy link
Collaborator

@fselmo fselmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I answered a bit on the typing. Let me know if I missed something there but that all does work locally for me. I think this all looks good to me since the tests are passing but I'd like a bit more time to look carefully at it. I can make another pass Monday 👀.

web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/_utils/abi.py Show resolved Hide resolved
web3/_utils/abi.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@fselmo fselmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good. I had some final thoughts I wanted to discuss before approving. I think the best approach would be a user choice approach where in all cases the ABIDeocdedNamedTuple is an opted-for choice. Curious on your input here and from @kclowes


edit: You may ignore any mentions above, this lgtm 🎉

web3/_utils/abi.py Outdated Show resolved Hide resolved
web3/_utils/contracts.py Show resolved Hide resolved
web3/_utils/events.py Show resolved Hide resolved
docs/web3.contract.rst Outdated Show resolved Hide resolved
Copy link
Collaborator

@fselmo fselmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore my previous ping, this lgtm in current state... 🎉 I'll resolve those conversations

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

Successfully merging this pull request may close these issues.

4 participants