-
Notifications
You must be signed in to change notification settings - Fork 191
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
QueryBuilder
: add flat
keyword to first
method
#5410
QueryBuilder
: add flat
keyword to first
method
#5410
Conversation
3bedc9b
to
0a92c72
Compare
def first(self) -> Optional[List[Any]]: | ||
"""Executes the query, asking for the first row of results. | ||
def first(self, flat: bool = False) -> Optional[Union[List[Any], Any]]: | ||
"""Return the first result of the query. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think it is important to indicate this actually executes a query, i.e. connects to the storage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment in docstring in vein of SQLA docs
I'd note, this is a little similar to https://docs.sqlalchemy.org/en/14/orm/query.html?highlight=scalar#sqlalchemy.orm.Query.scalar (plus thing like I'm tempted to say this should be a separate method, because it is never real ideal when you are returning unions of different types, although actually at least add overload typing, i.e. from typing import Any, List, Literal, overload
@overload
def first(self, flat: Literal[False]) -> Optional[List[Any]]:
...
@overload
def first(self, flat: Literal[True]) -> Optional[Any]:
... |
5c0564d
to
5400aee
Compare
@chrisjsewell should be good for second review |
Are the new |
Not due to the FYI, when you are adding |
But those are false positives surely? The default for |
No, the return type is |
if result is None: | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sphuber it can return None
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I saw that, but take the first hit aiida/orm/nodes/data/upf.py:136:27:
existing_upf = builder.first()
if existing_upf is None:
...
else:
existing_upf = existing_upf[0]
That looks like a false positive to me. If anything this would be the perfect candidate for first(flat=True)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same goes for the next "hits"
tests/orm/test_querybuilder.py:724:26: E1136: Value 'result' is unsubscriptable (unsubscriptable-object)
tests/orm/test_querybuilder.py:725:26: E1136: Value 'result' is unsubscriptable (unsubscriptable-object)
Also false positives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair, then IMO, I would just disable unsubscriptable-object
, because pylint does not seem to be doing a good job with them: pylint-dev/pylint#1498
I don't feel pylint should be trying to involve itself in type-checking, since that is what mypy is for, that does it a lot better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eurgh could also be overload, could be future annotations: pylint-dev/pylint#5189, pylint-dev/pylint#3979, pylint-dev/pylint#4369
Silly pylint
This keyword already exists for the `all` method and it will likewise be useful for `first` when only a single quantity is projected. In that case, often the caller doesn't want a list as a return value but simply the projected quantity. Allowing to get this directly from the method call as opposed to manually dereferencing the first item from the returned list often makes for cleaner code.
…t is being a pita
5400aee
to
952ed5a
Compare
@chrisjsewell pre-commit now passes. Should be good to go |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cheers
def first(self, flat: Literal[True]) -> Optional[Any]: | ||
... | ||
|
||
def first(self, flat: bool = False) -> Optional[list[Any] | Any]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def first(self, flat: bool = False) -> Optional[list[Any] | Any]: | |
def first(self, flat: bool = False) -> None | list[Any] | Any: |
Will approve anyway, but you are kind of mixing old and new type annotations in these changes
Fixes #5408
This keyword already exists for the
all
method and it will likewise beuseful for
first
when only a single quantity is projected. In thatcase, often the caller doesn't want a list as a return value but simply
the projected quantity. Allowing to get this directly from the method
call as opposed to manually dereferencing the first item from the
returned list often makes for cleaner code.