-
Notifications
You must be signed in to change notification settings - Fork 188
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
GroupPaths: A class to provide attribute/key access to Groups, with delimited labels. #3613
GroupPaths: A class to provide attribute/key access to Groups, with delimited labels. #3613
Conversation
We discussed some API changes with @chrisjsewell and @greschd that now @chrisjsewell will implement |
Two questions that came to my mind:
Any feedback is welcome |
Seems nice. However, is this a backwards-incompatible change? We could create both, although that is also kind of ugly. Do we have some way of specifying feature flags, e.g. in the configuration? |
Morning! |
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.
Maybe you weren't done yet, but here's my review - I think very little is left to do!
@giovannipizzi and @sphuber this is ready for 'final' review. |
One other thing I forgot. It would be ideal to include tab completion of paths. I know you have dynamic autocompletion for |
Why have the tests failed? Is it because of the problem we solved last week or is something else related with the quoted comment above? If all is worked out now and you can rebase, I can then review the PR. |
Yep @ramirezfranciscof, this is ready for review now 👍 |
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 for the contribution @chrisjsewell ! This looks like a very interesting tool to help browse one's database in an easy way. I have made some comments regarding some of the functionalities/behavior that I found a bit unexpected but let me know if these had already been discussed during the coding week and were agreed upon as is. As an extra thing I would also ask you to move the test you added from its current location (aiida/backends/tests/tools/groups
) to the new more external test section (test/tools/groups
).
Since this is still one of my firsts PR reviews it would maybe be good is somebody else (@ltalirz @CasperWA @greschd , I think @sphuber is kind of busy right now...) could give a quick look to check that I didn't miss something obvious or even check if my comments are relevant or I should be focusing on other stuff ("yo' dog, I heard you like reviews...").
Thanks @ramirezfranciscof, I will work through these (it may take a little while though!) |
Hi, |
I’ll finish it off next week 👍 |
745a860
to
faf2953
Compare
Codecov Report
@@ Coverage Diff @@
## develop #3613 +/- ##
===========================================
+ Coverage 78.00% 78.09% +0.08%
===========================================
Files 457 458 +1
Lines 33714 33924 +210
===========================================
+ Hits 26300 26494 +194
- Misses 7414 7430 +16
Continue to review full report at Codecov.
|
All changes made, over to you guys... |
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.
Hi @chrisjsewell thanks a lot. It is looking good. I am a bit late to the party with the review, but still have some questions. Sorry for that. Since these are mostly bigger design questions, it would be good to maybe discuss this in person today with the other people involved and hash those out before starting to adapt the code. I think that once we have decided on these open questions, it shouldn't amount to much work whichever which way we decide to go and it should be easy to implement. The features that would be non-breaking we can even decide to add at a later point in time so as to not block this PR. We should just make sure that we are sure about those that we cannot change easily after merging. Shall we perhaps meet after the meeting of 9 am today?
As discussed, CLI improvements to open in a separate "enhancements" issue, when this PR is merged:
$ verdi group path ls --recursive --count
Path Nodes
------- ------------
a 10
a/b 4
a/c 6
$ verdi group path ls a
a/b
a/c
$ verdi group path ls a --relative
b
c
|
Another thing I just realized @chrisjsewell , in terms of enhancements for the future, is to maybe make the currently hardcoded delimiter in |
Nope thats fine, its already a private variable, just needs to be added to the |
Introduced a cyclic import my moving the files??
|
No I think you just got unlucky and this happened in a previous commit that you merged in. These cyclic-imports are not always trustworthy and are notoriously difficult to track down. |
whats the course of action here 😕 ? Do I mess around with imports until it disappears, or do we turn a blind eye 🙈 |
aiida/tools/groups/paths.py
Outdated
"""Return the concrete group associated with this path.""" | ||
try: | ||
if self.type_string is not None: | ||
return orm.Group.objects.get(label=self.path) |
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 just noticed a potential problem with this implementation. Consider the following
Group(label='a', type_string='user').store()
Group(label='a', type_string='auto.import').store()
path = GroupPath('a', type_string=None)
path.group # This will except because the filters do not uniquely determine a single group.
You catch the NotExistent
case but not the MultipleObjectsError
that will be thrown in my example. Did you think about this and made the decision to ignore it, or is this something that wasn't discussed during the lifetime of the PR? I am pointing this out here, because quite a bit of the rest of the functionality may depend on this.
To be honest, I am not quite sure what should happen here. Maybe we should make the type_string
required. In this way, one can only use the GroupPath
to iterate over a specific type of groups, but at least you know that the label
will guarantee uniqueness then.
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.
No I wouldn't say it has been specifically addressed. I agree that we err on the side of disallowing a None
type_string
for now, and this can always be addressed in a later PR.
On a related note, how does your group sub-classing PR discriminate group classes; via the type string?
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.
see 5141b0d
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.
Yes, exactly, the type_string
is what is used to load the correct sub class. I am just now actually working on updating the QueryBuilder
such that querying with subclasses works properly and this is also based on the type_string
which itself is determined by the entry point name. However, working on this made me realize that using core
as the entry point name for the base Group
class, is not ideal, since this will never match any groups whose entry point that does not start with core.
, which is to say all groups from external plugins... Not sure what the best approach is here. Setting the entry point for Group
base class to empty string is not really possible I think, so I will just have to make an exception for it in the query builder filtering logic.
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.
👍
This is the use case where I could envisage you might want to start using GroupPath
with multiple type_string
. But yeh, I don't yet have a concrete solution for how to deal with path clashes in that instance.
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.
so in 22ee75a, as discussed, I have changed the group
property to the get_group
method. This will allow for the later extension of replacing type_string
to type_cls
, at which point the association of a path to only 0 or 1 groups cannot be guaranteed.
Within this extension, all "iterative" methods would still work fine (like children
and walk
), but for methods where you directly access a group; get_group
, delete_group
, get_or_create_group
, you would then want to add arguments/logic to ensure only one group is selected.
@ltalirz I note that your |
I think the |
#3892 was a merge into to develop though, wasn't it? |
Yes what I meant was that it the workflow only runs on new commits on |
ah ok fair enough |
Groups can be used to store nodes in AiiDA, but do not have any builtin hierarchy themselves. However, often it may be useful to think of groups as folders on a filesystem and the nodes within them as the files. Building this functionality directly on the database would require significant changes, but a virtual hierarchy based on the group labels can be readily provided. This is what the new utility class `GroupPath` facilitates. It allows group labels to be interpreted as the hierarchy of groups. Example: consider one has groups with the following labels group/sub/a group/sub/b group/other/c One could see this as the group `group` containing the sub groups `sub` and `other`, with `sub` containing `a` and `b` itself. The `GroupPath` class allows one to exploit this hierarchical naming:: path = GroupPath('group') path.sub.a.get_group() # will return group with label `group/sub/a` It can also be used to create groups that do not yet exist: path = GroupPath() path.some.group.get_or_create_group() This will create a `Group` with the label `some/group`. The `GroupPath` class implements many other useful methods to make the traversing and manipulating of groups a lot easier.
a9e3a5e
to
ec6d7ea
Compare
comments addressed
Great stuff, thanks @chrisjsewell! |
thanks 😁 |
Fixes #3589
Heya, this is some code that I've been using for a while, to manage my groups as a pseudo folder system, which has been super useful. From the tests you should be able to understand its functionality. For example, if you have three groups labelled
['f1/f2/f3a', 'f1/f2/f3b', 'f1/f2/f3-c/f4a']
, you can do:It appears to relate closely to 'Group Nesting' in the aiidacw2019-plan 😀