-
Notifications
You must be signed in to change notification settings - Fork 192
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
♻️ REFACTOR: Fully abstract QueryBuilder #5093
♻️ REFACTOR: Fully abstract QueryBuilder #5093
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #5093 +/- ##
===========================================
+ Coverage 80.56% 80.64% +0.08%
===========================================
Files 532 534 +2
Lines 37010 37066 +56
===========================================
+ Hits 29815 29887 +72
+ Misses 7195 7179 -16
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
for more information, see https://pre-commit.ci
This is good to go FYI |
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.
Thanks @chrisjsewell . I have given the changes a global look, but have to admit that due to the amount of changes have not been able to review everything in detail, so I am relying mostly on the tests here that seem to run without a problem. I left one comment about actually deprecating queryhelp
but since that was not actually changed in this PR, ok to merge this as is. Would be good to include the PR message in the commit, since that contains a useful summary of the changes
|
||
@property | ||
def queryhelp(self) -> QueryDict: | ||
def queryhelp(self) -> 'QueryDictType': |
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.
Shouldn't we just deprecate this so we can remove it at some point? No reason to keep this around if there is a preferred alternative
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.
Yeh I mentioned this here: #5081 (comment), lets open an issue for it to track
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.
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.
Ah yeah, I remember seeing this now. I am a bit surprised by you being against having deprecation warnings for a new major release? Why would that be objectionable? And why wouldn't that be a problem on a minor release?
Thanks 😄 yeh I promise I was very thorough! and with the rigorous use of type checking, it really does help to make sure all the function/method inputs/outputs are correct |
Fixes #4327
There are four primary modules involved in the QueryBuilder abstraction:
aiida/orm/implementation/django/querybuilder.py::DjagoQueryBuilder
aiida/orm/implementation/sqlalchemy/querybuilder.py::SqlaQueryBuilder
aiida/orm/implementation/querybuilder.py::BackendQueryBuilder
aiida/orm/querybuilder.py::QueryBuilder
Prior to #5092, all of these modules imported objects from SQLAlchemy, i.e. there was actually no abstraction, since everything was tightly coupled to SQLAlchemy.
As well as this lack of abstraction, the spread of logic and state across these modules (as well as the lack of typing and non-uniform method naming) made it very difficult to decipher the workings of the code.
This PR continues from #5092, to fully abstract the QueryBuilder; moving all sqlalchemy code to
SqlaQueryBuilder
, making theBackendQueryBuilder
a proper abstract class, and reducingQueryBuilder
backend interaction to these 6 calls:As you can see, whenever the backend is called it is passed the (JSONable) query dict, which it uses to build the query. As was previously the case on the frontend,
SqlaQueryBuilder
hashes this dict, to ensure the query is only rebuilt on changes.Some other changes of note:
aiida/orm/implementation/sqlalchemy/querybuilder.py
is split into a few modules, to improve modularityQueryBuilder.get_query
andQueryBuilder.inject_query
method has been removed, since naturally these break abstraction, since they rely on ansqlalchemy.Query
object (I don't know of any use-cases why these would be used)QueryBuilder.distinct
method save its state to the query dict, rather than directly calling thesqlachemy.Query.distinct
, e.g.limit
after callingQueryBuilder.one()
joining_keyword
; before it would only validate against all possible keywords, now it validates against only the keywords for the entity type:with_incoming
for all entities, setwith_node
for non-node entities:sqlalchemy_utils
is now only used intests/backends/aiida_sqlalchemy/test_utils.py
, so I have moved it to thetests
extras, rather thaninstall_requires