okstra 0.114.0 → 0.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/kr/architecture.md +2 -2
- package/docs/kr/follow-ups/2026-07-10-final-report-option-3.md +51 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/report-writer-worker.md +1 -0
- package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
- package/runtime/python/okstra_ctl/implementation_stage.py +46 -39
- package/runtime/python/okstra_ctl/report_views.py +151 -12
- package/runtime/python/okstra_ctl/run.py +24 -24
- package/runtime/python/okstra_ctl/worktree.py +1 -1
- package/runtime/python/okstra_token_usage/claude.py +58 -19
- package/runtime/python/okstra_token_usage/collect.py +3 -1
- package/runtime/python/okstra_vendor/__init__.py +3 -0
- package/runtime/schemas/final-report-v1.0.schema.json +20 -0
- package/runtime/templates/reports/final-report.template.md +14 -0
- package/runtime/templates/reports/i18n/en.json +23 -12
- package/runtime/templates/reports/i18n/ko.json +23 -12
- package/runtime/templates/reports/report.css +55 -0
- package/runtime/templates/reports/report.js +53 -1
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_approx_clust_coeff.py +0 -41
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_clique.py +0 -112
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_connectivity.py +0 -199
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_density.py +0 -146
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_distance_measures.py +0 -59
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_dominating_set.py +0 -78
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_kcomponents.py +0 -303
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_matching.py +0 -8
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_maxcut.py +0 -94
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_ramsey.py +0 -31
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_steinertree.py +0 -306
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_traveling_salesman.py +0 -1014
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_treewidth.py +0 -274
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_vertex_cover.py +0 -68
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/base_test.py +0 -81
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_connectivity.py +0 -143
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_correlation.py +0 -122
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_mixing.py +0 -174
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_neighbor_degree.py +0 -107
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_pairs.py +0 -87
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_basic.py +0 -125
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_centrality.py +0 -192
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_cluster.py +0 -84
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_covering.py +0 -33
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_edgelist.py +0 -240
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_extendability.py +0 -334
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_generators.py +0 -407
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_link_analysis.py +0 -218
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matching.py +0 -327
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matrix.py +0 -138
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_project.py +0 -409
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_redundancy.py +0 -35
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_spectral_bipartivity.py +0 -80
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality.py +0 -923
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality_subset.py +0 -354
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_closeness_centrality.py +0 -274
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality.py +0 -259
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality_subset.py +0 -147
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_closeness.py +0 -43
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_degree_centrality.py +0 -144
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_dispersion.py +0 -73
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py +0 -186
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_group.py +0 -277
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_harmonic_centrality.py +0 -122
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_katz_centrality.py +0 -345
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_laplacian_centrality.py +0 -220
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_load_centrality.py +0 -344
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_percolation_centrality.py +0 -87
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_reaching.py +0 -140
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_second_order_centrality.py +0 -82
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_subgraph.py +0 -110
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_trophic.py +0 -302
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_voterank.py +0 -64
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/test_coloring.py +0 -863
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_asyn_fluid.py +0 -147
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_bipartitions.py +0 -157
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_centrality.py +0 -85
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_divisive.py +0 -106
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_kclique.py +0 -91
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_label_propagation.py +0 -241
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_leiden.py +0 -138
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_local.py +0 -76
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_louvain.py +0 -264
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_lukes.py +0 -152
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_modularity_max.py +0 -340
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_quality.py +0 -139
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_utils.py +0 -26
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_attracting.py +0 -70
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_biconnected.py +0 -248
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_connected.py +0 -138
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_semiconnected.py +0 -55
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_strongly_connected.py +0 -193
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_weakly_connected.py +0 -96
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_connectivity.py +0 -421
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_cuts.py +0 -309
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_disjoint_paths.py +0 -249
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_augmentation.py +0 -502
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py +0 -488
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcomponents.py +0 -323
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcutsets.py +0 -280
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_stoer_wagner.py +0 -102
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gl1.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gw1.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/netgen-2.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_gomory_hu.py +0 -128
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow.py +0 -573
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow_large_graph.py +0 -155
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_mincost.py +0 -475
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_networksimplex.py +0 -481
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/wlm3.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.A99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.B99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.A99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.B99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_ismags.py +0 -719
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphism.py +0 -103
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py +0 -490
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_match_helpers.py +0 -64
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_temporalisomorphvf2.py +0 -212
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_tree_isomorphism.py +0 -202
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp.py +0 -1655
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp_helpers.py +0 -3118
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2userfunc.py +0 -196
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_hits.py +0 -77
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_pagerank.py +0 -213
- package/runtime/python/okstra_vendor/networkx/algorithms/minors/tests/test_contraction.py +0 -544
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_all.py +0 -328
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_binary.py +0 -451
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_product.py +0 -491
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_unary.py +0 -55
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_astar.py +0 -254
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense.py +0 -212
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py +0 -88
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_generic.py +0 -511
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_unweighted.py +0 -149
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_weighted.py +0 -983
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_asteroidal.py +0 -23
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_boundary.py +0 -154
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_bridges.py +0 -144
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_broadcasting.py +0 -109
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chains.py +0 -136
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chordal.py +0 -129
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_clique.py +0 -300
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cluster.py +0 -678
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_communicability.py +0 -80
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_core.py +0 -266
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_covering.py +0 -85
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cuts.py +0 -171
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cycles.py +0 -984
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_d_separation.py +0 -340
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dag.py +0 -835
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_measures.py +0 -831
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_regular.py +0 -85
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominance.py +0 -299
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominating.py +0 -115
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_efficiency.py +0 -58
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_euler.py +0 -314
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graph_hashing.py +0 -872
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graphical.py +0 -163
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hierarchy.py +0 -46
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hybrid.py +0 -24
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_isolate.py +0 -26
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_link_prediction.py +0 -615
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_lowest_common_ancestors.py +0 -459
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_matching.py +0 -556
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_max_weight_clique.py +0 -179
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_mis.py +0 -62
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_moral.py +0 -15
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_node_classification.py +0 -140
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_non_randomness.py +0 -60
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_perfect_graph.py +0 -27
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planar_drawing.py +0 -274
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planarity.py +0 -556
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_polynomials.py +0 -57
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_reciprocity.py +0 -37
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_regular.py +0 -88
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_richclub.py +0 -149
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_similarity.py +0 -1158
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_simple_paths.py +0 -803
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smallworld.py +0 -76
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smetric.py +0 -8
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_sparsifiers.py +0 -138
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_structuralholes.py +0 -191
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_summarization.py +0 -642
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_swap.py +0 -179
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_threshold.py +0 -270
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_time_dependent.py +0 -431
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_tournament.py +0 -161
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_triads.py +0 -248
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_vitality.py +0 -41
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_voronoi.py +0 -103
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_walks.py +0 -54
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_wiener.py +0 -157
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_beamsearch.py +0 -25
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_bfs.py +0 -203
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_dfs.py +0 -307
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgebfs.py +0 -147
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgedfs.py +0 -131
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_branchings.py +0 -624
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_coding.py +0 -114
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_decomposition.py +0 -79
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_distance_measures.py +0 -99
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_mst.py +0 -934
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_operations.py +0 -53
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_recognition.py +0 -174
- package/runtime/python/okstra_vendor/networkx/classes/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/dispatch_interface.py +0 -192
- package/runtime/python/okstra_vendor/networkx/classes/tests/historical_tests.py +0 -476
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_coreviews.py +0 -362
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph.py +0 -331
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph_historical.py +0 -110
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_filters.py +0 -177
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_function.py +0 -1045
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph.py +0 -950
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph_historical.py +0 -12
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_graphviews.py +0 -349
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_multidigraph.py +0 -459
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_multigraph.py +0 -528
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_reportviews.py +0 -1421
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_special.py +0 -131
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_subgraphviews.py +0 -371
- package/runtime/python/okstra_vendor/networkx/conftest.py +0 -261
- package/runtime/python/okstra_vendor/networkx/drawing/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_complex.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_empty_graph.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_house_with_colors.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_labels_and_colors.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_shortest_path.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_house_with_colors.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_agraph.py +0 -237
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_image_comparison_pylab_mpl.py +0 -229
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_latex.py +0 -285
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_layout.py +0 -631
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pydot.py +0 -146
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pylab.py +0 -1582
- package/runtime/python/okstra_vendor/networkx/generators/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_atlas.py +0 -75
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_classic.py +0 -642
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_cographs.py +0 -20
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_community.py +0 -362
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_degree_seq.py +0 -224
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_directed.py +0 -189
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_duplication.py +0 -103
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_ego.py +0 -39
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_expanders.py +0 -182
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_geometric.py +0 -488
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_harary_graph.py +0 -133
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_internet_as_graphs.py +0 -221
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_intersection.py +0 -28
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_interval_graph.py +0 -144
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_joint_degree_seq.py +0 -125
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_lattice.py +0 -264
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_line.py +0 -316
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_mycielski.py +0 -30
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_nonisomorphic_trees.py +0 -82
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_clustered.py +0 -33
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_graphs.py +0 -495
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_small.py +0 -220
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_spectral_graph_forge.py +0 -49
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_stochastic.py +0 -72
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_sudoku.py +0 -92
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_time_series.py +0 -64
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_trees.py +0 -195
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_triads.py +0 -15
- package/runtime/python/okstra_vendor/networkx/linalg/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_algebraic_connectivity.py +0 -400
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_attrmatrix.py +0 -108
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_bethehessian.py +0 -40
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_graphmatrix.py +0 -275
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_laplacian.py +0 -334
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_modularity.py +0 -86
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_spectrum.py +0 -70
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_adjacency.py +0 -78
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_cytoscape.py +0 -78
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_node_link.py +0 -109
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_tree.py +0 -48
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_adjlist.py +0 -354
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_edgelist.py +0 -318
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gexf.py +0 -612
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gml.py +0 -744
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graph6.py +0 -181
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graphml.py +0 -1531
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_leda.py +0 -30
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_p2g.py +0 -63
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_pajek.py +0 -128
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_sparse6.py +0 -166
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_text.py +0 -1742
- package/runtime/python/okstra_vendor/networkx/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_all_random_functions.py +0 -248
- package/runtime/python/okstra_vendor/networkx/tests/test_convert.py +0 -321
- package/runtime/python/okstra_vendor/networkx/tests/test_convert_numpy.py +0 -531
- package/runtime/python/okstra_vendor/networkx/tests/test_convert_pandas.py +0 -349
- package/runtime/python/okstra_vendor/networkx/tests/test_convert_scipy.py +0 -281
- package/runtime/python/okstra_vendor/networkx/tests/test_exceptions.py +0 -40
- package/runtime/python/okstra_vendor/networkx/tests/test_import.py +0 -11
- package/runtime/python/okstra_vendor/networkx/tests/test_lazy_imports.py +0 -96
- package/runtime/python/okstra_vendor/networkx/tests/test_relabel.py +0 -349
- package/runtime/python/okstra_vendor/networkx/tests/test_removed_functions_exception_messages.py +0 -8
- package/runtime/python/okstra_vendor/networkx/utils/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test__init.py +0 -11
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_backends.py +0 -225
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_config.py +0 -263
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_decorators.py +0 -510
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_heaps.py +0 -131
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_mapped_queue.py +0 -268
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_misc.py +0 -393
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_random_sequence.py +0 -53
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_rcm.py +0 -63
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_unionfind.py +0 -55
|
@@ -1,1531 +0,0 @@
|
|
|
1
|
-
import io
|
|
2
|
-
|
|
3
|
-
import pytest
|
|
4
|
-
|
|
5
|
-
import networkx as nx
|
|
6
|
-
from networkx.readwrite.graphml import GraphMLWriter
|
|
7
|
-
from networkx.utils import edges_equal, nodes_equal
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class BaseGraphML:
|
|
11
|
-
@classmethod
|
|
12
|
-
def setup_class(cls):
|
|
13
|
-
cls.simple_directed_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
14
|
-
<!-- This file was written by the JAVA GraphML Library.-->
|
|
15
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
16
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
17
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
18
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
19
|
-
<graph id="G" edgedefault="directed">
|
|
20
|
-
<node id="n0"/>
|
|
21
|
-
<node id="n1"/>
|
|
22
|
-
<node id="n2"/>
|
|
23
|
-
<node id="n3"/>
|
|
24
|
-
<node id="n4"/>
|
|
25
|
-
<node id="n5"/>
|
|
26
|
-
<node id="n6"/>
|
|
27
|
-
<node id="n7"/>
|
|
28
|
-
<node id="n8"/>
|
|
29
|
-
<node id="n9"/>
|
|
30
|
-
<node id="n10"/>
|
|
31
|
-
<edge id="foo" source="n0" target="n2"/>
|
|
32
|
-
<edge source="n1" target="n2"/>
|
|
33
|
-
<edge source="n2" target="n3"/>
|
|
34
|
-
<edge source="n3" target="n5"/>
|
|
35
|
-
<edge source="n3" target="n4"/>
|
|
36
|
-
<edge source="n4" target="n6"/>
|
|
37
|
-
<edge source="n6" target="n5"/>
|
|
38
|
-
<edge source="n5" target="n7"/>
|
|
39
|
-
<edge source="n6" target="n8"/>
|
|
40
|
-
<edge source="n8" target="n7"/>
|
|
41
|
-
<edge source="n8" target="n9"/>
|
|
42
|
-
</graph>
|
|
43
|
-
</graphml>"""
|
|
44
|
-
cls.simple_directed_graph = nx.DiGraph()
|
|
45
|
-
cls.simple_directed_graph.add_node("n10")
|
|
46
|
-
cls.simple_directed_graph.add_edge("n0", "n2", id="foo")
|
|
47
|
-
cls.simple_directed_graph.add_edge("n0", "n2")
|
|
48
|
-
cls.simple_directed_graph.add_edges_from(
|
|
49
|
-
[
|
|
50
|
-
("n1", "n2"),
|
|
51
|
-
("n2", "n3"),
|
|
52
|
-
("n3", "n5"),
|
|
53
|
-
("n3", "n4"),
|
|
54
|
-
("n4", "n6"),
|
|
55
|
-
("n6", "n5"),
|
|
56
|
-
("n5", "n7"),
|
|
57
|
-
("n6", "n8"),
|
|
58
|
-
("n8", "n7"),
|
|
59
|
-
("n8", "n9"),
|
|
60
|
-
]
|
|
61
|
-
)
|
|
62
|
-
cls.simple_directed_fh = io.BytesIO(cls.simple_directed_data.encode("UTF-8"))
|
|
63
|
-
|
|
64
|
-
cls.attribute_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
65
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
66
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
67
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
68
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
69
|
-
<key id="d0" for="node" attr.name="color" attr.type="string">
|
|
70
|
-
<default>yellow</default>
|
|
71
|
-
</key>
|
|
72
|
-
<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
|
|
73
|
-
<graph id="G" edgedefault="directed">
|
|
74
|
-
<node id="n0">
|
|
75
|
-
<data key="d0">green</data>
|
|
76
|
-
</node>
|
|
77
|
-
<node id="n1"/>
|
|
78
|
-
<node id="n2">
|
|
79
|
-
<data key="d0">blue</data>
|
|
80
|
-
</node>
|
|
81
|
-
<node id="n3">
|
|
82
|
-
<data key="d0">red</data>
|
|
83
|
-
</node>
|
|
84
|
-
<node id="n4"/>
|
|
85
|
-
<node id="n5">
|
|
86
|
-
<data key="d0">turquoise</data>
|
|
87
|
-
</node>
|
|
88
|
-
<edge id="e0" source="n0" target="n2">
|
|
89
|
-
<data key="d1">1.0</data>
|
|
90
|
-
</edge>
|
|
91
|
-
<edge id="e1" source="n0" target="n1">
|
|
92
|
-
<data key="d1">1.0</data>
|
|
93
|
-
</edge>
|
|
94
|
-
<edge id="e2" source="n1" target="n3">
|
|
95
|
-
<data key="d1">2.0</data>
|
|
96
|
-
</edge>
|
|
97
|
-
<edge id="e3" source="n3" target="n2"/>
|
|
98
|
-
<edge id="e4" source="n2" target="n4"/>
|
|
99
|
-
<edge id="e5" source="n3" target="n5"/>
|
|
100
|
-
<edge id="e6" source="n5" target="n4">
|
|
101
|
-
<data key="d1">1.1</data>
|
|
102
|
-
</edge>
|
|
103
|
-
</graph>
|
|
104
|
-
</graphml>
|
|
105
|
-
"""
|
|
106
|
-
cls.attribute_graph = nx.DiGraph(id="G")
|
|
107
|
-
cls.attribute_graph.graph["node_default"] = {"color": "yellow"}
|
|
108
|
-
cls.attribute_graph.add_node("n0", color="green")
|
|
109
|
-
cls.attribute_graph.add_node("n2", color="blue")
|
|
110
|
-
cls.attribute_graph.add_node("n3", color="red")
|
|
111
|
-
cls.attribute_graph.add_node("n4")
|
|
112
|
-
cls.attribute_graph.add_node("n5", color="turquoise")
|
|
113
|
-
cls.attribute_graph.add_edge("n0", "n2", id="e0", weight=1.0)
|
|
114
|
-
cls.attribute_graph.add_edge("n0", "n1", id="e1", weight=1.0)
|
|
115
|
-
cls.attribute_graph.add_edge("n1", "n3", id="e2", weight=2.0)
|
|
116
|
-
cls.attribute_graph.add_edge("n3", "n2", id="e3")
|
|
117
|
-
cls.attribute_graph.add_edge("n2", "n4", id="e4")
|
|
118
|
-
cls.attribute_graph.add_edge("n3", "n5", id="e5")
|
|
119
|
-
cls.attribute_graph.add_edge("n5", "n4", id="e6", weight=1.1)
|
|
120
|
-
cls.attribute_fh = io.BytesIO(cls.attribute_data.encode("UTF-8"))
|
|
121
|
-
|
|
122
|
-
cls.node_attribute_default_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
123
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
124
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
125
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
126
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
127
|
-
<key id="d0" for="node" attr.name="boolean_attribute" attr.type="boolean"><default>false</default></key>
|
|
128
|
-
<key id="d1" for="node" attr.name="int_attribute" attr.type="int"><default>0</default></key>
|
|
129
|
-
<key id="d2" for="node" attr.name="long_attribute" attr.type="long"><default>0</default></key>
|
|
130
|
-
<key id="d3" for="node" attr.name="float_attribute" attr.type="float"><default>0.0</default></key>
|
|
131
|
-
<key id="d4" for="node" attr.name="double_attribute" attr.type="double"><default>0.0</default></key>
|
|
132
|
-
<key id="d5" for="node" attr.name="string_attribute" attr.type="string"><default>Foo</default></key>
|
|
133
|
-
<graph id="G" edgedefault="directed">
|
|
134
|
-
<node id="n0"/>
|
|
135
|
-
<node id="n1"/>
|
|
136
|
-
<edge id="e0" source="n0" target="n1"/>
|
|
137
|
-
</graph>
|
|
138
|
-
</graphml>
|
|
139
|
-
"""
|
|
140
|
-
cls.node_attribute_default_graph = nx.DiGraph(id="G")
|
|
141
|
-
cls.node_attribute_default_graph.graph["node_default"] = {
|
|
142
|
-
"boolean_attribute": False,
|
|
143
|
-
"int_attribute": 0,
|
|
144
|
-
"long_attribute": 0,
|
|
145
|
-
"float_attribute": 0.0,
|
|
146
|
-
"double_attribute": 0.0,
|
|
147
|
-
"string_attribute": "Foo",
|
|
148
|
-
}
|
|
149
|
-
cls.node_attribute_default_graph.add_node("n0")
|
|
150
|
-
cls.node_attribute_default_graph.add_node("n1")
|
|
151
|
-
cls.node_attribute_default_graph.add_edge("n0", "n1", id="e0")
|
|
152
|
-
cls.node_attribute_default_fh = io.BytesIO(
|
|
153
|
-
cls.node_attribute_default_data.encode("UTF-8")
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
cls.attribute_named_key_ids_data = """<?xml version='1.0' encoding='utf-8'?>
|
|
157
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
158
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
159
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
160
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
161
|
-
<key id="edge_prop" for="edge" attr.name="edge_prop" attr.type="string"/>
|
|
162
|
-
<key id="prop2" for="node" attr.name="prop2" attr.type="string"/>
|
|
163
|
-
<key id="prop1" for="node" attr.name="prop1" attr.type="string"/>
|
|
164
|
-
<graph edgedefault="directed">
|
|
165
|
-
<node id="0">
|
|
166
|
-
<data key="prop1">val1</data>
|
|
167
|
-
<data key="prop2">val2</data>
|
|
168
|
-
</node>
|
|
169
|
-
<node id="1">
|
|
170
|
-
<data key="prop1">val_one</data>
|
|
171
|
-
<data key="prop2">val2</data>
|
|
172
|
-
</node>
|
|
173
|
-
<edge source="0" target="1">
|
|
174
|
-
<data key="edge_prop">edge_value</data>
|
|
175
|
-
</edge>
|
|
176
|
-
</graph>
|
|
177
|
-
</graphml>
|
|
178
|
-
"""
|
|
179
|
-
cls.attribute_named_key_ids_graph = nx.DiGraph()
|
|
180
|
-
cls.attribute_named_key_ids_graph.add_node("0", prop1="val1", prop2="val2")
|
|
181
|
-
cls.attribute_named_key_ids_graph.add_node("1", prop1="val_one", prop2="val2")
|
|
182
|
-
cls.attribute_named_key_ids_graph.add_edge("0", "1", edge_prop="edge_value")
|
|
183
|
-
fh = io.BytesIO(cls.attribute_named_key_ids_data.encode("UTF-8"))
|
|
184
|
-
cls.attribute_named_key_ids_fh = fh
|
|
185
|
-
|
|
186
|
-
cls.attribute_numeric_type_data = """<?xml version='1.0' encoding='utf-8'?>
|
|
187
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
188
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
189
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
190
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
191
|
-
<key attr.name="weight" attr.type="double" for="node" id="d1" />
|
|
192
|
-
<key attr.name="weight" attr.type="double" for="edge" id="d0" />
|
|
193
|
-
<graph edgedefault="directed">
|
|
194
|
-
<node id="n0">
|
|
195
|
-
<data key="d1">1</data>
|
|
196
|
-
</node>
|
|
197
|
-
<node id="n1">
|
|
198
|
-
<data key="d1">2.0</data>
|
|
199
|
-
</node>
|
|
200
|
-
<edge source="n0" target="n1">
|
|
201
|
-
<data key="d0">1</data>
|
|
202
|
-
</edge>
|
|
203
|
-
<edge source="n1" target="n0">
|
|
204
|
-
<data key="d0">k</data>
|
|
205
|
-
</edge>
|
|
206
|
-
<edge source="n1" target="n1">
|
|
207
|
-
<data key="d0">1.0</data>
|
|
208
|
-
</edge>
|
|
209
|
-
</graph>
|
|
210
|
-
</graphml>
|
|
211
|
-
"""
|
|
212
|
-
cls.attribute_numeric_type_graph = nx.DiGraph()
|
|
213
|
-
cls.attribute_numeric_type_graph.add_node("n0", weight=1)
|
|
214
|
-
cls.attribute_numeric_type_graph.add_node("n1", weight=2.0)
|
|
215
|
-
cls.attribute_numeric_type_graph.add_edge("n0", "n1", weight=1)
|
|
216
|
-
cls.attribute_numeric_type_graph.add_edge("n1", "n1", weight=1.0)
|
|
217
|
-
fh = io.BytesIO(cls.attribute_numeric_type_data.encode("UTF-8"))
|
|
218
|
-
cls.attribute_numeric_type_fh = fh
|
|
219
|
-
|
|
220
|
-
cls.simple_undirected_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
221
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
222
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
223
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
224
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
225
|
-
<graph id="G">
|
|
226
|
-
<node id="n0"/>
|
|
227
|
-
<node id="n1"/>
|
|
228
|
-
<node id="n2"/>
|
|
229
|
-
<node id="n10"/>
|
|
230
|
-
<edge id="foo" source="n0" target="n2"/>
|
|
231
|
-
<edge source="n1" target="n2"/>
|
|
232
|
-
<edge source="n2" target="n3"/>
|
|
233
|
-
</graph>
|
|
234
|
-
</graphml>"""
|
|
235
|
-
# <edge source="n8" target="n10" directed="false"/>
|
|
236
|
-
cls.simple_undirected_graph = nx.Graph()
|
|
237
|
-
cls.simple_undirected_graph.add_node("n10")
|
|
238
|
-
cls.simple_undirected_graph.add_edge("n0", "n2", id="foo")
|
|
239
|
-
cls.simple_undirected_graph.add_edges_from([("n1", "n2"), ("n2", "n3")])
|
|
240
|
-
fh = io.BytesIO(cls.simple_undirected_data.encode("UTF-8"))
|
|
241
|
-
cls.simple_undirected_fh = fh
|
|
242
|
-
|
|
243
|
-
cls.undirected_multigraph_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
244
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
245
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
246
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
247
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
248
|
-
<graph id="G">
|
|
249
|
-
<node id="n0"/>
|
|
250
|
-
<node id="n1"/>
|
|
251
|
-
<node id="n2"/>
|
|
252
|
-
<node id="n10"/>
|
|
253
|
-
<edge id="e0" source="n0" target="n2"/>
|
|
254
|
-
<edge id="e1" source="n1" target="n2"/>
|
|
255
|
-
<edge id="e2" source="n2" target="n1"/>
|
|
256
|
-
</graph>
|
|
257
|
-
</graphml>"""
|
|
258
|
-
cls.undirected_multigraph = nx.MultiGraph()
|
|
259
|
-
cls.undirected_multigraph.add_node("n10")
|
|
260
|
-
cls.undirected_multigraph.add_edge("n0", "n2", id="e0")
|
|
261
|
-
cls.undirected_multigraph.add_edge("n1", "n2", id="e1")
|
|
262
|
-
cls.undirected_multigraph.add_edge("n2", "n1", id="e2")
|
|
263
|
-
fh = io.BytesIO(cls.undirected_multigraph_data.encode("UTF-8"))
|
|
264
|
-
cls.undirected_multigraph_fh = fh
|
|
265
|
-
|
|
266
|
-
cls.undirected_multigraph_no_multiedge_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
267
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
268
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
269
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
270
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
271
|
-
<graph id="G">
|
|
272
|
-
<node id="n0"/>
|
|
273
|
-
<node id="n1"/>
|
|
274
|
-
<node id="n2"/>
|
|
275
|
-
<node id="n10"/>
|
|
276
|
-
<edge id="e0" source="n0" target="n2"/>
|
|
277
|
-
<edge id="e1" source="n1" target="n2"/>
|
|
278
|
-
<edge id="e2" source="n2" target="n3"/>
|
|
279
|
-
</graph>
|
|
280
|
-
</graphml>"""
|
|
281
|
-
cls.undirected_multigraph_no_multiedge = nx.MultiGraph()
|
|
282
|
-
cls.undirected_multigraph_no_multiedge.add_node("n10")
|
|
283
|
-
cls.undirected_multigraph_no_multiedge.add_edge("n0", "n2", id="e0")
|
|
284
|
-
cls.undirected_multigraph_no_multiedge.add_edge("n1", "n2", id="e1")
|
|
285
|
-
cls.undirected_multigraph_no_multiedge.add_edge("n2", "n3", id="e2")
|
|
286
|
-
fh = io.BytesIO(cls.undirected_multigraph_no_multiedge_data.encode("UTF-8"))
|
|
287
|
-
cls.undirected_multigraph_no_multiedge_fh = fh
|
|
288
|
-
|
|
289
|
-
cls.multigraph_only_ids_for_multiedges_data = """<?xml version="1.0" encoding="UTF-8"?>
|
|
290
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
291
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
292
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
293
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
294
|
-
<graph id="G">
|
|
295
|
-
<node id="n0"/>
|
|
296
|
-
<node id="n1"/>
|
|
297
|
-
<node id="n2"/>
|
|
298
|
-
<node id="n10"/>
|
|
299
|
-
<edge source="n0" target="n2"/>
|
|
300
|
-
<edge id="e1" source="n1" target="n2"/>
|
|
301
|
-
<edge id="e2" source="n2" target="n1"/>
|
|
302
|
-
</graph>
|
|
303
|
-
</graphml>"""
|
|
304
|
-
cls.multigraph_only_ids_for_multiedges = nx.MultiGraph()
|
|
305
|
-
cls.multigraph_only_ids_for_multiedges.add_node("n10")
|
|
306
|
-
cls.multigraph_only_ids_for_multiedges.add_edge("n0", "n2")
|
|
307
|
-
cls.multigraph_only_ids_for_multiedges.add_edge("n1", "n2", id="e1")
|
|
308
|
-
cls.multigraph_only_ids_for_multiedges.add_edge("n2", "n1", id="e2")
|
|
309
|
-
fh = io.BytesIO(cls.multigraph_only_ids_for_multiedges_data.encode("UTF-8"))
|
|
310
|
-
cls.multigraph_only_ids_for_multiedges_fh = fh
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
class TestReadGraphML(BaseGraphML):
|
|
314
|
-
def test_read_simple_directed_graphml(self):
|
|
315
|
-
G = self.simple_directed_graph
|
|
316
|
-
H = nx.read_graphml(self.simple_directed_fh)
|
|
317
|
-
assert sorted(G.nodes()) == sorted(H.nodes())
|
|
318
|
-
assert sorted(G.edges()) == sorted(H.edges())
|
|
319
|
-
assert sorted(G.edges(data=True)) == sorted(H.edges(data=True))
|
|
320
|
-
self.simple_directed_fh.seek(0)
|
|
321
|
-
|
|
322
|
-
PG = nx.parse_graphml(self.simple_directed_data)
|
|
323
|
-
assert sorted(G.nodes()) == sorted(PG.nodes())
|
|
324
|
-
assert sorted(G.edges()) == sorted(PG.edges())
|
|
325
|
-
assert sorted(G.edges(data=True)) == sorted(PG.edges(data=True))
|
|
326
|
-
|
|
327
|
-
def test_read_simple_undirected_graphml(self):
|
|
328
|
-
G = self.simple_undirected_graph
|
|
329
|
-
H = nx.read_graphml(self.simple_undirected_fh)
|
|
330
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
331
|
-
assert edges_equal(G.edges(), H.edges())
|
|
332
|
-
self.simple_undirected_fh.seek(0)
|
|
333
|
-
|
|
334
|
-
PG = nx.parse_graphml(self.simple_undirected_data)
|
|
335
|
-
assert nodes_equal(G.nodes(), PG.nodes())
|
|
336
|
-
assert edges_equal(G.edges(), PG.edges())
|
|
337
|
-
|
|
338
|
-
def test_read_undirected_multigraph_graphml(self):
|
|
339
|
-
G = self.undirected_multigraph
|
|
340
|
-
H = nx.read_graphml(self.undirected_multigraph_fh)
|
|
341
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
342
|
-
assert edges_equal(G.edges(), H.edges())
|
|
343
|
-
self.undirected_multigraph_fh.seek(0)
|
|
344
|
-
|
|
345
|
-
PG = nx.parse_graphml(self.undirected_multigraph_data)
|
|
346
|
-
assert nodes_equal(G.nodes(), PG.nodes())
|
|
347
|
-
assert edges_equal(G.edges(), PG.edges())
|
|
348
|
-
|
|
349
|
-
def test_read_undirected_multigraph_no_multiedge_graphml(self):
|
|
350
|
-
G = self.undirected_multigraph_no_multiedge
|
|
351
|
-
H = nx.read_graphml(self.undirected_multigraph_no_multiedge_fh)
|
|
352
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
353
|
-
assert edges_equal(G.edges(), H.edges())
|
|
354
|
-
self.undirected_multigraph_no_multiedge_fh.seek(0)
|
|
355
|
-
|
|
356
|
-
PG = nx.parse_graphml(self.undirected_multigraph_no_multiedge_data)
|
|
357
|
-
assert nodes_equal(G.nodes(), PG.nodes())
|
|
358
|
-
assert edges_equal(G.edges(), PG.edges())
|
|
359
|
-
|
|
360
|
-
def test_read_undirected_multigraph_only_ids_for_multiedges_graphml(self):
|
|
361
|
-
G = self.multigraph_only_ids_for_multiedges
|
|
362
|
-
H = nx.read_graphml(self.multigraph_only_ids_for_multiedges_fh)
|
|
363
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
364
|
-
assert edges_equal(G.edges(), H.edges())
|
|
365
|
-
self.multigraph_only_ids_for_multiedges_fh.seek(0)
|
|
366
|
-
|
|
367
|
-
PG = nx.parse_graphml(self.multigraph_only_ids_for_multiedges_data)
|
|
368
|
-
assert nodes_equal(G.nodes(), PG.nodes())
|
|
369
|
-
assert edges_equal(G.edges(), PG.edges())
|
|
370
|
-
|
|
371
|
-
def test_read_attribute_graphml(self):
|
|
372
|
-
G = self.attribute_graph
|
|
373
|
-
H = nx.read_graphml(self.attribute_fh)
|
|
374
|
-
assert nodes_equal(G.nodes(True), sorted(H.nodes(data=True)))
|
|
375
|
-
ge = sorted(G.edges(data=True))
|
|
376
|
-
he = sorted(H.edges(data=True))
|
|
377
|
-
for a, b in zip(ge, he):
|
|
378
|
-
assert a == b
|
|
379
|
-
self.attribute_fh.seek(0)
|
|
380
|
-
|
|
381
|
-
PG = nx.parse_graphml(self.attribute_data)
|
|
382
|
-
assert sorted(G.nodes(True)) == sorted(PG.nodes(data=True))
|
|
383
|
-
ge = sorted(G.edges(data=True))
|
|
384
|
-
he = sorted(PG.edges(data=True))
|
|
385
|
-
for a, b in zip(ge, he):
|
|
386
|
-
assert a == b
|
|
387
|
-
|
|
388
|
-
def test_node_default_attribute_graphml(self):
|
|
389
|
-
G = self.node_attribute_default_graph
|
|
390
|
-
H = nx.read_graphml(self.node_attribute_default_fh)
|
|
391
|
-
assert G.graph["node_default"] == H.graph["node_default"]
|
|
392
|
-
|
|
393
|
-
def test_directed_edge_in_undirected(self):
|
|
394
|
-
s = """<?xml version="1.0" encoding="UTF-8"?>
|
|
395
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
396
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
397
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
398
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
399
|
-
<graph id="G">
|
|
400
|
-
<node id="n0"/>
|
|
401
|
-
<node id="n1"/>
|
|
402
|
-
<node id="n2"/>
|
|
403
|
-
<edge source="n0" target="n1"/>
|
|
404
|
-
<edge source="n1" target="n2" directed='true'/>
|
|
405
|
-
</graph>
|
|
406
|
-
</graphml>"""
|
|
407
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
408
|
-
pytest.raises(nx.NetworkXError, nx.read_graphml, fh)
|
|
409
|
-
pytest.raises(nx.NetworkXError, nx.parse_graphml, s)
|
|
410
|
-
|
|
411
|
-
def test_undirected_edge_in_directed(self):
|
|
412
|
-
s = """<?xml version="1.0" encoding="UTF-8"?>
|
|
413
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
414
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
415
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
416
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
417
|
-
<graph id="G" edgedefault='directed'>
|
|
418
|
-
<node id="n0"/>
|
|
419
|
-
<node id="n1"/>
|
|
420
|
-
<node id="n2"/>
|
|
421
|
-
<edge source="n0" target="n1"/>
|
|
422
|
-
<edge source="n1" target="n2" directed='false'/>
|
|
423
|
-
</graph>
|
|
424
|
-
</graphml>"""
|
|
425
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
426
|
-
pytest.raises(nx.NetworkXError, nx.read_graphml, fh)
|
|
427
|
-
pytest.raises(nx.NetworkXError, nx.parse_graphml, s)
|
|
428
|
-
|
|
429
|
-
def test_key_raise(self):
|
|
430
|
-
s = """<?xml version="1.0" encoding="UTF-8"?>
|
|
431
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
432
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
433
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
434
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
435
|
-
<key id="d0" for="node" attr.name="color" attr.type="string">
|
|
436
|
-
<default>yellow</default>
|
|
437
|
-
</key>
|
|
438
|
-
<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
|
|
439
|
-
<graph id="G" edgedefault="directed">
|
|
440
|
-
<node id="n0">
|
|
441
|
-
<data key="d0">green</data>
|
|
442
|
-
</node>
|
|
443
|
-
<node id="n1"/>
|
|
444
|
-
<node id="n2">
|
|
445
|
-
<data key="d0">blue</data>
|
|
446
|
-
</node>
|
|
447
|
-
<edge id="e0" source="n0" target="n2">
|
|
448
|
-
<data key="d2">1.0</data>
|
|
449
|
-
</edge>
|
|
450
|
-
</graph>
|
|
451
|
-
</graphml>
|
|
452
|
-
"""
|
|
453
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
454
|
-
pytest.raises(nx.NetworkXError, nx.read_graphml, fh)
|
|
455
|
-
pytest.raises(nx.NetworkXError, nx.parse_graphml, s)
|
|
456
|
-
|
|
457
|
-
def test_hyperedge_raise(self):
|
|
458
|
-
s = """<?xml version="1.0" encoding="UTF-8"?>
|
|
459
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
460
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
461
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
462
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
463
|
-
<key id="d0" for="node" attr.name="color" attr.type="string">
|
|
464
|
-
<default>yellow</default>
|
|
465
|
-
</key>
|
|
466
|
-
<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
|
|
467
|
-
<graph id="G" edgedefault="directed">
|
|
468
|
-
<node id="n0">
|
|
469
|
-
<data key="d0">green</data>
|
|
470
|
-
</node>
|
|
471
|
-
<node id="n1"/>
|
|
472
|
-
<node id="n2">
|
|
473
|
-
<data key="d0">blue</data>
|
|
474
|
-
</node>
|
|
475
|
-
<hyperedge id="e0" source="n0" target="n2">
|
|
476
|
-
<endpoint node="n0"/>
|
|
477
|
-
<endpoint node="n1"/>
|
|
478
|
-
<endpoint node="n2"/>
|
|
479
|
-
</hyperedge>
|
|
480
|
-
</graph>
|
|
481
|
-
</graphml>
|
|
482
|
-
"""
|
|
483
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
484
|
-
pytest.raises(nx.NetworkXError, nx.read_graphml, fh)
|
|
485
|
-
pytest.raises(nx.NetworkXError, nx.parse_graphml, s)
|
|
486
|
-
|
|
487
|
-
def test_multigraph_keys(self):
|
|
488
|
-
# Test that reading multigraphs uses edge id attributes as keys
|
|
489
|
-
s = """<?xml version="1.0" encoding="UTF-8"?>
|
|
490
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
491
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
492
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
493
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
494
|
-
<graph id="G" edgedefault="directed">
|
|
495
|
-
<node id="n0"/>
|
|
496
|
-
<node id="n1"/>
|
|
497
|
-
<edge id="e0" source="n0" target="n1"/>
|
|
498
|
-
<edge id="e1" source="n0" target="n1"/>
|
|
499
|
-
</graph>
|
|
500
|
-
</graphml>
|
|
501
|
-
"""
|
|
502
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
503
|
-
G = nx.read_graphml(fh)
|
|
504
|
-
expected = [("n0", "n1", "e0"), ("n0", "n1", "e1")]
|
|
505
|
-
assert sorted(G.edges(keys=True)) == expected
|
|
506
|
-
fh.seek(0)
|
|
507
|
-
H = nx.parse_graphml(s)
|
|
508
|
-
assert sorted(H.edges(keys=True)) == expected
|
|
509
|
-
|
|
510
|
-
def test_preserve_multi_edge_data(self):
|
|
511
|
-
"""
|
|
512
|
-
Test that data and keys of edges are preserved on consequent
|
|
513
|
-
write and reads
|
|
514
|
-
"""
|
|
515
|
-
G = nx.MultiGraph()
|
|
516
|
-
G.add_node(1)
|
|
517
|
-
G.add_node(2)
|
|
518
|
-
G.add_edges_from(
|
|
519
|
-
[
|
|
520
|
-
# edges with no data, no keys:
|
|
521
|
-
(1, 2),
|
|
522
|
-
# edges with only data:
|
|
523
|
-
(1, 2, {"key": "data_key1"}),
|
|
524
|
-
(1, 2, {"id": "data_id2"}),
|
|
525
|
-
(1, 2, {"key": "data_key3", "id": "data_id3"}),
|
|
526
|
-
# edges with both data and keys:
|
|
527
|
-
(1, 2, 103, {"key": "data_key4"}),
|
|
528
|
-
(1, 2, 104, {"id": "data_id5"}),
|
|
529
|
-
(1, 2, 105, {"key": "data_key6", "id": "data_id7"}),
|
|
530
|
-
]
|
|
531
|
-
)
|
|
532
|
-
fh = io.BytesIO()
|
|
533
|
-
nx.write_graphml(G, fh)
|
|
534
|
-
fh.seek(0)
|
|
535
|
-
H = nx.read_graphml(fh, node_type=int)
|
|
536
|
-
assert edges_equal(G.edges(data=True, keys=True), H.edges(data=True, keys=True))
|
|
537
|
-
assert G._adj == H._adj
|
|
538
|
-
|
|
539
|
-
Gadj = {
|
|
540
|
-
str(node): {
|
|
541
|
-
str(nbr): {str(ekey): dd for ekey, dd in key_dict.items()}
|
|
542
|
-
for nbr, key_dict in nbr_dict.items()
|
|
543
|
-
}
|
|
544
|
-
for node, nbr_dict in G._adj.items()
|
|
545
|
-
}
|
|
546
|
-
fh.seek(0)
|
|
547
|
-
HH = nx.read_graphml(fh, node_type=str, edge_key_type=str)
|
|
548
|
-
assert Gadj == HH._adj
|
|
549
|
-
|
|
550
|
-
fh.seek(0)
|
|
551
|
-
string_fh = fh.read()
|
|
552
|
-
HH = nx.parse_graphml(string_fh, node_type=str, edge_key_type=str)
|
|
553
|
-
assert Gadj == HH._adj
|
|
554
|
-
|
|
555
|
-
def test_yfiles_extension(self):
|
|
556
|
-
data = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
557
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
558
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
559
|
-
xmlns:y="http://www.yworks.com/xml/graphml"
|
|
560
|
-
xmlns:yed="http://www.yworks.com/xml/yed/3"
|
|
561
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
562
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
563
|
-
<!--Created by yFiles for Java 2.7-->
|
|
564
|
-
<key for="graphml" id="d0" yfiles.type="resources"/>
|
|
565
|
-
<key attr.name="url" attr.type="string" for="node" id="d1"/>
|
|
566
|
-
<key attr.name="description" attr.type="string" for="node" id="d2"/>
|
|
567
|
-
<key for="node" id="d3" yfiles.type="nodegraphics"/>
|
|
568
|
-
<key attr.name="Description" attr.type="string" for="graph" id="d4">
|
|
569
|
-
<default/>
|
|
570
|
-
</key>
|
|
571
|
-
<key attr.name="url" attr.type="string" for="edge" id="d5"/>
|
|
572
|
-
<key attr.name="description" attr.type="string" for="edge" id="d6"/>
|
|
573
|
-
<key for="edge" id="d7" yfiles.type="edgegraphics"/>
|
|
574
|
-
<graph edgedefault="directed" id="G">
|
|
575
|
-
<node id="n0">
|
|
576
|
-
<data key="d3">
|
|
577
|
-
<y:ShapeNode>
|
|
578
|
-
<y:Geometry height="30.0" width="30.0" x="125.0" y="100.0"/>
|
|
579
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
580
|
-
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
|
581
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content"
|
|
582
|
-
borderDistance="0.0" fontFamily="Dialog" fontSize="13"
|
|
583
|
-
fontStyle="plain" hasBackgroundColor="false" hasLineColor="false"
|
|
584
|
-
height="19.1328125" modelName="internal" modelPosition="c"
|
|
585
|
-
textColor="#000000" visible="true" width="12.27099609375"
|
|
586
|
-
x="8.864501953125" y="5.43359375">1</y:NodeLabel>
|
|
587
|
-
<y:Shape type="rectangle"/>
|
|
588
|
-
</y:ShapeNode>
|
|
589
|
-
</data>
|
|
590
|
-
</node>
|
|
591
|
-
<node id="n1">
|
|
592
|
-
<data key="d3">
|
|
593
|
-
<y:ShapeNode>
|
|
594
|
-
<y:Geometry height="30.0" width="30.0" x="183.0" y="205.0"/>
|
|
595
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
596
|
-
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
|
597
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content"
|
|
598
|
-
borderDistance="0.0" fontFamily="Dialog" fontSize="13"
|
|
599
|
-
fontStyle="plain" hasBackgroundColor="false" hasLineColor="false"
|
|
600
|
-
height="19.1328125" modelName="internal" modelPosition="c"
|
|
601
|
-
textColor="#000000" visible="true" width="12.27099609375"
|
|
602
|
-
x="8.864501953125" y="5.43359375">2</y:NodeLabel>
|
|
603
|
-
<y:Shape type="rectangle"/>
|
|
604
|
-
</y:ShapeNode>
|
|
605
|
-
</data>
|
|
606
|
-
</node>
|
|
607
|
-
<node id="n2">
|
|
608
|
-
<data key="d6" xml:space="preserve"><![CDATA[description
|
|
609
|
-
line1
|
|
610
|
-
line2]]></data>
|
|
611
|
-
<data key="d3">
|
|
612
|
-
<y:GenericNode configuration="com.yworks.flowchart.terminator">
|
|
613
|
-
<y:Geometry height="40.0" width="80.0" x="950.0" y="286.0"/>
|
|
614
|
-
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
|
|
615
|
-
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
|
616
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content"
|
|
617
|
-
fontFamily="Dialog" fontSize="12" fontStyle="plain"
|
|
618
|
-
hasBackgroundColor="false" hasLineColor="false" height="17.96875"
|
|
619
|
-
horizontalTextPosition="center" iconTextGap="4" modelName="custom"
|
|
620
|
-
textColor="#000000" verticalTextPosition="bottom" visible="true"
|
|
621
|
-
width="67.984375" x="6.0078125" xml:space="preserve"
|
|
622
|
-
y="11.015625">3<y:LabelModel>
|
|
623
|
-
<y:SmartNodeLabelModel distance="4.0"/></y:LabelModel>
|
|
624
|
-
<y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0"
|
|
625
|
-
labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0"
|
|
626
|
-
offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
627
|
-
</y:GenericNode>
|
|
628
|
-
</data>
|
|
629
|
-
</node>
|
|
630
|
-
<edge id="e0" source="n0" target="n1">
|
|
631
|
-
<data key="d7">
|
|
632
|
-
<y:PolyLineEdge>
|
|
633
|
-
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
634
|
-
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
635
|
-
<y:Arrows source="none" target="standard"/>
|
|
636
|
-
<y:BendStyle smoothed="false"/>
|
|
637
|
-
</y:PolyLineEdge>
|
|
638
|
-
</data>
|
|
639
|
-
</edge>
|
|
640
|
-
</graph>
|
|
641
|
-
<data key="d0">
|
|
642
|
-
<y:Resources/>
|
|
643
|
-
</data>
|
|
644
|
-
</graphml>
|
|
645
|
-
"""
|
|
646
|
-
fh = io.BytesIO(data.encode("UTF-8"))
|
|
647
|
-
G = nx.read_graphml(fh, force_multigraph=True)
|
|
648
|
-
assert list(G.edges()) == [("n0", "n1")]
|
|
649
|
-
assert G.has_edge("n0", "n1", key="e0")
|
|
650
|
-
assert G.nodes["n0"]["label"] == "1"
|
|
651
|
-
assert G.nodes["n1"]["label"] == "2"
|
|
652
|
-
assert G.nodes["n2"]["label"] == "3"
|
|
653
|
-
assert G.nodes["n0"]["shape_type"] == "rectangle"
|
|
654
|
-
assert G.nodes["n1"]["shape_type"] == "rectangle"
|
|
655
|
-
assert G.nodes["n2"]["shape_type"] == "com.yworks.flowchart.terminator"
|
|
656
|
-
assert G.nodes["n2"]["description"] == "description\nline1\nline2"
|
|
657
|
-
fh.seek(0)
|
|
658
|
-
G = nx.read_graphml(fh)
|
|
659
|
-
assert list(G.edges()) == [("n0", "n1")]
|
|
660
|
-
assert G["n0"]["n1"]["id"] == "e0"
|
|
661
|
-
assert G.nodes["n0"]["label"] == "1"
|
|
662
|
-
assert G.nodes["n1"]["label"] == "2"
|
|
663
|
-
assert G.nodes["n2"]["label"] == "3"
|
|
664
|
-
assert G.nodes["n0"]["shape_type"] == "rectangle"
|
|
665
|
-
assert G.nodes["n1"]["shape_type"] == "rectangle"
|
|
666
|
-
assert G.nodes["n2"]["shape_type"] == "com.yworks.flowchart.terminator"
|
|
667
|
-
assert G.nodes["n2"]["description"] == "description\nline1\nline2"
|
|
668
|
-
|
|
669
|
-
H = nx.parse_graphml(data, force_multigraph=True)
|
|
670
|
-
assert list(H.edges()) == [("n0", "n1")]
|
|
671
|
-
assert H.has_edge("n0", "n1", key="e0")
|
|
672
|
-
assert H.nodes["n0"]["label"] == "1"
|
|
673
|
-
assert H.nodes["n1"]["label"] == "2"
|
|
674
|
-
assert H.nodes["n2"]["label"] == "3"
|
|
675
|
-
|
|
676
|
-
H = nx.parse_graphml(data)
|
|
677
|
-
assert list(H.edges()) == [("n0", "n1")]
|
|
678
|
-
assert H["n0"]["n1"]["id"] == "e0"
|
|
679
|
-
assert H.nodes["n0"]["label"] == "1"
|
|
680
|
-
assert H.nodes["n1"]["label"] == "2"
|
|
681
|
-
assert H.nodes["n2"]["label"] == "3"
|
|
682
|
-
|
|
683
|
-
def test_bool(self):
|
|
684
|
-
s = """<?xml version="1.0" encoding="UTF-8"?>
|
|
685
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
686
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
687
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
688
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
689
|
-
<key id="d0" for="node" attr.name="test" attr.type="boolean">
|
|
690
|
-
<default>false</default>
|
|
691
|
-
</key>
|
|
692
|
-
<graph id="G" edgedefault="directed">
|
|
693
|
-
<node id="n0">
|
|
694
|
-
<data key="d0">true</data>
|
|
695
|
-
</node>
|
|
696
|
-
<node id="n1"/>
|
|
697
|
-
<node id="n2">
|
|
698
|
-
<data key="d0">false</data>
|
|
699
|
-
</node>
|
|
700
|
-
<node id="n3">
|
|
701
|
-
<data key="d0">FaLsE</data>
|
|
702
|
-
</node>
|
|
703
|
-
<node id="n4">
|
|
704
|
-
<data key="d0">True</data>
|
|
705
|
-
</node>
|
|
706
|
-
<node id="n5">
|
|
707
|
-
<data key="d0">0</data>
|
|
708
|
-
</node>
|
|
709
|
-
<node id="n6">
|
|
710
|
-
<data key="d0">1</data>
|
|
711
|
-
</node>
|
|
712
|
-
</graph>
|
|
713
|
-
</graphml>
|
|
714
|
-
"""
|
|
715
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
716
|
-
G = nx.read_graphml(fh)
|
|
717
|
-
H = nx.parse_graphml(s)
|
|
718
|
-
for graph in [G, H]:
|
|
719
|
-
assert graph.nodes["n0"]["test"]
|
|
720
|
-
assert not graph.nodes["n2"]["test"]
|
|
721
|
-
assert not graph.nodes["n3"]["test"]
|
|
722
|
-
assert graph.nodes["n4"]["test"]
|
|
723
|
-
assert not graph.nodes["n5"]["test"]
|
|
724
|
-
assert graph.nodes["n6"]["test"]
|
|
725
|
-
|
|
726
|
-
def test_graphml_header_line(self):
|
|
727
|
-
good = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
728
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
729
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
730
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
731
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
732
|
-
<key id="d0" for="node" attr.name="test" attr.type="boolean">
|
|
733
|
-
<default>false</default>
|
|
734
|
-
</key>
|
|
735
|
-
<graph id="G">
|
|
736
|
-
<node id="n0">
|
|
737
|
-
<data key="d0">true</data>
|
|
738
|
-
</node>
|
|
739
|
-
</graph>
|
|
740
|
-
</graphml>
|
|
741
|
-
"""
|
|
742
|
-
bad = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
743
|
-
<graphml>
|
|
744
|
-
<key id="d0" for="node" attr.name="test" attr.type="boolean">
|
|
745
|
-
<default>false</default>
|
|
746
|
-
</key>
|
|
747
|
-
<graph id="G">
|
|
748
|
-
<node id="n0">
|
|
749
|
-
<data key="d0">true</data>
|
|
750
|
-
</node>
|
|
751
|
-
</graph>
|
|
752
|
-
</graphml>
|
|
753
|
-
"""
|
|
754
|
-
ugly = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
755
|
-
<graphml xmlns="https://ghghgh">
|
|
756
|
-
<key id="d0" for="node" attr.name="test" attr.type="boolean">
|
|
757
|
-
<default>false</default>
|
|
758
|
-
</key>
|
|
759
|
-
<graph id="G">
|
|
760
|
-
<node id="n0">
|
|
761
|
-
<data key="d0">true</data>
|
|
762
|
-
</node>
|
|
763
|
-
</graph>
|
|
764
|
-
</graphml>
|
|
765
|
-
"""
|
|
766
|
-
for s in (good, bad):
|
|
767
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
768
|
-
G = nx.read_graphml(fh)
|
|
769
|
-
H = nx.parse_graphml(s)
|
|
770
|
-
for graph in [G, H]:
|
|
771
|
-
assert graph.nodes["n0"]["test"]
|
|
772
|
-
|
|
773
|
-
fh = io.BytesIO(ugly.encode("UTF-8"))
|
|
774
|
-
pytest.raises(nx.NetworkXError, nx.read_graphml, fh)
|
|
775
|
-
pytest.raises(nx.NetworkXError, nx.parse_graphml, ugly)
|
|
776
|
-
|
|
777
|
-
def test_read_attributes_with_groups(self):
|
|
778
|
-
data = """\
|
|
779
|
-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
780
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
|
|
781
|
-
<!--Created by yEd 3.17-->
|
|
782
|
-
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
|
|
783
|
-
<key for="port" id="d1" yfiles.type="portgraphics"/>
|
|
784
|
-
<key for="port" id="d2" yfiles.type="portgeometry"/>
|
|
785
|
-
<key for="port" id="d3" yfiles.type="portuserdata"/>
|
|
786
|
-
<key attr.name="CustomProperty" attr.type="string" for="node" id="d4">
|
|
787
|
-
<default/>
|
|
788
|
-
</key>
|
|
789
|
-
<key attr.name="url" attr.type="string" for="node" id="d5"/>
|
|
790
|
-
<key attr.name="description" attr.type="string" for="node" id="d6"/>
|
|
791
|
-
<key for="node" id="d7" yfiles.type="nodegraphics"/>
|
|
792
|
-
<key for="graphml" id="d8" yfiles.type="resources"/>
|
|
793
|
-
<key attr.name="url" attr.type="string" for="edge" id="d9"/>
|
|
794
|
-
<key attr.name="description" attr.type="string" for="edge" id="d10"/>
|
|
795
|
-
<key for="edge" id="d11" yfiles.type="edgegraphics"/>
|
|
796
|
-
<graph edgedefault="directed" id="G">
|
|
797
|
-
<data key="d0"/>
|
|
798
|
-
<node id="n0">
|
|
799
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
800
|
-
<data key="d6"/>
|
|
801
|
-
<data key="d7">
|
|
802
|
-
<y:ShapeNode>
|
|
803
|
-
<y:Geometry height="30.0" width="30.0" x="125.0" y="-255.4611111111111"/>
|
|
804
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
805
|
-
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
806
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">2<y:LabelModel>
|
|
807
|
-
<y:SmartNodeLabelModel distance="4.0"/>
|
|
808
|
-
</y:LabelModel>
|
|
809
|
-
<y:ModelParameter>
|
|
810
|
-
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
811
|
-
</y:ModelParameter>
|
|
812
|
-
</y:NodeLabel>
|
|
813
|
-
<y:Shape type="rectangle"/>
|
|
814
|
-
</y:ShapeNode>
|
|
815
|
-
</data>
|
|
816
|
-
</node>
|
|
817
|
-
<node id="n1" yfiles.foldertype="group">
|
|
818
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
819
|
-
<data key="d5"/>
|
|
820
|
-
<data key="d6"/>
|
|
821
|
-
<data key="d7">
|
|
822
|
-
<y:ProxyAutoBoundsNode>
|
|
823
|
-
<y:Realizers active="0">
|
|
824
|
-
<y:GroupNode>
|
|
825
|
-
<y:Geometry height="250.38333333333333" width="140.0" x="-30.0" y="-330.3833333333333"/>
|
|
826
|
-
<y:Fill color="#F5F5F5" transparent="false"/>
|
|
827
|
-
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
|
|
828
|
-
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="140.0" x="0.0" y="0.0">Group 3</y:NodeLabel>
|
|
829
|
-
<y:Shape type="roundrectangle"/>
|
|
830
|
-
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
|
|
831
|
-
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
|
|
832
|
-
<y:BorderInsets bottom="1" bottomF="1.0" left="0" leftF="0.0" right="0" rightF="0.0" top="1" topF="1.0001736111111086"/>
|
|
833
|
-
</y:GroupNode>
|
|
834
|
-
<y:GroupNode>
|
|
835
|
-
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
|
|
836
|
-
<y:Fill color="#F5F5F5" transparent="false"/>
|
|
837
|
-
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
|
|
838
|
-
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 3</y:NodeLabel>
|
|
839
|
-
<y:Shape type="roundrectangle"/>
|
|
840
|
-
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
|
|
841
|
-
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
|
|
842
|
-
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
|
|
843
|
-
</y:GroupNode>
|
|
844
|
-
</y:Realizers>
|
|
845
|
-
</y:ProxyAutoBoundsNode>
|
|
846
|
-
</data>
|
|
847
|
-
<graph edgedefault="directed" id="n1:">
|
|
848
|
-
<node id="n1::n0" yfiles.foldertype="group">
|
|
849
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
850
|
-
<data key="d5"/>
|
|
851
|
-
<data key="d6"/>
|
|
852
|
-
<data key="d7">
|
|
853
|
-
<y:ProxyAutoBoundsNode>
|
|
854
|
-
<y:Realizers active="0">
|
|
855
|
-
<y:GroupNode>
|
|
856
|
-
<y:Geometry height="83.46111111111111" width="110.0" x="-15.0" y="-292.9222222222222"/>
|
|
857
|
-
<y:Fill color="#F5F5F5" transparent="false"/>
|
|
858
|
-
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
|
|
859
|
-
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="110.0" x="0.0" y="0.0">Group 1</y:NodeLabel>
|
|
860
|
-
<y:Shape type="roundrectangle"/>
|
|
861
|
-
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
|
|
862
|
-
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
|
|
863
|
-
<y:BorderInsets bottom="1" bottomF="1.0" left="0" leftF="0.0" right="0" rightF="0.0" top="1" topF="1.0001736111111086"/>
|
|
864
|
-
</y:GroupNode>
|
|
865
|
-
<y:GroupNode>
|
|
866
|
-
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
|
|
867
|
-
<y:Fill color="#F5F5F5" transparent="false"/>
|
|
868
|
-
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
|
|
869
|
-
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 1</y:NodeLabel>
|
|
870
|
-
<y:Shape type="roundrectangle"/>
|
|
871
|
-
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
|
|
872
|
-
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
|
|
873
|
-
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
|
|
874
|
-
</y:GroupNode>
|
|
875
|
-
</y:Realizers>
|
|
876
|
-
</y:ProxyAutoBoundsNode>
|
|
877
|
-
</data>
|
|
878
|
-
<graph edgedefault="directed" id="n1::n0:">
|
|
879
|
-
<node id="n1::n0::n0">
|
|
880
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
881
|
-
<data key="d6"/>
|
|
882
|
-
<data key="d7">
|
|
883
|
-
<y:ShapeNode>
|
|
884
|
-
<y:Geometry height="30.0" width="30.0" x="50.0" y="-255.4611111111111"/>
|
|
885
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
886
|
-
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
887
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">1<y:LabelModel>
|
|
888
|
-
<y:SmartNodeLabelModel distance="4.0"/>
|
|
889
|
-
</y:LabelModel>
|
|
890
|
-
<y:ModelParameter>
|
|
891
|
-
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
892
|
-
</y:ModelParameter>
|
|
893
|
-
</y:NodeLabel>
|
|
894
|
-
<y:Shape type="rectangle"/>
|
|
895
|
-
</y:ShapeNode>
|
|
896
|
-
</data>
|
|
897
|
-
</node>
|
|
898
|
-
<node id="n1::n0::n1">
|
|
899
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
900
|
-
<data key="d6"/>
|
|
901
|
-
<data key="d7">
|
|
902
|
-
<y:ShapeNode>
|
|
903
|
-
<y:Geometry height="30.0" width="30.0" x="0.0" y="-255.4611111111111"/>
|
|
904
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
905
|
-
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
906
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">3<y:LabelModel>
|
|
907
|
-
<y:SmartNodeLabelModel distance="4.0"/>
|
|
908
|
-
</y:LabelModel>
|
|
909
|
-
<y:ModelParameter>
|
|
910
|
-
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
911
|
-
</y:ModelParameter>
|
|
912
|
-
</y:NodeLabel>
|
|
913
|
-
<y:Shape type="rectangle"/>
|
|
914
|
-
</y:ShapeNode>
|
|
915
|
-
</data>
|
|
916
|
-
</node>
|
|
917
|
-
</graph>
|
|
918
|
-
</node>
|
|
919
|
-
<node id="n1::n1" yfiles.foldertype="group">
|
|
920
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
921
|
-
<data key="d5"/>
|
|
922
|
-
<data key="d6"/>
|
|
923
|
-
<data key="d7">
|
|
924
|
-
<y:ProxyAutoBoundsNode>
|
|
925
|
-
<y:Realizers active="0">
|
|
926
|
-
<y:GroupNode>
|
|
927
|
-
<y:Geometry height="83.46111111111111" width="110.0" x="-15.0" y="-179.4611111111111"/>
|
|
928
|
-
<y:Fill color="#F5F5F5" transparent="false"/>
|
|
929
|
-
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
|
|
930
|
-
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="110.0" x="0.0" y="0.0">Group 2</y:NodeLabel>
|
|
931
|
-
<y:Shape type="roundrectangle"/>
|
|
932
|
-
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
|
|
933
|
-
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
|
|
934
|
-
<y:BorderInsets bottom="1" bottomF="1.0" left="0" leftF="0.0" right="0" rightF="0.0" top="1" topF="1.0001736111111086"/>
|
|
935
|
-
</y:GroupNode>
|
|
936
|
-
<y:GroupNode>
|
|
937
|
-
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
|
|
938
|
-
<y:Fill color="#F5F5F5" transparent="false"/>
|
|
939
|
-
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
|
|
940
|
-
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 2</y:NodeLabel>
|
|
941
|
-
<y:Shape type="roundrectangle"/>
|
|
942
|
-
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
|
|
943
|
-
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
|
|
944
|
-
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
|
|
945
|
-
</y:GroupNode>
|
|
946
|
-
</y:Realizers>
|
|
947
|
-
</y:ProxyAutoBoundsNode>
|
|
948
|
-
</data>
|
|
949
|
-
<graph edgedefault="directed" id="n1::n1:">
|
|
950
|
-
<node id="n1::n1::n0">
|
|
951
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
952
|
-
<data key="d6"/>
|
|
953
|
-
<data key="d7">
|
|
954
|
-
<y:ShapeNode>
|
|
955
|
-
<y:Geometry height="30.0" width="30.0" x="0.0" y="-142.0"/>
|
|
956
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
957
|
-
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
958
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">5<y:LabelModel>
|
|
959
|
-
<y:SmartNodeLabelModel distance="4.0"/>
|
|
960
|
-
</y:LabelModel>
|
|
961
|
-
<y:ModelParameter>
|
|
962
|
-
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
963
|
-
</y:ModelParameter>
|
|
964
|
-
</y:NodeLabel>
|
|
965
|
-
<y:Shape type="rectangle"/>
|
|
966
|
-
</y:ShapeNode>
|
|
967
|
-
</data>
|
|
968
|
-
</node>
|
|
969
|
-
<node id="n1::n1::n1">
|
|
970
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
971
|
-
<data key="d6"/>
|
|
972
|
-
<data key="d7">
|
|
973
|
-
<y:ShapeNode>
|
|
974
|
-
<y:Geometry height="30.0" width="30.0" x="50.0" y="-142.0"/>
|
|
975
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
976
|
-
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
977
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">6<y:LabelModel>
|
|
978
|
-
<y:SmartNodeLabelModel distance="4.0"/>
|
|
979
|
-
</y:LabelModel>
|
|
980
|
-
<y:ModelParameter>
|
|
981
|
-
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
982
|
-
</y:ModelParameter>
|
|
983
|
-
</y:NodeLabel>
|
|
984
|
-
<y:Shape type="rectangle"/>
|
|
985
|
-
</y:ShapeNode>
|
|
986
|
-
</data>
|
|
987
|
-
</node>
|
|
988
|
-
</graph>
|
|
989
|
-
</node>
|
|
990
|
-
</graph>
|
|
991
|
-
</node>
|
|
992
|
-
<node id="n2">
|
|
993
|
-
<data key="d4"><![CDATA[CustomPropertyValue]]></data>
|
|
994
|
-
<data key="d6"/>
|
|
995
|
-
<data key="d7">
|
|
996
|
-
<y:ShapeNode>
|
|
997
|
-
<y:Geometry height="30.0" width="30.0" x="125.0" y="-142.0"/>
|
|
998
|
-
<y:Fill color="#FFCC00" transparent="false"/>
|
|
999
|
-
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
1000
|
-
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="9.1826171875" y="6.015625">9<y:LabelModel>
|
|
1001
|
-
<y:SmartNodeLabelModel distance="4.0"/>
|
|
1002
|
-
</y:LabelModel>
|
|
1003
|
-
<y:ModelParameter>
|
|
1004
|
-
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
1005
|
-
</y:ModelParameter>
|
|
1006
|
-
</y:NodeLabel>
|
|
1007
|
-
<y:Shape type="rectangle"/>
|
|
1008
|
-
</y:ShapeNode>
|
|
1009
|
-
</data>
|
|
1010
|
-
</node>
|
|
1011
|
-
<edge id="n1::n1::e0" source="n1::n1::n0" target="n1::n1::n1">
|
|
1012
|
-
<data key="d10"/>
|
|
1013
|
-
<data key="d11">
|
|
1014
|
-
<y:PolyLineEdge>
|
|
1015
|
-
<y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/>
|
|
1016
|
-
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
1017
|
-
<y:Arrows source="none" target="standard"/>
|
|
1018
|
-
<y:BendStyle smoothed="false"/>
|
|
1019
|
-
</y:PolyLineEdge>
|
|
1020
|
-
</data>
|
|
1021
|
-
</edge>
|
|
1022
|
-
<edge id="n1::n0::e0" source="n1::n0::n1" target="n1::n0::n0">
|
|
1023
|
-
<data key="d10"/>
|
|
1024
|
-
<data key="d11">
|
|
1025
|
-
<y:PolyLineEdge>
|
|
1026
|
-
<y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/>
|
|
1027
|
-
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
1028
|
-
<y:Arrows source="none" target="standard"/>
|
|
1029
|
-
<y:BendStyle smoothed="false"/>
|
|
1030
|
-
</y:PolyLineEdge>
|
|
1031
|
-
</data>
|
|
1032
|
-
</edge>
|
|
1033
|
-
<edge id="e0" source="n1::n0::n0" target="n0">
|
|
1034
|
-
<data key="d10"/>
|
|
1035
|
-
<data key="d11">
|
|
1036
|
-
<y:PolyLineEdge>
|
|
1037
|
-
<y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/>
|
|
1038
|
-
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
1039
|
-
<y:Arrows source="none" target="standard"/>
|
|
1040
|
-
<y:BendStyle smoothed="false"/>
|
|
1041
|
-
</y:PolyLineEdge>
|
|
1042
|
-
</data>
|
|
1043
|
-
</edge>
|
|
1044
|
-
<edge id="e1" source="n1::n1::n1" target="n2">
|
|
1045
|
-
<data key="d10"/>
|
|
1046
|
-
<data key="d11">
|
|
1047
|
-
<y:PolyLineEdge>
|
|
1048
|
-
<y:Path sx="15.0" sy="-0.0" tx="-15.0" ty="-0.0"/>
|
|
1049
|
-
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
1050
|
-
<y:Arrows source="none" target="standard"/>
|
|
1051
|
-
<y:BendStyle smoothed="false"/>
|
|
1052
|
-
</y:PolyLineEdge>
|
|
1053
|
-
</data>
|
|
1054
|
-
</edge>
|
|
1055
|
-
</graph>
|
|
1056
|
-
<data key="d8">
|
|
1057
|
-
<y:Resources/>
|
|
1058
|
-
</data>
|
|
1059
|
-
</graphml>
|
|
1060
|
-
"""
|
|
1061
|
-
# verify that nodes / attributes are correctly read when part of a group
|
|
1062
|
-
fh = io.BytesIO(data.encode("UTF-8"))
|
|
1063
|
-
G = nx.read_graphml(fh)
|
|
1064
|
-
data = [x for _, x in G.nodes(data=True)]
|
|
1065
|
-
assert len(data) == 9
|
|
1066
|
-
for node_data in data:
|
|
1067
|
-
assert node_data["CustomProperty"] != ""
|
|
1068
|
-
|
|
1069
|
-
def test_long_attribute_type(self):
|
|
1070
|
-
# test that graphs with attr.type="long" (as produced by botch and
|
|
1071
|
-
# dose3) can be parsed
|
|
1072
|
-
s = """<?xml version='1.0' encoding='utf-8'?>
|
|
1073
|
-
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
1074
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
1075
|
-
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
|
1076
|
-
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
1077
|
-
<key attr.name="cudfversion" attr.type="long" for="node" id="d6" />
|
|
1078
|
-
<graph edgedefault="directed">
|
|
1079
|
-
<node id="n1">
|
|
1080
|
-
<data key="d6">4284</data>
|
|
1081
|
-
</node>
|
|
1082
|
-
</graph>
|
|
1083
|
-
</graphml>"""
|
|
1084
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
1085
|
-
G = nx.read_graphml(fh)
|
|
1086
|
-
expected = [("n1", {"cudfversion": 4284})]
|
|
1087
|
-
assert sorted(G.nodes(data=True)) == expected
|
|
1088
|
-
fh.seek(0)
|
|
1089
|
-
H = nx.parse_graphml(s)
|
|
1090
|
-
assert sorted(H.nodes(data=True)) == expected
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
class TestWriteGraphML(BaseGraphML):
|
|
1094
|
-
writer = staticmethod(nx.write_graphml_lxml)
|
|
1095
|
-
|
|
1096
|
-
@classmethod
|
|
1097
|
-
def setup_class(cls):
|
|
1098
|
-
BaseGraphML.setup_class()
|
|
1099
|
-
_ = pytest.importorskip("lxml.etree")
|
|
1100
|
-
|
|
1101
|
-
def test_write_interface(self):
|
|
1102
|
-
try:
|
|
1103
|
-
import lxml.etree
|
|
1104
|
-
|
|
1105
|
-
assert nx.write_graphml == nx.write_graphml_lxml
|
|
1106
|
-
except ImportError:
|
|
1107
|
-
assert nx.write_graphml == nx.write_graphml_xml
|
|
1108
|
-
|
|
1109
|
-
def test_write_read_simple_directed_graphml(self):
|
|
1110
|
-
G = self.simple_directed_graph
|
|
1111
|
-
G.graph["hi"] = "there"
|
|
1112
|
-
fh = io.BytesIO()
|
|
1113
|
-
self.writer(G, fh)
|
|
1114
|
-
fh.seek(0)
|
|
1115
|
-
H = nx.read_graphml(fh)
|
|
1116
|
-
assert sorted(G.nodes()) == sorted(H.nodes())
|
|
1117
|
-
assert sorted(G.edges()) == sorted(H.edges())
|
|
1118
|
-
assert sorted(G.edges(data=True)) == sorted(H.edges(data=True))
|
|
1119
|
-
self.simple_directed_fh.seek(0)
|
|
1120
|
-
|
|
1121
|
-
def test_GraphMLWriter_add_graphs(self):
|
|
1122
|
-
gmlw = GraphMLWriter()
|
|
1123
|
-
G = self.simple_directed_graph
|
|
1124
|
-
H = G.copy()
|
|
1125
|
-
gmlw.add_graphs([G, H])
|
|
1126
|
-
|
|
1127
|
-
def test_write_read_simple_no_prettyprint(self):
|
|
1128
|
-
G = self.simple_directed_graph
|
|
1129
|
-
G.graph["hi"] = "there"
|
|
1130
|
-
G.graph["id"] = "1"
|
|
1131
|
-
fh = io.BytesIO()
|
|
1132
|
-
self.writer(G, fh, prettyprint=False)
|
|
1133
|
-
fh.seek(0)
|
|
1134
|
-
H = nx.read_graphml(fh)
|
|
1135
|
-
assert sorted(G.nodes()) == sorted(H.nodes())
|
|
1136
|
-
assert sorted(G.edges()) == sorted(H.edges())
|
|
1137
|
-
assert sorted(G.edges(data=True)) == sorted(H.edges(data=True))
|
|
1138
|
-
self.simple_directed_fh.seek(0)
|
|
1139
|
-
|
|
1140
|
-
def test_write_read_attribute_named_key_ids_graphml(self):
|
|
1141
|
-
from xml.etree.ElementTree import parse
|
|
1142
|
-
|
|
1143
|
-
G = self.attribute_named_key_ids_graph
|
|
1144
|
-
fh = io.BytesIO()
|
|
1145
|
-
self.writer(G, fh, named_key_ids=True)
|
|
1146
|
-
fh.seek(0)
|
|
1147
|
-
H = nx.read_graphml(fh)
|
|
1148
|
-
fh.seek(0)
|
|
1149
|
-
|
|
1150
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
1151
|
-
assert edges_equal(G.edges(), H.edges(), directed=True)
|
|
1152
|
-
assert edges_equal(G.edges(data=True), H.edges(data=True), directed=True)
|
|
1153
|
-
self.attribute_named_key_ids_fh.seek(0)
|
|
1154
|
-
|
|
1155
|
-
xml = parse(fh)
|
|
1156
|
-
# Children are the key elements, and the graph element
|
|
1157
|
-
children = list(xml.getroot())
|
|
1158
|
-
assert len(children) == 4
|
|
1159
|
-
|
|
1160
|
-
keys = [child.items() for child in children[:3]]
|
|
1161
|
-
|
|
1162
|
-
assert len(keys) == 3
|
|
1163
|
-
assert ("id", "edge_prop") in keys[0]
|
|
1164
|
-
assert ("attr.name", "edge_prop") in keys[0]
|
|
1165
|
-
assert ("id", "prop2") in keys[1]
|
|
1166
|
-
assert ("attr.name", "prop2") in keys[1]
|
|
1167
|
-
assert ("id", "prop1") in keys[2]
|
|
1168
|
-
assert ("attr.name", "prop1") in keys[2]
|
|
1169
|
-
|
|
1170
|
-
# Confirm the read graph nodes/edge are identical when compared to
|
|
1171
|
-
# default writing behavior.
|
|
1172
|
-
default_behavior_fh = io.BytesIO()
|
|
1173
|
-
nx.write_graphml(G, default_behavior_fh)
|
|
1174
|
-
default_behavior_fh.seek(0)
|
|
1175
|
-
H = nx.read_graphml(default_behavior_fh)
|
|
1176
|
-
|
|
1177
|
-
named_key_ids_behavior_fh = io.BytesIO()
|
|
1178
|
-
nx.write_graphml(G, named_key_ids_behavior_fh, named_key_ids=True)
|
|
1179
|
-
named_key_ids_behavior_fh.seek(0)
|
|
1180
|
-
J = nx.read_graphml(named_key_ids_behavior_fh)
|
|
1181
|
-
|
|
1182
|
-
assert all(n1 == n2 for (n1, n2) in zip(H.nodes, J.nodes))
|
|
1183
|
-
assert all(e1 == e2 for (e1, e2) in zip(H.edges, J.edges))
|
|
1184
|
-
|
|
1185
|
-
def test_write_read_attribute_numeric_type_graphml(self):
|
|
1186
|
-
from xml.etree.ElementTree import parse
|
|
1187
|
-
|
|
1188
|
-
G = self.attribute_numeric_type_graph
|
|
1189
|
-
fh = io.BytesIO()
|
|
1190
|
-
self.writer(G, fh, infer_numeric_types=True)
|
|
1191
|
-
fh.seek(0)
|
|
1192
|
-
H = nx.read_graphml(fh)
|
|
1193
|
-
fh.seek(0)
|
|
1194
|
-
|
|
1195
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
1196
|
-
assert edges_equal(G.edges(), H.edges(), directed=True)
|
|
1197
|
-
assert edges_equal(G.edges(data=True), H.edges(data=True), directed=True)
|
|
1198
|
-
self.attribute_numeric_type_fh.seek(0)
|
|
1199
|
-
|
|
1200
|
-
xml = parse(fh)
|
|
1201
|
-
# Children are the key elements, and the graph element
|
|
1202
|
-
children = list(xml.getroot())
|
|
1203
|
-
assert len(children) == 3
|
|
1204
|
-
|
|
1205
|
-
keys = [child.items() for child in children[:2]]
|
|
1206
|
-
|
|
1207
|
-
assert len(keys) == 2
|
|
1208
|
-
assert ("attr.type", "double") in keys[0]
|
|
1209
|
-
assert ("attr.type", "double") in keys[1]
|
|
1210
|
-
|
|
1211
|
-
def test_more_multigraph_keys(self, tmp_path):
|
|
1212
|
-
"""Writing keys as edge id attributes means keys become strings.
|
|
1213
|
-
The original keys are stored as data, so read them back in
|
|
1214
|
-
if `str(key) == edge_id`
|
|
1215
|
-
This allows the adjacency to remain the same.
|
|
1216
|
-
"""
|
|
1217
|
-
G = nx.MultiGraph()
|
|
1218
|
-
G.add_edges_from([("a", "b", 2), ("a", "b", 3)])
|
|
1219
|
-
fname = tmp_path / "test.graphml"
|
|
1220
|
-
self.writer(G, fname)
|
|
1221
|
-
H = nx.read_graphml(fname)
|
|
1222
|
-
assert H.is_multigraph()
|
|
1223
|
-
assert edges_equal(G.edges(keys=True), H.edges(keys=True))
|
|
1224
|
-
assert G._adj == H._adj
|
|
1225
|
-
|
|
1226
|
-
def test_default_attribute(self):
|
|
1227
|
-
G = nx.Graph(name="Fred")
|
|
1228
|
-
G.add_node(1, label=1, color="green")
|
|
1229
|
-
nx.add_path(G, [0, 1, 2, 3])
|
|
1230
|
-
G.add_edge(1, 2, weight=3)
|
|
1231
|
-
G.graph["node_default"] = {"color": "yellow"}
|
|
1232
|
-
G.graph["edge_default"] = {"weight": 7}
|
|
1233
|
-
fh = io.BytesIO()
|
|
1234
|
-
self.writer(G, fh)
|
|
1235
|
-
fh.seek(0)
|
|
1236
|
-
H = nx.read_graphml(fh, node_type=int)
|
|
1237
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
1238
|
-
assert edges_equal(G.edges(), H.edges())
|
|
1239
|
-
assert G.graph == H.graph
|
|
1240
|
-
|
|
1241
|
-
def test_mixed_type_attributes(self):
|
|
1242
|
-
G = nx.MultiGraph()
|
|
1243
|
-
G.add_node("n0", special=False)
|
|
1244
|
-
G.add_node("n1", special=0)
|
|
1245
|
-
G.add_edge("n0", "n1", special=False)
|
|
1246
|
-
G.add_edge("n0", "n1", special=0)
|
|
1247
|
-
fh = io.BytesIO()
|
|
1248
|
-
self.writer(G, fh)
|
|
1249
|
-
fh.seek(0)
|
|
1250
|
-
H = nx.read_graphml(fh)
|
|
1251
|
-
assert not H.nodes["n0"]["special"]
|
|
1252
|
-
assert H.nodes["n1"]["special"] == 0
|
|
1253
|
-
assert not H.edges["n0", "n1", 0]["special"]
|
|
1254
|
-
assert H.edges["n0", "n1", 1]["special"] == 0
|
|
1255
|
-
|
|
1256
|
-
def test_str_number_mixed_type_attributes(self):
|
|
1257
|
-
G = nx.MultiGraph()
|
|
1258
|
-
G.add_node("n0", special="hello")
|
|
1259
|
-
G.add_node("n1", special=0)
|
|
1260
|
-
G.add_edge("n0", "n1", special="hello")
|
|
1261
|
-
G.add_edge("n0", "n1", special=0)
|
|
1262
|
-
fh = io.BytesIO()
|
|
1263
|
-
self.writer(G, fh)
|
|
1264
|
-
fh.seek(0)
|
|
1265
|
-
H = nx.read_graphml(fh)
|
|
1266
|
-
assert H.nodes["n0"]["special"] == "hello"
|
|
1267
|
-
assert H.nodes["n1"]["special"] == 0
|
|
1268
|
-
assert H.edges["n0", "n1", 0]["special"] == "hello"
|
|
1269
|
-
assert H.edges["n0", "n1", 1]["special"] == 0
|
|
1270
|
-
|
|
1271
|
-
def test_mixed_int_type_number_attributes(self):
|
|
1272
|
-
np = pytest.importorskip("numpy")
|
|
1273
|
-
G = nx.MultiGraph()
|
|
1274
|
-
G.add_node("n0", special=np.int64(0))
|
|
1275
|
-
G.add_node("n1", special=1)
|
|
1276
|
-
G.add_edge("n0", "n1", special=np.int64(2))
|
|
1277
|
-
G.add_edge("n0", "n1", special=3)
|
|
1278
|
-
fh = io.BytesIO()
|
|
1279
|
-
self.writer(G, fh)
|
|
1280
|
-
fh.seek(0)
|
|
1281
|
-
H = nx.read_graphml(fh)
|
|
1282
|
-
assert H.nodes["n0"]["special"] == 0
|
|
1283
|
-
assert H.nodes["n1"]["special"] == 1
|
|
1284
|
-
assert H.edges["n0", "n1", 0]["special"] == 2
|
|
1285
|
-
assert H.edges["n0", "n1", 1]["special"] == 3
|
|
1286
|
-
|
|
1287
|
-
def test_multigraph_to_graph(self, tmp_path):
|
|
1288
|
-
# test converting multigraph to graph if no parallel edges found
|
|
1289
|
-
G = nx.MultiGraph()
|
|
1290
|
-
G.add_edges_from([("a", "b", 2), ("b", "c", 3)]) # no multiedges
|
|
1291
|
-
fname = tmp_path / "test.graphml"
|
|
1292
|
-
self.writer(G, fname)
|
|
1293
|
-
H = nx.read_graphml(fname)
|
|
1294
|
-
assert not H.is_multigraph()
|
|
1295
|
-
H = nx.read_graphml(fname, force_multigraph=True)
|
|
1296
|
-
assert H.is_multigraph()
|
|
1297
|
-
|
|
1298
|
-
# add a multiedge
|
|
1299
|
-
G.add_edge("a", "b", "e-id")
|
|
1300
|
-
fname = tmp_path / "test.graphml"
|
|
1301
|
-
self.writer(G, fname)
|
|
1302
|
-
H = nx.read_graphml(fname)
|
|
1303
|
-
assert H.is_multigraph()
|
|
1304
|
-
H = nx.read_graphml(fname, force_multigraph=True)
|
|
1305
|
-
assert H.is_multigraph()
|
|
1306
|
-
|
|
1307
|
-
def test_write_generate_edge_id_from_attribute(self, tmp_path):
|
|
1308
|
-
from xml.etree.ElementTree import parse
|
|
1309
|
-
|
|
1310
|
-
G = nx.Graph()
|
|
1311
|
-
G.add_edges_from([("a", "b"), ("b", "c"), ("a", "c")])
|
|
1312
|
-
edge_attributes = {e: str(e) for e in G.edges}
|
|
1313
|
-
nx.set_edge_attributes(G, edge_attributes, "eid")
|
|
1314
|
-
fname = tmp_path / "test.graphml"
|
|
1315
|
-
# set edge_id_from_attribute e.g. "eid" for write_graphml()
|
|
1316
|
-
self.writer(G, fname, edge_id_from_attribute="eid")
|
|
1317
|
-
# set edge_id_from_attribute e.g. "eid" for generate_graphml()
|
|
1318
|
-
generator = nx.generate_graphml(G, edge_id_from_attribute="eid")
|
|
1319
|
-
|
|
1320
|
-
H = nx.read_graphml(fname)
|
|
1321
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
1322
|
-
assert edges_equal(G.edges(), H.edges())
|
|
1323
|
-
# NetworkX adds explicit edge "id" from file as attribute
|
|
1324
|
-
nx.set_edge_attributes(G, edge_attributes, "id")
|
|
1325
|
-
assert edges_equal(G.edges(data=True), H.edges(data=True))
|
|
1326
|
-
|
|
1327
|
-
tree = parse(fname)
|
|
1328
|
-
children = list(tree.getroot())
|
|
1329
|
-
assert len(children) == 2
|
|
1330
|
-
edge_ids = [
|
|
1331
|
-
edge.attrib["id"]
|
|
1332
|
-
for edge in tree.getroot().findall(
|
|
1333
|
-
".//{http://graphml.graphdrawing.org/xmlns}edge"
|
|
1334
|
-
)
|
|
1335
|
-
]
|
|
1336
|
-
# verify edge id value is equal to specified attribute value
|
|
1337
|
-
assert sorted(edge_ids) == sorted(edge_attributes.values())
|
|
1338
|
-
|
|
1339
|
-
# check graphml generated from generate_graphml()
|
|
1340
|
-
data = "".join(generator)
|
|
1341
|
-
J = nx.parse_graphml(data)
|
|
1342
|
-
assert sorted(G.nodes()) == sorted(J.nodes())
|
|
1343
|
-
assert sorted(G.edges()) == sorted(J.edges())
|
|
1344
|
-
# NetworkX adds explicit edge "id" from file as attribute
|
|
1345
|
-
nx.set_edge_attributes(G, edge_attributes, "id")
|
|
1346
|
-
assert edges_equal(G.edges(data=True), J.edges(data=True))
|
|
1347
|
-
|
|
1348
|
-
def test_multigraph_write_generate_edge_id_from_attribute(self, tmp_path):
|
|
1349
|
-
from xml.etree.ElementTree import parse
|
|
1350
|
-
|
|
1351
|
-
G = nx.MultiGraph()
|
|
1352
|
-
G.add_edges_from([("a", "b"), ("b", "c"), ("a", "c"), ("a", "b")])
|
|
1353
|
-
edge_attributes = {e: str(e) for e in G.edges}
|
|
1354
|
-
nx.set_edge_attributes(G, edge_attributes, "eid")
|
|
1355
|
-
fname = tmp_path / "test.graphml"
|
|
1356
|
-
# set edge_id_from_attribute e.g. "eid" for write_graphml()
|
|
1357
|
-
self.writer(G, fname, edge_id_from_attribute="eid")
|
|
1358
|
-
# set edge_id_from_attribute e.g. "eid" for generate_graphml()
|
|
1359
|
-
generator = nx.generate_graphml(G, edge_id_from_attribute="eid")
|
|
1360
|
-
|
|
1361
|
-
H = nx.read_graphml(fname)
|
|
1362
|
-
assert H.is_multigraph()
|
|
1363
|
-
H = nx.read_graphml(fname, force_multigraph=True)
|
|
1364
|
-
assert H.is_multigraph()
|
|
1365
|
-
|
|
1366
|
-
assert nodes_equal(G.nodes(), H.nodes())
|
|
1367
|
-
assert edges_equal(G.edges(), H.edges())
|
|
1368
|
-
assert sorted(data.get("eid") for u, v, data in H.edges(data=True)) == sorted(
|
|
1369
|
-
edge_attributes.values()
|
|
1370
|
-
)
|
|
1371
|
-
# NetworkX uses edge_ids as keys in multigraphs if no key
|
|
1372
|
-
assert sorted(key for u, v, key in H.edges(keys=True)) == sorted(
|
|
1373
|
-
edge_attributes.values()
|
|
1374
|
-
)
|
|
1375
|
-
|
|
1376
|
-
tree = parse(fname)
|
|
1377
|
-
children = list(tree.getroot())
|
|
1378
|
-
assert len(children) == 2
|
|
1379
|
-
edge_ids = [
|
|
1380
|
-
edge.attrib["id"]
|
|
1381
|
-
for edge in tree.getroot().findall(
|
|
1382
|
-
".//{http://graphml.graphdrawing.org/xmlns}edge"
|
|
1383
|
-
)
|
|
1384
|
-
]
|
|
1385
|
-
# verify edge id value is equal to specified attribute value
|
|
1386
|
-
assert sorted(edge_ids) == sorted(edge_attributes.values())
|
|
1387
|
-
|
|
1388
|
-
# check graphml generated from generate_graphml()
|
|
1389
|
-
graphml_data = "".join(generator)
|
|
1390
|
-
J = nx.parse_graphml(graphml_data)
|
|
1391
|
-
assert J.is_multigraph()
|
|
1392
|
-
|
|
1393
|
-
assert nodes_equal(G.nodes(), J.nodes())
|
|
1394
|
-
assert edges_equal(G.edges(), J.edges())
|
|
1395
|
-
assert sorted(data.get("eid") for u, v, data in J.edges(data=True)) == sorted(
|
|
1396
|
-
edge_attributes.values()
|
|
1397
|
-
)
|
|
1398
|
-
# NetworkX uses edge_ids as keys in multigraphs if no key
|
|
1399
|
-
assert sorted(key for u, v, key in J.edges(keys=True)) == sorted(
|
|
1400
|
-
edge_attributes.values()
|
|
1401
|
-
)
|
|
1402
|
-
|
|
1403
|
-
def test_numpy_float64(self, tmp_path):
|
|
1404
|
-
np = pytest.importorskip("numpy")
|
|
1405
|
-
wt = np.float64(3.4)
|
|
1406
|
-
G = nx.Graph([(1, 2, {"weight": wt})])
|
|
1407
|
-
fname = tmp_path / "test.graphml"
|
|
1408
|
-
self.writer(G, fname)
|
|
1409
|
-
H = nx.read_graphml(fname, node_type=int)
|
|
1410
|
-
assert G.edges == H.edges
|
|
1411
|
-
wtG = G[1][2]["weight"]
|
|
1412
|
-
wtH = H[1][2]["weight"]
|
|
1413
|
-
assert wtG == pytest.approx(wtH, abs=1e-6)
|
|
1414
|
-
assert type(wtG) is np.float64
|
|
1415
|
-
assert type(wtH) is float
|
|
1416
|
-
|
|
1417
|
-
def test_numpy_float32(self, tmp_path):
|
|
1418
|
-
np = pytest.importorskip("numpy")
|
|
1419
|
-
wt = np.float32(3.4)
|
|
1420
|
-
G = nx.Graph([(1, 2, {"weight": wt})])
|
|
1421
|
-
fname = tmp_path / "test.graphml"
|
|
1422
|
-
self.writer(G, fname)
|
|
1423
|
-
H = nx.read_graphml(fname, node_type=int)
|
|
1424
|
-
assert G.edges == H.edges
|
|
1425
|
-
wtG = G[1][2]["weight"]
|
|
1426
|
-
wtH = H[1][2]["weight"]
|
|
1427
|
-
assert wtG == pytest.approx(wtH, abs=1e-6)
|
|
1428
|
-
assert type(wtG) is np.float32
|
|
1429
|
-
assert type(wtH) is float
|
|
1430
|
-
|
|
1431
|
-
def test_numpy_float64_inference(self, tmp_path):
|
|
1432
|
-
np = pytest.importorskip("numpy")
|
|
1433
|
-
G = self.attribute_numeric_type_graph
|
|
1434
|
-
G.edges[("n1", "n1")]["weight"] = np.float64(1.1)
|
|
1435
|
-
fname = tmp_path / "test.graphml"
|
|
1436
|
-
self.writer(G, fname, infer_numeric_types=True)
|
|
1437
|
-
H = nx.read_graphml(fname)
|
|
1438
|
-
assert G._adj == H._adj
|
|
1439
|
-
|
|
1440
|
-
def test_unicode_attributes(self, tmp_path):
|
|
1441
|
-
G = nx.Graph()
|
|
1442
|
-
name1 = chr(2344) + chr(123) + chr(6543)
|
|
1443
|
-
name2 = chr(5543) + chr(1543) + chr(324)
|
|
1444
|
-
node_type = str
|
|
1445
|
-
G.add_edge(name1, "Radiohead", foo=name2)
|
|
1446
|
-
fname = tmp_path / "test.graphml"
|
|
1447
|
-
self.writer(G, fname)
|
|
1448
|
-
H = nx.read_graphml(fname, node_type=node_type)
|
|
1449
|
-
assert G._adj == H._adj
|
|
1450
|
-
|
|
1451
|
-
def test_unicode_escape(self):
|
|
1452
|
-
# test for handling json escaped strings in python 2 Issue #1880
|
|
1453
|
-
import json
|
|
1454
|
-
|
|
1455
|
-
a = {"a": '{"a": "123"}'} # an object with many chars to escape
|
|
1456
|
-
sa = json.dumps(a)
|
|
1457
|
-
G = nx.Graph()
|
|
1458
|
-
G.graph["test"] = sa
|
|
1459
|
-
fh = io.BytesIO()
|
|
1460
|
-
self.writer(G, fh)
|
|
1461
|
-
fh.seek(0)
|
|
1462
|
-
H = nx.read_graphml(fh)
|
|
1463
|
-
assert G.graph["test"] == H.graph["test"]
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
class TestXMLGraphML(TestWriteGraphML):
|
|
1467
|
-
writer = staticmethod(nx.write_graphml_xml)
|
|
1468
|
-
|
|
1469
|
-
@classmethod
|
|
1470
|
-
def setup_class(cls):
|
|
1471
|
-
TestWriteGraphML.setup_class()
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
def test_exception_for_unsupported_datatype_node_attr():
|
|
1475
|
-
"""Test that a detailed exception is raised when an attribute is of a type
|
|
1476
|
-
not supported by GraphML, e.g. a list"""
|
|
1477
|
-
pytest.importorskip("lxml.etree")
|
|
1478
|
-
# node attribute
|
|
1479
|
-
G = nx.Graph()
|
|
1480
|
-
G.add_node(0, my_list_attribute=[0, 1, 2])
|
|
1481
|
-
fh = io.BytesIO()
|
|
1482
|
-
with pytest.raises(TypeError, match="GraphML does not support"):
|
|
1483
|
-
nx.write_graphml(G, fh)
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
def test_exception_for_unsupported_datatype_edge_attr():
|
|
1487
|
-
"""Test that a detailed exception is raised when an attribute is of a type
|
|
1488
|
-
not supported by GraphML, e.g. a list"""
|
|
1489
|
-
pytest.importorskip("lxml.etree")
|
|
1490
|
-
# edge attribute
|
|
1491
|
-
G = nx.Graph()
|
|
1492
|
-
G.add_edge(0, 1, my_list_attribute=[0, 1, 2])
|
|
1493
|
-
fh = io.BytesIO()
|
|
1494
|
-
with pytest.raises(TypeError, match="GraphML does not support"):
|
|
1495
|
-
nx.write_graphml(G, fh)
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
def test_exception_for_unsupported_datatype_graph_attr():
|
|
1499
|
-
"""Test that a detailed exception is raised when an attribute is of a type
|
|
1500
|
-
not supported by GraphML, e.g. a list"""
|
|
1501
|
-
pytest.importorskip("lxml.etree")
|
|
1502
|
-
# graph attribute
|
|
1503
|
-
G = nx.Graph()
|
|
1504
|
-
G.graph["my_list_attribute"] = [0, 1, 2]
|
|
1505
|
-
fh = io.BytesIO()
|
|
1506
|
-
with pytest.raises(TypeError, match="GraphML does not support"):
|
|
1507
|
-
nx.write_graphml(G, fh)
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
def test_empty_attribute():
|
|
1511
|
-
"""Tests that a GraphML string with an empty attribute can be parsed
|
|
1512
|
-
correctly."""
|
|
1513
|
-
s = """<?xml version='1.0' encoding='utf-8'?>
|
|
1514
|
-
<graphml>
|
|
1515
|
-
<key id="d1" for="node" attr.name="foo" attr.type="string"/>
|
|
1516
|
-
<key id="d2" for="node" attr.name="bar" attr.type="string"/>
|
|
1517
|
-
<graph>
|
|
1518
|
-
<node id="0">
|
|
1519
|
-
<data key="d1">aaa</data>
|
|
1520
|
-
<data key="d2">bbb</data>
|
|
1521
|
-
</node>
|
|
1522
|
-
<node id="1">
|
|
1523
|
-
<data key="d1">ccc</data>
|
|
1524
|
-
<data key="d2"></data>
|
|
1525
|
-
</node>
|
|
1526
|
-
</graph>
|
|
1527
|
-
</graphml>"""
|
|
1528
|
-
fh = io.BytesIO(s.encode("UTF-8"))
|
|
1529
|
-
G = nx.read_graphml(fh)
|
|
1530
|
-
assert G.nodes["0"] == {"foo": "aaa", "bar": "bbb"}
|
|
1531
|
-
assert G.nodes["1"] == {"foo": "ccc", "bar": ""}
|