Skip to content

Commit

Permalink
Update to NetworkX 3.2 (#77)
Browse files Browse the repository at this point in the history
* Update to NetworkX 3.2

* Use mamba instead for faster environment creation

* Drop Python 3.8
  • Loading branch information
eriknw authored Oct 9, 2023
1 parent 3caced2 commit 4fccd7e
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 32 deletions.
26 changes: 22 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,34 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Conda
- name: Setup mamba
uses: conda-incubator/setup-miniconda@v2
id: setup_mamba
continue-on-error: true
with:
miniforge-variant: Mambaforge
miniforge-version: latest
use-mamba: true
python-version: ${{ matrix.python-version }}
channels: conda-forge,${{ contains(matrix.python-version, 'pypy') && 'defaults' || 'nodefaults' }}
channel-priority: ${{ contains(matrix.python-version, 'pypy') && 'flexible' || 'strict' }}
activate-environment: graphblas
auto-activate-base: false
- name: Setup conda
uses: conda-incubator/setup-miniconda@v2
id: setup_conda
if: steps.setup_mamba.outcome == 'failure'
continue-on-error: false
with:
auto-update-conda: true
python-version: ${{ matrix.python-version }}
channels: conda-forge
activate-environment: testing
channels: conda-forge,${{ contains(matrix.python-version, 'pypy') && 'defaults' || 'nodefaults' }}
channel-priority: ${{ contains(matrix.python-version, 'pypy') && 'flexible' || 'strict' }}
activate-environment: graphblas
auto-activate-base: false
- name: Install dependencies
run: |
conda install -c conda-forge python-graphblas scipy pandas pytest-cov pytest-randomly pytest-mpl
$(command -v mamba || command -v conda) install python-graphblas scipy pandas pytest-cov pytest-randomly pytest-mpl
# matplotlib lxml pygraphviz pydot sympy # Extra networkx deps we don't need yet
pip install git+https://github.com/networkx/networkx.git@main --no-deps
pip install -e . --no-deps
Expand Down
38 changes: 20 additions & 18 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@
# To update: `pre-commit autoupdate`
# - &flake8_dependencies below needs updated manually
ci:
# See: https://pre-commit.ci/#configuration
autofix_prs: false
autoupdate_schedule: quarterly
skip: [no-commit-to-branch]
# See: https://pre-commit.ci/#configuration
autofix_prs: false
autoupdate_schedule: quarterly
autoupdate_commit_msg: "chore: update pre-commit hooks"
autofix_commit_msg: "style: pre-commit fixes"
skip: [no-commit-to-branch]
fail_fast: true
default_language_version:
python: python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
# - id: check-symlinks
- id: check-ast
- id: check-toml
- id: check-yaml
Expand All @@ -37,7 +39,7 @@ repos:
name: Validate pyproject.toml
# I don't yet trust ruff to do what autoflake does
- repo: https://github.com/PyCQA/autoflake
rev: v2.2.0
rev: v2.2.1
hooks:
- id: autoflake
args: [--in-place]
Expand All @@ -46,22 +48,22 @@ repos:
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v3.10.1
rev: v3.15.0
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py39-plus]
- repo: https://github.com/MarcoGorelli/auto-walrus
rev: v0.2.2
hooks:
- id: auto-walrus
args: [--line-length, "100"]
- repo: https://github.com/psf/black
rev: 23.7.0
rev: 23.9.1
hooks:
- id: black
# - id: black-jupyter
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.285
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.292
hooks:
- id: ruff
args: [--fix-only, --show-fixes]
Expand All @@ -72,22 +74,22 @@ repos:
additional_dependencies: &flake8_dependencies
# These versions need updated manually
- flake8==6.1.0
- flake8-bugbear==23.7.10
- flake8-simplify==0.20.0
- flake8-bugbear==23.9.16
- flake8-simplify==0.21.0
- repo: https://github.com/asottile/yesqa
rev: v1.5.0
hooks:
- id: yesqa
additional_dependencies: *flake8_dependencies
- repo: https://github.com/codespell-project/codespell
rev: v2.2.5
rev: v2.2.6
hooks:
- id: codespell
types_or: [python, rst, markdown]
additional_dependencies: [tomli]
files: ^(graphblas_algorithms|docs)/
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.285
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.292
hooks:
- id: ruff
# `pyroma` may help keep our package standards up to date if best practices change.
Expand All @@ -98,6 +100,6 @@ repos:
- id: pyroma
args: [-n, "10", .]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: no-commit-to-branch # no commit directly to main
107 changes: 107 additions & 0 deletions _nx_graphblas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
def get_info():
return {
"backend_name": "graphblas",
"project": "graphblas-algorithms",
"package": "graphblas_algorithms",
"url": "https://github.com/python-graphblas/graphblas-algorithms",
"short_summary": "Fast, OpenMP-enabled backend using GraphBLAS",
# "description": "TODO",
"functions": {
"adjacency_matrix": {},
"all_pairs_bellman_ford_path_length": {
"extra_parameters": {
"chunksize": "Split the computation into chunks; "
'may specify size as string or number of rows. Default "10 MiB"',
},
},
"all_pairs_shortest_path_length": {
"extra_parameters": {
"chunksize": "Split the computation into chunks; "
'may specify size as string or number of rows. Default "10 MiB"',
},
},
"ancestors": {},
"average_clustering": {},
"bellman_ford_path": {},
"bellman_ford_path_length": {},
"bethe_hessian_matrix": {},
"bfs_layers": {},
"boundary_expansion": {},
"clustering": {},
"complement": {},
"compose": {},
"conductance": {},
"cut_size": {},
"degree_centrality": {},
"descendants": {},
"descendants_at_distance": {},
"difference": {},
"directed_modularity_matrix": {},
"disjoint_union": {},
"edge_boundary": {},
"edge_expansion": {},
"efficiency": {},
"ego_graph": {},
"eigenvector_centrality": {},
"fast_could_be_isomorphic": {},
"faster_could_be_isomorphic": {},
"floyd_warshall": {},
"floyd_warshall_numpy": {},
"floyd_warshall_predecessor_and_distance": {},
"full_join": {},
"generalized_degree": {},
"google_matrix": {},
"has_path": {},
"hits": {},
"in_degree_centrality": {},
"inter_community_edges": {},
"intersection": {},
"intra_community_edges": {},
"is_connected": {},
"is_dominating_set": {},
"is_isolate": {},
"is_k_regular": {},
"isolates": {},
"is_regular": {},
"is_simple_path": {},
"is_tournament": {},
"is_triad": {},
"is_weakly_connected": {},
"katz_centrality": {},
"k_truss": {},
"laplacian_matrix": {},
"lowest_common_ancestor": {},
"mixing_expansion": {},
"modularity_matrix": {},
"mutual_weight": {},
"negative_edge_cycle": {},
"node_boundary": {},
"node_connected_component": {},
"node_expansion": {},
"normalized_cut_size": {},
"normalized_laplacian_matrix": {},
"number_of_isolates": {},
"out_degree_centrality": {},
"overall_reciprocity": {},
"pagerank": {},
"reciprocity": {},
"reverse": {},
"score_sequence": {},
"single_source_bellman_ford_path_length": {},
"single_source_shortest_path_length": {},
"single_target_shortest_path_length": {},
"s_metric": {},
"square_clustering": {
"extra_parameters": {
"chunksize": "Split the computation into chunks; "
'may specify size as string or number of rows. Default "256 MiB"',
},
},
"symmetric_difference": {},
"tournament_matrix": {},
"transitivity": {},
"triangles": {},
"union": {},
"volume": {},
},
}
3 changes: 2 additions & 1 deletion graphblas_algorithms/classes/digraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ def __missing__(self, key):


class DiGraph(Graph):
__networkx_backend__ = "graphblas"
__networkx_plugin__ = "graphblas"

# "-" properties ignore self-edges, "+" properties include self-edges
Expand Down Expand Up @@ -611,7 +612,7 @@ def to_undirected(self, reciprocal=False, as_view=False, *, name=None):
return Graph(B, key_to_id=self._key_to_id)

def reverse(self, copy=True):
# We could even re-use many of the cached values
# We could even reuse many of the cached values
A = self._A.T # This probably mostly works, but does not yet support assignment
if copy:
A = A.new()
Expand Down
1 change: 1 addition & 0 deletions graphblas_algorithms/classes/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ def __missing__(self, key):


class Graph:
__networkx_backend__ = "graphblas"
__networkx_plugin__ = "graphblas"

# "-" properties ignore self-edges, "+" properties include self-edges
Expand Down
19 changes: 14 additions & 5 deletions graphblas_algorithms/nxapi/smetric.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import warnings

from graphblas_algorithms import algorithms
from graphblas_algorithms.classes.digraph import to_graph

from .exception import NetworkXError

__all__ = ["s_metric"]


def s_metric(G, normalized=True):
if normalized:
raise NetworkXError("Normalization not implemented")
def s_metric(G, **kwargs):
if kwargs:
if "normalized" in kwargs:
warnings.warn(
"\n\nThe `normalized` keyword is deprecated and will be removed\n"
"in the future. To silence this warning, remove `normalized`\n"
"when calling `s_metric`.\n\nThe value of `normalized` is ignored.",
DeprecationWarning,
stacklevel=2,
)
else:
raise TypeError(f"s_metric got an unexpected keyword argument '{kwargs.popitem()[0]}'")
G = to_graph(G)
return algorithms.s_metric(G)
1 change: 1 addition & 0 deletions graphblas_algorithms/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def test_packages():
path = pathlib.Path(ga.__file__).parent
pkgs = [f"graphblas_algorithms.{x}" for x in setuptools.find_packages(path)]
pkgs.append("graphblas_algorithms")
pkgs.append("_nx_graphblas")
pkgs.sort()
pyproject = path.parent / "pyproject.toml"
if not pyproject.exists():
Expand Down
18 changes: 14 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ name = "graphblas-algorithms"
dynamic = ["version"]
description = "Graph algorithms written in GraphBLAS and backend for NetworkX"
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.9"
license = {file = "LICENSE"}
authors = [
{name = "Erik Welch", email = "erik.n.welch@gmail.com"},
Expand Down Expand Up @@ -43,7 +43,6 @@ classifiers = [
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -65,6 +64,12 @@ dependencies = [
[project.entry-points."networkx.plugins"]
graphblas = "graphblas_algorithms.interface:Dispatcher"

[project.entry-points."networkx.backends"]
graphblas = "graphblas_algorithms.interface:Dispatcher"

[project.entry-points."networkx.backend_info"]
graphblas = "_nx_graphblas:get_info"

[project.urls]
homepage = "https://github.com/python-graphblas/graphblas-algorithms"
# documentation = "https://graphblas-algorithms.readthedocs.io"
Expand All @@ -90,6 +95,7 @@ all = [
# $ find graphblas_algorithms/ -name __init__.py -print | sort | sed -e 's/\/__init__.py//g' -e 's/\//./g'
# $ python -c 'import tomli ; [print(x) for x in sorted(tomli.load(open("pyproject.toml", "rb"))["tool"]["setuptools"]["packages"])]'
packages = [
"_nx_graphblas",
"graphblas_algorithms",
"graphblas_algorithms.algorithms",
"graphblas_algorithms.algorithms.centrality",
Expand Down Expand Up @@ -127,7 +133,7 @@ dirty_template = "{tag}+{ccount}.g{sha}.dirty"

[tool.black]
line-length = 100
target-version = ["py38", "py39", "py310", "py311"]
target-version = ["py39", "py310", "py311"]

[tool.isort]
sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
Expand All @@ -143,6 +149,7 @@ skip = [
]

[tool.pytest.ini_options]
minversion = "6.0"
testpaths = "graphblas_algorithms"
xfail_strict = false
markers = [
Expand All @@ -169,7 +176,10 @@ exclude_lines = [
[tool.ruff]
# https://github.com/charliermarsh/ruff/
line-length = 100
target-version = "py38"
target-version = "py39"
unfixable = [
"F841" # unused-variable (Note: can leave useless expression)
]
select = [
"ALL",
]
Expand Down

0 comments on commit 4fccd7e

Please sign in to comment.