Open mmlynarik opened 2 years ago
I believe this is concerned entirely with SQLAlchemy, not with SQLModel, and has to do with the required semantics to construct a BinaryExpression
object.
Hero.age == None
evaluates to a BinaryExpression
object which is eventually used to construct the SQL query that the SQLAlchemy engine issues to your DBMS.
Hero.age is None
evaluates to False
immediately, and not a BinaryExpression
, which short-circuits the query no matter the value of age
in a row.
From a cursory search, it does not seem that the is
operator can be overridden in Python. This could help explain why the only possibility is by using the ==
operator, which can be overridden.
@mmlynarik Along the lines of .like()
, would it be acceptable if we implement something like Hero.age.is(None)
?
@mmlynarik Along the lines of
.like()
, would it be acceptable if we implement something likeHero.age.is(None)
?
If it worked as expected, then definitely yes:)
Ok, I am working on a PR implementing this, repo owners please give me some time 👍
You can use Hero.age.is_(None)
@tc-imba where to import is_
?
@tc-imba where to import
is_
?
is_
is an attribute. You don't need to import it to use it.
My understanding is this:
where(Hero.age is None)
cannot be implemented, because the is
operator cannot be overloaded (==
can be overloaded via the __eq__
method, etc.).
where(Hero.age.is(None))
cannot be implemented, because is
is a reserved keyword and therefore no valid identifier.
where(Hero.age.is_(None))
works and probably is the closest we can get. It follows PEP 8 Naming Styles by using a trailing underscore to "avoid conflicts with Python keyword".
But is_
is not working with autocompletion, at least not in Pycharm. Hero.age
is inferred to be int | None
, which is exactly what I want in 99% of cases. But it means that Hero.age.is_
raises a warning "unresolved reference".
Not sure there is a good way to deal with it.
For IS NOT NULL
, you could use is_not
where(Hero.age.is_not(None))
My understanding is this:
where(Hero.age is None)
cannot be implemented, because theis
operator cannot be overloaded (==
can be overloaded via the__eq__
method, etc.).
where(Hero.age.is(None))
cannot be implemented, becauseis
is a reserved keyword and therefore no valid identifier.
where(Hero.age.is_(None))
works and probably is the closest we can get. It follows PEP 8 Naming Styles by using a trailing underscore to "avoid conflicts with Python keyword".But
is_
is not working with autocompletion, at least not in Pycharm.Hero.age
is inferred to beint | None
, which is exactly what I want in 99% of cases. But it means thatHero.age.is_
raises a warning "unresolved reference". Not sure there is a good way to deal with it.
The same goes for the in_
operator method (an presumably all the other operators as well):
select(Ticket).where(Ticket.stage_id.in_(stage_ids))
This also let mypy and other type using tool cry out loud like "int" has no attribute "in_" [attr-defined]mypy(error)
I guess the issue title could be updated to smth like Proper handling of column operator methods in WHERE condition
looking for a team without heros like
select(Team).where(Team.heros == None)
isn't compatible with E711
but select(Team).where(Team.heros is None)
doesn't work
Team.heros is None
cannot be made to work because the Python language does not allow overloading is
, but does allow overloading ==
.
Team.heros == None
checks for equality, not identity. It seems to do what you want, but it is a PEP 8 violation.
Team.heros.is_(None)
should also do what you want, and is more idiomatic because it checks for identity (like is
), not equality (like ==
), following the PEP 8 recommendation.
In the end, write the code that works for you. PEP 8 is just a recommendation, and flake8 is just a tool. If you prefer to ignore a recommendation, PEP 8 has a section about that as well.
First Check
Commit to Help
Example Code
Description
To make the where condition
Hero.age is None
functional, because currently it is evaluated as false even though it should be true. Otherwise, one needs to useHero.age == None
, which raises linting error.Wanted Solution
To make the where condition
Hero.age is None
functional, because currently it is evaluated as false even though it should be true. Otherwise, one needs to useHero.age == None
, which raises linting error.Wanted Code
Alternatives
No response
Operating System
Linux
Operating System Details
No response
SQLModel Version
0.0.4
Python Version
3.8.5
Additional Context
No response