-
Notifications
You must be signed in to change notification settings - Fork 37
Description
You are helping refactor an existing open-source Python library called py3plex for multilayer/multiplex network analysis and visualization.
General goals: Improve code quality, consistency, and maintainability. Modernize the codebase for Python 3.10+. Keep the public API behavior backwards compatible where reasonable.
Constraints: Do NOT change the external behavior of public functions unless absolutely necessary. Prefer incremental, file-by-file refactors with clear diffs. Follow PEP8 and use a formatter-compatible style (for example black or ruff format).
Focus areas and tasks:
Typing and public API: In py3plex/core/.py, py3plex/visualization/.py, and py3plex/wrappers/*.py, add type hints to all public functions, methods and class attributes. Use collections.abc types such as Iterable, Mapping, and Sequence where appropriate. Create reusable type aliases for core concepts, for example Node, LayerId, Weight, and EdgeTuple = (n1, l1, n2, l2, w). Ensure method signatures of multi_layer_network and related classes are fully typed. In py3plex/init.py, define all listing the officially supported public API and re-export only the stable top-level classes and functions.
Imports and style consistency: Remove wildcard imports in the library and examples, replacing “from py3plex.visualization.multilayer import *” with explicit imports. Normalize formatting by removing spaces before parentheses in function calls (use foo() not foo ()) and respecting a reasonable max line length (for example 88 or 100 characters). Convert internal absolute imports to explicit relative imports where appropriate.
Exceptions and error handling: Define a small exception hierarchy in a dedicated module (for example py3plex/exceptions.py) with a base Py3plexError and more specific classes such as InvalidInputFormat, LayerNotFound, and ExternalToolError. Replace generic “except:” or “except Exception:” in library code with specific exceptions (such as ValueError, FileNotFoundError, subprocess.CalledProcessError) or with the new Py3plexError subclasses that carry descriptive error messages. Ensure parsing functions like load_network, subnetwork, and aggregate_edges use these exceptions consistently.
Logging instead of print and custom monitor: Introduce standard logging by defining a module-level logger such as logger = logging.getLogger("py3plex") in core modules. Replace print-based status messages and any custom monitor-style calls in library code with logger.debug, logger.info, logger.warning, and logger.error as appropriate. Keep examples free to use print, but show how to enable logging in docs or examples when users want detailed output.
Visualization module cleanup: In py3plex/visualization/multilayer.py and related visualization files, standardize function signatures and use consistent parameter names for graphs, colors, and layout parameters. Factor common keyword arguments (such as layout_parameters, color_list, and edge style options) into a small @DataClass configuration object. Move low-level Matplotlib drawing routines into private helper functions (for example _draw_nodes and _draw_edges) and keep public functions as thin wrappers that validate inputs, set up configuration, and call the helpers.
External tool wrappers: In py3plex/wrappers/* (for node2vec, Infomap, and similar tools), centralize subprocess calls in a small helper module. Add explicit timeouts and robust error handling for missing binaries or non-zero exit codes. Wrap subprocess errors in ExternalToolError with a clear, user-facing message that explains what went wrong and how to fix it. Allow configuring binary paths via environment variables or configuration constants instead of only via positional arguments.
Tests and CI: Add or extend tests to cover failure modes such as invalid input_type values, missing layers, and bad file formats. Add tests for external tool failures, including missing binaries and failed subprocess calls. If not present, add coverage configuration (for example pytest-cov with a cov-fail-under threshold) and ensure it runs in CI so new changes maintain coverage.
Examples: In examples/*.py, wrap the main code into functions and guard execution with “if name == 'main':”. Remove duplicated logic by sharing helper functions where sensible. Update examples to use the cleaned-up imports, the preferred coding style, and, optionally, type hints for function signatures so they reflect the modernized API patterns.
Work plan: Start with the core data structures in py3plex/core/*.py, then move to visualization modules, then wrappers, and finally examples and tests. For each file, propose a unified diff (git-style patch) implementing the above changes. Keep changes small and reviewable, and ensure tests still pass after each set of refactors. As you generate changes, briefly explain what was changed, why it improves code quality, and any potential backwards-compatibility impacts that py3plex users should be aware of. no new md allowed