Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/networkx/readwrite/json_graph/node_link.py: 18%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

44 statements  

1import warnings 

2from itertools import count 

3 

4import networkx as nx 

5 

6__all__ = ["node_link_data", "node_link_graph"] 

7 

8 

9def _to_tuple(x): 

10 """Converts lists to tuples, including nested lists. 

11 

12 All other non-list inputs are passed through unmodified. This function is 

13 intended to be used to convert potentially nested lists from json files 

14 into valid nodes. 

15 

16 Examples 

17 -------- 

18 >>> _to_tuple([1, 2, [3, 4]]) 

19 (1, 2, (3, 4)) 

20 """ 

21 if not isinstance(x, tuple | list): 

22 return x 

23 return tuple(map(_to_tuple, x)) 

24 

25 

26def node_link_data( 

27 G, 

28 *, 

29 source="source", 

30 target="target", 

31 name="id", 

32 key="key", 

33 edges="edges", 

34 nodes="nodes", 

35): 

36 """Returns data in node-link format that is suitable for JSON serialization 

37 and use in JavaScript documents. 

38 

39 Parameters 

40 ---------- 

41 G : NetworkX graph 

42 source : string 

43 A string that provides the 'source' attribute name for storing NetworkX-internal graph data. 

44 target : string 

45 A string that provides the 'target' attribute name for storing NetworkX-internal graph data. 

46 name : string 

47 A string that provides the 'name' attribute name for storing NetworkX-internal graph data. 

48 key : string 

49 A string that provides the 'key' attribute name for storing NetworkX-internal graph data. 

50 edges : string 

51 A string that provides the 'edges' attribute name for storing NetworkX-internal graph data. 

52 nodes : string 

53 A string that provides the 'nodes' attribute name for storing NetworkX-internal graph data. 

54 

55 Returns 

56 ------- 

57 data : dict 

58 A dictionary with node-link formatted data. 

59 

60 Raises 

61 ------ 

62 NetworkXError 

63 If the values of 'source', 'target' and 'key' are not unique. 

64 

65 Examples 

66 -------- 

67 >>> from pprint import pprint 

68 >>> G = nx.Graph([("A", "B")]) 

69 >>> data1 = nx.node_link_data(G) 

70 >>> pprint(data1) 

71 {'directed': False, 

72 'edges': [{'source': 'A', 'target': 'B'}], 

73 'graph': {}, 

74 'multigraph': False, 

75 'nodes': [{'id': 'A'}, {'id': 'B'}]} 

76 

77 To serialize with JSON 

78 

79 >>> import json 

80 >>> s1 = json.dumps(data1) 

81 >>> pprint(s1) 

82 ('{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"id": "A"}, ' 

83 '{"id": "B"}], "edges": [{"source": "A", "target": "B"}]}') 

84 

85 

86 A graph can also be serialized by passing `node_link_data` as an encoder function. 

87 

88 >>> s1 = json.dumps(G, default=nx.node_link_data) 

89 >>> pprint(s1) 

90 ('{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"id": "A"}, ' 

91 '{"id": "B"}], "edges": [{"source": "A", "target": "B"}]}') 

92 

93 The attribute names for storing NetworkX-internal graph data can 

94 be specified as keyword options. 

95 

96 >>> H = nx.gn_graph(2) 

97 >>> data2 = nx.node_link_data( 

98 ... H, edges="links", source="from", target="to", nodes="vertices" 

99 ... ) 

100 >>> pprint(data2) 

101 {'directed': True, 

102 'graph': {}, 

103 'links': [{'from': 1, 'to': 0}], 

104 'multigraph': False, 

105 'vertices': [{'id': 0}, {'id': 1}]} 

106 

107 Notes 

108 ----- 

109 Graph, node, and edge attributes are stored in this format. Note that 

110 attribute keys will be converted to strings in order to comply with JSON. 

111 

112 Attribute 'key' is only used for multigraphs. 

113 

114 To use `node_link_data` in conjunction with `node_link_graph`, 

115 the keyword names for the attributes must match. 

116 

117 See Also 

118 -------- 

119 node_link_graph, adjacency_data, tree_data 

120 """ 

121 multigraph = G.is_multigraph() 

122 

123 # Allow 'key' to be omitted from attrs if the graph is not a multigraph. 

124 key = None if not multigraph else key 

125 if len({source, target, key}) < 3: 

126 raise nx.NetworkXError("Attribute names are not unique.") 

127 data = { 

128 "directed": G.is_directed(), 

129 "multigraph": multigraph, 

130 "graph": G.graph, 

131 nodes: [{**G.nodes[n], name: n} for n in G], 

132 } 

133 if multigraph: 

134 data[edges] = [ 

135 {**d, source: u, target: v, key: k} 

136 for u, v, k, d in G.edges(keys=True, data=True) 

137 ] 

138 else: 

139 data[edges] = [{**d, source: u, target: v} for u, v, d in G.edges(data=True)] 

140 return data 

141 

142 

143@nx._dispatchable(graphs=None, returns_graph=True) 

144def node_link_graph( 

145 data, 

146 directed=False, 

147 multigraph=True, 

148 *, 

149 source="source", 

150 target="target", 

151 name="id", 

152 key="key", 

153 edges="edges", 

154 nodes="nodes", 

155): 

156 """Returns graph from node-link data format. 

157 

158 Useful for de-serialization from JSON. 

159 

160 Parameters 

161 ---------- 

162 data : dict 

163 node-link formatted graph data 

164 

165 directed : bool 

166 If True, and direction not specified in data, return a directed graph. 

167 

168 multigraph : bool 

169 If True, and multigraph not specified in data, return a multigraph. 

170 

171 source : string 

172 A string that provides the 'source' attribute name for storing NetworkX-internal graph data. 

173 target : string 

174 A string that provides the 'target' attribute name for storing NetworkX-internal graph data. 

175 name : string 

176 A string that provides the 'name' attribute name for storing NetworkX-internal graph data. 

177 key : string 

178 A string that provides the 'key' attribute name for storing NetworkX-internal graph data. 

179 edges : string 

180 A string that provides the 'edges' attribute name for storing NetworkX-internal graph data. 

181 nodes : string 

182 A string that provides the 'nodes' attribute name for storing NetworkX-internal graph data. 

183 

184 Returns 

185 ------- 

186 G : NetworkX graph 

187 A NetworkX graph object 

188 

189 Examples 

190 -------- 

191 

192 Create data in node-link format by converting a graph. 

193 

194 >>> from pprint import pprint 

195 >>> G = nx.Graph([("A", "B")]) 

196 >>> data = nx.node_link_data(G) 

197 >>> pprint(data) 

198 {'directed': False, 

199 'edges': [{'source': 'A', 'target': 'B'}], 

200 'graph': {}, 

201 'multigraph': False, 

202 'nodes': [{'id': 'A'}, {'id': 'B'}]} 

203 

204 Revert data in node-link format to a graph. 

205 

206 >>> H = nx.node_link_graph(data) 

207 >>> print(H.edges) 

208 [('A', 'B')] 

209 

210 To serialize and deserialize a graph with JSON, 

211 

212 >>> import json 

213 >>> d = json.dumps(nx.node_link_data(G)) 

214 >>> H = nx.node_link_graph(json.loads(d)) 

215 >>> print(G.edges, H.edges) 

216 [('A', 'B')] [('A', 'B')] 

217 

218 

219 Notes 

220 ----- 

221 Attribute 'key' is only used for multigraphs. 

222 

223 To use `node_link_data` in conjunction with `node_link_graph`, 

224 the keyword names for the attributes must match. 

225 

226 See Also 

227 -------- 

228 node_link_data, adjacency_data, tree_data 

229 """ 

230 multigraph = data.get("multigraph", multigraph) 

231 directed = data.get("directed", directed) 

232 if multigraph: 

233 graph = nx.MultiGraph() 

234 else: 

235 graph = nx.Graph() 

236 if directed: 

237 graph = graph.to_directed() 

238 

239 # Allow 'key' to be omitted from attrs if the graph is not a multigraph. 

240 key = None if not multigraph else key 

241 graph.graph = data.get("graph", {}) 

242 c = count() 

243 for d in data[nodes]: 

244 node = _to_tuple(d.get(name, next(c))) 

245 nodedata = {str(k): v for k, v in d.items() if k != name} 

246 graph.add_node(node, **nodedata) 

247 for d in data[edges]: 

248 src = tuple(d[source]) if isinstance(d[source], list) else d[source] 

249 tgt = tuple(d[target]) if isinstance(d[target], list) else d[target] 

250 if not multigraph: 

251 edgedata = {str(k): v for k, v in d.items() if k != source and k != target} 

252 graph.add_edge(src, tgt, **edgedata) 

253 else: 

254 ky = d.get(key, None) 

255 edgedata = { 

256 str(k): v 

257 for k, v in d.items() 

258 if k != source and k != target and k != key 

259 } 

260 graph.add_edge(src, tgt, ky, **edgedata) 

261 return graph