topolib 0.0.0__py3-none-any.whl → 0.4.1__py3-none-any.whl

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.

Potentially problematic release.


This version of topolib might be problematic. Click here for more details.

@@ -1,24 +1,34 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topolib
3
- Version: 0.0.0
3
+ Version: 0.4.1
4
4
  Summary: A compact Python library for modeling, analyzing, and visualizing optical network topologies.
5
- Author-email: Danilo Bórquez-Paredes <danilo.borquez.p@uai.cl>
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://gitlab.com/DaniloBorquez/topolib
8
- Project-URL: Documentation, https://topolib.readthedocs.io/
9
- Project-URL: Source, https://gitlab.com/DaniloBorquez/topolib
10
- Project-URL: Issues, https://gitlab.com/DaniloBorquez/topolib/-/issues
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Operating System :: OS Independent
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: network,topology,optical,analysis,visualization
8
+ Author: Danilo Bórquez-Paredes
9
+ Author-email: danilo.borquez.p@uai.cl
10
+ Requires-Python: >=3.10
13
11
  Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
14
20
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
15
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
- Requires-Python: >=3.10
22
+ Requires-Dist: contextily
23
+ Requires-Dist: geopandas
24
+ Requires-Dist: matplotlib
25
+ Requires-Dist: networkx (>=2.6)
26
+ Requires-Dist: numpy (>=1.21)
27
+ Requires-Dist: shapely
28
+ Project-URL: Documentation, https://topolib.readthedocs.io/
29
+ Project-URL: Homepage, https://gitlab.com/DaniloBorquez/topolib
30
+ Project-URL: Repository, https://gitlab.com/DaniloBorquez/topolib
17
31
  Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
- Requires-Dist: numpy>=1.21
20
- Requires-Dist: networkx>=2.6
21
- Dynamic: license-file
22
32
 
23
33
  # Topolib 🚀
24
34
 
@@ -125,3 +135,4 @@ See `CONTRIBUTING.md` for development guidelines, commit message rules and pre-c
125
135
  ## License
126
136
 
127
137
  See `LICENSE` in the project root.
138
+
@@ -0,0 +1,18 @@
1
+ topolib/__init__.py,sha256=iLmy2rOkHS_4KZWMD8BgT7R3tLMKeaTCDVf3B4FyYxM,91
2
+ topolib/analysis/__init__.py,sha256=qvUC9wV_jQNQIlwJXk7LJ-dkTXhH1Ttn0lKWIdwBbrc,52
3
+ topolib/analysis/metrics.py,sha256=Di4HGHlz9c2UTCYdfnmjtPjo7w3wwYuyDPeXI7bR0zA,2592
4
+ topolib/assets/Abilene_IXP.json,sha256=5cnPMbjsNDjmpySdQDYQ2yd83zOFvCRjlAnbX1wyzgk,6010
5
+ topolib/assets/China_pop.json,sha256=v-bs5qib8-CB81rvBNNM9ssoelrNGuFrPEyRCht9YpY,22262
6
+ topolib/assets/DT-50_pop.json,sha256=hCv1MCvipgdrQ34VT-qXJ68BdATriQ8ZObh0fLPqar4,29719
7
+ topolib/elements/__init__.py,sha256=ZWSd5uwVtppJtMnZ30zrAdzXhUAYIK62RrUaH9rsWu0,180
8
+ topolib/elements/link.py,sha256=BwjdCR8peh7dDpKunZodlIsjKcfvwjKxyQ3tmp1obb8,3778
9
+ topolib/elements/node.py,sha256=uOnljwA3jcVR4utUfI-om4SIt_QBsEQt8QLW9uvjr3Y,4974
10
+ topolib/topology/__init__.py,sha256=2VRhVm4ZvKBiTDB2T8BDmLZBpwGCVFRF3fvtxxC_d28,86
11
+ topolib/topology/path.py,sha256=oUNwmpBcS6LMMAJIxokROm3MVqr7vRR44M3Fh5ADq_w,2057
12
+ topolib/topology/topology.py,sha256=PzPx80TxWMcOwpOCh4fohcWT2YUra-4m04tBjqyMU40,5605
13
+ topolib/visualization/__init__.py,sha256=wv065-KB5uDbTaQIASPVfMMW5sE76Bs-q0oai48vAzk,29
14
+ topolib/visualization/mapview.py,sha256=4iKJMYsH6oFNj9tOcgSKLVRtoYfUuH3XLjShsGwUXcM,2799
15
+ topolib-0.4.1.dist-info/METADATA,sha256=WSUvBwdpmS9NRSwm-r5lT2pzJyKFuQ-xUe9khXm_xAY,4671
16
+ topolib-0.4.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
17
+ topolib-0.4.1.dist-info/licenses/LICENSE,sha256=kbnIP0XU6f2ualiTjEawdlU81IGPBbwc-_GF3N-1e9E,1081
18
+ topolib-0.4.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1,75 +0,0 @@
1
- @startuml TopolibModularClassDiagram
2
-
3
- package topolib.topology {
4
- class Topology {
5
- - {static} topologies
6
- -nodes: List<Node>
7
- -links: List<Link>
8
- +add_node(node: Node)
9
- +remove_node(node_id: int)
10
- +add_link(link: Link)
11
- +remove_link(link_id: int)
12
- +update_metrics()
13
- +export_json(): str
14
- +get_geographic_area(): float
15
- +get_diameter(): float
16
- +calculate_laplacian(): Matrix
17
- +get_shortest_paths(s: int, d: int, N: int): List<Path>
18
- +get_disjoint_paths(s: int, d: int, N: int): List<Path>
19
- }
20
-
21
- class Path {
22
- -nodes: List<Node>
23
- -total_length: float
24
- +get_summary(): str
25
- }
26
- }
27
-
28
- package topolib.elements {
29
- class Node {
30
- -id: int
31
- -name: str
32
- -latitude: float
33
- -longitude: float
34
- +coordinates(): Tuple[float, float]
35
- }
36
-
37
- class Link {
38
- -id: int
39
- -source: Node
40
- -target: Node
41
- -length: float
42
- }
43
- }
44
-
45
- package topolib.analysis {
46
- class Metrics {
47
- +get_max_node_degree(topology: Topology): int
48
- +get_min_node_degree(topology: Topology): int
49
- +get_avg_node_degree(topology: Topology): float
50
- +get_max_link_length(topology: Topology): float
51
- +get_min_link_length(topology: Topology): float
52
- +get_avg_link_length(topology: Topology): float
53
- +get_connection_matrix(topology: Topology): numpy.ndarray
54
- +get_link_value_matrix(topology: Topology): numpy.ndarray
55
- +get_node_degree_matrix(topology: Topology): numpy.ndarray
56
- }
57
- }
58
-
59
- package topolib.visualization {
60
- class MapView {
61
- +display_osm(topology: Topology)
62
- +display_paper(topology: Topology)
63
- }
64
- }
65
-
66
- topolib.topology.Topology --> topolib.elements.Node : uses
67
- topolib.topology.Topology --> topolib.elements.Link : uses
68
- topolib.topology.Topology --> topolib.analysis.Metrics : calculates
69
- topolib.topology.Topology --> topolib.visualization.MapView : visualizes
70
- topolib.topology.Topology --> topolib.topology.Path : generates
71
-
72
- topolib.elements.Link --> topolib.elements.Node : connects
73
- topolib.topology.Path --> topolib.elements.Node : traverses
74
-
75
- @enduml
docs/Makefile DELETED
@@ -1,20 +0,0 @@
1
- # Minimal makefile for Sphinx documentation
2
- #
3
-
4
- # You can set these variables from the command line, and also
5
- # from the environment for the first two.
6
- SPHINXOPTS ?=
7
- SPHINXBUILD ?= sphinx-build
8
- SOURCEDIR = source
9
- BUILDDIR = build
10
-
11
- # Put it first so that "make" without argument is like "make help".
12
- help:
13
- @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14
-
15
- .PHONY: help Makefile
16
-
17
- # Catch-all target: route all unknown targets to Sphinx using the new
18
- # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19
- %: Makefile
20
- @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
docs/requirements.txt DELETED
@@ -1,2 +0,0 @@
1
- sphinx
2
- sphinx_rtd_theme
docs/source/conf.py DELETED
@@ -1,37 +0,0 @@
1
- # Configuration file for the Sphinx documentation builder.
2
-
3
- # -- Add project root to sys.path for autodoc --
4
- import os
5
- import sys
6
- sys.path.insert(0, os.path.abspath(
7
- os.path.join(os.path.dirname(__file__), '../../')))
8
- #
9
- # For the full list of built-in configuration values, see the documentation:
10
- # https://www.sphinx-doc.org/en/master/usage/configuration.html
11
-
12
- # -- Project information -----------------------------------------------------
13
- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
14
-
15
- project = 'topolib'
16
- copyright = '2025, Danilo Borquez'
17
- author = 'Danilo Borquez'
18
- release = '0.1.0'
19
-
20
- # -- General configuration ---------------------------------------------------
21
- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
22
-
23
- extensions = [
24
- 'sphinx.ext.autodoc',
25
- 'sphinx.ext.napoleon',
26
- ]
27
-
28
- templates_path = ['_templates']
29
- exclude_patterns = []
30
-
31
- language = 'en'
32
-
33
- # -- Options for HTML output -------------------------------------------------
34
- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
35
-
36
- html_theme = 'sphinx_rtd_theme'
37
- html_static_path = ['_static']
docs/source/index.rst DELETED
@@ -1,33 +0,0 @@
1
- .. topolib documentation master file, created by
2
- sphinx-quickstart on Wed Oct 8 18:21:25 2025.
3
- You can adapt this file completely to your liking, but it should at least
4
- contain the root `toctree` directive.
5
-
6
-
7
- Welcome to Topolib's documentation!
8
- ===================================
9
-
10
- **Topolib** is a compact Python library for modeling, analyzing, and visualizing optical network topologies.
11
- It provides a clean, object-oriented API for nodes, links, topologies, metrics, and visualization tools, making it ideal for research, teaching, and rapid prototyping in network science and engineering.
12
-
13
- **Key features:**
14
-
15
- - Modular design: elements, topology, analysis, and visualization
16
- - Easy-to-use classes for nodes, links, and paths
17
- - Built-in metrics and analysis helpers
18
- - JSON import/export and interoperability
19
- - Ready for integration with Sphinx, Read the Docs, and PyPI
20
-
21
- Get started by exploring the modules below, or see the README for quick usage examples.
22
-
23
- .. note::
24
- This documentation is generated automatically from the source code and is always up to date with the latest release.
25
-
26
-
27
-
28
- .. toctree::
29
- :maxdepth: 2
30
- :caption: Contents:
31
-
32
- modules
33
-
docs/source/modules.rst DELETED
@@ -1,7 +0,0 @@
1
- topolib
2
- =======
3
-
4
- .. toctree::
5
- :maxdepth: 4
6
-
7
- topolib
@@ -1,21 +0,0 @@
1
- topolib.analysis package
2
- ========================
3
-
4
- Submodules
5
- ----------
6
-
7
- topolib.analysis.metrics module
8
- -------------------------------
9
-
10
- .. automodule:: topolib.analysis.metrics
11
- :members:
12
- :undoc-members:
13
- :show-inheritance:
14
-
15
- Module contents
16
- ---------------
17
-
18
- .. automodule:: topolib.analysis
19
- :members:
20
- :undoc-members:
21
- :show-inheritance:
@@ -1,23 +0,0 @@
1
- topolib.elements package
2
- ========================
3
-
4
- Submodules
5
- ----------
6
-
7
- topolib.elements.link module
8
- ----------------------------
9
-
10
- .. automodule:: topolib.elements.link
11
- :members:
12
- :undoc-members:
13
- :show-inheritance:
14
-
15
- topolib.elements.node module
16
- ----------------------------
17
-
18
- .. automodule:: topolib.elements.node
19
- :members:
20
- :undoc-members:
21
- :show-inheritance:
22
-
23
-
docs/source/topolib.rst DELETED
@@ -1,20 +0,0 @@
1
- topolib package
2
- ===============
3
-
4
- Subpackages
5
- -----------
6
-
7
- .. toctree::
8
- :maxdepth: 4
9
-
10
- topolib.analysis
11
- topolib.elements
12
- topolib.topology
13
-
14
- Module contents
15
- ---------------
16
-
17
- .. automodule:: topolib
18
- :members:
19
- :undoc-members:
20
- :show-inheritance:
@@ -1,29 +0,0 @@
1
- topolib.topology package
2
- ========================
3
-
4
- Submodules
5
- ----------
6
-
7
- topolib.topology.path module
8
- ----------------------------
9
-
10
- .. automodule:: topolib.topology.path
11
- :members:
12
- :undoc-members:
13
- :show-inheritance:
14
-
15
- topolib.topology.topology module
16
- --------------------------------
17
-
18
- .. automodule:: topolib.topology.topology
19
- :members:
20
- :undoc-members:
21
- :show-inheritance:
22
-
23
- Module contents
24
- ---------------
25
-
26
- .. automodule:: topolib.topology
27
- :members:
28
- :undoc-members:
29
- :show-inheritance:
@@ -1,11 +0,0 @@
1
- from topolib.visualization.mapview import MapView
2
- from topolib.topology.topology import Topology
3
-
4
- if __name__ == "__main__":
5
- # Load real topology from JSON (you can change the file to another one from assets)
6
- topo = Topology.from_json("topolib/assets/China_pop.json")
7
- mapview = MapView(topo)
8
- mapview.show_map()
9
- topo = Topology.from_json("topolib/assets/DT-50_pop.json")
10
- mapview = MapView(topo)
11
- mapview.show_map()
tests/__init__.py DELETED
@@ -1 +0,0 @@
1
- # This file marks the tests directory as a Python package.
tests/test_link.py DELETED
@@ -1,77 +0,0 @@
1
- import pytest
2
- from topolib.elements.node import Node
3
- from topolib.elements.link import Link
4
-
5
-
6
- def test_link_creation_and_properties():
7
- n1 = Node(1, "A", 0.0, 0.0)
8
- n2 = Node(2, "B", 1.0, 1.0)
9
- link = Link(10, n1, n2, 5.5)
10
-
11
- assert link.id == 10
12
- assert link.source is n1
13
- assert link.target is n2
14
- assert link.length == 5.5
15
-
16
-
17
- def test_link_length_validation():
18
- n1 = Node(1, "A", 0.0, 0.0)
19
- n2 = Node(2, "B", 1.0, 1.0)
20
- with pytest.raises(ValueError):
21
- Link(1, n1, n2, -1)
22
- with pytest.raises(TypeError):
23
- Link(1, n1, n2, "not-a-number")
24
-
25
-
26
- def test_link_endpoint_validation():
27
- n1 = Node(1, "A", 0.0, 0.0)
28
-
29
- # a dummy object without node attributes
30
- class Dummy:
31
- pass
32
-
33
- with pytest.raises(TypeError):
34
- Link(1, Dummy(), n1, 1.0)
35
- with pytest.raises(TypeError):
36
- Link(1, n1, Dummy(), 1.0)
37
-
38
-
39
- def test_endpoints_and_repr():
40
- n1 = Node(1, "A", 0.0, 0.0)
41
- n2 = Node(2, "B", 1.0, 1.0)
42
- link = Link(2, n1, n2, 10)
43
- assert link.endpoints() == (n1, n2)
44
- assert "Link(id=2" in repr(link)
45
-
46
-
47
- def test_link_setters_and_errors():
48
- n1 = Node(1, "A", 0.0, 0.0)
49
- n2 = Node(2, "B", 1.0, 1.0)
50
- link = Link(99, n1, n2, 1.0)
51
- # Test id setter
52
- link.id = 123
53
- assert link.id == 123
54
-
55
- # Test source setter error
56
- class Dummy:
57
- pass
58
-
59
- with pytest.raises(TypeError):
60
- link.source = Dummy()
61
- # Test target setter error
62
- with pytest.raises(TypeError):
63
- link.target = Dummy()
64
- # Test length setter error (non-numeric)
65
- with pytest.raises(TypeError):
66
- link.length = "bad"
67
- # Test length setter error (negative)
68
- with pytest.raises(ValueError):
69
- link.length = -5
70
-
71
-
72
- def test_link_length_setter_typeerror():
73
- n1 = Node(1, "A", 0.0, 0.0)
74
- n2 = Node(2, "B", 1.0, 1.0)
75
- link = Link(1, n1, n2, 1.0)
76
- with pytest.raises(TypeError):
77
- link.length = object() # No convertible a float, cubre el except
tests/test_mapview.py DELETED
@@ -1,33 +0,0 @@
1
- """
2
- Unit tests for the MapView class in topolib.visualization.mapview.
3
- Covers interface and error raising for unimplemented methods.
4
- """
5
-
6
- import pytest
7
- from topolib.visualization import MapView
8
- from topolib.topology import Topology
9
- from topolib.elements.node import Node
10
- from topolib.elements.link import Link
11
- import matplotlib.pyplot as plt
12
-
13
-
14
- def test_mapview_show_map_runs(monkeypatch):
15
- """
16
- Smoke test for MapView.show_map():
17
- - Creates a minimal topology (2 nodes, 1 link)
18
- - Instantiates MapView
19
- - Mocks plt.show to avoid GUI popup
20
- - Asserts that show_map() runs without error
21
- """
22
- # Create minimal topology
23
- n1 = Node(1, "A", 0.0, 0.0)
24
- n2 = Node(2, "B", 1.0, 1.0)
25
- l1 = Link(1, n1, n2, 10.0)
26
- topo = Topology(nodes=[n1, n2], links=[l1], name="TestNet")
27
- mv = MapView(topo)
28
-
29
- # Mock plt.show to avoid opening a window
30
- monkeypatch.setattr(plt, "show", lambda: None)
31
-
32
- # Should not raise any exception
33
- mv.show_map()
tests/test_metrics.py DELETED
@@ -1,53 +0,0 @@
1
- import pytest
2
-
3
- from topolib.analysis.metrics import Metrics
4
- from topolib.topology import Topology
5
-
6
-
7
- from topolib.elements.node import Node
8
- from topolib.elements.link import Link
9
-
10
-
11
- def test_node_degree():
12
- n1 = Node(1, "A", 0.0, 0.0)
13
- n2 = Node(2, "B", 1.0, 1.0)
14
- n3 = Node(3, "C", 2.0, 2.0)
15
- l1 = Link(1, n1, n2, 10)
16
- l2 = Link(2, n2, n3, 20)
17
- topo = Topology(nodes=[n1, n2, n3], links=[l1, l2])
18
- result = Metrics.node_degree(topo)
19
- assert result == {1: 1, 2: 2, 3: 1}
20
-
21
-
22
- def test_link_length_stats():
23
- n1 = Node(1, "A", 0.0, 0.0)
24
- n2 = Node(2, "B", 1.0, 1.0)
25
- l1 = Link(1, n1, n2, 10)
26
- l2 = Link(2, n2, n1, 20)
27
- topo = Topology(nodes=[n1, n2], links=[l1, l2])
28
- stats = Metrics.link_length_stats(topo)
29
- assert stats["min"] == 10
30
- assert stats["max"] == 20
31
- assert stats["avg"] == 15
32
- # Empty case
33
- topo_empty = Topology()
34
- assert Metrics.link_length_stats(topo_empty) == {
35
- "min": None,
36
- "max": None,
37
- "avg": None,
38
- }
39
-
40
-
41
- def test_connection_matrix():
42
- n1 = Node(1, "A", 0.0, 0.0)
43
- n2 = Node(2, "B", 1.0, 1.0)
44
- n3 = Node(3, "C", 2.0, 2.0)
45
- l1 = Link(1, n1, n2, 10)
46
- l2 = Link(2, n2, n3, 20)
47
- topo = Topology(nodes=[n1, n2, n3], links=[l1, l2])
48
- matrix = Metrics.connection_matrix(topo)
49
- assert matrix == [
50
- [0, 1, 0],
51
- [1, 0, 1],
52
- [0, 1, 0],
53
- ]
tests/test_node.py DELETED
@@ -1,44 +0,0 @@
1
- import pytest
2
- from topolib.elements.node import Node
3
-
4
-
5
- def test_node_creation():
6
- node = Node(1, "A", -33.45, -70.66, weight=2.5, pop=100000)
7
- assert node.id == 1
8
- assert node.name == "A"
9
- assert node.latitude == -33.45
10
- assert node.longitude == -70.66
11
- assert node.weight == 2.5
12
- assert node.pop == 100000
13
-
14
-
15
- def test_node_setters():
16
- node = Node(0, "", 0.0, 0.0)
17
- node.id = 10
18
- node.name = "TestNode"
19
- node.latitude = 55.5
20
- node.longitude = -120.1
21
- node.weight = 3.7
22
- node.pop = 12345
23
- assert node.id == 10
24
- assert node.name == "TestNode"
25
- assert node.latitude == 55.5
26
- assert node.longitude == -120.1
27
- assert node.weight == 3.7
28
- assert node.pop == 12345
29
-
30
-
31
- def test_node_coordinates():
32
- node = Node(2, "B", 10.0, 20.0)
33
- coords = node.coordinates()
34
- assert coords == (10.0, 20.0)
35
-
36
-
37
- def test_node_dc_ixp_attributes():
38
- n = Node(1, "A", 0.0, 0.0, dc=42, ixp=7)
39
- assert n.dc == 42
40
- assert n.ixp == 7
41
- n.dc = 100
42
- n.ixp = 3
43
- assert n.dc == 100
44
- assert n.ixp == 3
tests/test_path.py DELETED
@@ -1,46 +0,0 @@
1
- import pytest
2
- from topolib.topology.path import Path
3
-
4
-
5
- class DummyNode:
6
- def __init__(self, id):
7
- self.id = id
8
-
9
- def __repr__(self):
10
- return f"Node({self.id})"
11
-
12
-
13
- class DummyLink:
14
- def __init__(self, id):
15
- self.id = id
16
-
17
- def __repr__(self):
18
- return f"Link({self.id})"
19
-
20
-
21
- def test_path_creation():
22
- nodes = [DummyNode(1), DummyNode(2), DummyNode(3)]
23
- links = [DummyLink("a"), DummyLink("b")]
24
- path = Path(nodes, links)
25
- assert path.nodes == nodes
26
- assert path.links == links
27
- assert path.length() == 2
28
- assert path.hop_count() == 2
29
- assert path.endpoints() == (nodes[0], nodes[-1])
30
-
31
-
32
- def test_path_invalid():
33
- with pytest.raises(ValueError):
34
- Path([], [])
35
- with pytest.raises(ValueError):
36
- Path([DummyNode(1)], [])
37
- with pytest.raises(ValueError):
38
- Path([DummyNode(1), DummyNode(2)], [DummyLink("a"), DummyLink("b")])
39
-
40
-
41
- def test_path_repr():
42
- nodes = [DummyNode(1), DummyNode(2)]
43
- links = [DummyLink("a")]
44
- path = Path(nodes, links)
45
- s = repr(path)
46
- assert s.startswith("Path(nodes=")
tests/test_topology.py DELETED
@@ -1,225 +0,0 @@
1
- """
2
- Unit tests for the Topology class.
3
- Covers all public methods, success and error cases, and adjacency matrix validation (numpy), including NetworkX integration.
4
- """
5
-
6
- import pytest
7
- import numpy as np
8
- from topolib.topology import Topology
9
- from topolib.elements.node import Node
10
- from topolib.elements.link import Link
11
-
12
-
13
- def test_add_and_get_nodes():
14
- topo = Topology()
15
- n1 = Node(1, "A", 0.0, 0.0)
16
- n2 = Node(2, "B", 1.0, 1.0)
17
- topo.add_node(n1)
18
- topo.add_node(n2)
19
- assert n1 in topo.nodes and n2 in topo.nodes
20
- assert len(topo.nodes) == 2
21
- # Check that nodes are present in the internal networkx graph
22
- assert n1.id in topo._graph.nodes # type: ignore
23
- assert n2.id in topo._graph.nodes # type: ignore
24
-
25
-
26
- def test_add_duplicate_node_allowed():
27
- # The current design allows duplicate nodes (no check in Topology)
28
- topo = Topology()
29
- n1 = Node(1, "A", 0.0, 0.0)
30
- topo.add_node(n1)
31
- topo.add_node(n1)
32
- assert topo.nodes.count(n1) == 2
33
-
34
-
35
- def test_remove_node():
36
- topo = Topology()
37
- n1 = Node(1, "A", 0.0, 0.0)
38
- n2 = Node(2, "B", 1.0, 1.0)
39
- topo.add_node(n1)
40
- topo.add_node(n2)
41
- topo.remove_node(n1.id)
42
- assert n1 not in topo.nodes
43
- assert n2 in topo.nodes
44
- # Check that the node was removed from the internal graph
45
- assert n1.id not in topo._graph.nodes # type: ignore
46
-
47
-
48
- def test_remove_nonexistent_node():
49
- import networkx as nx
50
-
51
- topo = Topology()
52
- n1 = Node(1, "A", 0.0, 0.0)
53
- # Should raise NetworkXError when trying to remove a node not in the graph
54
- with pytest.raises(nx.NetworkXError):
55
- topo.remove_node(n1.id)
56
- assert n1 not in topo.nodes
57
-
58
-
59
- def test_add_and_get_links():
60
- topo = Topology()
61
- n1 = Node(1, "A", 0.0, 0.0)
62
- n2 = Node(2, "B", 1.0, 1.0)
63
- topo.add_node(n1)
64
- topo.add_node(n2)
65
- l1 = Link(1, n1, n2, 10.0)
66
- topo.add_link(l1)
67
- assert l1 in topo.links
68
- assert len(topo.links) == 1
69
- # Check that the edge is present in the internal networkx graph
70
- assert topo._graph.has_edge(n1.id, n2.id) # type: ignore
71
-
72
-
73
- def test_add_link_with_missing_nodes():
74
- # The current design allows adding links even if nodes are not in the topology
75
- topo = Topology()
76
- n1 = Node(1, "A", 0.0, 0.0)
77
- n2 = Node(2, "B", 1.0, 1.0)
78
- l1 = Link(1, n1, n2, 10.0)
79
- topo.add_link(l1)
80
- assert l1 in topo.links
81
-
82
-
83
- def test_remove_link():
84
- topo = Topology()
85
- n1 = Node(1, "A", 0.0, 0.0)
86
- n2 = Node(2, "B", 1.0, 1.0)
87
- topo.add_node(n1)
88
- topo.add_node(n2)
89
- l1 = Link(1, n1, n2, 10.0)
90
- topo.add_link(l1)
91
- topo.remove_link(l1.id)
92
- assert l1 not in topo.links
93
- # Check that the edge was removed from the internal graph
94
- assert not topo._graph.has_edge(n1.id, n2.id) # type: ignore
95
-
96
-
97
- def test_remove_nonexistent_link():
98
- topo = Topology()
99
- n1 = Node(1, "A", 0.0, 0.0)
100
- n2 = Node(2, "B", 1.0, 1.0)
101
- topo.add_node(n1)
102
- topo.add_node(n2)
103
- # Should not raise, just does nothing
104
- topo.remove_link(999)
105
- assert len(topo.links) == 0
106
-
107
-
108
- def test_adjacency_matrix():
109
- topo = Topology()
110
- n1 = Node(1, "A", 0.0, 0.0)
111
- n2 = Node(2, "B", 1.0, 1.0)
112
- n3 = Node(3, "C", 2.0, 2.0)
113
- topo.add_node(n1)
114
- topo.add_node(n2)
115
- topo.add_node(n3)
116
- l1 = Link(1, n1, n2, 10.0)
117
- l2 = Link(2, n2, n3, 20.0)
118
- topo.add_link(l1)
119
- topo.add_link(l2)
120
- matrix = topo.adjacency_matrix()
121
- assert isinstance(matrix, np.ndarray)
122
- assert matrix.shape == (3, 3)
123
- # Check connections
124
- idx = {n.id: i for i, n in enumerate(topo.nodes)}
125
- assert matrix[idx[n1.id], idx[n2.id]] == 1
126
- assert matrix[idx[n2.id], idx[n3.id]] == 1
127
- assert matrix[idx[n1.id], idx[n3.id]] == 0
128
- # Validate with networkx adjacency
129
- adj_nx = np.asarray(
130
- np.array(
131
- [
132
- [1 if topo._graph.has_edge(n1.id, n2.id) else 0 for n2 in topo.nodes] # type: ignore
133
- for n1 in topo.nodes
134
- ]
135
- )
136
- )
137
- assert np.array_equal(matrix, adj_nx)
138
-
139
-
140
- def test_adjacency_matrix_empty():
141
- topo = Topology()
142
- matrix = topo.adjacency_matrix()
143
- assert isinstance(matrix, np.ndarray)
144
- assert matrix.shape == (0, 0)
145
-
146
-
147
- def test_topology_from_json():
148
- import os
149
- import tempfile
150
- import json
151
- from topolib.topology import Topology
152
-
153
- # Usar un ejemplo mínimo de topología
154
- data = {
155
- "name": "TestNet",
156
- "nodes": [
157
- {
158
- "id": 1,
159
- "name": "A",
160
- "latitude": 0.0,
161
- "longitude": 0.0,
162
- "weight": 1.5,
163
- "pop": 1000,
164
- },
165
- {
166
- "id": 2,
167
- "name": "B",
168
- "latitude": 1.0,
169
- "longitude": 1.0,
170
- "weight": 2.5,
171
- "pop": 2000,
172
- },
173
- ],
174
- "links": [{"id": 10, "src": 1, "dst": 2, "length": 42.0}],
175
- }
176
- with tempfile.NamedTemporaryFile("w+", suffix=".json", delete=False) as f:
177
- json.dump(data, f)
178
- f.flush()
179
- path = f.name
180
- topo = Topology.from_json(path)
181
- os.remove(path)
182
- assert len(topo.nodes) == 2
183
- assert len(topo.links) == 1
184
- n1, n2 = topo.nodes
185
- assert n1.name == "A"
186
- assert n2.pop == 2000
187
- l = topo.links[0]
188
- assert l.length == 42.0
189
- assert l.source.id == 1 and l.target.id == 2
190
-
191
-
192
- def test_topology_from_json_reads_dc_ixp(tmp_path):
193
- import json
194
- from topolib.topology import Topology
195
-
196
- # Crear un archivo JSON temporal con los nuevos campos
197
- data = {
198
- "name": "TestNet",
199
- "nodes": [
200
- {
201
- "id": 1,
202
- "name": "A",
203
- "latitude": 0.0,
204
- "longitude": 0.0,
205
- "dc": 10,
206
- "ixp": 2,
207
- },
208
- {
209
- "id": 2,
210
- "name": "B",
211
- "latitude": 1.0,
212
- "longitude": 1.0,
213
- "dc": 20,
214
- "ixp": 5,
215
- },
216
- ],
217
- "links": [],
218
- }
219
- json_file = tmp_path / "testnet.json"
220
- json_file.write_text(json.dumps(data))
221
- topo = Topology.from_json(str(json_file))
222
- assert topo.nodes[0].dc == 10
223
- assert topo.nodes[0].ixp == 2
224
- assert topo.nodes[1].dc == 20
225
- assert topo.nodes[1].ixp == 5
tests/test_version.py DELETED
@@ -1,6 +0,0 @@
1
- import importlib
2
-
3
- def test_package_exports_version():
4
- pkg = importlib.import_module("topolib")
5
- assert hasattr(pkg, "__version__"), "topolib should expose __version__"
6
- assert isinstance(pkg.__version__, str), "__version__ should be a string"
@@ -1,38 +0,0 @@
1
- diagrams/class_diagram.puml,sha256=4EUNpMrbHJYJ8wDM4DqtlIrJDTrvoyIeIiUdOoPsWlM,2183
2
- docs/Makefile,sha256=4zv3TVkTACm6JBaKgTES3ZI9cETXgM6ULbZkXZP1as8,638
3
- docs/requirements.txt,sha256=JBlj0kqsxcteWZpXAEKCobzqG-piWPAfj3_Bx46i9-c,24
4
- docs/source/conf.py,sha256=YeakUjMbnzKQov9CjOiFPmL4mOQ2JP2aHa4No55OYB4,1170
5
- docs/source/index.rst,sha256=ZFCeE5lH5ijU_oVfhGCYe5pq7ko_C1PhML0UHeKVXsg,1171
6
- docs/source/modules.rst,sha256=kRhINzEdye-kWHfUkCy6NByB3oT6FpEcCDWOscakUAA,58
7
- docs/source/topolib.analysis.rst,sha256=1NFOxh0O6ebf19ruvCcb9Oile2uzm_hWkKSb0RufT90,355
8
- docs/source/topolib.elements.rst,sha256=vk_Q_frmUk69gfxOx-_1VNdl7x3tLvc-QAIF4Wxo7wI,379
9
- docs/source/topolib.rst,sha256=J1kJ07JXz0yVyChjPofjTkP02Ns1fM96k9QX3HJCVVs,260
10
- docs/source/topolib.topology.rst,sha256=rdJH23kxZuGtB6rFISAWKUfEFGp5mZS1zRQ4zgwDRSc,510
11
- examples/show_topology_in_map.py,sha256=xjgLiSBHZJ8KYeaCdOBkwAAEJk4hSDkCxBvKNW7Ll9U,441
12
- tests/__init__.py,sha256=eAUS1VPZN5alBWqBdLK4sDxjRPxCvviXncxNvztzVGU,59
13
- tests/test_link.py,sha256=TEfNEivuE17OMmVP4YSi2-8-Mh9_2RDUXBG6Ds3Ljuc,1960
14
- tests/test_mapview.py,sha256=oOx_mYBSy95cacv4PfknP1N5VJzFTEoprhKLovU35Yo,977
15
- tests/test_metrics.py,sha256=-9RM5BGb-oqHl6JNPHIzVTsxPSPBvcHeMxDJqqqnlGs,1374
16
- tests/test_node.py,sha256=9nkrnAP8TnmtSXc83w-e8QJaCG56pzgTbdnueZZrta0,1049
17
- tests/test_path.py,sha256=Dg6NQ7Oz9UrvM4dqNOh-80odzCEWl8q2vM3BAGxpmqA,1091
18
- tests/test_topology.py,sha256=TnGKrtYRPG9wO85lCpVLg6MoOYhHgkWrwjA40xE652g,6258
19
- tests/test_version.py,sha256=rJheq9nRxTaSmvl5yEFGPNmwnMa0I-NkSu2oH47jpt0,253
20
- topolib/__init__.py,sha256=iLmy2rOkHS_4KZWMD8BgT7R3tLMKeaTCDVf3B4FyYxM,91
21
- topolib/analysis/__init__.py,sha256=qvUC9wV_jQNQIlwJXk7LJ-dkTXhH1Ttn0lKWIdwBbrc,52
22
- topolib/analysis/metrics.py,sha256=Di4HGHlz9c2UTCYdfnmjtPjo7w3wwYuyDPeXI7bR0zA,2592
23
- topolib/assets/Abilene_IXP.json,sha256=5cnPMbjsNDjmpySdQDYQ2yd83zOFvCRjlAnbX1wyzgk,6010
24
- topolib/assets/China_pop.json,sha256=v-bs5qib8-CB81rvBNNM9ssoelrNGuFrPEyRCht9YpY,22262
25
- topolib/assets/DT-50_pop.json,sha256=hCv1MCvipgdrQ34VT-qXJ68BdATriQ8ZObh0fLPqar4,29719
26
- topolib/elements/__init__.py,sha256=ZWSd5uwVtppJtMnZ30zrAdzXhUAYIK62RrUaH9rsWu0,180
27
- topolib/elements/link.py,sha256=BwjdCR8peh7dDpKunZodlIsjKcfvwjKxyQ3tmp1obb8,3778
28
- topolib/elements/node.py,sha256=uOnljwA3jcVR4utUfI-om4SIt_QBsEQt8QLW9uvjr3Y,4974
29
- topolib/topology/__init__.py,sha256=2VRhVm4ZvKBiTDB2T8BDmLZBpwGCVFRF3fvtxxC_d28,86
30
- topolib/topology/path.py,sha256=oUNwmpBcS6LMMAJIxokROm3MVqr7vRR44M3Fh5ADq_w,2057
31
- topolib/topology/topology.py,sha256=PzPx80TxWMcOwpOCh4fohcWT2YUra-4m04tBjqyMU40,5605
32
- topolib/visualization/__init__.py,sha256=wv065-KB5uDbTaQIASPVfMMW5sE76Bs-q0oai48vAzk,29
33
- topolib/visualization/mapview.py,sha256=4iKJMYsH6oFNj9tOcgSKLVRtoYfUuH3XLjShsGwUXcM,2799
34
- topolib-0.0.0.dist-info/licenses/LICENSE,sha256=kbnIP0XU6f2ualiTjEawdlU81IGPBbwc-_GF3N-1e9E,1081
35
- topolib-0.0.0.dist-info/METADATA,sha256=4OEpNmsfDsL7k0230z4ObnVFu3o2mKT_SEeJifiE8P4,4294
36
- topolib-0.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- topolib-0.0.0.dist-info/top_level.txt,sha256=7ynOTanzCkVNSIj7GUDQ1TveIoSt3tcfSi0I0JYTrq0,37
38
- topolib-0.0.0.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- diagrams
2
- docs
3
- examples
4
- tests
5
- topolib