py3plex 2.0.6__tar.gz → 2.0.8__tar.gz

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.
Files changed (953) hide show
  1. {py3plex-2.0.6/py3plex.egg-info → py3plex-2.0.8}/PKG-INFO +2 -2
  2. {py3plex-2.0.6 → py3plex-2.0.8}/README.md +1 -1
  3. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/__init__.py +3 -2
  4. py3plex-2.0.8/py3plex/_version.py +3 -0
  5. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/cli.py +11 -14
  6. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/config.py +3 -2
  7. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/multinet.py +20 -17
  8. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/builder.py +1 -1
  9. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/executor.py +53 -2
  10. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/program.py +3 -3
  11. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/result.py +62 -2
  12. py3plex-2.0.8/py3plex/safe_dsl_expression.py +83 -0
  13. {py3plex-2.0.6 → py3plex-2.0.8/py3plex.egg-info}/PKG-INFO +2 -2
  14. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex.egg-info/SOURCES.txt +2 -0
  15. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex_mcp/__init__.py +2 -2
  16. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex_mcp/server.py +4 -13
  17. {py3plex-2.0.6 → py3plex-2.0.8}/pyproject.toml +4 -1
  18. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_book_conf.py +1 -1
  19. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_book_manuscript_integrity.py +4 -4
  20. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_cli.py +30 -0
  21. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_create_showcase_flow.py +2 -1
  22. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_doc_conf.py +9 -3
  23. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_communities.py +6 -0
  24. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_export.py +49 -0
  25. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_multilayer_measure_topology.py +21 -12
  26. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_v2.py +19 -0
  27. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mcp_server.py +20 -0
  28. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_program.py +2 -1
  29. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_version_consistency.py +33 -6
  30. {py3plex-2.0.6 → py3plex-2.0.8}/LICENSE +0 -0
  31. {py3plex-2.0.6 → py3plex-2.0.8}/MANIFEST.in +0 -0
  32. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/__main__.py +0 -0
  33. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/_parallel.py +0 -0
  34. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/_safe_expression.py +0 -0
  35. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/agent.py +0 -0
  36. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/__init__.py +0 -0
  37. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/backend.py +0 -0
  38. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/closure.py +0 -0
  39. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/fixed_point.py +0 -0
  40. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/lift.py +0 -0
  41. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/paths.py +0 -0
  42. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/registry.py +0 -0
  43. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/semiring.py +0 -0
  44. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algebra/witness.py +0 -0
  45. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/__init__.py +0 -0
  46. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/advanced_random_generators.py +0 -0
  47. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/attribute_correlation.py +0 -0
  48. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/centrality/__init__.py +0 -0
  49. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/centrality/approx_betweenness.py +0 -0
  50. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/centrality/approx_closeness.py +0 -0
  51. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/centrality/approx_pagerank.py +0 -0
  52. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/centrality/explain.py +0 -0
  53. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/centrality_toolkit.py +0 -0
  54. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_comparison.py +0 -0
  55. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/NoRC.py +0 -0
  56. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/__init__.py +0 -0
  57. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/auto_select.py +0 -0
  58. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/autocommunity.py +0 -0
  59. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/autocommunity_executor.py +0 -0
  60. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/budget.py +0 -0
  61. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/community_louvain.py +0 -0
  62. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/community_measures.py +0 -0
  63. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/community_ranking.py +0 -0
  64. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/community_wrapper.py +0 -0
  65. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/distributional.py +0 -0
  66. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/flow_hierarchy.py +0 -0
  67. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/__init__.py +0 -0
  68. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/conftest.py +0 -0
  69. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-bipartite.py +0 -0
  70. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-file-io.py +0 -0
  71. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-multiplex.py +0 -0
  72. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-networkx.py +0 -0
  73. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-simple.py +0 -0
  74. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram-expanded.py +0 -0
  75. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram.py +0 -0
  76. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/infomap.py +0 -0
  77. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/infomap/interfaces/python/setup.py +0 -0
  78. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/label_propagation.py +0 -0
  79. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/leiden_multilayer.py +0 -0
  80. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/leiden_uq.py +0 -0
  81. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/mdl_benchmark.py +0 -0
  82. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/multilayer_benchmark.py +0 -0
  83. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/multilayer_modularity.py +0 -0
  84. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/multilayer_quality_metrics.py +0 -0
  85. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/node_ranking.py +0 -0
  86. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/runner.py +0 -0
  87. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/sbm_metrics.py +0 -0
  88. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/sbm_wrapper.py +0 -0
  89. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/spectral_multilayer.py +0 -0
  90. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/community_detection/successive_halving.py +0 -0
  91. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/curvature/__init__.py +0 -0
  92. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/curvature/ollivier_ricci_multilayer.py +0 -0
  93. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/general/__init__.py +0 -0
  94. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/general/benchmark_classification.py +0 -0
  95. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/general/walkers.py +0 -0
  96. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/graph_summarization.py +0 -0
  97. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/__init__.py +0 -0
  98. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/__main__.py +0 -0
  99. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/assets/builtin.n3 +0 -0
  100. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/__init__.py +0 -0
  101. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/converters.py +0 -0
  102. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/example.py +0 -0
  103. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/helpers.py +0 -0
  104. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/kb.py +0 -0
  105. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/load.py +0 -0
  106. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/predicate.py +0 -0
  107. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/rule.py +0 -0
  108. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/settings.py +0 -0
  109. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/core/term_parsers.py +0 -0
  110. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/learners/__init__.py +0 -0
  111. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/learners/bottomup.py +0 -0
  112. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/learners/learner.py +0 -0
  113. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/learners/optimal.py +0 -0
  114. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/stats/__init__.py +0 -0
  115. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/stats/adjustment.py +0 -0
  116. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/stats/scorefunctions.py +0 -0
  117. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/stats/significance.py +0 -0
  118. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/hedwig/stats/validate.py +0 -0
  119. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/layer_similarity.py +0 -0
  120. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/meta_flow_report.py +0 -0
  121. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multicentrality.py +0 -0
  122. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/__init__.py +0 -0
  123. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/centrality.py +0 -0
  124. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/entanglement.py +0 -0
  125. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/multirank.py +0 -0
  126. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/multixrank.py +0 -0
  127. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/supra_matrix_function_centrality.py +0 -0
  128. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_algorithms/versatility.py +0 -0
  129. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/multilayer_clustering.py +0 -0
  130. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/network_classification/PPR.py +0 -0
  131. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/network_classification/__init__.py +0 -0
  132. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/network_classification/label_propagation.py +0 -0
  133. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/node_ranking/__init__.py +0 -0
  134. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/node_ranking/node_ranking.py +0 -0
  135. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/requirements_registry.py +0 -0
  136. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/robustness_testing.py +0 -0
  137. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/routing/__init__.py +0 -0
  138. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/routing/multiplex_paths.py +0 -0
  139. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/__init__.py +0 -0
  140. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/conversions.py +0 -0
  141. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/diagnostics.py +0 -0
  142. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/inference_vi.py +0 -0
  143. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/model_selection.py +0 -0
  144. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/multilayer_sbm.py +0 -0
  145. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/objectives.py +0 -0
  146. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/uq.py +0 -0
  147. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sbm/utils.py +0 -0
  148. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/sir_multiplex.py +0 -0
  149. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistical_report.py +0 -0
  150. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/__init__.py +0 -0
  151. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/basic_statistics.py +0 -0
  152. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/bayesian_distances.py +0 -0
  153. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/bayesiantests.py +0 -0
  154. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/correlation_networks.py +0 -0
  155. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/critical_distances.py +0 -0
  156. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/enrichment_modules.py +0 -0
  157. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/multilayer_statistics.py +0 -0
  158. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/powerlaw.py +0 -0
  159. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/stats_comparison.py +0 -0
  160. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/statistics/topology.py +0 -0
  161. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/temporal/__init__.py +0 -0
  162. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/temporal/centrality.py +0 -0
  163. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/temporal/community.py +0 -0
  164. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/temporal_multiplex/__init__.py +0 -0
  165. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/algorithms/term_parsers/__init__.py +0 -0
  166. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/alignment/__init__.py +0 -0
  167. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/alignment/features.py +0 -0
  168. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/alignment/metrics.py +0 -0
  169. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/alignment/solvers.py +0 -0
  170. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/benchmarks/__init__.py +0 -0
  171. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/benchmarks/budget.py +0 -0
  172. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/benchmarks/metrics.py +0 -0
  173. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/benchmarks/runners.py +0 -0
  174. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/centrality/__init__.py +0 -0
  175. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/centrality/robustness.py +0 -0
  176. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/claims/__init__.py +0 -0
  177. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/claims/generator.py +0 -0
  178. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/claims/learner.py +0 -0
  179. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/claims/scorer.py +0 -0
  180. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/claims/types.py +0 -0
  181. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/comparison/__init__.py +0 -0
  182. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/comparison/executor.py +0 -0
  183. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/comparison/metrics.py +0 -0
  184. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/comparison/result.py +0 -0
  185. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/__init__.py +0 -0
  186. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/convert.py +0 -0
  187. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/converters/__init__.py +0 -0
  188. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/converters/dgl_converter.py +0 -0
  189. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/converters/igraph_converter.py +0 -0
  190. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/converters/networkx_converter.py +0 -0
  191. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/converters/pyg_converter.py +0 -0
  192. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/converters/scipy_converter.py +0 -0
  193. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/equality.py +0 -0
  194. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/exceptions.py +0 -0
  195. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/ir.py +0 -0
  196. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/schema.py +0 -0
  197. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/compat/sidecar.py +0 -0
  198. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/contracts/__init__.py +0 -0
  199. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/contracts/contract.py +0 -0
  200. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/contracts/engine.py +0 -0
  201. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/contracts/failure_modes.py +0 -0
  202. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/contracts/predicates.py +0 -0
  203. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/contracts/result.py +0 -0
  204. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/HINMINE/IO.py +0 -0
  205. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/HINMINE/__init__.py +0 -0
  206. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/HINMINE/dataStructures.py +0 -0
  207. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/HINMINE/decomposition.py +0 -0
  208. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/__init__.py +0 -0
  209. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/converters.py +0 -0
  210. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/immutable.py +0 -0
  211. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/lazy_evaluation.py +0 -0
  212. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/nx_compat.py +0 -0
  213. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/parsers.py +0 -0
  214. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/random_generators.py +0 -0
  215. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/schema_validation.py +0 -0
  216. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/supporting.py +0 -0
  217. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/temporal_multinet.py +0 -0
  218. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/core/types.py +0 -0
  219. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterexamples/__init__.py +0 -0
  220. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterexamples/claim_lang.py +0 -0
  221. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterexamples/ddmin.py +0 -0
  222. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterexamples/engine.py +0 -0
  223. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterexamples/types.py +0 -0
  224. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterexamples/witness.py +0 -0
  225. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterfactual/__init__.py +0 -0
  226. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterfactual/comparator.py +0 -0
  227. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterfactual/engine.py +0 -0
  228. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterfactual/presets.py +0 -0
  229. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterfactual/result.py +0 -0
  230. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/counterfactual/spec.py +0 -0
  231. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/datasets/__init__.py +0 -0
  232. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/datasets/_data/aarhus_cs.edges +0 -0
  233. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/datasets/_data/synthetic_multilayer.edges +0 -0
  234. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/datasets/_generators.py +0 -0
  235. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/datasets/_loaders.py +0 -0
  236. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/diagnostics/__init__.py +0 -0
  237. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/diagnostics/builders.py +0 -0
  238. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/diagnostics/codes.py +0 -0
  239. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/diagnostics/core.py +0 -0
  240. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/diagnostics/utils.py +0 -0
  241. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/__init__.py +0 -0
  242. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/algebra.py +0 -0
  243. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/ast.py +0 -0
  244. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/attribution.py +0 -0
  245. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/benchmark.py +0 -0
  246. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/benchmark_result.py +0 -0
  247. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/builder_parser.py +0 -0
  248. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/cache.py +0 -0
  249. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/communities.py +0 -0
  250. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/community_uq.py +0 -0
  251. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/compositional_uq.py +0 -0
  252. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/context.py +0 -0
  253. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/errors.py +0 -0
  254. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/executor_semiring.py +0 -0
  255. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/executors/__init__.py +0 -0
  256. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/executors/benchmark_executor.py +0 -0
  257. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/explain.py +0 -0
  258. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/export.py +0 -0
  259. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/expressions.py +0 -0
  260. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/fastpath.py +0 -0
  261. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/layers.py +0 -0
  262. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/__init__.py +0 -0
  263. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/diagnostic.py +0 -0
  264. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/lint_context.py +0 -0
  265. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/__init__.py +0 -0
  266. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/base.py +0 -0
  267. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/dsl001_unknown_layer.py +0 -0
  268. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/dsl002_unknown_attribute.py +0 -0
  269. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/dsl101_type_mismatch.py +0 -0
  270. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/dsl201_unsatisfiable.py +0 -0
  271. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/dsl202_redundant.py +0 -0
  272. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/perf301_full_scan.py +0 -0
  273. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/rules/perf302_cross_layer.py +0 -0
  274. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/schema.py +0 -0
  275. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/type_resolver.py +0 -0
  276. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/lint/types.py +0 -0
  277. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/metrics.py +0 -0
  278. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/operator_registry.py +0 -0
  279. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/operators.py +0 -0
  280. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/patterns/__init__.py +0 -0
  281. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/patterns/builder.py +0 -0
  282. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/patterns/compiler.py +0 -0
  283. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/patterns/engine.py +0 -0
  284. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/patterns/ir.py +0 -0
  285. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/patterns/result.py +0 -0
  286. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/plan.py +0 -0
  287. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/planner.py +0 -0
  288. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/predictive.py +0 -0
  289. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/__init__.py +0 -0
  290. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/cache.py +0 -0
  291. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/cost.py +0 -0
  292. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/diff.py +0 -0
  293. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/distribution.py +0 -0
  294. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/executor.py +0 -0
  295. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/explain.py +0 -0
  296. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/rewrite.py +0 -0
  297. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/program/types.py +0 -0
  298. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/provenance.py +0 -0
  299. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/reduction.py +0 -0
  300. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/registry.py +0 -0
  301. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/selection_uq.py +0 -0
  302. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/serializer.py +0 -0
  303. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/uq_algebra.py +0 -0
  304. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/uq_resolution.py +0 -0
  305. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl/warnings.py +0 -0
  306. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dsl_legacy.py +0 -0
  307. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/__init__.py +0 -0
  308. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/_utils.py +0 -0
  309. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/ast.py +0 -0
  310. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/builder.py +0 -0
  311. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/compartmental.py +0 -0
  312. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/config.py +0 -0
  313. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/core.py +0 -0
  314. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/errors.py +0 -0
  315. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/executor.py +0 -0
  316. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/models.py +0 -0
  317. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/processes.py +0 -0
  318. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/registry.py +0 -0
  319. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/result.py +0 -0
  320. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/dynamics/serializer.py +0 -0
  321. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/embeddings/__init__.py +0 -0
  322. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/embeddings/base.py +0 -0
  323. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/embeddings/cache.py +0 -0
  324. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/embeddings/link_ops.py +0 -0
  325. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/embeddings/metapath2vec.py +0 -0
  326. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/embeddings/netmf.py +0 -0
  327. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ergonomics.py +0 -0
  328. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/errors.py +0 -0
  329. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/exceptions.py +0 -0
  330. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/__init__.py +0 -0
  331. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/artifacts.py +0 -0
  332. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/cli.py +0 -0
  333. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/env.py +0 -0
  334. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/errors.py +0 -0
  335. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/model.py +0 -0
  336. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/runner.py +0 -0
  337. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/store.py +0 -0
  338. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/experiments/utils.py +0 -0
  339. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/fast_examples.py +0 -0
  340. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/graph_ops.py +0 -0
  341. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/__init__.py +0 -0
  342. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/api.py +0 -0
  343. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/canonical_format.py +0 -0
  344. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/converters.py +0 -0
  345. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/exceptions.py +0 -0
  346. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/formats/__init__.py +0 -0
  347. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/formats/arrow_format.py +0 -0
  348. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/formats/csv_format.py +0 -0
  349. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/formats/json_format.py +0 -0
  350. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/multinet_bridge.py +0 -0
  351. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/parquet_format.py +0 -0
  352. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/io/schema.py +0 -0
  353. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/lab/__init__.py +0 -0
  354. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/lab/base.py +0 -0
  355. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/linter.py +0 -0
  356. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/logging_config.py +0 -0
  357. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/meta/__init__.py +0 -0
  358. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/meta/builder.py +0 -0
  359. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/meta/result.py +0 -0
  360. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/meta/stats.py +0 -0
  361. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/meta/utils.py +0 -0
  362. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/__init__.py +0 -0
  363. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/__init__.py +0 -0
  364. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/base.py +0 -0
  365. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/deepwalk.py +0 -0
  366. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/evaluation.py +0 -0
  367. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/line.py +0 -0
  368. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/metapath2vec.py +0 -0
  369. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/multiplex.py +0 -0
  370. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/netmf.py +0 -0
  371. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/node2vec.py +0 -0
  372. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/similarity.py +0 -0
  373. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/trainer.py +0 -0
  374. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/ml/embedding/utils.py +0 -0
  375. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/multinet/__init__.py +0 -0
  376. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/multinet/aggregation.py +0 -0
  377. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/nullmodels/__init__.py +0 -0
  378. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/nullmodels/executor.py +0 -0
  379. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/nullmodels/models.py +0 -0
  380. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/nullmodels/result.py +0 -0
  381. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/__init__.py +0 -0
  382. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/cost_model.py +0 -0
  383. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/logical_plan.py +0 -0
  384. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/optimizer.py +0 -0
  385. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/physical_plan.py +0 -0
  386. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/plan_nodes.py +0 -0
  387. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/optimizer/rules.py +0 -0
  388. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/__init__.py +0 -0
  389. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/cli.py +0 -0
  390. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/errors.py +0 -0
  391. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/executor.py +0 -0
  392. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/network.py +0 -0
  393. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/operators.py +0 -0
  394. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/readers.py +0 -0
  395. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/schema.py +0 -0
  396. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/spill.py +0 -0
  397. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/out_of_core/utils.py +0 -0
  398. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/paths/__init__.py +0 -0
  399. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/paths/algorithms.py +0 -0
  400. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/paths/executor.py +0 -0
  401. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/paths/result.py +0 -0
  402. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/pipeline.py +0 -0
  403. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/plugins/__init__.py +0 -0
  404. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/plugins/base.py +0 -0
  405. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/plugins/examples.py +0 -0
  406. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/plugins/registry.py +0 -0
  407. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/profiling.py +0 -0
  408. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/provenance/__init__.py +0 -0
  409. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/provenance/bundle.py +0 -0
  410. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/provenance/capture.py +0 -0
  411. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/provenance/replay.py +0 -0
  412. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/provenance/schema.py +0 -0
  413. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/requirements.py +0 -0
  414. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/robustness/__init__.py +0 -0
  415. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/robustness/experiments.py +0 -0
  416. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/robustness/perturbations.py +0 -0
  417. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/runtime/__init__.py +0 -0
  418. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/runtime/capabilities.py +0 -0
  419. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/__init__.py +0 -0
  420. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/capabilities.py +0 -0
  421. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/community_registry.py +0 -0
  422. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/evaluate.py +0 -0
  423. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/metric_registry.py +0 -0
  424. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/result.py +0 -0
  425. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/selection/wins.py +0 -0
  426. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/semiring/__init__.py +0 -0
  427. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/semiring/core.py +0 -0
  428. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/semiring/engine.py +0 -0
  429. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/semiring/pareto.py +0 -0
  430. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/semiring/registry.py +0 -0
  431. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/semiring/types.py +0 -0
  432. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/sensitivity/__init__.py +0 -0
  433. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/sensitivity/executor.py +0 -0
  434. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/sensitivity/metrics.py +0 -0
  435. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/sensitivity/perturbations.py +0 -0
  436. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/sensitivity/types.py +0 -0
  437. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/stats/__init__.py +0 -0
  438. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/stats/provenance.py +0 -0
  439. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/stats/registry.py +0 -0
  440. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/stats/statvalue.py +0 -0
  441. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/stats/uncertainty.py +0 -0
  442. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/temporal_utils.py +0 -0
  443. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/temporal_utils_extended.py +0 -0
  444. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/temporal_view.py +0 -0
  445. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/__init__.py +0 -0
  446. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/bootstrap.py +0 -0
  447. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/ci_utils.py +0 -0
  448. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/community_ensemble.py +0 -0
  449. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/community_result.py +0 -0
  450. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/context.py +0 -0
  451. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/estimation.py +0 -0
  452. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/noise_models.py +0 -0
  453. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/null_models.py +0 -0
  454. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/partition.py +0 -0
  455. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/partition_metrics.py +0 -0
  456. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/partition_reducers.py +0 -0
  457. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/partition_types.py +0 -0
  458. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/partition_uq.py +0 -0
  459. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/plan.py +0 -0
  460. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/reducers/__init__.py +0 -0
  461. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/reducers/base.py +0 -0
  462. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/resampling_graph.py +0 -0
  463. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/runner.py +0 -0
  464. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/selection_execution.py +0 -0
  465. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/selection_reducers.py +0 -0
  466. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/selection_types.py +0 -0
  467. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/selection_uq.py +0 -0
  468. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/stratification.py +0 -0
  469. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/uncertainty/types.py +0 -0
  470. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/utils.py +0 -0
  471. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/validation.py +0 -0
  472. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/__init__.py +0 -0
  473. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/benchmark_visualizations.py +0 -0
  474. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/bezier.py +0 -0
  475. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/colors.py +0 -0
  476. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/drawing_machinery.py +0 -0
  477. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/embedding_visualization/__init__.py +0 -0
  478. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/embedding_visualization/embedding_tools.py +0 -0
  479. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/embedding_visualization/embedding_visualization.py +0 -0
  480. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/fa2/__init__.py +0 -0
  481. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/fa2/fa2util.py +0 -0
  482. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/fa2/forceatlas2.py +0 -0
  483. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/layout_algorithms.py +0 -0
  484. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/multilayer.py +0 -0
  485. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/polyfit.py +0 -0
  486. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/pymnet_style.py +0 -0
  487. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/ricci_layout.py +0 -0
  488. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/ricci_multilayer_vis.py +0 -0
  489. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/visualization/sankey.py +0 -0
  490. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/workflows.py +0 -0
  491. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/wrappers/__init__.py +0 -0
  492. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/wrappers/benchmark_nodes.py +0 -0
  493. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/wrappers/r_interop.py +0 -0
  494. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex/wrappers/train_node2vec_embedding.py +0 -0
  495. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex.egg-info/dependency_links.txt +0 -0
  496. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex.egg-info/entry_points.txt +0 -0
  497. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex.egg-info/not-zip-safe +0 -0
  498. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex.egg-info/requires.txt +0 -0
  499. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex.egg-info/top_level.txt +0 -0
  500. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex_mcp/errors.py +0 -0
  501. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex_mcp/registry.py +0 -0
  502. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex_mcp/safe_paths.py +0 -0
  503. {py3plex-2.0.6 → py3plex-2.0.8}/py3plex_mcp/schemas.py +0 -0
  504. {py3plex-2.0.6 → py3plex-2.0.8}/setup.cfg +0 -0
  505. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_advanced_metrics_properties.py +0 -0
  506. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_agent_api.py +0 -0
  507. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_agents_documentation_claims.py +0 -0
  508. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_agents_ergonomics_features.py +0 -0
  509. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_agents_golden_paths.py +0 -0
  510. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_aggregation.py +0 -0
  511. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algebra_backend.py +0 -0
  512. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algebra_core.py +0 -0
  513. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algebra_fixed_point.py +0 -0
  514. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algebra_paths.py +0 -0
  515. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algebra_registry.py +0 -0
  516. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algebra_witness.py +0 -0
  517. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithm_properties.py +0 -0
  518. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithms_attribute_correlation.py +0 -0
  519. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithms_correlation_networks.py +0 -0
  520. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithms_init.py +0 -0
  521. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithms_random_generators.py +0 -0
  522. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithms_requirements_registry.py +0 -0
  523. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_algorithms_statistics_bayesian_distances.py +0 -0
  524. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_alignment.py +0 -0
  525. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_alignment_contracts.py +0 -0
  526. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_alignment_correctness_additional.py +0 -0
  527. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_approximate_centrality.py +0 -0
  528. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ast_roundtrip.py +0 -0
  529. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ast_roundtrip_integration.py +0 -0
  530. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_attribute_correlation.py +0 -0
  531. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_attribute_correlation_contracts.py +0 -0
  532. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_auto_community.py +0 -0
  533. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_autocommunity_benchmarks.py +0 -0
  534. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_autocommunity_executor.py +0 -0
  535. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_autocommunity_meta.py +0 -0
  536. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_autocommunity_successive_halving.py +0 -0
  537. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_bayesian_distances.py +0 -0
  538. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_bench_aggregation_unit.py +0 -0
  539. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmark_budget_fairness.py +0 -0
  540. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmark_dsl_basic.py +0 -0
  541. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmark_integration.py +0 -0
  542. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmark_multiplex_centrality.py +0 -0
  543. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmark_time.py +0 -0
  544. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmarks_budget.py +0 -0
  545. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_benchmarks_init.py +0 -0
  546. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_book_snippets.py +0 -0
  547. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_builder_dsl_mutate.py +0 -0
  548. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_capabilities_basic.py +0 -0
  549. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_capabilities_optional_missing.py +0 -0
  550. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_centrality_explain.py +0 -0
  551. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_centrality_explain_integration.py +0 -0
  552. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_centrality_robustness.py +0 -0
  553. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_centrality_robustness_oracles.py +0 -0
  554. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_centrality_uncertainty.py +0 -0
  555. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_centrality_weight_handling.py +0 -0
  556. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_check_api_consistency.py +0 -0
  557. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_check_doc_coverage.py +0 -0
  558. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_check_type_coverage.py +0 -0
  559. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ci_python_versions.py +0 -0
  560. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_claim_learning.py +0 -0
  561. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_claims_types.py +0 -0
  562. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_cli_check.py +0 -0
  563. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_cli_ergonomics.py +0 -0
  564. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_cli_piping.py +0 -0
  565. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_clustering_multilayer.py +0 -0
  566. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_code_improvements.py +0 -0
  567. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_community_comparison_coverage.py +0 -0
  568. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_community_detection_modules.py +0 -0
  569. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_community_distribution.py +0 -0
  570. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_community_measures.py +0 -0
  571. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_community_measures_coverage.py +0 -0
  572. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_comparison.py +0 -0
  573. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_comparison_executor.py +0 -0
  574. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_comparison_metrics.py +0 -0
  575. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_comparison_metrics_additional.py +0 -0
  576. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_comparison_result.py +0 -0
  577. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_comparison_uninitialized_and_resistance_oracles.py +0 -0
  578. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_compat_exceptions.py +0 -0
  579. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_compat_roundtrip.py +0 -0
  580. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_config_api.py +0 -0
  581. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_config_benchmark.py +0 -0
  582. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_contracts.py +0 -0
  583. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_contracts_basic.py +0 -0
  584. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_contracts_extended.py +0 -0
  585. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_contracts_failure_modes.py +0 -0
  586. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_contracts_integration.py +0 -0
  587. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_functionality.py +0 -0
  588. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_immutable.py +0 -0
  589. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_lazy_evaluation.py +0 -0
  590. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_multinet_and_parsers.py +0 -0
  591. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_multinet_correctness.py +0 -0
  592. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_multiplex_edges.py +0 -0
  593. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_schema_validation.py +0 -0
  594. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_core_supporting.py +0 -0
  595. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_correlation_networks.py +0 -0
  596. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_counterexamples.py +0 -0
  597. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_counterexamples_properties.py +0 -0
  598. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_counterfactual.py +0 -0
  599. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_counterfactual_presets.py +0 -0
  600. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_coverage_grouping.py +0 -0
  601. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_create_mosaic_banner.py +0 -0
  602. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_crosshair_pure_functions.py +0 -0
  603. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_data_files_presence.py +0 -0
  604. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_datasets.py +0 -0
  605. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_datasets_contracts.py +0 -0
  606. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_datasets_oracles.py +0 -0
  607. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_degenerate_networks.py +0 -0
  608. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dependency_cleanup.py +0 -0
  609. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_determinism_randomness.py +0 -0
  610. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_diagnostics.py +0 -0
  611. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_diagnostics_utils.py +0 -0
  612. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_docs_embeddings_section.py +0 -0
  613. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_docs_examples.py +0 -0
  614. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_docs_quality_pass.py +0 -0
  615. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_doctests.py +0 -0
  616. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dplyr_integration.py +0 -0
  617. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl.py +0 -0
  618. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_aggregation_enhancements.py +0 -0
  619. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_ast_equivalence.py +0 -0
  620. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_ast_immutability.py +0 -0
  621. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_auto_community.py +0 -0
  622. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_community_filtering.py +0 -0
  623. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_community_uq_integration.py +0 -0
  624. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_compact_compute.py +0 -0
  625. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_compiler_explain.py +0 -0
  626. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_compiler_pipeline.py +0 -0
  627. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_compositional_uq.py +0 -0
  628. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_condition_semantics.py +0 -0
  629. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_d_factory.py +0 -0
  630. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_documentation_examples.py +0 -0
  631. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_dplyr_style.py +0 -0
  632. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_dynamics_integration.py +0 -0
  633. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_edge_grouping_coverage.py +0 -0
  634. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_edge_queries.py +0 -0
  635. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_enhancements.py +0 -0
  636. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_ergonomics.py +0 -0
  637. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_errors.py +0 -0
  638. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_errors_extended.py +0 -0
  639. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_executor_additional.py +0 -0
  640. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_explain.py +0 -0
  641. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_expressions.py +0 -0
  642. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_extensions.py +0 -0
  643. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_graphops_equivalence.py +0 -0
  644. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_grouping_coverage.py +0 -0
  645. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_interactive.py +0 -0
  646. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_joins.py +0 -0
  647. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_layer_resolution.py +0 -0
  648. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_layer_selection.py +0 -0
  649. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_layer_set_algebra.py +0 -0
  650. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_legacy_approximate.py +0 -0
  651. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_legacy_edges.py +0 -0
  652. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_lint.py +0 -0
  653. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_metric_registry.py +0 -0
  654. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_operators.py +0 -0
  655. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_patterns.py +0 -0
  656. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_patterns_correctness.py +0 -0
  657. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_patterns_quick_reference.py +0 -0
  658. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_pipes.py +0 -0
  659. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_planner.py +0 -0
  660. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_planner_config.py +0 -0
  661. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_predict_reduce.py +0 -0
  662. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_program_rewrite.py +0 -0
  663. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_program_types.py +0 -0
  664. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_progress_logging.py +0 -0
  665. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_properties.py +0 -0
  666. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_provenance.py +0 -0
  667. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_query_optimization.py +0 -0
  668. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_query_zoo.py +0 -0
  669. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_result_algebra_edge_cases.py +0 -0
  670. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_selection_fastpath.py +0 -0
  671. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_semiring_integration.py +0 -0
  672. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_serializer.py +0 -0
  673. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_smart_defaults.py +0 -0
  674. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_temporal_range_execution.py +0 -0
  675. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_uncertainty.py +0 -0
  676. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_uq_ergonomics.py +0 -0
  677. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_uq_propagation.py +0 -0
  678. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dsl_zoo_features.py +0 -0
  679. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics.py +0 -0
  680. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_algorithm_contracts.py +0 -0
  681. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_config_and_results_correctness.py +0 -0
  682. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_conservation.py +0 -0
  683. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_core.py +0 -0
  684. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_executor_edge_cases.py +0 -0
  685. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_metamorphic.py +0 -0
  686. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_parallel_determinism.py +0 -0
  687. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_reference_runs.py +0 -0
  688. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_uq_integration.py +0 -0
  689. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_dynamics_utils.py +0 -0
  690. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_edge_cases.py +0 -0
  691. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_edgelist_format.py +0 -0
  692. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_embeddings_direct_units.py +0 -0
  693. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ergonomic_helpers.py +0 -0
  694. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ergonomics.py +0 -0
  695. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ergonomics_helpers.py +0 -0
  696. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_errors.py +0 -0
  697. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_errors_coverage.py +0 -0
  698. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_CBSSD.py +0 -0
  699. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_community_detection.py +0 -0
  700. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_decomposition_and_classification.py +0 -0
  701. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_decomposition_ground_truth.py +0 -0
  702. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_dsl_builder_api.py +0 -0
  703. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_dynamics_core_examples.py +0 -0
  704. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_embedding_construction.py +0 -0
  705. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_embedding_visualization.py +0 -0
  706. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_incidence_gadget_encoding.py +0 -0
  707. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_interactive_multilayer.py +0 -0
  708. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_inverse_network.py +0 -0
  709. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_layer_extraction.py +0 -0
  710. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_manipulation.py +0 -0
  711. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_multilayer_vectorized_aggregation.py +0 -0
  712. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_multiplex_aggregate.py +0 -0
  713. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_multiplex_dynamics.py +0 -0
  714. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_n2v_embedding.py +0 -0
  715. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_network_decomposition.py +0 -0
  716. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_network_decomposition_meta_paths.py +0 -0
  717. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_numeric_encoding.py +0 -0
  718. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_pattern_matching.py +0 -0
  719. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_example_ppr.py +0 -0
  720. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_examples_zoo_consolidation.py +0 -0
  721. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_exception_taxonomy.py +0 -0
  722. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_exceptions.py +0 -0
  723. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_experiments.py +0 -0
  724. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_explain_attribution.py +0 -0
  725. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_fast_examples.py +0 -0
  726. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_flagship_progress_demo.py +0 -0
  727. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_flow_hierarchy.py +0 -0
  728. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_formal_phase1_alignment.py +0 -0
  729. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_fuzzing_properties.py +0 -0
  730. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_generate_all_outputs.py +0 -0
  731. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_generate_quickstart_outputs.py +0 -0
  732. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_generate_visualization_images.py +0 -0
  733. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_golden_toy_examples.py +0 -0
  734. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_graph_ops.py +0 -0
  735. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_graph_summarization.py +0 -0
  736. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_hedwig_adjustment.py +0 -0
  737. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_hedwig_significance.py +0 -0
  738. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_improved_errors.py +0 -0
  739. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_incidence_gadget_encoding.py +0 -0
  740. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_infomap_fix.py +0 -0
  741. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_interlayer_links_fix.py +0 -0
  742. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_api_edge_cases.py +0 -0
  743. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_arrow.py +0 -0
  744. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_contracts_additional.py +0 -0
  745. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_conversion_formats.py +0 -0
  746. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_converters.py +0 -0
  747. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_exceptions.py +0 -0
  748. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_integration.py +0 -0
  749. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_roundtrip.py +0 -0
  750. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_io_schema.py +0 -0
  751. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_issue_19_fix.py +0 -0
  752. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_lab.py +0 -0
  753. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_lab_additional.py +0 -0
  754. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_lab_correctness.py +0 -0
  755. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_label_propagation.py +0 -0
  756. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_layer_extraction_fix.py +0 -0
  757. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_layer_similarity.py +0 -0
  758. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_layout_algorithms.py +0 -0
  759. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_lazy_evaluation.py +0 -0
  760. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_leiden_multilayer.py +0 -0
  761. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_link_checker.py +0 -0
  762. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_linter.py +0 -0
  763. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_logging_config_unit.py +0 -0
  764. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_logging_conversion.py +0 -0
  765. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_main_module.py +0 -0
  766. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_master_regulators_example.py +0 -0
  767. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_math_invariants.py +0 -0
  768. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mdl_benchmark.py +0 -0
  769. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mdl_score.py +0 -0
  770. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mdl_score_corruption_monotonicity.py +0 -0
  771. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mdl_score_reference_differential.py +0 -0
  772. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mdl_score_resolution_limit_sweep.py +0 -0
  773. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_meta_analysis.py +0 -0
  774. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_meta_flow_report.py +0 -0
  775. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_meta_utils.py +0 -0
  776. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_metamorphic.py +0 -0
  777. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_metapath2vec.py +0 -0
  778. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ml_embedding_evaluation.py +0 -0
  779. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ml_embedding_primitives.py +0 -0
  780. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_monoplex_nx_wrapper.py +0 -0
  781. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_mpc.py +0 -0
  782. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_centrality.py +0 -0
  783. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_clustering_coefficients.py +0 -0
  784. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_cornercases.py +0 -0
  785. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_edge_fix.py +0 -0
  786. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_embedding_models.py +0 -0
  787. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_integration.py +0 -0
  788. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_leiden_uq.py +0 -0
  789. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_modularity.py +0 -0
  790. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_quality_metrics.py +0 -0
  791. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_quality_metrics_coverage.py +0 -0
  792. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_statistics.py +0 -0
  793. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multilayer_visualizations.py +0 -0
  794. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multinet_aggregation.py +0 -0
  795. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multinet_aggregation_additional.py +0 -0
  796. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multiplex_layer_interop.py +0 -0
  797. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multiplex_participation.py +0 -0
  798. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multiplex_properties.py +0 -0
  799. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multirank.py +0 -0
  800. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_multixrank.py +0 -0
  801. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_network_conversion.py +0 -0
  802. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_network_version.py +0 -0
  803. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_networkx_compatibility.py +0 -0
  804. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_new_algorithms.py +0 -0
  805. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_new_multilayer_metrics.py +0 -0
  806. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_node_edge_parity.py +0 -0
  807. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_node_ranking_comprehensive.py +0 -0
  808. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_norc.py +0 -0
  809. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_nullmodel_sanity.py +0 -0
  810. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_nullmodels.py +0 -0
  811. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_nullmodels_contracts.py +0 -0
  812. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_nx_compat_extended.py +0 -0
  813. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ollivier_ricci_multilayer.py +0 -0
  814. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_optimizer_submodules.py +0 -0
  815. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_out_of_core.py +0 -0
  816. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_parallel.py +0 -0
  817. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_parallel_execution.py +0 -0
  818. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_parsers_comprehensive.py +0 -0
  819. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_parsers_coverage.py +0 -0
  820. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_partition_uq.py +0 -0
  821. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_partition_uq_integration.py +0 -0
  822. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_paths.py +0 -0
  823. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_paths_additional.py +0 -0
  824. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_paths_contracts.py +0 -0
  825. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_paths_executor.py +0 -0
  826. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_paths_result.py +0 -0
  827. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_performance_core.py +0 -0
  828. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_pipeline.py +0 -0
  829. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_plugin_examples.py +0 -0
  830. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_plugin_system.py +0 -0
  831. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_plugins.py +0 -0
  832. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_plugins_contracts.py +0 -0
  833. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_profiling.py +0 -0
  834. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_profiling_additional.py +0 -0
  835. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_program_cache_identity.py +0 -0
  836. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_program_cost_executor.py +0 -0
  837. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_properties.py +0 -0
  838. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_provenance_canonical.py +0 -0
  839. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_provenance_replay.py +0 -0
  840. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_provenance_schema.py +0 -0
  841. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_public_api_exports.py +0 -0
  842. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_pymnet_style.py +0 -0
  843. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_pypi_publish_workflow.py +0 -0
  844. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_query_algebra.py +0 -0
  845. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_query_equivalence.py +0 -0
  846. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_r_interop.py +0 -0
  847. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_random_generators_additional.py +0 -0
  848. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_random_generators_extended.py +0 -0
  849. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_random_walkers.py +0 -0
  850. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_random_walks.py +0 -0
  851. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_readme_contributor_onboarding.py +0 -0
  852. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_readme_flagship_example.py +0 -0
  853. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_requirements.py +0 -0
  854. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_result_explain_debug.py +0 -0
  855. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_ricci_visualization.py +0 -0
  856. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_robustness.py +0 -0
  857. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_robustness_additional.py +0 -0
  858. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_robustness_testing.py +0 -0
  859. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_root_conftest.py +0 -0
  860. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_roundtrip_invariants.py +0 -0
  861. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_run_quickstart_snippets.py +0 -0
  862. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_safe_expression.py +0 -0
  863. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sankey_visualization.py +0 -0
  864. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sbm_autocommunity.py +0 -0
  865. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sbm_generator.py +0 -0
  866. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sbm_metrics.py +0 -0
  867. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sbm_runner_integration.py +0 -0
  868. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_schema_and_immutable.py +0 -0
  869. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_seeding.py +0 -0
  870. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_selection_uq.py +0 -0
  871. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_selection_uq_empty_groups.py +0 -0
  872. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_selection_uq_integration.py +0 -0
  873. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_semiring_negative_cases.py +0 -0
  874. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_semiring_pareto.py +0 -0
  875. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_semiring_registry.py +0 -0
  876. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_semiring_types.py +0 -0
  877. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_semiring_verification.py +0 -0
  878. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sensitivity_executor.py +0 -0
  879. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sidecar.py +0 -0
  880. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sir_epidemic.py +0 -0
  881. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sir_long_convergence.py +0 -0
  882. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_sir_multiplex.py +0 -0
  883. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_spectral_multilayer.py +0 -0
  884. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_statistical_report.py +0 -0
  885. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_comparison.py +0 -0
  886. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_core.py +0 -0
  887. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_edge_cases.py +0 -0
  888. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_provenance.py +0 -0
  889. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_provenance_dataclass.py +0 -0
  890. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_registry.py +0 -0
  891. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_scalar_uncertainty.py +0 -0
  892. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stats_verify.py +0 -0
  893. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_stratified_uq.py +0 -0
  894. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_streaming_topk.py +0 -0
  895. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_successive_halving.py +0 -0
  896. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_supporting_extended.py +0 -0
  897. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_supra_matrix_function_centrality.py +0 -0
  898. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal.py +0 -0
  899. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_algorithms.py +0 -0
  900. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_builder.py +0 -0
  901. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_dsl.py +0 -0
  902. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_duration_parsing.py +0 -0
  903. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_multinet.py +0 -0
  904. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_utils.py +0 -0
  905. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_utils_extended.py +0 -0
  906. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_view.py +0 -0
  907. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_temporal_windowed_queries.py +0 -0
  908. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_tensor_representation.py +0 -0
  909. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_tutorial_10min.py +0 -0
  910. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_type_coverage_scan.py +0 -0
  911. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty.py +0 -0
  912. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_additional.py +0 -0
  913. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_builder_integration.py +0 -0
  914. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_defaults.py +0 -0
  915. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_dsl_integration.py +0 -0
  916. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_engines.py +0 -0
  917. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_oracles.py +0 -0
  918. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uncertainty_runner.py +0 -0
  919. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uq_algebra.py +0 -0
  920. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uq_integration.py +0 -0
  921. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uq_resolution.py +0 -0
  922. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_uq_spine.py +0 -0
  923. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_user_journey_simulation.py +0 -0
  924. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_utils.py +0 -0
  925. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_utils_coverage.py +0 -0
  926. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_utils_extended.py +0 -0
  927. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_utils_search_paths.py +0 -0
  928. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_validation.py +0 -0
  929. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_validation_module.py +0 -0
  930. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_api_differential.py +0 -0
  931. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_centrality.py +0 -0
  932. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_communities.py +0 -0
  933. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_determinism_parallelism.py +0 -0
  934. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_dsl_equivalence.py +0 -0
  935. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_metamorphic_harness.py +0 -0
  936. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_verification_provenance_oracles.py +0 -0
  937. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_versatility.py +0 -0
  938. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_benchmark.py +0 -0
  939. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_bezier.py +0 -0
  940. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_colors.py +0 -0
  941. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_imports.py +0 -0
  942. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_layouts.py +0 -0
  943. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_multilayer_additional.py +0 -0
  944. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_polyfit.py +0 -0
  945. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_ricci_layout_helpers.py +0 -0
  946. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualization_supra_heatmap.py +0 -0
  947. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_visualize_matrix_fix.py +0 -0
  948. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_workflows.py +0 -0
  949. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_wrappers_additional.py +0 -0
  950. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_wrappers_benchmark_nodes.py +0 -0
  951. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_wrappers_node2vec.py +0 -0
  952. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_wrappers_r_interop.py +0 -0
  953. {py3plex-2.0.6 → py3plex-2.0.8}/tests/test_wrappers_train_node2vec.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py3plex
3
- Version: 2.0.6
3
+ Version: 2.0.8
4
4
  Summary: A Multilayer network analysis python3 library
5
5
  Author-email: Blaž Škrlj <blaz.skrlj@ijs.si>
6
6
  License: MIT
@@ -120,7 +120,7 @@ Dynamic: license-file
120
120
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/py3plex)](https://pypistats.org/packages/py3plex)
121
121
  ![CLI Tool](https://img.shields.io/badge/CLI%20Tool-Available-brightgreen)
122
122
  ![Docker](https://img.shields.io/badge/Docker-Available-blue)
123
- ![Lines of Code](https://img.shields.io/badge/lines-213.6K-blue)
123
+ ![Lines of Code](https://img.shields.io/badge/lines-213.8K-blue)
124
124
  ![Test Count](https://img.shields.io/badge/tests-9.7K-blue)
125
125
 
126
126
  *Multilayer networks* are complex networks with additional information assigned to nodes or edges (or both). This library includes
@@ -16,7 +16,7 @@
16
16
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/py3plex)](https://pypistats.org/packages/py3plex)
17
17
  ![CLI Tool](https://img.shields.io/badge/CLI%20Tool-Available-brightgreen)
18
18
  ![Docker](https://img.shields.io/badge/Docker-Available-blue)
19
- ![Lines of Code](https://img.shields.io/badge/lines-213.6K-blue)
19
+ ![Lines of Code](https://img.shields.io/badge/lines-213.8K-blue)
20
20
  ![Test Count](https://img.shields.io/badge/tests-9.7K-blue)
21
21
 
22
22
  *Multilayer networks* are complex networks with additional information assigned to nodes or edges (or both). This library includes
@@ -51,8 +51,9 @@ For detailed documentation, see: https://skblaz.github.io/py3plex/
51
51
  """
52
52
 
53
53
  # Version information
54
- __version__ = "2.0.6"
55
- __api_version__ = "2.0.6"
54
+ from ._version import __version__
55
+
56
+ __api_version__ = __version__
56
57
 
57
58
  from py3plex.core.multinet import multi_layer_network
58
59
  from py3plex.core.types import (
@@ -0,0 +1,3 @@
1
+ """Single source for py3plex release version metadata."""
2
+
3
+ __version__ = "2.0.8"
@@ -1779,11 +1779,10 @@ def cmd_query(args: argparse.Namespace) -> int:
1779
1779
  # Execute query. Some lower-level layout/progress utilities print
1780
1780
  # diagnostics directly to stdout; keep command stdout parseable.
1781
1781
  if args.dsl:
1782
- # Interpret as Python DSL builder syntax
1783
- from py3plex.dsl.builder_parser import parse_builder_query
1782
+ # Parse builder syntax as a restricted AST expression; never run it as Python.
1783
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
1784
1784
 
1785
- query_builder = parse_builder_query(query_str)
1786
-
1785
+ query_builder = evaluate_dsl_expression(query_str)
1787
1786
  with contextlib.redirect_stdout(sys.stderr):
1788
1787
  result = query_builder.execute(network)
1789
1788
  else:
@@ -1927,20 +1926,18 @@ def cmd_dsl_lint(args: argparse.Namespace) -> int:
1927
1926
  logger.error(f"Failed to load network: {e}")
1928
1927
  return 2
1929
1928
 
1930
- # Parse query using the restricted builder syntax.
1929
+ # Parse documented builder expressions without evaluating Python code.
1931
1930
  from py3plex.dsl import lint, explain
1932
- from py3plex.dsl.builder_parser import parse_builder_query
1933
-
1934
- # Try to parse as builder syntax first
1931
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
1932
+
1935
1933
  try:
1936
- query_builder = parse_builder_query(query_str)
1934
+ query_builder = evaluate_dsl_expression(query_str)
1937
1935
  query_ast = query_builder.to_ast()
1938
- except Exception:
1939
- # Fall back to treating it as a note that we need string DSL support
1940
- logger.error("String DSL syntax not yet supported for linting.")
1941
- logger.error("Please use builder syntax: Q.nodes().from_layers(L['social']).where(degree__gt=5)")
1936
+ except (ValueError, TypeError) as exc:
1937
+ logger.error("Invalid DSL builder expression: %s", exc)
1938
+ logger.error("Use builder syntax such as Q.nodes().from_layers(L['social']).where(degree__gt=5)")
1942
1939
  return 2
1943
-
1940
+
1944
1941
  # Run linting
1945
1942
  if args.explain:
1946
1943
  # Get detailed explanation
@@ -218,8 +218,9 @@ WARN_DEPRECATED: bool = True
218
218
  # Library Metadata
219
219
  # ─────────────────────────────────────────────────────────────────────────────
220
220
 
221
- __api_version__ = "2.0.6"
222
- __version__ = "2.0.6"
221
+ from ._version import __version__
222
+
223
+ __api_version__ = __version__
223
224
 
224
225
  # ─────────────────────────────────────────────────────────────────────────────
225
226
  # Helper Functions
@@ -1089,23 +1089,26 @@ class multi_layer_network:
1089
1089
  - :meth:`get_edges` for filtering coupling edges (multiplex_edges param)
1090
1090
  """
1091
1091
  unique_layers = {n[1] for n in self.core_network.nodes()}
1092
- unique_nodes = {n[0] for n in self.core_network.nodes()}
1093
-
1094
- # for potential_node in itertools.product(unique_nodes,unique_layers):
1095
- # self.core_network.add_node(potential_node)
1096
-
1097
- # draw edges between same nodes across layers
1098
- for node in unique_nodes:
1099
- for layer_first in unique_layers:
1100
- for layer_second in unique_layers:
1101
- if layer_first != layer_second:
1102
- coupled_edge = ((node, layer_first), (node, layer_second))
1103
- self.core_network.add_edge(
1104
- coupled_edge[0],
1105
- coupled_edge[1],
1106
- type="coupling",
1107
- weight=self.coupling_weight,
1108
- )
1092
+
1093
+ # Add one undirected coupling edge per pair of replicas. Iterating
1094
+ # over ordered layer pairs creates parallel edges in a MultiGraph and
1095
+ # also creates replicas for layers in which a node is absent.
1096
+ for node in {n[0] for n in self.core_network.nodes()}:
1097
+ node_layers = sorted(
1098
+ layer for layer in unique_layers if (node, layer) in self.core_network
1099
+ )
1100
+ layer_pairs = (
1101
+ itertools.combinations(node_layers, 2)
1102
+ if not self.directed
1103
+ else itertools.permutations(node_layers, 2)
1104
+ )
1105
+ for layer_first, layer_second in layer_pairs:
1106
+ self.core_network.add_edge(
1107
+ (node, layer_first),
1108
+ (node, layer_second),
1109
+ type="coupling",
1110
+ weight=self.coupling_weight,
1111
+ )
1109
1112
 
1110
1113
  def load_layer_name_mapping(self, mapping_name, header=False):
1111
1114
  """Layer-node mapping loader method
@@ -4723,7 +4723,7 @@ class CommunityQueryBuilder(QueryBuilder):
4723
4723
  uq_enabled = uq_config is not None
4724
4724
 
4725
4725
  if uq_enabled:
4726
- uq_method = uq_config.uq_method or "seed"
4726
+ uq_method = uq_config.method or "seed"
4727
4727
  uq_n_samples = uq_config.n_samples or 10
4728
4728
  else:
4729
4729
  uq_method = "seed"
@@ -2614,6 +2614,8 @@ def _execute_select(
2614
2614
  # Step 4: Compute measures
2615
2615
  stage_start = time.monotonic()
2616
2616
  attributes: Dict[str, Dict] = {}
2617
+ if select.select_cols or select.rename_map:
2618
+ _add_intrinsic_node_attributes(attributes, items, select.target)
2617
2619
 
2618
2620
  # Track approximation usage for provenance (initialize before compute block)
2619
2621
  approx_used = []
@@ -2720,6 +2722,20 @@ def _execute_select(
2720
2722
  select=select,
2721
2723
  )
2722
2724
 
2725
+ if compute_item.name in {"communities", "community"}:
2726
+ # Community computation is an analysis operation,
2727
+ # not merely a derived column: retain the
2728
+ # partition on the network for subsequent queries.
2729
+ partition = {
2730
+ item: (
2731
+ value.get("mean", value)
2732
+ if isinstance(value, dict)
2733
+ else value
2734
+ )
2735
+ for item, value in values.items()
2736
+ }
2737
+ network.assign_partition(partition)
2738
+
2723
2739
  attributes[result_name] = values
2724
2740
  except (UQResolutionError, UQSchemaValidationError):
2725
2741
  # UQ errors should propagate (fail-fast)
@@ -3018,7 +3034,7 @@ def _execute_auto_community(
3018
3034
  uq_enabled = uq_config is not None
3019
3035
 
3020
3036
  if uq_enabled:
3021
- uq_method = uq_config.uq_method or "seed"
3037
+ uq_method = uq_config.method or "seed"
3022
3038
  uq_n_samples = uq_config.n_samples or 10
3023
3039
  else:
3024
3040
  uq_method = "seed"
@@ -3717,6 +3733,8 @@ def _execute_select_with_items(
3717
3733
 
3718
3734
  # Compute measures if needed
3719
3735
  attributes: Dict[str, Dict] = {}
3736
+ if select.select_cols or select.rename_map:
3737
+ _add_intrinsic_node_attributes(attributes, items, select.target)
3720
3738
  if select.compute:
3721
3739
  if progress:
3722
3740
  logger.info(f"Computing {len(select.compute)} measure(s)")
@@ -3767,6 +3785,26 @@ def _execute_select_with_items(
3767
3785
  )
3768
3786
 
3769
3787
 
3788
+ def _add_intrinsic_node_attributes(
3789
+ attributes: Dict[str, Dict], items: List[Any], target: Target
3790
+ ) -> None:
3791
+ """Expose node identifiers as query columns before post-processing."""
3792
+ if target != Target.NODES:
3793
+ return
3794
+
3795
+ attributes["id"] = {}
3796
+ attributes["node"] = {}
3797
+ attributes["layer"] = {}
3798
+ for item in items:
3799
+ if isinstance(item, tuple) and len(item) >= 2:
3800
+ node, layer = item[0], item[1]
3801
+ else:
3802
+ node, layer = item, None
3803
+ attributes["id"][item] = node
3804
+ attributes["node"][item] = node
3805
+ attributes["layer"][item] = layer
3806
+
3807
+
3770
3808
  def _execute_embedding(
3771
3809
  result: Any,
3772
3810
  network: Any,
@@ -6130,7 +6168,11 @@ def _apply_select(
6130
6168
  Returns:
6131
6169
  Filtered attributes dict
6132
6170
  """
6133
- return {col: attributes[col] for col in columns if col in attributes}
6171
+ missing = [col for col in columns if col not in attributes]
6172
+ if missing:
6173
+ available = list(attributes)
6174
+ raise UnknownAttributeError(missing[0], available)
6175
+ return {col: attributes[col] for col in columns}
6134
6176
 
6135
6177
 
6136
6178
  def _apply_drop(
@@ -6757,6 +6799,15 @@ def _execute_nodes_with_community(
6757
6799
  provenance_builder=provenance_builder,
6758
6800
  provenance_record=provenance_record
6759
6801
  )
6802
+
6803
+ # Node attributes are not automatically materialized as query columns.
6804
+ # Expose the partition assignment explicitly for community queries.
6805
+ community_attr = "community" if partition_name == "default" else f"community_{partition_name}"
6806
+ result.attributes[community_attr] = {
6807
+ item: network.core_network.nodes[item].get(community_attr)
6808
+ for item in result.items
6809
+ if item in network.core_network
6810
+ }
6760
6811
 
6761
6812
  # Add community metadata
6762
6813
  result.meta["community_detection"] = {
@@ -756,10 +756,10 @@ class GraphProgram:
756
756
  )
757
757
 
758
758
  return cls(
759
- canonical_ast=copy.deepcopy(ast),
760
- type_signature=type_signature,
759
+ _canonical_ast=copy.deepcopy(ast),
760
+ _type_signature=type_signature,
761
761
  program_hash=program_hash,
762
- metadata=metadata,
762
+ _metadata=metadata,
763
763
  )
764
764
 
765
765
  @classmethod
@@ -19,6 +19,28 @@ _EXPLANATION_ATTRS = {
19
19
  }
20
20
 
21
21
 
22
+ def _json_safe(value: Any) -> Any:
23
+ """Convert common scientific Python values to JSON-compatible values."""
24
+ if isinstance(value, dict):
25
+ return {
26
+ key if isinstance(key, str) else json.dumps(_json_safe(key), separators=(",", ":")): _json_safe(item)
27
+ for key, item in value.items()
28
+ }
29
+ if isinstance(value, (list, tuple)):
30
+ return [_json_safe(item) for item in value]
31
+ if isinstance(value, set):
32
+ return [_json_safe(item) for item in sorted(value, key=repr)]
33
+ if value is None or isinstance(value, (str, int, float, bool)):
34
+ return value
35
+ if hasattr(value, "to_json_dict"):
36
+ return _json_safe(value.to_json_dict())
37
+ if hasattr(value, "tolist"):
38
+ return _json_safe(value.tolist())
39
+ if hasattr(value, "item"):
40
+ return _json_safe(value.item())
41
+ return repr(value)
42
+
43
+
22
44
  def _expand_embeddings_into_df(
23
45
  df: Any,
24
46
  embeddings: Dict[str, Any],
@@ -978,6 +1000,34 @@ class QueryResult:
978
1000
 
979
1001
  return subgraph
980
1002
 
1003
+ def to_csv(self, path: Union[str, "Path"], **kwargs) -> None:
1004
+ """Write result rows to a CSV file.
1005
+
1006
+ Keyword arguments are passed to :meth:`pandas.DataFrame.to_csv`.
1007
+ The DataFrame index is omitted by default because result fields
1008
+ already identify each row.
1009
+ """
1010
+ kwargs.setdefault("index", False)
1011
+ self.to_pandas().to_csv(path, **kwargs)
1012
+
1013
+ def to_json(self, path: Optional[Union[str, Path]] = None, **kwargs) -> str:
1014
+ """Serialize the complete result to JSON, optionally writing it to *path*.
1015
+
1016
+ The JSON object contains ``target``, ``items``, ``attributes``, and
1017
+ ``meta`` fields. Keyword arguments are passed to :func:`json.dumps`.
1018
+ """
1019
+ payload = {
1020
+ "target": self.target,
1021
+ "items": self.items,
1022
+ "attributes": self.attributes,
1023
+ "meta": self.meta,
1024
+ }
1025
+ kwargs.setdefault("indent", 2)
1026
+ output = json.dumps(_json_safe(payload), **kwargs)
1027
+ if path is not None:
1028
+ Path(path).write_text(output, encoding="utf-8")
1029
+ return output
1030
+
981
1031
  def to_arrow(self):
982
1032
  """Export results to Apache Arrow table.
983
1033
 
@@ -994,8 +1044,18 @@ class QueryResult:
994
1044
  "pyarrow is required for to_arrow(). Install with: pip install pyarrow"
995
1045
  )
996
1046
 
997
- # Convert items to strings for Arrow compatibility
998
- data = {"id": [str(item) for item in self.items]}
1047
+ # Keep node replica identity in separate columns, matching to_pandas().
1048
+ # Stringifying the (node, layer) tuple into one id loses the layer as a
1049
+ # usable field in downstream Arrow/Parquet analysis.
1050
+ if self.target == "nodes":
1051
+ data = {
1052
+ "id": [item[0] if isinstance(item, tuple) and len(item) >= 2 else item
1053
+ for item in self.items],
1054
+ "layer": [item[1] if isinstance(item, tuple) and len(item) >= 2 else None
1055
+ for item in self.items],
1056
+ }
1057
+ else:
1058
+ data = {"id": [str(item) for item in self.items]}
999
1059
 
1000
1060
  for attr_name, values in self.attributes.items():
1001
1061
  if isinstance(values, dict):
@@ -0,0 +1,83 @@
1
+ """Safe interpreter for the CLI's documented Python-style DSL builder syntax."""
2
+ import ast
3
+ import operator
4
+
5
+
6
+ _ALLOWED_METHODS = {
7
+ "nodes", "edges", "communities", "from_layers", "where", "compute",
8
+ "order_by", "limit", "top_k", "group_by", "per_layer", "coverage",
9
+ "end_grouping", "uq", "select", "drop", "rename", "distinct",
10
+ "summarize", "mutate", "rank_by", "zscore", "having", "during",
11
+ "window", "approx", "seed", "provenance", "hint", "to_ast",
12
+ "int", "float", "str", "ref",
13
+ }
14
+ _ALLOWED_BINOPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.BitOr: operator.or_, ast.BitAnd: operator.and_}
15
+ _ALLOWED_UNARY = {ast.USub: operator.neg, ast.UAdd: operator.pos}
16
+
17
+
18
+ def evaluate_dsl_expression(source):
19
+ """Evaluate a builder expression using explicit AST nodes and allowlists."""
20
+ from py3plex.dsl import Q, L, Param
21
+
22
+ try:
23
+ tree = ast.parse(source, mode="eval")
24
+ except SyntaxError as exc:
25
+ raise ValueError(f"Invalid DSL expression: {exc.msg}") from exc
26
+
27
+ def visit(node):
28
+ if isinstance(node, ast.Constant):
29
+ if isinstance(node.value, (str, int, float, bool, type(None))):
30
+ return node.value
31
+ raise ValueError("Unsupported literal in DSL expression")
32
+ if isinstance(node, ast.Name):
33
+ if node.id in {"Q", "L", "Param"}:
34
+ return {"Q": Q, "L": L, "Param": Param}[node.id]
35
+ raise ValueError(f"Name {node.id!r} is not allowed in DSL expressions")
36
+ if isinstance(node, ast.Attribute):
37
+ if node.attr.startswith("_"):
38
+ raise ValueError("Private attributes are not allowed in DSL expressions")
39
+ if isinstance(node.value, ast.Name) and node.value.id in {"Q", "L", "Param"}:
40
+ owner = visit(node.value)
41
+ is_layer = owner is L
42
+ elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Attribute):
43
+ if node.value.func.attr not in _ALLOWED_METHODS:
44
+ raise ValueError("Method chain contains an unsupported operation")
45
+ owner = visit(node.value)
46
+ is_layer = False
47
+ else:
48
+ raise ValueError("Attribute access is allowed only on DSL namespaces or builder results")
49
+ if node.attr not in _ALLOWED_METHODS and not is_layer:
50
+ raise ValueError(f"Attribute {node.attr!r} is not allowed in DSL expressions")
51
+ try:
52
+ return getattr(owner, node.attr)
53
+ except AttributeError as exc:
54
+ raise ValueError(f"Unsupported DSL attribute {node.attr!r}") from exc
55
+ if isinstance(node, ast.Call):
56
+ if node.keywords and any(keyword.arg is None for keyword in node.keywords):
57
+ raise ValueError("Keyword argument unpacking is not allowed")
58
+ function = visit(node.func)
59
+ if isinstance(node.func, ast.Attribute) and node.func.attr not in _ALLOWED_METHODS:
60
+ raise ValueError(f"Method {node.func.attr!r} is not allowed in DSL expressions")
61
+ return function(*[visit(arg) for arg in node.args], **{kw.arg: visit(kw.value) for kw in node.keywords})
62
+ if isinstance(node, ast.Subscript):
63
+ if not isinstance(node.value, ast.Name) or node.value.id != "L":
64
+ raise ValueError("Subscripts are allowed only on L")
65
+ key = visit(node.slice)
66
+ if not isinstance(key, str):
67
+ raise ValueError("Layer names must be strings")
68
+ return L[key]
69
+ if isinstance(node, ast.BinOp) and type(node.op) in _ALLOWED_BINOPS:
70
+ return _ALLOWED_BINOPS[type(node.op)](visit(node.left), visit(node.right))
71
+ if isinstance(node, ast.UnaryOp) and type(node.op) in _ALLOWED_UNARY:
72
+ return _ALLOWED_UNARY[type(node.op)](visit(node.operand))
73
+ if isinstance(node, (ast.List, ast.Tuple, ast.Set)):
74
+ values = [visit(item) for item in node.elts]
75
+ return values if isinstance(node, ast.List) else tuple(values) if isinstance(node, ast.Tuple) else set(values)
76
+ if isinstance(node, ast.Dict):
77
+ return {visit(k): visit(v) for k, v in zip(node.keys, node.values)}
78
+ raise ValueError(f"Syntax {type(node).__name__} is not allowed in DSL expressions")
79
+
80
+ result = visit(tree.body)
81
+ if not callable(getattr(result, "to_ast", None)):
82
+ raise ValueError("DSL expression must produce a query builder")
83
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py3plex
3
- Version: 2.0.6
3
+ Version: 2.0.8
4
4
  Summary: A Multilayer network analysis python3 library
5
5
  Author-email: Blaž Škrlj <blaz.skrlj@ijs.si>
6
6
  License: MIT
@@ -120,7 +120,7 @@ Dynamic: license-file
120
120
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/py3plex)](https://pypistats.org/packages/py3plex)
121
121
  ![CLI Tool](https://img.shields.io/badge/CLI%20Tool-Available-brightgreen)
122
122
  ![Docker](https://img.shields.io/badge/Docker-Available-blue)
123
- ![Lines of Code](https://img.shields.io/badge/lines-213.6K-blue)
123
+ ![Lines of Code](https://img.shields.io/badge/lines-213.8K-blue)
124
124
  ![Test Count](https://img.shields.io/badge/tests-9.7K-blue)
125
125
 
126
126
  *Multilayer networks* are complex networks with additional information assigned to nodes or edges (or both). This library includes
@@ -6,6 +6,7 @@ py3plex/__init__.py
6
6
  py3plex/__main__.py
7
7
  py3plex/_parallel.py
8
8
  py3plex/_safe_expression.py
9
+ py3plex/_version.py
9
10
  py3plex/agent.py
10
11
  py3plex/cli.py
11
12
  py3plex/config.py
@@ -20,6 +21,7 @@ py3plex/logging_config.py
20
21
  py3plex/pipeline.py
21
22
  py3plex/profiling.py
22
23
  py3plex/requirements.py
24
+ py3plex/safe_dsl_expression.py
23
25
  py3plex/temporal_utils.py
24
26
  py3plex/temporal_utils_extended.py
25
27
  py3plex/temporal_view.py
@@ -7,10 +7,10 @@ Usage:
7
7
  pip install py3plex[mcp]
8
8
  py3plex-mcp
9
9
 
10
- Version: 2.0.6
10
+ Version: 2.0.8
11
11
  """
12
12
 
13
- __version__ = "2.0.6"
13
+ from py3plex._version import __version__
14
14
 
15
15
  __all__ = [
16
16
  "__version__",
@@ -35,7 +35,7 @@ except ImportError:
35
35
 
36
36
  from py3plex.core import multinet
37
37
  from py3plex.dsl_legacy import execute_query
38
- from py3plex.dsl import Q, L, Param, QueryResult # DSL v2 support
38
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
39
39
  from py3plex_mcp.errors import (
40
40
  MCPError,
41
41
  NetworkNotFoundError,
@@ -216,18 +216,9 @@ async def py3plex_run_query(
216
216
  # Execute query based on DSL version
217
217
  try:
218
218
  if use_v2:
219
- # DSL v2: Evaluate Python expression to build query
220
- # Security: We only expose Q, L, Param from dsl module
221
- safe_globals = {
222
- "Q": Q,
223
- "L": L,
224
- "Param": Param,
225
- "__builtins__": {},
226
- }
227
- # Evaluate the query expression
228
- query_builder = eval(query, safe_globals, {})
229
-
230
- # Execute the query
219
+ # MCP query strings are untrusted input. Parse only the
220
+ # documented DSL builder expression grammar.
221
+ query_builder = evaluate_dsl_expression(query)
231
222
  result = query_builder.execute(net, progress=False)
232
223
  else:
233
224
  # Legacy DSL: String-based query
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "py3plex"
7
- version = "2.0.6"
7
+ dynamic = ["version"]
8
8
  description = "A Multilayer network analysis python3 library"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -151,6 +151,9 @@ Repository = "https://github.com/SkBlaz/py3plex"
151
151
  py3plex = "py3plex.cli:main"
152
152
  py3plex-mcp = "py3plex_mcp.server:main"
153
153
 
154
+ [tool.setuptools.dynamic]
155
+ version = {attr = "py3plex._version.__version__"}
156
+
154
157
  [tool.setuptools]
155
158
  zip-safe = false
156
159
  include-package-data = true
@@ -38,7 +38,7 @@ def test_conf_exposes_expected_metadata(conf_module):
38
38
  module, expected_path = conf_module
39
39
 
40
40
  assert module.project == "Practical Multilayer Network Analysis with Py3plex"
41
- assert module.version == module.release == "2.0.6"
41
+ assert module.version == module.release == "2.0.8"
42
42
  assert module.language == "en"
43
43
  assert module.master_doc == "index"
44
44
  assert module.templates_path == ["_templates"]
@@ -1,5 +1,5 @@
1
1
  from pathlib import Path
2
- import tomllib
2
+ import re
3
3
 
4
4
 
5
5
  BOOK_ROOT = Path(__file__).resolve().parents[1] / "book"
@@ -83,13 +83,13 @@ def _book_mentions_package_dir(combined_book: str, package_dir: str) -> bool:
83
83
 
84
84
  def test_front_matter_uses_canonical_version():
85
85
  text = _read("front_matter.rst")
86
- assert "version 2.0.6 (2026)" in text
86
+ assert "version 2.0.8 (2026)" in text
87
87
  assert "version 1.0 (2025)" not in text
88
88
 
89
89
 
90
90
  def test_book_version_matches_project_version():
91
- project_data = tomllib.loads((BOOK_ROOT.parent / "pyproject.toml").read_text(encoding="utf-8"))
92
- project_version = project_data["project"]["version"]
91
+ version_source = (BOOK_ROOT.parent / "py3plex/_version.py").read_text(encoding="utf-8")
92
+ project_version = re.search(r'^__version__\s*=\s*"([^"]+)"', version_source, re.MULTILINE).group(1)
93
93
  assert f"version {project_version} (2026)" in _read("front_matter.rst")
94
94
  assert f"Version {project_version}" in _read("bibliography.rst")
95
95
 
@@ -1587,3 +1587,33 @@ class TestCLITutorial:
1587
1587
  # Should include code snippets
1588
1588
  assert "from py3plex.core import multinet" in captured.out
1589
1589
  assert "network.add_edges" in captured.out
1590
+
1591
+
1592
+ class TestSafeDSLExpression:
1593
+ def test_accepts_documented_builder_chains(self):
1594
+ from py3plex.dsl.builder import QueryBuilder
1595
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
1596
+
1597
+ builder = evaluate_dsl_expression(
1598
+ 'Q.nodes().from_layers(L["social"] + L["work"]).compute("degree").order_by("degree")'
1599
+ )
1600
+ assert isinstance(builder, QueryBuilder)
1601
+ assert builder.to_ast().select.compute[0].name == "degree"
1602
+
1603
+ @pytest.mark.parametrize(
1604
+ "expression",
1605
+ [
1606
+ '__import__("os").system("touch /tmp/py3plex_cli_pwned")',
1607
+ 'Q.nodes().__class__',
1608
+ 'L.__class__',
1609
+ 'Q.nodes().execute.__globals__',
1610
+ '[x for x in (1, 2)]',
1611
+ 'lambda: Q.nodes()',
1612
+ 'Q.nodes().where(degree__gt=(1).__class__)',
1613
+ ],
1614
+ )
1615
+ def test_rejects_python_execution_and_introspection(self, expression):
1616
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
1617
+
1618
+ with pytest.raises(ValueError):
1619
+ evaluate_dsl_expression(expression)
@@ -49,6 +49,7 @@ def test_create_showcase_network_structure():
49
49
 
50
50
 
51
51
  def test_create_publication_quality_visualization_draws_and_saves(monkeypatch, capsys):
52
+ existing_figures = set(csf.plt.get_fignums())
52
53
  draw_calls = {}
53
54
 
54
55
  def fake_draw(graphs, multilinks, labels=None, ax=None, **kwargs):
@@ -109,4 +110,4 @@ def test_create_publication_quality_visualization_draws_and_saves(monkeypatch, c
109
110
  assert any("Multilayer Flow Visualization" in text for text in saved["texts"])
110
111
  assert any("Nodes sized and colored by network activity" in text for text in saved["texts"])
111
112
 
112
- assert csf.plt.get_fignums() == []
113
+ assert set(csf.plt.get_fignums()) == existing_figures