Skip to content

Commit ecf6081

Browse files
CopilotSkBlaz
andauthored
Audit and tighten top-level public API exports (config + IO convenience aliases) (#1306)
* Initial plan * Export config and IO convenience APIs at top-level Agent-Logs-Url: https://github.com/SkBlaz/py3plex/sessions/49273dd3-4fd5-4b72-af96-60555bbf4034 Co-authored-by: SkBlaz <10035780+SkBlaz@users.noreply.github.com> * Refine public API export test dependency check Agent-Logs-Url: https://github.com/SkBlaz/py3plex/sessions/49273dd3-4fd5-4b72-af96-60555bbf4034 Co-authored-by: SkBlaz <10035780+SkBlaz@users.noreply.github.com> * Fix Python 3.8 CI by lazily exposing top-level IO aliases Agent-Logs-Url: https://github.com/SkBlaz/py3plex/sessions/45f0a857-b71d-4c02-a004-ae360f90e34d Co-authored-by: SkBlaz <10035780+SkBlaz@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: SkBlaz <10035780+SkBlaz@users.noreply.github.com>
1 parent ddac513 commit ecf6081

2 files changed

Lines changed: 96 additions & 1 deletion

File tree

py3plex/__init__.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
profile_performance,
124124
timed_section,
125125
)
126+
import py3plex.config as config
126127

127128
# Plugin system - import for easy access
128129
from py3plex.plugins import (
@@ -163,7 +164,6 @@
163164
make_random_multiplex,
164165
make_social_network,
165166
)
166-
167167
# Dynamics module for simulating dynamical processes
168168
from py3plex.dynamics import (
169169
D,
@@ -199,6 +199,34 @@
199199
estimate_uncertainty,
200200
)
201201

202+
203+
def save_to_arrow(network, path, **kwargs):
204+
"""Lazy top-level alias for :func:`py3plex.io.save_to_arrow`."""
205+
from py3plex.io import save_to_arrow as _save_to_arrow
206+
207+
return _save_to_arrow(network, path, **kwargs)
208+
209+
210+
def load_from_arrow(path, as_multinet=True, **kwargs):
211+
"""Lazy top-level alias for :func:`py3plex.io.load_from_arrow`."""
212+
from py3plex.io import load_from_arrow as _load_from_arrow
213+
214+
return _load_from_arrow(path, as_multinet=as_multinet, **kwargs)
215+
216+
217+
def save_network_to_parquet(network, path, **kwargs):
218+
"""Lazy top-level alias for :func:`py3plex.io.save_network_to_parquet`."""
219+
from py3plex.io import save_network_to_parquet as _save_network_to_parquet
220+
221+
return _save_network_to_parquet(network, path, **kwargs)
222+
223+
224+
def load_network_from_parquet(path, **kwargs):
225+
"""Lazy top-level alias for :func:`py3plex.io.load_network_from_parquet`."""
226+
from py3plex.io import load_network_from_parquet as _load_network_from_parquet
227+
228+
return _load_network_from_parquet(path, **kwargs)
229+
202230
__all__ = [
203231
# Version info
204232
"__version__",
@@ -299,6 +327,13 @@
299327
"make_social_network",
300328
"list_datasets",
301329
"get_data_dir",
330+
# Config module
331+
"config",
332+
# I/O convenience functions
333+
"save_to_arrow",
334+
"load_from_arrow",
335+
"save_network_to_parquet",
336+
"load_network_from_parquet",
302337
# Dynamics (simulation)
303338
"D",
304339
"SimulationBuilder",

tests/test_public_api_exports.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""Tests for top-level py3plex public API exports."""
2+
import pytest
3+
4+
5+
def _import_py3plex_or_skip():
6+
"""Import py3plex or skip when optional heavy deps are unavailable."""
7+
try:
8+
import py3plex
9+
except ModuleNotFoundError as exc:
10+
if exc.name in {"matplotlib", "networkx"}:
11+
pytest.skip(f"optional dependency missing for top-level import: {exc.name}")
12+
raise
13+
return py3plex
14+
15+
16+
def test_config_exported_from_main_package():
17+
"""config should be exported from top-level py3plex package."""
18+
py3plex = _import_py3plex_or_skip()
19+
20+
assert "config" in py3plex.__all__
21+
assert hasattr(py3plex, "config")
22+
23+
from py3plex import config as config_from_main
24+
import py3plex.config as config_module
25+
26+
assert config_from_main is config_module
27+
28+
29+
def test_io_convenience_functions_exported_from_main_package():
30+
"""Arrow/Parquet convenience I/O functions should be top-level exports."""
31+
py3plex = _import_py3plex_or_skip()
32+
33+
names = [
34+
"save_to_arrow",
35+
"load_from_arrow",
36+
"save_network_to_parquet",
37+
"load_network_from_parquet",
38+
]
39+
40+
for name in names:
41+
assert name in py3plex.__all__
42+
assert hasattr(py3plex, name)
43+
assert callable(getattr(py3plex, name))
44+
45+
46+
def test_io_convenience_functions_match_io_module():
47+
"""Top-level I/O convenience exports should be callable lazy aliases."""
48+
py3plex = _import_py3plex_or_skip()
49+
50+
names = [
51+
"save_to_arrow",
52+
"load_from_arrow",
53+
"save_network_to_parquet",
54+
"load_network_from_parquet",
55+
]
56+
57+
for name in names:
58+
fn = getattr(py3plex, name)
59+
assert callable(fn)
60+
assert fn.__module__ == "py3plex"

0 commit comments

Comments
 (0)