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

feat: getattr and iter dunders #42

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ repos:
rev: 0.7.17
hooks:
- id: mdformat
additional_dependencies: [mdformat-gfm, mdformat-frontmatter]
additional_dependencies: [mdformat-gfm, mdformat-frontmatter, mdformat-pyproject]

default_language_version:
python: python3
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ Lastly, to get information about a token, including its contract address, you ca
from ape_tokens import tokens

bat = tokens["BAT"]
# Or, access via attribute
bat = tokens.BAT

print(bat.address)
```
17 changes: 16 additions & 1 deletion ape_tokens/managers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Iterator, Mapping

from ape.contracts import ContractInstance
from ape.exceptions import ContractNotFoundError
from ape.types import ContractType
Expand Down Expand Up @@ -106,14 +108,21 @@
)


class TokenManager(ManagerAccessMixin, dict):
class TokenManager(ManagerAccessMixin, Mapping[str, ContractInstance]):
@cached_property
def _manager(self) -> TokenListManager:
return TokenListManager()

def __repr__(self) -> str:
return f"<ape_tokens.TokenManager default='{self._manager.default_tokenlist}'>"

def __len__(self) -> int:
return len(list(self._manager.get_tokens(chainid=self.provider.chain_id)))

def __iter__(self) -> Iterator[ContractInstance]:
Copy link
Member

Choose a reason for hiding this comment

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

I tried running:

[x for x in tokens]

but got this:

KeyError: "Symbol 'AZRX' is not a known token symbol"

In [2]: [x for x in tokens]

kinda weird. I do have multiple token lists installed though.

Copy link
Member

Choose a reason for hiding this comment

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

I wonder if something like:

 def __iter__(self) -> Iterator[ContractInstance]:
        yielded = set()
        for token in self._manager.get_tokens(chain_id=self.provider.chain_id):
            if token.symbol in yielded:
                # Handle multiple lists.
                continue

            try:
                yield self[token.symbol]
            except KeyError:
                # Perhaps in another list?
                continue

            yielded.add(token.symbol)

would work for this situation.
I tried it again, except changed it to:

for x in tokens:
   ...:     print(x)

I see the first like hundred get printed out super fast, and then it suddenly is very slow at outputting them.
hmmmmm

Copy link
Author

Choose a reason for hiding this comment

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

is it possible the slowness is from downloading the last of the tokenlists? Looking at this code again I'm not sure where else a slowdown might come from.

Copy link
Author

Choose a reason for hiding this comment

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

I think this should be fixed now with my latest commit.

for token in self._manager.get_tokens(chainid=self.provider.chain_id):
BobTheBuidler marked this conversation as resolved.
Show resolved Hide resolved
yield self[token.symbol]

def __getitem__(self, symbol: str) -> ContractInstance:
try:
token_info = self._manager.get_token_info(
Expand All @@ -130,3 +139,9 @@ def __getitem__(self, symbol: str) -> ContractInstance:
return self.chain_manager.contracts.instance_at(
checksummed_address, contract_type=ERC20
)

def __getattr__(self, symbol: str) -> ContractInstance:
try:
return self[symbol]
except KeyError as e:
raise AttributeError(str(e)) from None
Loading