diff --git a/java/pom.xml b/java/pom.xml --- a/java/pom.xml +++ b/java/pom.xml @@ -36,6 +36,12 @@ 5.7.0 test + + org.junit.jupiter + junit-jupiter-params + 5.7.0 + test + org.slf4j slf4j-simple diff --git a/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java b/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java --- a/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java +++ b/java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java @@ -238,6 +238,7 @@ private final TraversalRequest request; private final NodePropertyBuilder.NodeDataMask nodeDataMask; private final NodeObserver nodeObserver; + private long remainingMatches; private Node.Builder nodeBuilder; @@ -258,6 +259,11 @@ if (request.hasMaxEdges()) { setMaxEdges(request.getMaxEdges()); } + if (request.hasMaxMatchingNodes() && request.getMaxMatchingNodes() > 0) { + this.remainingMatches = request.getMaxMatchingNodes(); + } else { + this.remainingMatches = -1; + } } @Override @@ -273,14 +279,28 @@ NodePropertyBuilder.buildNodeProperties(g, nodeDataMask, nodeBuilder, node); } super.visitNode(node); - if (request.getReturnNodes().hasMinTraversalSuccessors() - && traversalSuccessors < request.getReturnNodes().getMinTraversalSuccessors() - || request.getReturnNodes().hasMaxTraversalSuccessors() - && traversalSuccessors > request.getReturnNodes().getMaxTraversalSuccessors()) { - nodeBuilder = null; + + boolean nodeMatchesConstraints = true; + + if (request.getReturnNodes().hasMinTraversalSuccessors()) { + nodeMatchesConstraints &= traversalSuccessors >= request.getReturnNodes().getMinTraversalSuccessors(); } - if (nodeBuilder != null) { - nodeObserver.onNext(nodeBuilder.build()); + if (request.getReturnNodes().hasMaxTraversalSuccessors()) { + nodeMatchesConstraints &= traversalSuccessors <= request.getReturnNodes().getMaxTraversalSuccessors(); + } + + if (nodeMatchesConstraints) { + if (nodeBuilder != null) { + nodeObserver.onNext(nodeBuilder.build()); + } + + if (remainingMatches >= 0) { + remainingMatches--; + if (remainingMatches == 0) { + // We matched as many nodes as allowed + throw new StopTraversalException(); + } + } } } diff --git a/java/src/test/java/org/softwareheritage/graph/GraphTest.java b/java/src/test/java/org/softwareheritage/graph/GraphTest.java --- a/java/src/test/java/org/softwareheritage/graph/GraphTest.java +++ b/java/src/test/java/org/softwareheritage/graph/GraphTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.BeforeAll; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class GraphTest { static SwhBidirectionalGraph graph; @@ -53,6 +54,34 @@ assertEquals(expectedList, actualList); } + public static void assertContainsAll(Collection expected, Collection actual) { + ArrayList expectedList = new ArrayList<>(expected); + ArrayList actualList = new ArrayList<>(actual); + expectedList.sort(Comparator.comparing(Object::toString)); + Iterator expectedIterator = expectedList.iterator(); + + actualList.sort(Comparator.comparing(Object::toString)); + + for (T actualItem : actualList) { + boolean found = false; + while (expectedIterator.hasNext()) { + if (expectedIterator.next().equals(actualItem)) { + found = true; + break; + } + } + if (!found) { + // TODO: better message when actualItem is present twice in actualList, + // but only once in expectedList + fail(String.format("%s not found in %s", actualItem, expectedList)); + } + } + } + + public static void assertLength(int expected, Collection actual) { + assertEquals(String.format("Size of collection %s:", actual), expected, actual.size()); + } + public static ArrayList lazyLongIteratorToList(LazyLongIterator input) { ArrayList inputList = new ArrayList<>(); Iterator inputIt = LazyLongIterators.eager(input); diff --git a/java/src/test/java/org/softwareheritage/graph/rpc/CountEdgesTest.java b/java/src/test/java/org/softwareheritage/graph/rpc/CountEdgesTest.java --- a/java/src/test/java/org/softwareheritage/graph/rpc/CountEdgesTest.java +++ b/java/src/test/java/org/softwareheritage/graph/rpc/CountEdgesTest.java @@ -15,6 +15,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class CountEdgesTest extends TraversalServiceTest { private TraversalRequest.Builder getTraversalRequestBuilder(SWHID src) { @@ -41,6 +43,29 @@ assertEquals(13, actual.getCount()); } + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 13, 14, 15, Integer.MAX_VALUE}) + public void forwardFromRootWithLimit(int limit) { + CountResponse actual = client + .countEdges(getTraversalRequestBuilder(new SWHID(TEST_ORIGIN_ID)).setMaxMatchingNodes(limit).build()); + + switch (limit) { + case 1: + // 1. origin -> snp:20 + assertEquals(1, actual.getCount()); + break; + case 2: + // 1. origin -> snp:20 + // 2. either snp:20 -> rev:9 or snp:20 -> rel:10 + assertEquals(3, actual.getCount()); + break; + default : + // Counts all edges + assertEquals(13, actual.getCount()); + break; + } + } + @Test public void forwardFromMiddle() { CountResponse actual = client.countEdges(getTraversalRequestBuilder(fakeSWHID("dir", 12)).build()); diff --git a/java/src/test/java/org/softwareheritage/graph/rpc/CountNodesTest.java b/java/src/test/java/org/softwareheritage/graph/rpc/CountNodesTest.java --- a/java/src/test/java/org/softwareheritage/graph/rpc/CountNodesTest.java +++ b/java/src/test/java/org/softwareheritage/graph/rpc/CountNodesTest.java @@ -15,6 +15,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class CountNodesTest extends TraversalServiceTest { private TraversalRequest.Builder getTraversalRequestBuilder(SWHID src) { @@ -41,6 +43,19 @@ assertEquals(12, actual.getCount()); } + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 5, 11, 12, 13, 14, 15, Integer.MAX_VALUE}) + public void forwardFromRootWithLimit(int limit) { + CountResponse actual = client + .countNodes(getTraversalRequestBuilder(new SWHID(TEST_ORIGIN_ID)).setMaxMatchingNodes(limit).build()); + + if (limit == 0) { + assertEquals(12, actual.getCount()); + } else { + assertEquals(Math.min(limit, 12), actual.getCount()); + } + } + @Test public void forwardFromMiddle() { CountResponse actual = client.countNodes(getTraversalRequestBuilder(fakeSWHID("dir", 12)).build()); @@ -75,6 +90,14 @@ assertEquals(6, actual.getCount()); } + @ParameterizedTest + @ValueSource(ints = {1, 2, 3, 4, 5, 6, 7}) + public void backwardRevToRevRevToRelWithLimit(int limit) { + CountResponse actual = client.countNodes(getTraversalRequestBuilder(fakeSWHID("rev", 3)) + .setEdges("rev:rev,rev:rel").setDirection(GraphDirection.BACKWARD).setMaxMatchingNodes(limit).build()); + assertEquals(Math.min(limit, 6), actual.getCount()); + } + @Test public void testWithEmptyMask() { CountResponse actual = client.countNodes( diff --git a/java/src/test/java/org/softwareheritage/graph/rpc/TraverseLeavesTest.java b/java/src/test/java/org/softwareheritage/graph/rpc/TraverseLeavesTest.java --- a/java/src/test/java/org/softwareheritage/graph/rpc/TraverseLeavesTest.java +++ b/java/src/test/java/org/softwareheritage/graph/rpc/TraverseLeavesTest.java @@ -8,6 +8,8 @@ package org.softwareheritage.graph.rpc; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.softwareheritage.graph.GraphTest; import org.softwareheritage.graph.SWHID; @@ -19,18 +21,38 @@ .setReturnNodes(NodeFilter.newBuilder().setMaxTraversalSuccessors(0).build()); } - @Test - public void forwardFromSnp() { - TraversalRequest request = getLeavesRequestBuilder(fakeSWHID("snp", 20)).build(); - + private void _checkForwardFromSnp(int limit, ArrayList actualLeaves) { ArrayList expectedLeaves = new ArrayList<>(); expectedLeaves.add(new SWHID("swh:1:cnt:0000000000000000000000000000000000000001")); expectedLeaves.add(new SWHID("swh:1:cnt:0000000000000000000000000000000000000004")); expectedLeaves.add(new SWHID("swh:1:cnt:0000000000000000000000000000000000000005")); expectedLeaves.add(new SWHID("swh:1:cnt:0000000000000000000000000000000000000007")); + if (limit == 0) { + GraphTest.assertEqualsAnyOrder(expectedLeaves, actualLeaves); + } else { + GraphTest.assertContainsAll(expectedLeaves, actualLeaves); + GraphTest.assertLength(Math.max(0, Math.min(limit, 4)), actualLeaves); + } + } + + @Test + public void forwardFromSnp() { + TraversalRequest request = getLeavesRequestBuilder(fakeSWHID("snp", 20)).build(); + ArrayList actualLeaves = getSWHIDs(client.traverse(request)); - GraphTest.assertEqualsAnyOrder(expectedLeaves, actualLeaves); + + _checkForwardFromSnp(0, actualLeaves); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 3, 4, 5, Integer.MAX_VALUE}) + public void forwardFromSnpWithLimit(int limit) { + TraversalRequest request = getLeavesRequestBuilder(fakeSWHID("snp", 20)).setMaxMatchingNodes(limit).build(); + + ArrayList actualLeaves = getSWHIDs(client.traverse(request)); + + _checkForwardFromSnp(limit, actualLeaves); } @Test @@ -97,4 +119,15 @@ expectedLeaves.add(new SWHID("swh:1:dir:0000000000000000000000000000000000000012")); GraphTest.assertEqualsAnyOrder(expectedLeaves, actualLeaves); } + + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, Integer.MAX_VALUE}) + public void backwardCntToDirDirToDirWithLimit(int limit) { + TraversalRequest request = getLeavesRequestBuilder(fakeSWHID("cnt", 5)).setEdges("cnt:dir,dir:dir") + .setDirection(GraphDirection.BACKWARD).setMaxMatchingNodes(limit).build(); + ArrayList actualLeaves = getSWHIDs(client.traverse(request)); + ArrayList expectedLeaves = new ArrayList<>(); + expectedLeaves.add(new SWHID("swh:1:dir:0000000000000000000000000000000000000012")); + GraphTest.assertEqualsAnyOrder(expectedLeaves, actualLeaves); + } } diff --git a/proto/swhgraph.proto b/proto/swhgraph.proto --- a/proto/swhgraph.proto +++ b/proto/swhgraph.proto @@ -106,6 +106,9 @@ /* FieldMask of which fields are to be returned (e.g., "swhid,cnt.length"). * By default, all fields are returned. */ optional google.protobuf.FieldMask mask = 8; + /* Maximum number of matching results before stopping. For Traverse(), this is + * the total number of results. Defaults to infinite. */ + optional int64 max_matching_nodes = 9; } /* FindPathToRequest describes a request to find a shortest path between a diff --git a/swh/graph/grpc/swhgraph_pb2.py b/swh/graph/grpc/swhgraph_pb2.py --- a/swh/graph/grpc/swhgraph_pb2.py +++ b/swh/graph/grpc/swhgraph_pb2.py @@ -16,7 +16,7 @@ from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dswh/graph/grpc/swhgraph.proto\x12\tswh.graph\x1a google/protobuf/field_mask.proto\"W\n\x0eGetNodeRequest\x12\r\n\x05swhid\x18\x01 \x01(\t\x12-\n\x04mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x07\n\x05_mask\"\xd8\x02\n\x10TraversalRequest\x12\x0b\n\x03src\x18\x01 \x03(\t\x12,\n\tdirection\x18\x02 \x01(\x0e\x32\x19.swh.graph.GraphDirection\x12\x12\n\x05\x65\x64ges\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tmax_edges\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\tmin_depth\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12\x16\n\tmax_depth\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x30\n\x0creturn_nodes\x18\x07 \x01(\x0b\x32\x15.swh.graph.NodeFilterH\x04\x88\x01\x01\x12-\n\x04mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x08\n\x06_edgesB\x0c\n\n_max_edgesB\x0c\n\n_min_depthB\x0c\n\n_max_depthB\x0f\n\r_return_nodesB\x07\n\x05_mask\"\x97\x02\n\x11\x46indPathToRequest\x12\x0b\n\x03src\x18\x01 \x03(\t\x12%\n\x06target\x18\x02 \x01(\x0b\x32\x15.swh.graph.NodeFilter\x12,\n\tdirection\x18\x03 \x01(\x0e\x32\x19.swh.graph.GraphDirection\x12\x12\n\x05\x65\x64ges\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tmax_edges\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\tmax_depth\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12-\n\x04mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x03\x88\x01\x01\x42\x08\n\x06_edgesB\x0c\n\n_max_edgesB\x0c\n\n_max_depthB\x07\n\x05_mask\"\x81\x03\n\x16\x46indPathBetweenRequest\x12\x0b\n\x03src\x18\x01 \x03(\t\x12\x0b\n\x03\x64st\x18\x02 \x03(\t\x12,\n\tdirection\x18\x03 \x01(\x0e\x32\x19.swh.graph.GraphDirection\x12\x39\n\x11\x64irection_reverse\x18\x04 \x01(\x0e\x32\x19.swh.graph.GraphDirectionH\x00\x88\x01\x01\x12\x12\n\x05\x65\x64ges\x18\x05 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\redges_reverse\x18\x06 \x01(\tH\x02\x88\x01\x01\x12\x16\n\tmax_edges\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\tmax_depth\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12-\n\x04mask\x18\t \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x14\n\x12_direction_reverseB\x08\n\x06_edgesB\x10\n\x0e_edges_reverseB\x0c\n\n_max_edgesB\x0c\n\n_max_depthB\x07\n\x05_mask\"\xb2\x01\n\nNodeFilter\x12\x12\n\x05types\x18\x01 \x01(\tH\x00\x88\x01\x01\x12%\n\x18min_traversal_successors\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12%\n\x18max_traversal_successors\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x08\n\x06_typesB\x1b\n\x19_min_traversal_successorsB\x1b\n\x19_max_traversal_successors\"\x92\x02\n\x04Node\x12\r\n\x05swhid\x18\x01 \x01(\t\x12\'\n\tsuccessor\x18\x02 \x03(\x0b\x32\x14.swh.graph.Successor\x12\x1b\n\x0enum_successors\x18\t \x01(\x03H\x01\x88\x01\x01\x12%\n\x03\x63nt\x18\x03 \x01(\x0b\x32\x16.swh.graph.ContentDataH\x00\x12&\n\x03rev\x18\x05 \x01(\x0b\x32\x17.swh.graph.RevisionDataH\x00\x12%\n\x03rel\x18\x06 \x01(\x0b\x32\x16.swh.graph.ReleaseDataH\x00\x12$\n\x03ori\x18\x08 \x01(\x0b\x32\x15.swh.graph.OriginDataH\x00\x42\x06\n\x04\x64\x61taB\x11\n\x0f_num_successors\"U\n\x04Path\x12\x1d\n\x04node\x18\x01 \x03(\x0b\x32\x0f.swh.graph.Node\x12\x1b\n\x0emidpoint_index\x18\x02 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_midpoint_index\"N\n\tSuccessor\x12\x12\n\x05swhid\x18\x01 \x01(\tH\x00\x88\x01\x01\x12#\n\x05label\x18\x02 \x03(\x0b\x32\x14.swh.graph.EdgeLabelB\x08\n\x06_swhid\"U\n\x0b\x43ontentData\x12\x13\n\x06length\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x17\n\nis_skipped\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\t\n\x07_lengthB\r\n\x0b_is_skipped\"\xc6\x02\n\x0cRevisionData\x12\x13\n\x06\x61uthor\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x18\n\x0b\x61uthor_date\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\x12\x61uthor_date_offset\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x16\n\tcommitter\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\x1b\n\x0e\x63ommitter_date\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\"\n\x15\x63ommitter_date_offset\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07message\x18\x07 \x01(\x0cH\x06\x88\x01\x01\x42\t\n\x07_authorB\x0e\n\x0c_author_dateB\x15\n\x13_author_date_offsetB\x0c\n\n_committerB\x11\n\x0f_committer_dateB\x18\n\x16_committer_date_offsetB\n\n\x08_message\"\xcd\x01\n\x0bReleaseData\x12\x13\n\x06\x61uthor\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x18\n\x0b\x61uthor_date\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\x12\x61uthor_date_offset\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x11\n\x04name\x18\x04 \x01(\x0cH\x03\x88\x01\x01\x12\x14\n\x07message\x18\x05 \x01(\x0cH\x04\x88\x01\x01\x42\t\n\x07_authorB\x0e\n\x0c_author_dateB\x15\n\x13_author_date_offsetB\x07\n\x05_nameB\n\n\x08_message\"&\n\nOriginData\x12\x10\n\x03url\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x06\n\x04_url\"-\n\tEdgeLabel\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\x12\n\npermission\x18\x02 \x01(\x05\"\x1e\n\rCountResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\"\x0e\n\x0cStatsRequest\"\x9b\x02\n\rStatsResponse\x12\x11\n\tnum_nodes\x18\x01 \x01(\x03\x12\x11\n\tnum_edges\x18\x02 \x01(\x03\x12\x19\n\x11\x63ompression_ratio\x18\x03 \x01(\x01\x12\x15\n\rbits_per_node\x18\x04 \x01(\x01\x12\x15\n\rbits_per_edge\x18\x05 \x01(\x01\x12\x14\n\x0c\x61vg_locality\x18\x06 \x01(\x01\x12\x14\n\x0cindegree_min\x18\x07 \x01(\x03\x12\x14\n\x0cindegree_max\x18\x08 \x01(\x03\x12\x14\n\x0cindegree_avg\x18\t \x01(\x01\x12\x15\n\routdegree_min\x18\n \x01(\x03\x12\x15\n\routdegree_max\x18\x0b \x01(\x03\x12\x15\n\routdegree_avg\x18\x0c \x01(\x01*+\n\x0eGraphDirection\x12\x0b\n\x07\x46ORWARD\x10\x00\x12\x0c\n\x08\x42\x41\x43KWARD\x10\x01\x32\xcf\x03\n\x10TraversalService\x12\x35\n\x07GetNode\x12\x19.swh.graph.GetNodeRequest\x1a\x0f.swh.graph.Node\x12:\n\x08Traverse\x12\x1b.swh.graph.TraversalRequest\x1a\x0f.swh.graph.Node0\x01\x12;\n\nFindPathTo\x12\x1c.swh.graph.FindPathToRequest\x1a\x0f.swh.graph.Path\x12\x45\n\x0f\x46indPathBetween\x12!.swh.graph.FindPathBetweenRequest\x1a\x0f.swh.graph.Path\x12\x43\n\nCountNodes\x12\x1b.swh.graph.TraversalRequest\x1a\x18.swh.graph.CountResponse\x12\x43\n\nCountEdges\x12\x1b.swh.graph.TraversalRequest\x1a\x18.swh.graph.CountResponse\x12:\n\x05Stats\x12\x17.swh.graph.StatsRequest\x1a\x18.swh.graph.StatsResponseB0\n\x1eorg.softwareheritage.graph.rpcB\x0cGraphServiceP\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dswh/graph/grpc/swhgraph.proto\x12\tswh.graph\x1a google/protobuf/field_mask.proto\"W\n\x0eGetNodeRequest\x12\r\n\x05swhid\x18\x01 \x01(\t\x12-\n\x04mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x07\n\x05_mask\"\x90\x03\n\x10TraversalRequest\x12\x0b\n\x03src\x18\x01 \x03(\t\x12,\n\tdirection\x18\x02 \x01(\x0e\x32\x19.swh.graph.GraphDirection\x12\x12\n\x05\x65\x64ges\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tmax_edges\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\tmin_depth\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12\x16\n\tmax_depth\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x30\n\x0creturn_nodes\x18\x07 \x01(\x0b\x32\x15.swh.graph.NodeFilterH\x04\x88\x01\x01\x12-\n\x04mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1f\n\x12max_matching_nodes\x18\t \x01(\x03H\x06\x88\x01\x01\x42\x08\n\x06_edgesB\x0c\n\n_max_edgesB\x0c\n\n_min_depthB\x0c\n\n_max_depthB\x0f\n\r_return_nodesB\x07\n\x05_maskB\x15\n\x13_max_matching_nodes\"\x97\x02\n\x11\x46indPathToRequest\x12\x0b\n\x03src\x18\x01 \x03(\t\x12%\n\x06target\x18\x02 \x01(\x0b\x32\x15.swh.graph.NodeFilter\x12,\n\tdirection\x18\x03 \x01(\x0e\x32\x19.swh.graph.GraphDirection\x12\x12\n\x05\x65\x64ges\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tmax_edges\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\tmax_depth\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12-\n\x04mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x03\x88\x01\x01\x42\x08\n\x06_edgesB\x0c\n\n_max_edgesB\x0c\n\n_max_depthB\x07\n\x05_mask\"\x81\x03\n\x16\x46indPathBetweenRequest\x12\x0b\n\x03src\x18\x01 \x03(\t\x12\x0b\n\x03\x64st\x18\x02 \x03(\t\x12,\n\tdirection\x18\x03 \x01(\x0e\x32\x19.swh.graph.GraphDirection\x12\x39\n\x11\x64irection_reverse\x18\x04 \x01(\x0e\x32\x19.swh.graph.GraphDirectionH\x00\x88\x01\x01\x12\x12\n\x05\x65\x64ges\x18\x05 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\redges_reverse\x18\x06 \x01(\tH\x02\x88\x01\x01\x12\x16\n\tmax_edges\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\tmax_depth\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12-\n\x04mask\x18\t \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x14\n\x12_direction_reverseB\x08\n\x06_edgesB\x10\n\x0e_edges_reverseB\x0c\n\n_max_edgesB\x0c\n\n_max_depthB\x07\n\x05_mask\"\xb2\x01\n\nNodeFilter\x12\x12\n\x05types\x18\x01 \x01(\tH\x00\x88\x01\x01\x12%\n\x18min_traversal_successors\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12%\n\x18max_traversal_successors\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x08\n\x06_typesB\x1b\n\x19_min_traversal_successorsB\x1b\n\x19_max_traversal_successors\"\x92\x02\n\x04Node\x12\r\n\x05swhid\x18\x01 \x01(\t\x12\'\n\tsuccessor\x18\x02 \x03(\x0b\x32\x14.swh.graph.Successor\x12\x1b\n\x0enum_successors\x18\t \x01(\x03H\x01\x88\x01\x01\x12%\n\x03\x63nt\x18\x03 \x01(\x0b\x32\x16.swh.graph.ContentDataH\x00\x12&\n\x03rev\x18\x05 \x01(\x0b\x32\x17.swh.graph.RevisionDataH\x00\x12%\n\x03rel\x18\x06 \x01(\x0b\x32\x16.swh.graph.ReleaseDataH\x00\x12$\n\x03ori\x18\x08 \x01(\x0b\x32\x15.swh.graph.OriginDataH\x00\x42\x06\n\x04\x64\x61taB\x11\n\x0f_num_successors\"U\n\x04Path\x12\x1d\n\x04node\x18\x01 \x03(\x0b\x32\x0f.swh.graph.Node\x12\x1b\n\x0emidpoint_index\x18\x02 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_midpoint_index\"N\n\tSuccessor\x12\x12\n\x05swhid\x18\x01 \x01(\tH\x00\x88\x01\x01\x12#\n\x05label\x18\x02 \x03(\x0b\x32\x14.swh.graph.EdgeLabelB\x08\n\x06_swhid\"U\n\x0b\x43ontentData\x12\x13\n\x06length\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x17\n\nis_skipped\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\t\n\x07_lengthB\r\n\x0b_is_skipped\"\xc6\x02\n\x0cRevisionData\x12\x13\n\x06\x61uthor\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x18\n\x0b\x61uthor_date\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\x12\x61uthor_date_offset\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x16\n\tcommitter\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\x1b\n\x0e\x63ommitter_date\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\"\n\x15\x63ommitter_date_offset\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07message\x18\x07 \x01(\x0cH\x06\x88\x01\x01\x42\t\n\x07_authorB\x0e\n\x0c_author_dateB\x15\n\x13_author_date_offsetB\x0c\n\n_committerB\x11\n\x0f_committer_dateB\x18\n\x16_committer_date_offsetB\n\n\x08_message\"\xcd\x01\n\x0bReleaseData\x12\x13\n\x06\x61uthor\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x18\n\x0b\x61uthor_date\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\x12\x61uthor_date_offset\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x11\n\x04name\x18\x04 \x01(\x0cH\x03\x88\x01\x01\x12\x14\n\x07message\x18\x05 \x01(\x0cH\x04\x88\x01\x01\x42\t\n\x07_authorB\x0e\n\x0c_author_dateB\x15\n\x13_author_date_offsetB\x07\n\x05_nameB\n\n\x08_message\"&\n\nOriginData\x12\x10\n\x03url\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x06\n\x04_url\"-\n\tEdgeLabel\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\x12\n\npermission\x18\x02 \x01(\x05\"\x1e\n\rCountResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\"\x0e\n\x0cStatsRequest\"\x9b\x02\n\rStatsResponse\x12\x11\n\tnum_nodes\x18\x01 \x01(\x03\x12\x11\n\tnum_edges\x18\x02 \x01(\x03\x12\x19\n\x11\x63ompression_ratio\x18\x03 \x01(\x01\x12\x15\n\rbits_per_node\x18\x04 \x01(\x01\x12\x15\n\rbits_per_edge\x18\x05 \x01(\x01\x12\x14\n\x0c\x61vg_locality\x18\x06 \x01(\x01\x12\x14\n\x0cindegree_min\x18\x07 \x01(\x03\x12\x14\n\x0cindegree_max\x18\x08 \x01(\x03\x12\x14\n\x0cindegree_avg\x18\t \x01(\x01\x12\x15\n\routdegree_min\x18\n \x01(\x03\x12\x15\n\routdegree_max\x18\x0b \x01(\x03\x12\x15\n\routdegree_avg\x18\x0c \x01(\x01*+\n\x0eGraphDirection\x12\x0b\n\x07\x46ORWARD\x10\x00\x12\x0c\n\x08\x42\x41\x43KWARD\x10\x01\x32\xcf\x03\n\x10TraversalService\x12\x35\n\x07GetNode\x12\x19.swh.graph.GetNodeRequest\x1a\x0f.swh.graph.Node\x12:\n\x08Traverse\x12\x1b.swh.graph.TraversalRequest\x1a\x0f.swh.graph.Node0\x01\x12;\n\nFindPathTo\x12\x1c.swh.graph.FindPathToRequest\x1a\x0f.swh.graph.Path\x12\x45\n\x0f\x46indPathBetween\x12!.swh.graph.FindPathBetweenRequest\x1a\x0f.swh.graph.Path\x12\x43\n\nCountNodes\x12\x1b.swh.graph.TraversalRequest\x1a\x18.swh.graph.CountResponse\x12\x43\n\nCountEdges\x12\x1b.swh.graph.TraversalRequest\x1a\x18.swh.graph.CountResponse\x12:\n\x05Stats\x12\x17.swh.graph.StatsRequest\x1a\x18.swh.graph.StatsResponseB0\n\x1eorg.softwareheritage.graph.rpcB\x0cGraphServiceP\x01\x62\x06proto3') _GRAPHDIRECTION = DESCRIPTOR.enum_types_by_name['GraphDirection'] GraphDirection = enum_type_wrapper.EnumTypeWrapper(_GRAPHDIRECTION) @@ -157,40 +157,40 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n\036org.softwareheritage.graph.rpcB\014GraphServiceP\001' - _GRAPHDIRECTION._serialized_start=2854 - _GRAPHDIRECTION._serialized_end=2897 + _GRAPHDIRECTION._serialized_start=2910 + _GRAPHDIRECTION._serialized_end=2953 _GETNODEREQUEST._serialized_start=78 _GETNODEREQUEST._serialized_end=165 _TRAVERSALREQUEST._serialized_start=168 - _TRAVERSALREQUEST._serialized_end=512 - _FINDPATHTOREQUEST._serialized_start=515 - _FINDPATHTOREQUEST._serialized_end=794 - _FINDPATHBETWEENREQUEST._serialized_start=797 - _FINDPATHBETWEENREQUEST._serialized_end=1182 - _NODEFILTER._serialized_start=1185 - _NODEFILTER._serialized_end=1363 - _NODE._serialized_start=1366 - _NODE._serialized_end=1640 - _PATH._serialized_start=1642 - _PATH._serialized_end=1727 - _SUCCESSOR._serialized_start=1729 - _SUCCESSOR._serialized_end=1807 - _CONTENTDATA._serialized_start=1809 - _CONTENTDATA._serialized_end=1894 - _REVISIONDATA._serialized_start=1897 - _REVISIONDATA._serialized_end=2223 - _RELEASEDATA._serialized_start=2226 - _RELEASEDATA._serialized_end=2431 - _ORIGINDATA._serialized_start=2433 - _ORIGINDATA._serialized_end=2471 - _EDGELABEL._serialized_start=2473 - _EDGELABEL._serialized_end=2518 - _COUNTRESPONSE._serialized_start=2520 - _COUNTRESPONSE._serialized_end=2550 - _STATSREQUEST._serialized_start=2552 - _STATSREQUEST._serialized_end=2566 - _STATSRESPONSE._serialized_start=2569 - _STATSRESPONSE._serialized_end=2852 - _TRAVERSALSERVICE._serialized_start=2900 - _TRAVERSALSERVICE._serialized_end=3363 + _TRAVERSALREQUEST._serialized_end=568 + _FINDPATHTOREQUEST._serialized_start=571 + _FINDPATHTOREQUEST._serialized_end=850 + _FINDPATHBETWEENREQUEST._serialized_start=853 + _FINDPATHBETWEENREQUEST._serialized_end=1238 + _NODEFILTER._serialized_start=1241 + _NODEFILTER._serialized_end=1419 + _NODE._serialized_start=1422 + _NODE._serialized_end=1696 + _PATH._serialized_start=1698 + _PATH._serialized_end=1783 + _SUCCESSOR._serialized_start=1785 + _SUCCESSOR._serialized_end=1863 + _CONTENTDATA._serialized_start=1865 + _CONTENTDATA._serialized_end=1950 + _REVISIONDATA._serialized_start=1953 + _REVISIONDATA._serialized_end=2279 + _RELEASEDATA._serialized_start=2282 + _RELEASEDATA._serialized_end=2487 + _ORIGINDATA._serialized_start=2489 + _ORIGINDATA._serialized_end=2527 + _EDGELABEL._serialized_start=2529 + _EDGELABEL._serialized_end=2574 + _COUNTRESPONSE._serialized_start=2576 + _COUNTRESPONSE._serialized_end=2606 + _STATSREQUEST._serialized_start=2608 + _STATSREQUEST._serialized_end=2622 + _STATSRESPONSE._serialized_start=2625 + _STATSRESPONSE._serialized_end=2908 + _TRAVERSALSERVICE._serialized_start=2956 + _TRAVERSALSERVICE._serialized_end=3419 # @@protoc_insertion_point(module_scope) diff --git a/swh/graph/grpc/swhgraph_pb2.pyi b/swh/graph/grpc/swhgraph_pb2.pyi --- a/swh/graph/grpc/swhgraph_pb2.pyi +++ b/swh/graph/grpc/swhgraph_pb2.pyi @@ -3,75 +3,69 @@ isort:skip_file """ import builtins -import collections.abc import google.protobuf.descriptor import google.protobuf.field_mask_pb2 import google.protobuf.internal.containers import google.protobuf.internal.enum_type_wrapper import google.protobuf.message -import sys import typing - -if sys.version_info >= (3, 10): - import typing as typing_extensions -else: - import typing_extensions +import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor class _GraphDirection: - ValueType = typing.NewType("ValueType", builtins.int) + ValueType = typing.NewType('ValueType', builtins.int) V: typing_extensions.TypeAlias = ValueType - -class _GraphDirectionEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_GraphDirection.ValueType], builtins.type): # noqa: F821 +class _GraphDirectionEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_GraphDirection.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor FORWARD: _GraphDirection.ValueType # 0 """Forward DAG: ori -> snp -> rel -> rev -> dir -> cnt""" + BACKWARD: _GraphDirection.ValueType # 1 """Transposed DAG: cnt -> dir -> rev -> rel -> snp -> ori""" class GraphDirection(_GraphDirection, metaclass=_GraphDirectionEnumTypeWrapper): """Direction of the graph""" + pass FORWARD: GraphDirection.ValueType # 0 """Forward DAG: ori -> snp -> rel -> rev -> dir -> cnt""" + BACKWARD: GraphDirection.ValueType # 1 """Transposed DAG: cnt -> dir -> rev -> rel -> snp -> ori""" + global___GraphDirection = GraphDirection + class GetNodeRequest(google.protobuf.message.Message): """Describe a node to return""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - SWHID_FIELD_NUMBER: builtins.int MASK_FIELD_NUMBER: builtins.int - swhid: builtins.str + swhid: typing.Text """SWHID of the node to return""" + @property def mask(self) -> google.protobuf.field_mask_pb2.FieldMask: """FieldMask of which fields are to be returned (e.g., "swhid,cnt.length"). By default, all fields are returned. """ - def __init__( - self, + pass + def __init__(self, *, - swhid: builtins.str = ..., - mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_mask", b"_mask", "mask", b"mask"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_mask", b"_mask", "mask", b"mask", "swhid", b"swhid"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask", b"_mask"]) -> typing_extensions.Literal["mask"] | None: ... - + swhid: typing.Text = ..., + mask: typing.Optional[google.protobuf.field_mask_pb2.FieldMask] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_mask",b"_mask","mask",b"mask"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_mask",b"_mask","mask",b"mask","swhid",b"swhid"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask",b"_mask"]) -> typing.Optional[typing_extensions.Literal["mask"]]: ... global___GetNodeRequest = GetNodeRequest class TraversalRequest(google.protobuf.message.Message): """TraversalRequest describes how a breadth-first traversal should be performed, and what should be returned to the client. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor - SRC_FIELD_NUMBER: builtins.int DIRECTION_FIELD_NUMBER: builtins.int EDGES_FIELD_NUMBER: builtins.int @@ -80,64 +74,79 @@ MAX_DEPTH_FIELD_NUMBER: builtins.int RETURN_NODES_FIELD_NUMBER: builtins.int MASK_FIELD_NUMBER: builtins.int + MAX_MATCHING_NODES_FIELD_NUMBER: builtins.int @property - def src(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + def src(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: """Set of source nodes (SWHIDs)""" + pass direction: global___GraphDirection.ValueType """Direction of the graph to traverse. Defaults to FORWARD.""" - edges: builtins.str + + edges: typing.Text """Edge restriction string (e.g. "rev:dir,dir:cnt"). Defaults to "*" (all). """ + max_edges: builtins.int """Maximum number of edges accessed in the traversal, after which it stops. Defaults to infinite. """ + min_depth: builtins.int """Do not return nodes with a depth lower than this number. By default, all depths are returned. """ + max_depth: builtins.int """Maximum depth of the traversal, after which it stops. Defaults to infinite. """ + @property def return_nodes(self) -> global___NodeFilter: """Filter which nodes will be sent to the stream. By default, all nodes are returned. """ + pass @property def mask(self) -> google.protobuf.field_mask_pb2.FieldMask: """FieldMask of which fields are to be returned (e.g., "swhid,cnt.length"). By default, all fields are returned. """ - def __init__( - self, + pass + max_matching_nodes: builtins.int + """Maximum number of matching results before stopping. For Traverse(), this is + the total number of results. Defaults to infinite. + """ + + def __init__(self, *, - src: collections.abc.Iterable[builtins.str] | None = ..., + src: typing.Optional[typing.Iterable[typing.Text]] = ..., direction: global___GraphDirection.ValueType = ..., - edges: builtins.str | None = ..., - max_edges: builtins.int | None = ..., - min_depth: builtins.int | None = ..., - max_depth: builtins.int | None = ..., - return_nodes: global___NodeFilter | None = ..., - mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_edges", b"_edges", "_mask", b"_mask", "_max_depth", b"_max_depth", "_max_edges", b"_max_edges", "_min_depth", b"_min_depth", "_return_nodes", b"_return_nodes", "edges", b"edges", "mask", b"mask", "max_depth", b"max_depth", "max_edges", b"max_edges", "min_depth", b"min_depth", "return_nodes", b"return_nodes"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_edges", b"_edges", "_mask", b"_mask", "_max_depth", b"_max_depth", "_max_edges", b"_max_edges", "_min_depth", b"_min_depth", "_return_nodes", b"_return_nodes", "direction", b"direction", "edges", b"edges", "mask", b"mask", "max_depth", b"max_depth", "max_edges", b"max_edges", "min_depth", b"min_depth", "return_nodes", b"return_nodes", "src", b"src"]) -> None: ... + edges: typing.Optional[typing.Text] = ..., + max_edges: typing.Optional[builtins.int] = ..., + min_depth: typing.Optional[builtins.int] = ..., + max_depth: typing.Optional[builtins.int] = ..., + return_nodes: typing.Optional[global___NodeFilter] = ..., + mask: typing.Optional[google.protobuf.field_mask_pb2.FieldMask] = ..., + max_matching_nodes: typing.Optional[builtins.int] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_edges",b"_edges","_mask",b"_mask","_max_depth",b"_max_depth","_max_edges",b"_max_edges","_max_matching_nodes",b"_max_matching_nodes","_min_depth",b"_min_depth","_return_nodes",b"_return_nodes","edges",b"edges","mask",b"mask","max_depth",b"max_depth","max_edges",b"max_edges","max_matching_nodes",b"max_matching_nodes","min_depth",b"min_depth","return_nodes",b"return_nodes"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_edges",b"_edges","_mask",b"_mask","_max_depth",b"_max_depth","_max_edges",b"_max_edges","_max_matching_nodes",b"_max_matching_nodes","_min_depth",b"_min_depth","_return_nodes",b"_return_nodes","direction",b"direction","edges",b"edges","mask",b"mask","max_depth",b"max_depth","max_edges",b"max_edges","max_matching_nodes",b"max_matching_nodes","min_depth",b"min_depth","return_nodes",b"return_nodes","src",b"src"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges", b"_edges"]) -> typing_extensions.Literal["edges"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges",b"_edges"]) -> typing.Optional[typing_extensions.Literal["edges"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask", b"_mask"]) -> typing_extensions.Literal["mask"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask",b"_mask"]) -> typing.Optional[typing_extensions.Literal["mask"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_depth", b"_max_depth"]) -> typing_extensions.Literal["max_depth"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_depth",b"_max_depth"]) -> typing.Optional[typing_extensions.Literal["max_depth"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_edges", b"_max_edges"]) -> typing_extensions.Literal["max_edges"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_edges",b"_max_edges"]) -> typing.Optional[typing_extensions.Literal["max_edges"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_min_depth", b"_min_depth"]) -> typing_extensions.Literal["min_depth"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_matching_nodes",b"_max_matching_nodes"]) -> typing.Optional[typing_extensions.Literal["max_matching_nodes"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_return_nodes", b"_return_nodes"]) -> typing_extensions.Literal["return_nodes"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_min_depth",b"_min_depth"]) -> typing.Optional[typing_extensions.Literal["min_depth"]]: ... + @typing.overload + def WhichOneof(self, oneof_group: typing_extensions.Literal["_return_nodes",b"_return_nodes"]) -> typing.Optional[typing_extensions.Literal["return_nodes"]]: ... global___TraversalRequest = TraversalRequest class FindPathToRequest(google.protobuf.message.Message): @@ -145,9 +154,7 @@ set of nodes and a given target criteria, as well as what should be returned in the path. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor - SRC_FIELD_NUMBER: builtins.int TARGET_FIELD_NUMBER: builtins.int DIRECTION_FIELD_NUMBER: builtins.int @@ -156,52 +163,57 @@ MAX_DEPTH_FIELD_NUMBER: builtins.int MASK_FIELD_NUMBER: builtins.int @property - def src(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + def src(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: """Set of source nodes (SWHIDs)""" + pass @property def target(self) -> global___NodeFilter: """Target criteria, i.e., what constitutes a valid path destination.""" + pass direction: global___GraphDirection.ValueType """Direction of the graph to traverse. Defaults to FORWARD.""" - edges: builtins.str + + edges: typing.Text """Edge restriction string (e.g. "rev:dir,dir:cnt"). Defaults to "*" (all). """ + max_edges: builtins.int """Maximum number of edges accessed in the traversal, after which it stops. Defaults to infinite. """ + max_depth: builtins.int """Maximum depth of the traversal, after which it stops. Defaults to infinite. """ + @property def mask(self) -> google.protobuf.field_mask_pb2.FieldMask: """FieldMask of which fields are to be returned (e.g., "swhid,cnt.length"). By default, all fields are returned. """ - def __init__( - self, + pass + def __init__(self, *, - src: collections.abc.Iterable[builtins.str] | None = ..., - target: global___NodeFilter | None = ..., + src: typing.Optional[typing.Iterable[typing.Text]] = ..., + target: typing.Optional[global___NodeFilter] = ..., direction: global___GraphDirection.ValueType = ..., - edges: builtins.str | None = ..., - max_edges: builtins.int | None = ..., - max_depth: builtins.int | None = ..., - mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_edges", b"_edges", "_mask", b"_mask", "_max_depth", b"_max_depth", "_max_edges", b"_max_edges", "edges", b"edges", "mask", b"mask", "max_depth", b"max_depth", "max_edges", b"max_edges", "target", b"target"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_edges", b"_edges", "_mask", b"_mask", "_max_depth", b"_max_depth", "_max_edges", b"_max_edges", "direction", b"direction", "edges", b"edges", "mask", b"mask", "max_depth", b"max_depth", "max_edges", b"max_edges", "src", b"src", "target", b"target"]) -> None: ... + edges: typing.Optional[typing.Text] = ..., + max_edges: typing.Optional[builtins.int] = ..., + max_depth: typing.Optional[builtins.int] = ..., + mask: typing.Optional[google.protobuf.field_mask_pb2.FieldMask] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_edges",b"_edges","_mask",b"_mask","_max_depth",b"_max_depth","_max_edges",b"_max_edges","edges",b"edges","mask",b"mask","max_depth",b"max_depth","max_edges",b"max_edges","target",b"target"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_edges",b"_edges","_mask",b"_mask","_max_depth",b"_max_depth","_max_edges",b"_max_edges","direction",b"direction","edges",b"edges","mask",b"mask","max_depth",b"max_depth","max_edges",b"max_edges","src",b"src","target",b"target"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges", b"_edges"]) -> typing_extensions.Literal["edges"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges",b"_edges"]) -> typing.Optional[typing_extensions.Literal["edges"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask", b"_mask"]) -> typing_extensions.Literal["mask"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask",b"_mask"]) -> typing.Optional[typing_extensions.Literal["mask"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_depth", b"_max_depth"]) -> typing_extensions.Literal["max_depth"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_depth",b"_max_depth"]) -> typing.Optional[typing_extensions.Literal["max_depth"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_edges", b"_max_edges"]) -> typing_extensions.Literal["max_edges"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_edges",b"_max_edges"]) -> typing.Optional[typing_extensions.Literal["max_edges"]]: ... global___FindPathToRequest = FindPathToRequest class FindPathBetweenRequest(google.protobuf.message.Message): @@ -209,9 +221,7 @@ set of source nodes and a set of destination nodes. It works by performing a bidirectional breadth-first traversal from both sets at the same time. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor - SRC_FIELD_NUMBER: builtins.int DST_FIELD_NUMBER: builtins.int DIRECTION_FIELD_NUMBER: builtins.int @@ -222,26 +232,31 @@ MAX_DEPTH_FIELD_NUMBER: builtins.int MASK_FIELD_NUMBER: builtins.int @property - def src(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + def src(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: """Set of source nodes (SWHIDs)""" + pass @property - def dst(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + def dst(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: """Set of destination nodes (SWHIDs)""" + pass direction: global___GraphDirection.ValueType """Direction of the graph to traverse from the source set. Defaults to FORWARD. """ + direction_reverse: global___GraphDirection.ValueType """Direction of the graph to traverse from the destination set. Defaults to the opposite of `direction`. If direction and direction_reverse are identical, it will find the first common successor of both sets in the given direction. """ - edges: builtins.str + + edges: typing.Text """Edge restriction string for the traversal from the source set. (e.g. "rev:dir,dir:cnt"). Defaults to "*" (all). """ - edges_reverse: builtins.str + + edges_reverse: typing.Text """Edge restriction string for the reverse traversal from the destination set. If not specified: @@ -250,92 +265,91 @@ - If direction != direction_reverse, defaults to the reverse of `edges` (e.g. "rev:dir" becomes "dir:rev"). """ + max_edges: builtins.int """Maximum number of edges accessed in the traversal, after which it stops. Defaults to infinite. """ + max_depth: builtins.int """Maximum depth of the traversal, after which it stops. Defaults to infinite. """ + @property def mask(self) -> google.protobuf.field_mask_pb2.FieldMask: """FieldMask of which fields are to be returned (e.g., "swhid,cnt.length"). By default, all fields are returned. """ - def __init__( - self, + pass + def __init__(self, *, - src: collections.abc.Iterable[builtins.str] | None = ..., - dst: collections.abc.Iterable[builtins.str] | None = ..., + src: typing.Optional[typing.Iterable[typing.Text]] = ..., + dst: typing.Optional[typing.Iterable[typing.Text]] = ..., direction: global___GraphDirection.ValueType = ..., - direction_reverse: global___GraphDirection.ValueType | None = ..., - edges: builtins.str | None = ..., - edges_reverse: builtins.str | None = ..., - max_edges: builtins.int | None = ..., - max_depth: builtins.int | None = ..., - mask: google.protobuf.field_mask_pb2.FieldMask | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_direction_reverse", b"_direction_reverse", "_edges", b"_edges", "_edges_reverse", b"_edges_reverse", "_mask", b"_mask", "_max_depth", b"_max_depth", "_max_edges", b"_max_edges", "direction_reverse", b"direction_reverse", "edges", b"edges", "edges_reverse", b"edges_reverse", "mask", b"mask", "max_depth", b"max_depth", "max_edges", b"max_edges"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_direction_reverse", b"_direction_reverse", "_edges", b"_edges", "_edges_reverse", b"_edges_reverse", "_mask", b"_mask", "_max_depth", b"_max_depth", "_max_edges", b"_max_edges", "direction", b"direction", "direction_reverse", b"direction_reverse", "dst", b"dst", "edges", b"edges", "edges_reverse", b"edges_reverse", "mask", b"mask", "max_depth", b"max_depth", "max_edges", b"max_edges", "src", b"src"]) -> None: ... + direction_reverse: typing.Optional[global___GraphDirection.ValueType] = ..., + edges: typing.Optional[typing.Text] = ..., + edges_reverse: typing.Optional[typing.Text] = ..., + max_edges: typing.Optional[builtins.int] = ..., + max_depth: typing.Optional[builtins.int] = ..., + mask: typing.Optional[google.protobuf.field_mask_pb2.FieldMask] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_direction_reverse",b"_direction_reverse","_edges",b"_edges","_edges_reverse",b"_edges_reverse","_mask",b"_mask","_max_depth",b"_max_depth","_max_edges",b"_max_edges","direction_reverse",b"direction_reverse","edges",b"edges","edges_reverse",b"edges_reverse","mask",b"mask","max_depth",b"max_depth","max_edges",b"max_edges"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_direction_reverse",b"_direction_reverse","_edges",b"_edges","_edges_reverse",b"_edges_reverse","_mask",b"_mask","_max_depth",b"_max_depth","_max_edges",b"_max_edges","direction",b"direction","direction_reverse",b"direction_reverse","dst",b"dst","edges",b"edges","edges_reverse",b"edges_reverse","mask",b"mask","max_depth",b"max_depth","max_edges",b"max_edges","src",b"src"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_direction_reverse", b"_direction_reverse"]) -> typing_extensions.Literal["direction_reverse"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_direction_reverse",b"_direction_reverse"]) -> typing.Optional[typing_extensions.Literal["direction_reverse"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges", b"_edges"]) -> typing_extensions.Literal["edges"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges",b"_edges"]) -> typing.Optional[typing_extensions.Literal["edges"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges_reverse", b"_edges_reverse"]) -> typing_extensions.Literal["edges_reverse"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_edges_reverse",b"_edges_reverse"]) -> typing.Optional[typing_extensions.Literal["edges_reverse"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask", b"_mask"]) -> typing_extensions.Literal["mask"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_mask",b"_mask"]) -> typing.Optional[typing_extensions.Literal["mask"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_depth", b"_max_depth"]) -> typing_extensions.Literal["max_depth"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_depth",b"_max_depth"]) -> typing.Optional[typing_extensions.Literal["max_depth"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_edges", b"_max_edges"]) -> typing_extensions.Literal["max_edges"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_edges",b"_max_edges"]) -> typing.Optional[typing_extensions.Literal["max_edges"]]: ... global___FindPathBetweenRequest = FindPathBetweenRequest class NodeFilter(google.protobuf.message.Message): """Represents various criteria that make a given node "valid". A node is only valid if all the subcriteria present in this message are fulfilled. """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor - TYPES_FIELD_NUMBER: builtins.int MIN_TRAVERSAL_SUCCESSORS_FIELD_NUMBER: builtins.int MAX_TRAVERSAL_SUCCESSORS_FIELD_NUMBER: builtins.int - types: builtins.str + types: typing.Text """Node restriction string. (e.g. "dir,cnt,rev"). Defaults to "*" (all).""" + min_traversal_successors: builtins.int """Minimum number of successors encountered *during the traversal*. Default: no constraint """ + max_traversal_successors: builtins.int """Maximum number of successors encountered *during the traversal*. Default: no constraint """ - def __init__( - self, + + def __init__(self, *, - types: builtins.str | None = ..., - min_traversal_successors: builtins.int | None = ..., - max_traversal_successors: builtins.int | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_max_traversal_successors", b"_max_traversal_successors", "_min_traversal_successors", b"_min_traversal_successors", "_types", b"_types", "max_traversal_successors", b"max_traversal_successors", "min_traversal_successors", b"min_traversal_successors", "types", b"types"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_max_traversal_successors", b"_max_traversal_successors", "_min_traversal_successors", b"_min_traversal_successors", "_types", b"_types", "max_traversal_successors", b"max_traversal_successors", "min_traversal_successors", b"min_traversal_successors", "types", b"types"]) -> None: ... + types: typing.Optional[typing.Text] = ..., + min_traversal_successors: typing.Optional[builtins.int] = ..., + max_traversal_successors: typing.Optional[builtins.int] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_max_traversal_successors",b"_max_traversal_successors","_min_traversal_successors",b"_min_traversal_successors","_types",b"_types","max_traversal_successors",b"max_traversal_successors","min_traversal_successors",b"min_traversal_successors","types",b"types"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_max_traversal_successors",b"_max_traversal_successors","_min_traversal_successors",b"_min_traversal_successors","_types",b"_types","max_traversal_successors",b"max_traversal_successors","min_traversal_successors",b"min_traversal_successors","types",b"types"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_traversal_successors", b"_max_traversal_successors"]) -> typing_extensions.Literal["max_traversal_successors"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_max_traversal_successors",b"_max_traversal_successors"]) -> typing.Optional[typing_extensions.Literal["max_traversal_successors"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_min_traversal_successors", b"_min_traversal_successors"]) -> typing_extensions.Literal["min_traversal_successors"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_min_traversal_successors",b"_min_traversal_successors"]) -> typing.Optional[typing_extensions.Literal["min_traversal_successors"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_types", b"_types"]) -> typing_extensions.Literal["types"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_types",b"_types"]) -> typing.Optional[typing_extensions.Literal["types"]]: ... global___NodeFilter = NodeFilter class Node(google.protobuf.message.Message): """Represents a node in the graph.""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - SWHID_FIELD_NUMBER: builtins.int SUCCESSOR_FIELD_NUMBER: builtins.int NUM_SUCCESSORS_FIELD_NUMBER: builtins.int @@ -343,13 +357,16 @@ REV_FIELD_NUMBER: builtins.int REL_FIELD_NUMBER: builtins.int ORI_FIELD_NUMBER: builtins.int - swhid: builtins.str + swhid: typing.Text """The SWHID of the graph node.""" + @property def successor(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Successor]: """List of relevant successors of this node.""" + pass num_successors: builtins.int """Number of relevant successors.""" + @property def cnt(self) -> global___ContentData: ... @property @@ -358,36 +375,33 @@ def rel(self) -> global___ReleaseData: ... @property def ori(self) -> global___OriginData: ... - def __init__( - self, + def __init__(self, *, - swhid: builtins.str = ..., - successor: collections.abc.Iterable[global___Successor] | None = ..., - num_successors: builtins.int | None = ..., - cnt: global___ContentData | None = ..., - rev: global___RevisionData | None = ..., - rel: global___ReleaseData | None = ..., - ori: global___OriginData | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_num_successors", b"_num_successors", "cnt", b"cnt", "data", b"data", "num_successors", b"num_successors", "ori", b"ori", "rel", b"rel", "rev", b"rev"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_num_successors", b"_num_successors", "cnt", b"cnt", "data", b"data", "num_successors", b"num_successors", "ori", b"ori", "rel", b"rel", "rev", b"rev", "successor", b"successor", "swhid", b"swhid"]) -> None: ... - @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_num_successors", b"_num_successors"]) -> typing_extensions.Literal["num_successors"] | None: ... - @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["data", b"data"]) -> typing_extensions.Literal["cnt", "rev", "rel", "ori"] | None: ... - + swhid: typing.Text = ..., + successor: typing.Optional[typing.Iterable[global___Successor]] = ..., + num_successors: typing.Optional[builtins.int] = ..., + cnt: typing.Optional[global___ContentData] = ..., + rev: typing.Optional[global___RevisionData] = ..., + rel: typing.Optional[global___ReleaseData] = ..., + ori: typing.Optional[global___OriginData] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_num_successors",b"_num_successors","cnt",b"cnt","data",b"data","num_successors",b"num_successors","ori",b"ori","rel",b"rel","rev",b"rev"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_num_successors",b"_num_successors","cnt",b"cnt","data",b"data","num_successors",b"num_successors","ori",b"ori","rel",b"rel","rev",b"rev","successor",b"successor","swhid",b"swhid"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing_extensions.Literal["_num_successors",b"_num_successors"]) -> typing.Optional[typing_extensions.Literal["num_successors"]]: ... + @typing.overload + def WhichOneof(self, oneof_group: typing_extensions.Literal["data",b"data"]) -> typing.Optional[typing_extensions.Literal["cnt","rev","rel","ori"]]: ... global___Node = Node class Path(google.protobuf.message.Message): """Represents a path in the graph.""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - NODE_FIELD_NUMBER: builtins.int MIDPOINT_INDEX_FIELD_NUMBER: builtins.int @property def node(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Node]: """List of nodes in the path, from source to destination""" + pass midpoint_index: builtins.int """Index of the "midpoint" of the path. For paths obtained with bidirectional search queries, this is the node that joined the two @@ -395,73 +409,66 @@ performing a FindPathBetween search with two backward graphs, this will be the index of the common ancestor in the path. """ - def __init__( - self, - *, - node: collections.abc.Iterable[global___Node] | None = ..., - midpoint_index: builtins.int | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_midpoint_index", b"_midpoint_index", "midpoint_index", b"midpoint_index"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_midpoint_index", b"_midpoint_index", "midpoint_index", b"midpoint_index", "node", b"node"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["_midpoint_index", b"_midpoint_index"]) -> typing_extensions.Literal["midpoint_index"] | None: ... + def __init__(self, + *, + node: typing.Optional[typing.Iterable[global___Node]] = ..., + midpoint_index: typing.Optional[builtins.int] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_midpoint_index",b"_midpoint_index","midpoint_index",b"midpoint_index"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_midpoint_index",b"_midpoint_index","midpoint_index",b"midpoint_index","node",b"node"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_midpoint_index",b"_midpoint_index"]) -> typing.Optional[typing_extensions.Literal["midpoint_index"]]: ... global___Path = Path class Successor(google.protobuf.message.Message): """Represents a successor of a given node.""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - SWHID_FIELD_NUMBER: builtins.int LABEL_FIELD_NUMBER: builtins.int - swhid: builtins.str + swhid: typing.Text """The SWHID of the successor""" + @property def label(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___EdgeLabel]: """A list of edge labels for the given edge""" - def __init__( - self, + pass + def __init__(self, *, - swhid: builtins.str | None = ..., - label: collections.abc.Iterable[global___EdgeLabel] | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_swhid", b"_swhid", "swhid", b"swhid"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_swhid", b"_swhid", "label", b"label", "swhid", b"swhid"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["_swhid", b"_swhid"]) -> typing_extensions.Literal["swhid"] | None: ... - + swhid: typing.Optional[typing.Text] = ..., + label: typing.Optional[typing.Iterable[global___EdgeLabel]] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_swhid",b"_swhid","swhid",b"swhid"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_swhid",b"_swhid","label",b"label","swhid",b"swhid"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_swhid",b"_swhid"]) -> typing.Optional[typing_extensions.Literal["swhid"]]: ... global___Successor = Successor class ContentData(google.protobuf.message.Message): """Content node properties""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - LENGTH_FIELD_NUMBER: builtins.int IS_SKIPPED_FIELD_NUMBER: builtins.int length: builtins.int """Length of the blob, in bytes""" + is_skipped: builtins.bool """Whether the content was skipped during ingestion.""" - def __init__( - self, + + def __init__(self, *, - length: builtins.int | None = ..., - is_skipped: builtins.bool | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_is_skipped", b"_is_skipped", "_length", b"_length", "is_skipped", b"is_skipped", "length", b"length"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_is_skipped", b"_is_skipped", "_length", b"_length", "is_skipped", b"is_skipped", "length", b"length"]) -> None: ... + length: typing.Optional[builtins.int] = ..., + is_skipped: typing.Optional[builtins.bool] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_is_skipped",b"_is_skipped","_length",b"_length","is_skipped",b"is_skipped","length",b"length"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_is_skipped",b"_is_skipped","_length",b"_length","is_skipped",b"is_skipped","length",b"length"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_is_skipped", b"_is_skipped"]) -> typing_extensions.Literal["is_skipped"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_is_skipped",b"_is_skipped"]) -> typing.Optional[typing_extensions.Literal["is_skipped"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_length", b"_length"]) -> typing_extensions.Literal["length"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_length",b"_length"]) -> typing.Optional[typing_extensions.Literal["length"]]: ... global___ContentData = ContentData class RevisionData(google.protobuf.message.Message): """Revision node properties""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - AUTHOR_FIELD_NUMBER: builtins.int AUTHOR_DATE_FIELD_NUMBER: builtins.int AUTHOR_DATE_OFFSET_FIELD_NUMBER: builtins.int @@ -471,53 +478,56 @@ MESSAGE_FIELD_NUMBER: builtins.int author: builtins.int """Revision author ID (anonymized)""" + author_date: builtins.int """UNIX timestamp of the revision date (UTC)""" + author_date_offset: builtins.int """Timezone of the revision author date as an offset from UTC""" + committer: builtins.int """Revision committer ID (anonymized)""" + committer_date: builtins.int """UNIX timestamp of the revision committer date (UTC)""" + committer_date_offset: builtins.int """Timezone of the revision committer date as an offset from UTC""" + message: builtins.bytes """Revision message""" - def __init__( - self, + + def __init__(self, *, - author: builtins.int | None = ..., - author_date: builtins.int | None = ..., - author_date_offset: builtins.int | None = ..., - committer: builtins.int | None = ..., - committer_date: builtins.int | None = ..., - committer_date_offset: builtins.int | None = ..., - message: builtins.bytes | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_author", b"_author", "_author_date", b"_author_date", "_author_date_offset", b"_author_date_offset", "_committer", b"_committer", "_committer_date", b"_committer_date", "_committer_date_offset", b"_committer_date_offset", "_message", b"_message", "author", b"author", "author_date", b"author_date", "author_date_offset", b"author_date_offset", "committer", b"committer", "committer_date", b"committer_date", "committer_date_offset", b"committer_date_offset", "message", b"message"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_author", b"_author", "_author_date", b"_author_date", "_author_date_offset", b"_author_date_offset", "_committer", b"_committer", "_committer_date", b"_committer_date", "_committer_date_offset", b"_committer_date_offset", "_message", b"_message", "author", b"author", "author_date", b"author_date", "author_date_offset", b"author_date_offset", "committer", b"committer", "committer_date", b"committer_date", "committer_date_offset", b"committer_date_offset", "message", b"message"]) -> None: ... + author: typing.Optional[builtins.int] = ..., + author_date: typing.Optional[builtins.int] = ..., + author_date_offset: typing.Optional[builtins.int] = ..., + committer: typing.Optional[builtins.int] = ..., + committer_date: typing.Optional[builtins.int] = ..., + committer_date_offset: typing.Optional[builtins.int] = ..., + message: typing.Optional[builtins.bytes] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_author",b"_author","_author_date",b"_author_date","_author_date_offset",b"_author_date_offset","_committer",b"_committer","_committer_date",b"_committer_date","_committer_date_offset",b"_committer_date_offset","_message",b"_message","author",b"author","author_date",b"author_date","author_date_offset",b"author_date_offset","committer",b"committer","committer_date",b"committer_date","committer_date_offset",b"committer_date_offset","message",b"message"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_author",b"_author","_author_date",b"_author_date","_author_date_offset",b"_author_date_offset","_committer",b"_committer","_committer_date",b"_committer_date","_committer_date_offset",b"_committer_date_offset","_message",b"_message","author",b"author","author_date",b"author_date","author_date_offset",b"author_date_offset","committer",b"committer","committer_date",b"committer_date","committer_date_offset",b"committer_date_offset","message",b"message"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_author", b"_author"]) -> typing_extensions.Literal["author"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_author",b"_author"]) -> typing.Optional[typing_extensions.Literal["author"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date", b"_author_date"]) -> typing_extensions.Literal["author_date"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date",b"_author_date"]) -> typing.Optional[typing_extensions.Literal["author_date"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date_offset", b"_author_date_offset"]) -> typing_extensions.Literal["author_date_offset"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date_offset",b"_author_date_offset"]) -> typing.Optional[typing_extensions.Literal["author_date_offset"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_committer", b"_committer"]) -> typing_extensions.Literal["committer"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_committer",b"_committer"]) -> typing.Optional[typing_extensions.Literal["committer"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_committer_date", b"_committer_date"]) -> typing_extensions.Literal["committer_date"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_committer_date",b"_committer_date"]) -> typing.Optional[typing_extensions.Literal["committer_date"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_committer_date_offset", b"_committer_date_offset"]) -> typing_extensions.Literal["committer_date_offset"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_committer_date_offset",b"_committer_date_offset"]) -> typing.Optional[typing_extensions.Literal["committer_date_offset"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_message", b"_message"]) -> typing_extensions.Literal["message"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_message",b"_message"]) -> typing.Optional[typing_extensions.Literal["message"]]: ... global___RevisionData = RevisionData class ReleaseData(google.protobuf.message.Message): """Release node properties""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - AUTHOR_FIELD_NUMBER: builtins.int AUTHOR_DATE_FIELD_NUMBER: builtins.int AUTHOR_DATE_OFFSET_FIELD_NUMBER: builtins.int @@ -525,102 +535,94 @@ MESSAGE_FIELD_NUMBER: builtins.int author: builtins.int """Release author ID (anonymized)""" + author_date: builtins.int """UNIX timestamp of the release date (UTC)""" + author_date_offset: builtins.int """Timezone of the release author date as an offset from UTC""" + name: builtins.bytes """Release name""" + message: builtins.bytes """Release message""" - def __init__( - self, + + def __init__(self, *, - author: builtins.int | None = ..., - author_date: builtins.int | None = ..., - author_date_offset: builtins.int | None = ..., - name: builtins.bytes | None = ..., - message: builtins.bytes | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_author", b"_author", "_author_date", b"_author_date", "_author_date_offset", b"_author_date_offset", "_message", b"_message", "_name", b"_name", "author", b"author", "author_date", b"author_date", "author_date_offset", b"author_date_offset", "message", b"message", "name", b"name"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_author", b"_author", "_author_date", b"_author_date", "_author_date_offset", b"_author_date_offset", "_message", b"_message", "_name", b"_name", "author", b"author", "author_date", b"author_date", "author_date_offset", b"author_date_offset", "message", b"message", "name", b"name"]) -> None: ... + author: typing.Optional[builtins.int] = ..., + author_date: typing.Optional[builtins.int] = ..., + author_date_offset: typing.Optional[builtins.int] = ..., + name: typing.Optional[builtins.bytes] = ..., + message: typing.Optional[builtins.bytes] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_author",b"_author","_author_date",b"_author_date","_author_date_offset",b"_author_date_offset","_message",b"_message","_name",b"_name","author",b"author","author_date",b"author_date","author_date_offset",b"author_date_offset","message",b"message","name",b"name"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_author",b"_author","_author_date",b"_author_date","_author_date_offset",b"_author_date_offset","_message",b"_message","_name",b"_name","author",b"author","author_date",b"author_date","author_date_offset",b"author_date_offset","message",b"message","name",b"name"]) -> None: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_author", b"_author"]) -> typing_extensions.Literal["author"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_author",b"_author"]) -> typing.Optional[typing_extensions.Literal["author"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date", b"_author_date"]) -> typing_extensions.Literal["author_date"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date",b"_author_date"]) -> typing.Optional[typing_extensions.Literal["author_date"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date_offset", b"_author_date_offset"]) -> typing_extensions.Literal["author_date_offset"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_author_date_offset",b"_author_date_offset"]) -> typing.Optional[typing_extensions.Literal["author_date_offset"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_message", b"_message"]) -> typing_extensions.Literal["message"] | None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_message",b"_message"]) -> typing.Optional[typing_extensions.Literal["message"]]: ... @typing.overload - def WhichOneof(self, oneof_group: typing_extensions.Literal["_name", b"_name"]) -> typing_extensions.Literal["name"] | None: ... - + def WhichOneof(self, oneof_group: typing_extensions.Literal["_name",b"_name"]) -> typing.Optional[typing_extensions.Literal["name"]]: ... global___ReleaseData = ReleaseData class OriginData(google.protobuf.message.Message): """Origin node properties""" - DESCRIPTOR: google.protobuf.descriptor.Descriptor - URL_FIELD_NUMBER: builtins.int - url: builtins.str + url: typing.Text """URL of the origin""" - def __init__( - self, - *, - url: builtins.str | None = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_url", b"_url", "url", b"url"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_url", b"_url", "url", b"url"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["_url", b"_url"]) -> typing_extensions.Literal["url"] | None: ... + def __init__(self, + *, + url: typing.Optional[typing.Text] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_url",b"_url","url",b"url"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_url",b"_url","url",b"url"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_url",b"_url"]) -> typing.Optional[typing_extensions.Literal["url"]]: ... global___OriginData = OriginData class EdgeLabel(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - NAME_FIELD_NUMBER: builtins.int PERMISSION_FIELD_NUMBER: builtins.int name: builtins.bytes """Directory entry name for directories, branch name for snapshots""" + permission: builtins.int """Entry permission (only set for directories).""" - def __init__( - self, + + def __init__(self, *, name: builtins.bytes = ..., permission: builtins.int = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["name", b"name", "permission", b"permission"]) -> None: ... - + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["name",b"name","permission",b"permission"]) -> None: ... global___EdgeLabel = EdgeLabel class CountResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - COUNT_FIELD_NUMBER: builtins.int count: builtins.int - def __init__( - self, + def __init__(self, *, count: builtins.int = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["count", b"count"]) -> None: ... - + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["count",b"count"]) -> None: ... global___CountResponse = CountResponse class StatsRequest(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - - def __init__( - self, - ) -> None: ... - + def __init__(self, + ) -> None: ... global___StatsRequest = StatsRequest class StatsResponse(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - NUM_NODES_FIELD_NUMBER: builtins.int NUM_EDGES_FIELD_NUMBER: builtins.int COMPRESSION_RATIO_FIELD_NUMBER: builtins.int @@ -635,35 +637,45 @@ OUTDEGREE_AVG_FIELD_NUMBER: builtins.int num_nodes: builtins.int """Number of nodes in the graph""" + num_edges: builtins.int """Number of edges in the graph""" + compression_ratio: builtins.float """Ratio between the graph size and the information-theoretical lower bound """ + bits_per_node: builtins.float """Number of bits per node (overall graph size in bits divided by the number of nodes) """ + bits_per_edge: builtins.float """Number of bits per edge (overall graph size in bits divided by the number of arcs). """ + avg_locality: builtins.float indegree_min: builtins.int """Smallest indegree""" + indegree_max: builtins.int """Largest indegree""" + indegree_avg: builtins.float """Average indegree""" + outdegree_min: builtins.int """Smallest outdegree""" + outdegree_max: builtins.int """Largest outdegree""" + outdegree_avg: builtins.float """Average outdegree""" - def __init__( - self, + + def __init__(self, *, num_nodes: builtins.int = ..., num_edges: builtins.int = ..., @@ -677,7 +689,6 @@ outdegree_min: builtins.int = ..., outdegree_max: builtins.int = ..., outdegree_avg: builtins.float = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["avg_locality", b"avg_locality", "bits_per_edge", b"bits_per_edge", "bits_per_node", b"bits_per_node", "compression_ratio", b"compression_ratio", "indegree_avg", b"indegree_avg", "indegree_max", b"indegree_max", "indegree_min", b"indegree_min", "num_edges", b"num_edges", "num_nodes", b"num_nodes", "outdegree_avg", b"outdegree_avg", "outdegree_max", b"outdegree_max", "outdegree_min", b"outdegree_min"]) -> None: ... - + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["avg_locality",b"avg_locality","bits_per_edge",b"bits_per_edge","bits_per_node",b"bits_per_node","compression_ratio",b"compression_ratio","indegree_avg",b"indegree_avg","indegree_max",b"indegree_max","indegree_min",b"indegree_min","num_edges",b"num_edges","num_nodes",b"num_nodes","outdegree_avg",b"outdegree_avg","outdegree_max",b"outdegree_max","outdegree_min",b"outdegree_min"]) -> None: ... global___StatsResponse = StatsResponse