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

DataTree.lineage should be renamed to .parents #286

Merged

Conversation

etienneschalk
Copy link
Contributor

@etienneschalk etienneschalk commented Dec 3, 2023

Open Points

Checklist

  • Subtask DataTree.lineage should be renamed to .parents of Consistency between DataTree methods and pathlib.PurePath methods #283
  • Tests added
    • Renamed test_lineage to test_parents
    • Rewrote test_lineage so that it tests that the lineage and parents properties are equivalent
    • Wrote test_iter_lineage to verify that iter_lineage and iter_parents yield the same results
  • Passes pre-commit run --all-files
    • ⚠️ I had to add a #type: ignore comment
  • New functions/methods are listed in api.rst
    • lineage and iter_lineage removed (see open point (3))
    • parents and iter_parents added
  • Changes are summarized in docs/source/whats-new.rst
    • In section "Deprecation"

@TomNicholas
Copy link
Collaborator

Thanks for this! I will give a proper review tomorrow!

Should a deprecation warning be added?

Technically we should add the new method, alias the old method to point to the new, and raise a DeprecationWarning whenever the old method is used.

Does this need it's own issue?

No, we'll just tick off that bullet point when this done.

@etienneschalk
Copy link
Contributor Author

Technically we should add the new method, alias the old method to point to the new, and raise a DeprecationWarning whenever the old method is used.

Okay, I only substituted lineage by parents. I will rework the PR.

I can get inspiration from other places where warnings (DeprecationWarning) are raised, and the xarray contributing guidelines also underline the importance of not breaking the API : Backwards Compatibility

Copy link
Collaborator

@TomNicholas TomNicholas left a comment

Choose a reason for hiding this comment

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

This is looking good so far! Just one comment about iter_parents.

docs/source/whats-new.rst Show resolved Hide resolved
datatree/treenode.py Outdated Show resolved Hide resolved
datatree/tests/test_treenode.py Outdated Show resolved Hide resolved
datatree/mapping.py Outdated Show resolved Hide resolved
@TomNicholas
Copy link
Collaborator

Should lineage and iter_lineage be removed from api.rst?

I actually can't remember how we normally do this, but I think probably better to leave them in and only remove them from api.rst once they are actually removed from the library.

I can get inspiration from other places where warnings (DeprecationWarning) are raised, and the xarray contributing guidelines also underline the importance of not breaking the API : Backwards Compatibility

It's great that you found this! And whilst broadly we should try to follow that, in datatree we do not need to be as strict about it as we are in xarray (see https://github.com/xarray-contrib/datatree#development-roadmap).

@etienneschalk
Copy link
Contributor Author

So, I added back lineage in api.rst and my credit, it is ready for review!

@@ -236,25 +236,48 @@ def _post_attach_children(self: Tree, children: Mapping[str, Tree]) -> None:
"""Method call after attaching `children`."""
pass

def iter_lineage(self: Tree) -> Iterator[Tree]:
def iter_parents(self: Tree) -> Iterator[Tree]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry I don't think I was clear. I think we should never add .iter_parents, instead recommending the new .parents as the replacement for both .lineage and .iter_lineage. So there should not be any method called iter_parents.

@@ -95,7 +95,7 @@ def test_ancestors(self):
michael = TreeNode(children={"Tony": tony})
vito = TreeNode(children={"Michael": michael})
assert tony.root is vito
assert tony.lineage == (tony, michael, vito)
assert tony.parents == (michael, vito)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

A node's parents do not include the node itself, in opposition to lineage.

Note:lineage is still tested in test_lineage

@@ -236,26 +235,53 @@ def _post_attach_children(self: Tree, children: Mapping[str, Tree]) -> None:
"""Method call after attaching `children`."""
pass

def iter_lineage(self: Tree) -> Iterator[Tree]:
def _iter_parents(self: Tree) -> Iterator[Tree]:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I kept the private _iter_parents method as it is useful to insulate the "low-level" logic (while + yield) from the parents method that just have to consume the iterator into a tuple. I could not find a way of not keeping this intermediate private method that would have been more elegant

"Please use `parents` from now on.",
DeprecationWarning,
)
return self.iter_lineage()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Call chain: lineage -> iter_lineage -> parents

@@ -643,12 +668,12 @@ def _path_to_ancestor(self, ancestor: NamedNode) -> NodePath:
raise NotFoundInTreeError(
"Cannot find relative path to ancestor because nodes do not lie within the same tree"
)
if ancestor.path not in list(a.path for a in self.ancestors):
if ancestor.path not in list(a.path for a in (self, *self.parents)):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know if the project has some test coverage tool, but I'm pretty sure this change is actually useless, as the case of the node being compared has been handled previously in the if branch of relative_to. So iterating on the parents, not including the node itself, might be correct

path_upwards = "../" * generation_gap if generation_gap > 0 else "/"
parents_paths = list(parent.path for parent in (self, *self.parents))
generation_gap = list(parents_paths).index(ancestor.path)
path_upwards = "../" * generation_gap if generation_gap > 0 else "."
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same, this path was causing me issues, but the else branch might never be reached, for the same reason. However, using a dot fixed some tests during development. It makes sense: the path from a node itself is not the root (/) but . as declared in existing test_relative_paths:

result = sue.relative_to(john)

@etienneschalk etienneschalk force-pushed the eschalk/rename-lineage-to-parents branch from dcf24fd to 2c0b3ea Compare December 9, 2023 20:22
@TomNicholas
Copy link
Collaborator

I don't know why I keep having to re-approve the automated tests on this PR ☹️

This is looking great @etienneschalk ! Tag me when you feel it's ready for another review!

@etienneschalk
Copy link
Contributor Author

Hello @TomNicholas ,

It seems that the CI is not automatically triggered on push and required manual intervention from a maintainer.

I assume that having passing CI checks is a pre-condition to make a new review from your side worth it.

What actions can I do on my side to fix these tests? I see some are failed or cancelled.

Locally, what I do currently before pushing is:

  • Run pytest
  • Make sure pre-commit pass

However, I don't:

@TomNicholas
Copy link
Collaborator

It seems that the CI is not automatically triggered on push and required manual intervention from a maintainer.

Yeah... I'm trying to work out what's causing that but drawing a blank so far.

What actions can I do on my side to fix these tests? I see some are failed or cancelled.

I think we have another issue caused by using the most recent version of xarray, see #270.

@etienneschalk
Copy link
Contributor Author

etienneschalk commented Jan 6, 2024

This PR should be ready to be merged, after #298 has been merged (to fix #284)

@TomNicholas TomNicholas enabled auto-merge (squash) January 19, 2024 22:35
@TomNicholas TomNicholas merged commit 8fbf2be into xarray-contrib:main Jan 19, 2024
14 checks passed
@TomNicholas
Copy link
Collaborator

Thanks so much @etienneschalk ! Sorry it took me a while to look at this ❤️

@etienneschalk etienneschalk deleted the eschalk/rename-lineage-to-parents branch January 20, 2024 13:11
flamingbear pushed a commit to flamingbear/xarray that referenced this pull request Jan 24, 2024
…e#286

* Replace 'lineage' occurences in code by 'parents'

* Replace 'lineage' occurences in api.rst by 'parents'

* MyPy ignore

* whats-new

* Re-introduce lineage and deprecate it

* Added credit

* Added back lineage in api.rst

* Update datatree/tests/test_treenode.py

Co-authored-by: Tom Nicholas <tom@cworthy.org>

* Updated lineage and parents, broke tests

* Replaced slash by point, tests pass

* New PR

* Fix tests

* Remove iter_parents from api.rst

* Avoid entering into the more complex else branch

---------

Co-authored-by: Tom Nicholas <tom@cworthy.org>
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.

None yet

2 participants