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

Too many positional arguments #139

Open
wants to merge 9 commits into
base: v2
Choose a base branch
from

Conversation

apurvabanka
Copy link

No description provided.

Copy link
Collaborator

@bh2smith bh2smith left a comment

Choose a reason for hiding this comment

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

So everything looks good here so far. It seems that there is some duplication (i.e. x = params.get("x", None) appears multiple times) that we could probably avoid with a dedicated parameter parsing function.

On another note, this improvement is going to break the current interface and probably warrants a full version bump (i.e. v2). Since this is the first breaking change introduced and its not overly substantial. I would propose creating a v2 branch that we can merge this into and it would be introduced when the project is preparing for v2. This way, you would still become a project contributor although the changes may not be reflected for quite a some time.

I wonder if the Dune team has any thoughts on how we should approach this... @msf?.

In the meantime, I will create a v2 branch and update this PR to point there.

@bh2smith bh2smith changed the base branch from main to v2 October 21, 2024 11:11
@apurvabanka
Copy link
Author

apurvabanka commented Oct 22, 2024

@bh2smith I have added a comment in the issue linked to this PR. Can you respond with your suggestions?

#137

@apurvabanka apurvabanka marked this pull request as ready for review October 22, 2024 18:15
@apurvabanka
Copy link
Author

@bh2smith Updated the PR with the changes and test cases. Please proceed with the review.

@apurvabanka
Copy link
Author

@bh2smith Can you review this PR? I have added all the changes and test cases as well.

@bh2smith
Copy link
Collaborator

Hey sorry its been so long. I was kinda waiting on @msf here but I guess we will just go with my suggestion of creating a v2 branch and merging this there.

I do have one, somewhat large, ask about how we approach this.

Instead of using a dictionary for the params I would insist that we use a data class for two reasons.

  1. Accessing entries of a dictionary by key is annoying params["something"] vs params.something
  2. Having a data class, gives developers some inference on what is expected to go there directly in their IDE without having to go to the docs to try and remember.

So I would request that you replace the occurrences of params: Optional[Dict[str, Any]] = None with params: Optional[ResultPageParams] = None

where:

from dataclasses import dataclass
from typing import Optional, List

@dataclass
class ResultPageParams:
    limit: Optional[int] = None
    offset: Optional[int] = None
    columns: Optional[List[str]] = None
    sample_count: Optional[int] = None
    filters: Optional[str] = None
    sort_by: Optional[List[str]] = None

and as for your question

How to handle params for create_table function?

I would suggest doing the same thing. That is create a data class representing some the optional arguments (i.e. those with defaults set {description & is_private}).

Alternatively, we could change pylint to allow 6 parameters instead of 5.

Sorry again for taking so long to get back. I hope the suggested change isn't too involved, but I think it will result in a much better end product. We may also be able to sneak this feature into v1, by taking on the new dataclass as an argument and warning users that the other parameters will deprecated in v2.

allow_partial_results: str = "true",
params: Optional[Dict[str, Any]] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

A good way to start here would be, create the proposed data class and put it here as optional.

See how the function needs to be changed because of the replacement...

Actually, I just noticed this is _build_parameters... This will likely be replaces with a method like to_dict on the class itself. The data class can implement both to_dict and from_dict (this might come for free with the @DataClass decorator although I can't remember).

Nit: It looks like you forgot to include allow_partial_results here, but I really think this _build_parameters function will no longer be necessary once this class is in place.

Comment on lines 51 to 64
params = self._build_parameters(
columns=columns,
sample_count=sample_count,
filters=filters,
sort_by=sort_by,
limit=limit,
offset=offset,
if params is None:
params = {}
limit = params.get("limit", None)
offset = params.get("offset", None)
columns = params.get("columns", None)
sample_count = params.get("sample_counts", None)
filters = params.get("filters", None)
sort_by = params.get("sort_by", None)

build_params = self._build_parameters(
params={
"columns": columns,
"sample_count": sample_count,
"filters": filters,
"sort_by": sort_by,
"limit": limit,
"offset": offset,
}
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

All of this should become unnecessary and all we will need to do is params.to_dict() wherever it gets passed into a request.

sample_count: Optional[int] = None,
filters: Optional[str] = None,
sort_by: Optional[List[str]] = None,
params: Optional[GetExecutionResultsParams] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hey, ya you did it here.

Comment on lines 123 to 134
build_params = None
if params is not None:
build_params = self._build_parameters(
params={
"columns": params.columns,
"sample_count": params.sample_count,
"filters": params.filters,
"sort_by": params.sort_by,
"limit": params.limit,
"offset": params.offset,
}
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is unnecessary. and can either be passed to the next function as is. It should only be at the very last step it needs to be transformed to a dict.

Comment on lines 106 to 113
if params is None:
params = {}
performance = params.get("performance", None)
batch_size = params.get("batch_size", None)
columns = params.get("columns", None)
sample_count = params.get("sample_count", None)
filters = params.get("filters", None)
sort_by = params.get("sort_by", None)
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is way too much redundant code here. All of this appears too many times over.

@@ -40,6 +40,44 @@
from dune_client.query import QueryBase, parse_query_object_or_id


class GetResultParams(NamedTuple):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok so I see you have created all these classes, but its unclear where they are being used. Since there is so much dictionary manipulation happening above... Something seems wrong.

Copy link
Author

Choose a reason for hiding this comment

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

Should I add a doc string for their usage? I have re-used these classes as parameters for multiple functions.

@apurvabanka
Copy link
Author

Hey sorry its been so long. I was kinda waiting on @msf here but I guess we will just go with my suggestion of creating a v2 branch and merging this there.

I do have one, somewhat large, ask about how we approach this.

Instead of using a dictionary for the params I would insist that we use a data class for two reasons.

  1. Accessing entries of a dictionary by key is annoying params["something"] vs params.something
  2. Having a data class, gives developers some inference on what is expected to go there directly in their IDE without having to go to the docs to try and remember.

So I would request that you replace the occurrences of params: Optional[Dict[str, Any]] = None with params: Optional[ResultPageParams] = None

where:

from dataclasses import dataclass
from typing import Optional, List

@dataclass
class ResultPageParams:
    limit: Optional[int] = None
    offset: Optional[int] = None
    columns: Optional[List[str]] = None
    sample_count: Optional[int] = None
    filters: Optional[str] = None
    sort_by: Optional[List[str]] = None

and as for your question

How to handle params for create_table function?

I would suggest doing the same thing. That is create a data class representing some the optional arguments (i.e. those with defaults set {description & is_private}).

Alternatively, we could change pylint to allow 6 parameters instead of 5.

Sorry again for taking so long to get back. I hope the suggested change isn't too involved, but I think it will result in a much better end product. We may also be able to sneak this feature into v1, by taking on the new dataclass as an argument and warning users that the other parameters will deprecated in v2.

I do agree using classes is a better way to implement params. Will in-corporate those changes in the code.

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.

2 participants