Repository: networkx/networkx

Issue:
Join operation in trees---not handling label_attribute
<!-- If you have a general question about NetworkX, please use the discussions tab to create a new discussion -->

<!--- Provide a general summary of the issue in the Title above -->
[https://github.com/networkx/networkx/blob/main/networkx/algorithms/tree/operations.py](https://github.com/networkx/networkx/blob/main/networkx/algorithms/tree/operations.py)
1. The resulting graph of join operation in trees isn't including the old labels of inputs.
2.  Not handling the cases where label_attribute is passed as an argument.

### Current Behavior
![Screenshot from 2023-03-11 17-03-33](https://user-images.githubusercontent.com/88175932/224483929-b1ebff93-2e5e-46a6-9c6e-11de1dc53ca1.png)

<!--- Tell us what happens instead of the expected behavior -->

### Expected Behavior

![image](https://user-images.githubusercontent.com/88175932/224484244-9e9653fe-2aa8-4f02-9bee-39942a2ab08f.png)


<!--- Tell us what should happen -->

### Steps to Reproduce
As shown above
<!--- Provide a minimal example that reproduces the bug -->

### Environment

<!--- Please provide details about your local environment -->

Python version: 3.10.6
NetworkX version: 3.0

### Additional context
[https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.tree.operations.join.html](https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.tree.operations.join.html)

<!--- Add any other context about the problem here, screenshots, etc. -->
Improve test coverage for operations.py (join)
<!-- If you have a general question about NetworkX, please use the discussions tab to create a new discussion -->

<!--- Provide a general summary of the issue in the Title above -->

### Current Behavior
https://app.codecov.io/gh/networkx/networkx/blob/main/networkx/algorithms/tree/operations.py  the current test coverage is 92.8%. There are still some cases needed to be handled.
<!--- Tell us what happens instead of the expected behavior -->

### Expected Behavior

<!--- Tell us what should happen -->
https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.tree.operations.join.html
1. Test case to check label_attribute should be added 
2. In the documentation its written that the inputs must be tree. But this function works for graphs too. Could you tell me if its for  trees or graphs as well?
### Steps to Reproduce

<!--- Provide a minimal example that reproduces the bug -->

### Environment

<!--- Please provide details about your local environment -->

Python version:3.10.6
NetworkX version:3.0

### Additional context

<!--- Add any other context about the problem here, screenshots, etc. -->



Discussion:

Resolving patch:
diff --git a/networkx/algorithms/tree/operations.py b/networkx/algorithms/tree/operations.py
--- a/networkx/algorithms/tree/operations.py
+++ b/networkx/algorithms/tree/operations.py
@@ -78,25 +78,13 @@ def join(rooted_trees, label_attribute=None):
 
     # Get the relabeled roots.
     roots = [
-        next(v for v, d in tree.nodes(data=True) if d.get("_old") == root)
+        next(v for v, d in tree.nodes(data=True) if d.get(label_attribute) == root)
         for tree, root in zip(trees, roots)
     ]
 
-    # Remove the old node labels.
+    # Add all sets of nodes and edges, attributes
     for tree in trees:
-        for v in tree:
-            tree.nodes[v].pop("_old")
-
-    # Add all sets of nodes and edges, with data.
-    nodes = (tree.nodes(data=True) for tree in trees)
-    edges = (tree.edges(data=True) for tree in trees)
-    R.add_nodes_from(chain.from_iterable(nodes))
-    R.add_edges_from(chain.from_iterable(edges))
-
-    # Add graph attributes; later attributes take precedent over earlier
-    # attributes.
-    for tree in trees:
-        R.graph.update(tree.graph)
+        R.update(tree)
 
     # Finally, join the subtrees at the root. We know 0 is unused by the
     # way we relabeled the subtrees.


Test patch:
diff --git a/networkx/algorithms/tree/tests/test_operations.py b/networkx/algorithms/tree/tests/test_operations.py
--- a/networkx/algorithms/tree/tests/test_operations.py
+++ b/networkx/algorithms/tree/tests/test_operations.py
@@ -2,10 +2,20 @@
 
 """
 
+from itertools import chain
+
 import networkx as nx
 from networkx.utils import edges_equal, nodes_equal
 
 
+def _check_label_attribute(input_trees, res_tree, label_attribute="_old"):
+    res_attr_dict = nx.get_node_attributes(res_tree, label_attribute)
+    res_attr_set = set(res_attr_dict.values())
+    input_label = (list(tree[0].nodes()) for tree in input_trees)
+    input_label_set = set(chain.from_iterable(input_label))
+    return res_attr_set == input_label_set
+
+
 class TestJoin:
     """Unit tests for the :func:`networkx.tree.join` function."""
 
@@ -24,14 +34,18 @@ def test_single(self):
 
         """
         T = nx.empty_graph(1)
-        actual = nx.join([(T, 0)])
+        trees = [(T, 0)]
+        actual = nx.join(trees)
         expected = nx.path_graph(2)
         assert nodes_equal(list(expected), list(actual))
         assert edges_equal(list(expected.edges()), list(actual.edges()))
+        assert _check_label_attribute(trees, actual)
 
     def test_basic(self):
         """Tests for joining multiple subtrees at a root node."""
         trees = [(nx.full_rary_tree(2, 2**2 - 1), 0) for i in range(2)]
-        actual = nx.join(trees)
+        label_attribute = "old_values"
+        actual = nx.join(trees, label_attribute)
         expected = nx.full_rary_tree(2, 2**3 - 1)
         assert nx.is_isomorphic(actual, expected)
+        assert _check_label_attribute(trees, actual, label_attribute)