From 98adf73fd8bc747b079beed86d9f26c34644b4f2 Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Wed, 28 Feb 2024 11:09:58 -0600 Subject: [PATCH 1/8] Updates nx-cugraph README.md with current GPU and CUDA requirements, moves README updater check from CI test script to pre-commit. --- .pre-commit-config.yaml | 9 +++++++ ci/test_python.sh | 7 ----- python/nx-cugraph/Makefile | 7 ++--- python/nx-cugraph/README.md | 20 +++++++++----- python/nx-cugraph/scripts/update_readme.py | 31 +++++++++++++++++++--- 5 files changed, 53 insertions(+), 21 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6b7ff14417c..59f8b1ce746 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,3 +57,12 @@ repos: hooks: - id: rapids-dependency-file-generator args: ["--clean"] + - repo: local + hooks: + - id: nx-cugraph-readme-check + name: nx-cugraph-readme-check + entry: bash -c PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md + files: ^python/nx-cugraph/ + types: [python] + language: python + pass_filenames: false diff --git a/ci/test_python.sh b/ci/test_python.sh index 9fa1de2e5e7..8fa9a90ae69 100755 --- a/ci/test_python.sh +++ b/ci/test_python.sh @@ -127,13 +127,6 @@ python -m nx_cugraph.scripts.print_tree --dispatch-name --plc --incomplete --dif python -m nx_cugraph.scripts.print_table popd -rapids-logger "ensure nx-cugraph autogenerated files are up to date" -pushd python/nx-cugraph -make || true -git diff --exit-code . -git checkout . -popd - rapids-logger "pytest cugraph-service (single GPU)" ./ci/run_cugraph_service_pytests.sh \ --verbose \ diff --git a/python/nx-cugraph/Makefile b/python/nx-cugraph/Makefile index 6500d834ee7..a4af186f763 100644 --- a/python/nx-cugraph/Makefile +++ b/python/nx-cugraph/Makefile @@ -16,9 +16,6 @@ lint-update: plugin-info: python _nx_cugraph/__init__.py -objects.inv: - wget https://networkx.org/documentation/stable/objects.inv - .PHONY: readme -readme: objects.inv - python scripts/update_readme.py README.md objects.inv +readme: + python scripts/update_readme.py README.md diff --git a/python/nx-cugraph/README.md b/python/nx-cugraph/README.md index 8201dc34eb2..fa045cf658e 100644 --- a/python/nx-cugraph/README.md +++ b/python/nx-cugraph/README.md @@ -7,11 +7,10 @@ to run supported algorithms with GPU acceleration. ## System Requirements nx-cugraph requires the following: - - * NVIDIA GPU, Pascal architecture or later + * NVIDIA GPU, Volta architecture or later, with [compute capability](https://developer.nvidia.com/cuda-gpus) 7.0+ * CUDA 11.2, 11.4, 11.5, 11.8, or 12.0 - * Python versions 3.9, 3.10, or 3.11 - * NetworkX >= version 3.2 + * Python version 3.10 + * NetworkX >= version 3.0 (version 3.2 recommended) More details about system requirements can be found in the [RAPIDS System Requirements documentation](https://docs.rapids.ai/install#system-req). @@ -20,16 +19,25 @@ More details about system requirements can be found in the [RAPIDS System Requir nx-cugraph can be installed using either conda or pip. ### conda +#### latest nightly version ``` conda install -c rapidsai-nightly -c conda-forge -c nvidia nx-cugraph ``` +#### latest stable version +``` +conda install -c rapidsai -c conda-forge -c nvidia nx-cugraph +``` ### pip +#### latest nightly version +``` +python -m pip install nx-cugraph-cu11 --extra-index-url https://pypi.anaconda.org/rapidsai-wheels-nightly/simple +``` +#### latest stable version ``` python -m pip install nx-cugraph-cu11 --extra-index-url https://pypi.nvidia.com ``` Notes: - - * Nightly wheel builds will not be available until the 23.12 release, therefore the index URL for the stable release version is being used in the pip install command above. + * The pip example above installs for CUDA 11. To install for CUDA 12, replace `-cu11` with `-cu12` * Additional information relevant to installing any RAPIDS package can be found [here](https://rapids.ai/#quick-start). ## Enabling nx-cugraph diff --git a/python/nx-cugraph/scripts/update_readme.py b/python/nx-cugraph/scripts/update_readme.py index 1ab5a76c4c0..878c620a394 100644 --- a/python/nx-cugraph/scripts/update_readme.py +++ b/python/nx-cugraph/scripts/update_readme.py @@ -16,10 +16,13 @@ import zlib from collections import namedtuple from pathlib import Path +import urllib.request from warnings import warn from nx_cugraph.scripts.print_tree import create_tree, tree_lines +_objs_file_url = "https://networkx.org/documentation/stable/objects.inv" + # See: https://sphobjinv.readthedocs.io/en/stable/syntax.html DocObject = namedtuple( "DocObject", @@ -190,14 +193,36 @@ def get_payload_internal(keys): return text +def find_or_download_objs_file(objs_file_dir): + """ + Returns the path to /objects.inv, downloading it from + _objs_file_url if it does not already exist. + """ + objs_file_path = objs_file_dir / "objects.inv" + if not objs_file_path.exists(): + request = urllib.request.Request(_objs_file_url) + with urllib.request.urlopen(request) as response: + with open(objs_file_path, "wb") as out: + out.write(response.read()) + return objs_file_path + + if __name__ == "__main__": parser = argparse.ArgumentParser( "Update README.md to show NetworkX functions implemented by nx-cugraph" ) parser.add_argument("readme_filename", help="Path to the README.md file") parser.add_argument( - "networkx_objects", help="Path to the objects.inv file from networkx docs" + "networkx_objects", nargs="?", default=None, + help="Path to the objects.inv file from networkx docs. Optional." ) args = parser.parse_args() - with Path(args.readme_filename).open("a+") as readme_file: - main(readme_file, args.networkx_objects) + + readme_filename = args.readme_filename + readme_path = Path(readme_filename) + objects_filename = args.networkx_objects + if objects_filename is None: + objects_filename = find_or_download_objs_file(readme_path.parent) + + with readme_path.open("a+") as readme_file: + main(readme_filename, objects_filename) From 83d843e24154fe607443eeafff8f2f0e0b66a75e Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Thu, 29 Feb 2024 14:19:23 -0600 Subject: [PATCH 2/8] Updates check name. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 59f8b1ce746..2b94531a254 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -60,7 +60,7 @@ repos: - repo: local hooks: - id: nx-cugraph-readme-check - name: nx-cugraph-readme-check + name: nx-cugraph README updater entry: bash -c PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md files: ^python/nx-cugraph/ types: [python] From db8b05be63c6f6f6f145835f51199efc7e6c5ecd Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Fri, 8 Mar 2024 14:38:09 -0600 Subject: [PATCH 3/8] Updates python version to include 3.11, adds detail to recommended NX version. --- python/nx-cugraph/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/nx-cugraph/README.md b/python/nx-cugraph/README.md index fa045cf658e..ac73b30ac53 100644 --- a/python/nx-cugraph/README.md +++ b/python/nx-cugraph/README.md @@ -9,8 +9,8 @@ to run supported algorithms with GPU acceleration. nx-cugraph requires the following: * NVIDIA GPU, Volta architecture or later, with [compute capability](https://developer.nvidia.com/cuda-gpus) 7.0+ * CUDA 11.2, 11.4, 11.5, 11.8, or 12.0 - * Python version 3.10 - * NetworkX >= version 3.0 (version 3.2 recommended) + * Python version 3.10 or 3.11 + * NetworkX >= version 3.0 (version 3.2 or higher recommended) More details about system requirements can be found in the [RAPIDS System Requirements documentation](https://docs.rapids.ai/install#system-req). From 8a73239dac8e754bcd8cfbd5813e826fd4a9c279 Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Sat, 9 Mar 2024 02:49:14 -0600 Subject: [PATCH 4/8] Restores nx-cugraph Makefile to explicitly download and use objects.inv. --- python/nx-cugraph/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/nx-cugraph/Makefile b/python/nx-cugraph/Makefile index a4af186f763..6500d834ee7 100644 --- a/python/nx-cugraph/Makefile +++ b/python/nx-cugraph/Makefile @@ -16,6 +16,9 @@ lint-update: plugin-info: python _nx_cugraph/__init__.py +objects.inv: + wget https://networkx.org/documentation/stable/objects.inv + .PHONY: readme -readme: - python scripts/update_readme.py README.md +readme: objects.inv + python scripts/update_readme.py README.md objects.inv From 7236c95273f43cfdd81dbb5b1a268b98da477e9d Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Mon, 11 Mar 2024 20:32:05 -0500 Subject: [PATCH 5/8] Adds python 3.9 back to README, fixes command to work with bash -c, adds NX>=3.2 to pre-commit python environment for nx-cugraph hooks, adds markdown as a type for nx-cugraph README updater, stubs out nx-cugraph runtime deps to allow import without installing them for nx-cugraph pre-commit hooks. --- .pre-commit-config.yaml | 13 +++- python/nx-cugraph/README.md | 2 +- python/nx-cugraph/_nx_cugraph/__init__.py | 76 +++++++++++++--------- python/nx-cugraph/scripts/update_readme.py | 20 +++++- 4 files changed, 75 insertions(+), 36 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7230dde9ae4..1ad5d464818 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -63,8 +63,19 @@ repos: hooks: - id: nx-cugraph-readme-check name: nx-cugraph README updater - entry: bash -c PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md + entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md" + files: ^python/nx-cugraph/ + types_or: [python, markdown] + language: python + pass_filenames: false + additional_dependencies: ["networkx>=3.2"] + - repo: local + hooks: + - id: nx-cugraph-meta-data-update + name: nx-cugraph meta-data updater + entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/_nx_cugraph/__init__.py" files: ^python/nx-cugraph/ types: [python] language: python pass_filenames: false + additional_dependencies: ["networkx>=3.2"] diff --git a/python/nx-cugraph/README.md b/python/nx-cugraph/README.md index ac73b30ac53..b1ed6d5bde4 100644 --- a/python/nx-cugraph/README.md +++ b/python/nx-cugraph/README.md @@ -9,7 +9,7 @@ to run supported algorithms with GPU acceleration. nx-cugraph requires the following: * NVIDIA GPU, Volta architecture or later, with [compute capability](https://developer.nvidia.com/cuda-gpus) 7.0+ * CUDA 11.2, 11.4, 11.5, 11.8, or 12.0 - * Python version 3.10 or 3.11 + * Python version 3.9, 3.10, or 3.11 * NetworkX >= version 3.0 (version 3.2 or higher recommended) More details about system requirements can be found in the [RAPIDS System Requirements documentation](https://docs.rapids.ai/install#system-req). diff --git a/python/nx-cugraph/_nx_cugraph/__init__.py b/python/nx-cugraph/_nx_cugraph/__init__.py index b2f13d25ff3..0d30b244a99 100644 --- a/python/nx-cugraph/_nx_cugraph/__init__.py +++ b/python/nx-cugraph/_nx_cugraph/__init__.py @@ -128,46 +128,46 @@ }, "additional_docs": { # BEGIN: additional_docs - "average_clustering": "Directed graphs and `weight` parameter are not yet supported.", - "betweenness_centrality": "`weight` parameter is not yet supported, and RNG with seed may be different.", - "bfs_edges": "`sort_neighbors` parameter is not yet supported.", - "bfs_predecessors": "`sort_neighbors` parameter is not yet supported.", - "bfs_successors": "`sort_neighbors` parameter is not yet supported.", - "bfs_tree": "`sort_neighbors` parameter is not yet supported.", - "clustering": "Directed graphs and `weight` parameter are not yet supported.", - "core_number": "Directed graphs are not yet supported.", - "edge_betweenness_centrality": "`weight` parameter is not yet supported, and RNG with seed may be different.", - "eigenvector_centrality": "`nstart` parameter is not used, but it is checked for validity.", - "from_pandas_edgelist": "cudf.DataFrame inputs also supported; value columns with str is unsuppported.", - "generic_bfs_edges": "`neighbors` and `sort_neighbors` parameters are not yet supported.", - "k_truss": ( - "Currently raises `NotImplementedError` for graphs with more than one connected\n" - "component when k >= 3. We expect to fix this soon." + 'average_clustering': 'Directed graphs and `weight` parameter are not yet supported.', + 'betweenness_centrality': '`weight` parameter is not yet supported, and RNG with seed may be different.', + 'bfs_edges': '`sort_neighbors` parameter is not yet supported.', + 'bfs_predecessors': '`sort_neighbors` parameter is not yet supported.', + 'bfs_successors': '`sort_neighbors` parameter is not yet supported.', + 'bfs_tree': '`sort_neighbors` parameter is not yet supported.', + 'clustering': 'Directed graphs and `weight` parameter are not yet supported.', + 'core_number': 'Directed graphs are not yet supported.', + 'edge_betweenness_centrality': '`weight` parameter is not yet supported, and RNG with seed may be different.', + 'eigenvector_centrality': '`nstart` parameter is not used, but it is checked for validity.', + 'from_pandas_edgelist': 'cudf.DataFrame inputs also supported; value columns with str is unsuppported.', + 'generic_bfs_edges': '`neighbors` and `sort_neighbors` parameters are not yet supported.', + 'k_truss': ( + 'Currently raises `NotImplementedError` for graphs with more than one connected\n' + 'component when k >= 3. We expect to fix this soon.' ), - "katz_centrality": "`nstart` isn't used (but is checked), and `normalized=False` is not supported.", - "louvain_communities": "`seed` parameter is currently ignored, and self-loops are not yet supported.", - "pagerank": "`dangling` parameter is not supported, but it is checked for validity.", - "transitivity": "Directed graphs are not yet supported.", + 'katz_centrality': "`nstart` isn't used (but is checked), and `normalized=False` is not supported.", + 'louvain_communities': '`seed` parameter is currently ignored, and self-loops are not yet supported.', + 'pagerank': '`dangling` parameter is not supported, but it is checked for validity.', + 'transitivity': 'Directed graphs are not yet supported.', # END: additional_docs }, "additional_parameters": { # BEGIN: additional_parameters - "eigenvector_centrality": { - "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", + 'eigenvector_centrality': { + 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', }, - "hits": { - "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", - 'weight : string or None, optional (default="weight")': "The edge attribute to use as the edge weight.", + 'hits': { + 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', + 'weight : string or None, optional (default="weight")': 'The edge attribute to use as the edge weight.', }, - "katz_centrality": { - "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", + 'katz_centrality': { + 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', }, - "louvain_communities": { - "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", - "max_level : int, optional": "Upper limit of the number of macro-iterations (max: 500).", + 'louvain_communities': { + 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', + 'max_level : int, optional': 'Upper limit of the number of macro-iterations (max: 500).', }, - "pagerank": { - "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", + 'pagerank': { + 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', }, # END: additional_parameters }, @@ -208,6 +208,20 @@ def get_info(): if __name__ == "__main__": from pathlib import Path + # This script imports nx_cugraph modules, which imports nx_cugraph runtime + # dependencies. The modules do not need the runtime deps, so stub them out + # to avoid installing them. + class Stub: + def __getattr__(self, *args, **kwargs): + return Stub() + + def __call__(self, *args, **kwargs): + return Stub() + import sys + sys.modules["cupy"] = Stub() + sys.modules["numpy"] = Stub() + sys.modules["pylibcugraph"] = Stub() + from _nx_cugraph.core import main filepath = Path(__file__) diff --git a/python/nx-cugraph/scripts/update_readme.py b/python/nx-cugraph/scripts/update_readme.py index 878c620a394..8acaf85eb61 100644 --- a/python/nx-cugraph/scripts/update_readme.py +++ b/python/nx-cugraph/scripts/update_readme.py @@ -19,8 +19,6 @@ import urllib.request from warnings import warn -from nx_cugraph.scripts.print_tree import create_tree, tree_lines - _objs_file_url = "https://networkx.org/documentation/stable/objects.inv" # See: https://sphobjinv.readthedocs.io/en/stable/syntax.html @@ -78,6 +76,8 @@ def replace_body(text, match, new_body): def main(readme_file, objects_filename): """``readme_file`` must be readable and writable, so use mode ``"a+"``""" + from nx_cugraph.scripts.print_tree import create_tree, tree_lines + # Use the `objects.inv` file to determine URLs. For details about this file, see: # https://sphobjinv.readthedocs.io/en/stable/syntax.html # We might be better off using a library like that, but roll our own for now. @@ -208,6 +208,20 @@ def find_or_download_objs_file(objs_file_dir): if __name__ == "__main__": + # This script imports a nx_cugraph script module, which imports nx_cugraph + # runtime dependencies. The script module does not need the runtime deps, + # so stub them out to avoid installing them. + class Stub: + def __getattr__(self, *args, **kwargs): + return Stub() + + def __call__(self, *args, **kwargs): + return Stub() + import sys + sys.modules["cupy"] = Stub() + sys.modules["numpy"] = Stub() + sys.modules["pylibcugraph"] = Stub() + parser = argparse.ArgumentParser( "Update README.md to show NetworkX functions implemented by nx-cugraph" ) @@ -225,4 +239,4 @@ def find_or_download_objs_file(objs_file_dir): objects_filename = find_or_download_objs_file(readme_path.parent) with readme_path.open("a+") as readme_file: - main(readme_filename, objects_filename) + main(readme_file, objects_filename) From ec2f888212f1290e4813255136ebe0fcb1b712d8 Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Mon, 11 Mar 2024 22:54:20 -0500 Subject: [PATCH 6/8] Adds additional pre-commit hook to update the nx-cugraph meta-data, adds function to produce a string repr with a quoting preference compatible with black, re-generates the _nx_cugraph/__init__.py modified with the wrong quoting preference from the prior commit. --- .pre-commit-config.yaml | 16 +++--- python/nx-cugraph/_nx_cugraph/__init__.py | 64 ++++++++++++----------- python/nx-cugraph/_nx_cugraph/core.py | 19 +++++-- 3 files changed, 55 insertions(+), 44 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ad5d464818..fa4d0b39a5e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,21 +61,21 @@ repos: args: ["--clean"] - repo: local hooks: - - id: nx-cugraph-readme-check - name: nx-cugraph README updater - entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md" + - id: nx-cugraph-meta-data-update + name: nx-cugraph meta-data updater + entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/_nx_cugraph/__init__.py" files: ^python/nx-cugraph/ - types_or: [python, markdown] + types: [python] language: python pass_filenames: false additional_dependencies: ["networkx>=3.2"] - repo: local hooks: - - id: nx-cugraph-meta-data-update - name: nx-cugraph meta-data updater - entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/_nx_cugraph/__init__.py" + - id: nx-cugraph-readme-update + name: nx-cugraph README updater + entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md" files: ^python/nx-cugraph/ - types: [python] + types_or: [python, markdown] language: python pass_filenames: false additional_dependencies: ["networkx>=3.2"] diff --git a/python/nx-cugraph/_nx_cugraph/__init__.py b/python/nx-cugraph/_nx_cugraph/__init__.py index 0d30b244a99..aa6effbe8e8 100644 --- a/python/nx-cugraph/_nx_cugraph/__init__.py +++ b/python/nx-cugraph/_nx_cugraph/__init__.py @@ -128,46 +128,46 @@ }, "additional_docs": { # BEGIN: additional_docs - 'average_clustering': 'Directed graphs and `weight` parameter are not yet supported.', - 'betweenness_centrality': '`weight` parameter is not yet supported, and RNG with seed may be different.', - 'bfs_edges': '`sort_neighbors` parameter is not yet supported.', - 'bfs_predecessors': '`sort_neighbors` parameter is not yet supported.', - 'bfs_successors': '`sort_neighbors` parameter is not yet supported.', - 'bfs_tree': '`sort_neighbors` parameter is not yet supported.', - 'clustering': 'Directed graphs and `weight` parameter are not yet supported.', - 'core_number': 'Directed graphs are not yet supported.', - 'edge_betweenness_centrality': '`weight` parameter is not yet supported, and RNG with seed may be different.', - 'eigenvector_centrality': '`nstart` parameter is not used, but it is checked for validity.', - 'from_pandas_edgelist': 'cudf.DataFrame inputs also supported; value columns with str is unsuppported.', - 'generic_bfs_edges': '`neighbors` and `sort_neighbors` parameters are not yet supported.', - 'k_truss': ( - 'Currently raises `NotImplementedError` for graphs with more than one connected\n' - 'component when k >= 3. We expect to fix this soon.' + "average_clustering": "Directed graphs and `weight` parameter are not yet supported.", + "betweenness_centrality": "`weight` parameter is not yet supported, and RNG with seed may be different.", + "bfs_edges": "`sort_neighbors` parameter is not yet supported.", + "bfs_predecessors": "`sort_neighbors` parameter is not yet supported.", + "bfs_successors": "`sort_neighbors` parameter is not yet supported.", + "bfs_tree": "`sort_neighbors` parameter is not yet supported.", + "clustering": "Directed graphs and `weight` parameter are not yet supported.", + "core_number": "Directed graphs are not yet supported.", + "edge_betweenness_centrality": "`weight` parameter is not yet supported, and RNG with seed may be different.", + "eigenvector_centrality": "`nstart` parameter is not used, but it is checked for validity.", + "from_pandas_edgelist": "cudf.DataFrame inputs also supported; value columns with str is unsuppported.", + "generic_bfs_edges": "`neighbors` and `sort_neighbors` parameters are not yet supported.", + "k_truss": ( + "Currently raises `NotImplementedError` for graphs with more than one connected\n" + "component when k >= 3. We expect to fix this soon." ), - 'katz_centrality': "`nstart` isn't used (but is checked), and `normalized=False` is not supported.", - 'louvain_communities': '`seed` parameter is currently ignored, and self-loops are not yet supported.', - 'pagerank': '`dangling` parameter is not supported, but it is checked for validity.', - 'transitivity': 'Directed graphs are not yet supported.', + "katz_centrality": "`nstart` isn't used (but is checked), and `normalized=False` is not supported.", + "louvain_communities": "`seed` parameter is currently ignored, and self-loops are not yet supported.", + "pagerank": "`dangling` parameter is not supported, but it is checked for validity.", + "transitivity": "Directed graphs are not yet supported.", # END: additional_docs }, "additional_parameters": { # BEGIN: additional_parameters - 'eigenvector_centrality': { - 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', + "eigenvector_centrality": { + "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", }, - 'hits': { - 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', - 'weight : string or None, optional (default="weight")': 'The edge attribute to use as the edge weight.', + "hits": { + "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", + 'weight : string or None, optional (default="weight")': "The edge attribute to use as the edge weight.", }, - 'katz_centrality': { - 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', + "katz_centrality": { + "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", }, - 'louvain_communities': { - 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', - 'max_level : int, optional': 'Upper limit of the number of macro-iterations (max: 500).', + "louvain_communities": { + "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", + "max_level : int, optional": "Upper limit of the number of macro-iterations (max: 500).", }, - 'pagerank': { - 'dtype : dtype or None, optional': 'The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.', + "pagerank": { + "dtype : dtype or None, optional": "The data type (np.float32, np.float64, or None) to use for the edge weights in the algorithm. If None, then dtype is determined by the edge values.", }, # END: additional_parameters }, @@ -217,7 +217,9 @@ def __getattr__(self, *args, **kwargs): def __call__(self, *args, **kwargs): return Stub() + import sys + sys.modules["cupy"] = Stub() sys.modules["numpy"] = Stub() sys.modules["pylibcugraph"] = Stub() diff --git a/python/nx-cugraph/_nx_cugraph/core.py b/python/nx-cugraph/_nx_cugraph/core.py index c4de197f3b1..7261079999a 100644 --- a/python/nx-cugraph/_nx_cugraph/core.py +++ b/python/nx-cugraph/_nx_cugraph/core.py @@ -45,18 +45,27 @@ def update_text(text, lines_to_add, target, indent=" " * 8): return f"{text[:start]}{begin}{to_add}\n{indent}{text[stop:]}" +def dq_repr(s): + """Return repr(s) quoted with the double quote preference used by black.""" + rs = repr(s) + if rs.startswith("'") and '"' not in rs: + rs = rs.strip("'").replace('"', '\\"') + return f'"{rs}"' + return rs + + def dict_to_lines(d, *, indent=""): for key in sorted(d): val = d[key] if "\n" not in val: - yield f"{indent}{key!r}: {val!r}," + yield f"{indent}{dq_repr(key)}: {dq_repr(val)}," else: - yield f"{indent}{key!r}: (" + yield f"{indent}{dq_repr(key)}: (" *lines, last_line = val.split("\n") for line in lines: line += "\n" - yield f" {indent}{line!r}" - yield f" {indent}{last_line!r}" + yield f" {indent}{dq_repr(line)}" + yield f" {indent}{dq_repr(last_line)}" yield f"{indent})," @@ -83,7 +92,7 @@ def main(filepath): to_add = [] for name in sorted(additional_parameters): params = additional_parameters[name] - to_add.append(f"{name!r}: {{") + to_add.append(f"{dq_repr(name)}: {{") to_add.extend(dict_to_lines(params, indent=" " * 4)) to_add.append("},") text = update_text(text, to_add, "additional_parameters") From b332ccfa0b65cc155acbf5511d7fac4036b42a84 Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Mon, 11 Mar 2024 23:23:31 -0500 Subject: [PATCH 7/8] Improves help string for objects.inv option, minor code changes suggested by ruff. --- python/nx-cugraph/scripts/update_readme.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/python/nx-cugraph/scripts/update_readme.py b/python/nx-cugraph/scripts/update_readme.py index 8acaf85eb61..fcaa1769d8b 100644 --- a/python/nx-cugraph/scripts/update_readme.py +++ b/python/nx-cugraph/scripts/update_readme.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright (c) 2024, NVIDIA CORPORATION. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,10 +12,10 @@ # limitations under the License. import argparse import re +import urllib.request import zlib from collections import namedtuple from pathlib import Path -import urllib.request from warnings import warn _objs_file_url = "https://networkx.org/documentation/stable/objects.inv" @@ -201,9 +200,11 @@ def find_or_download_objs_file(objs_file_dir): objs_file_path = objs_file_dir / "objects.inv" if not objs_file_path.exists(): request = urllib.request.Request(_objs_file_url) - with urllib.request.urlopen(request) as response: - with open(objs_file_path, "wb") as out: - out.write(response.read()) + with ( + urllib.request.urlopen(request) as response, + Path(objs_file_path).open("wb") as out, + ): + out.write(response.read()) return objs_file_path @@ -217,7 +218,9 @@ def __getattr__(self, *args, **kwargs): def __call__(self, *args, **kwargs): return Stub() + import sys + sys.modules["cupy"] = Stub() sys.modules["numpy"] = Stub() sys.modules["pylibcugraph"] = Stub() @@ -227,8 +230,13 @@ def __call__(self, *args, **kwargs): ) parser.add_argument("readme_filename", help="Path to the README.md file") parser.add_argument( - "networkx_objects", nargs="?", default=None, - help="Path to the objects.inv file from networkx docs. Optional." + "networkx_objects", + nargs="?", + default=None, + help="Optional path to the objects.inv file from the NetworkX docs. Default is " + "the objects.inv file in the directory containing the specified README.md. If " + "an objects.inv file does not exist in that location, one will be downloaded " + "and saved to that location.", ) args = parser.parse_args() From f8443202b10f11196197f253fe39385939e70745 Mon Sep 17 00:00:00 2001 From: Rick Ratzel Date: Wed, 13 Mar 2024 10:20:01 -0500 Subject: [PATCH 8/8] Removes unnecessary .replace() leftover from prior version. --- python/nx-cugraph/_nx_cugraph/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/nx-cugraph/_nx_cugraph/core.py b/python/nx-cugraph/_nx_cugraph/core.py index 7261079999a..82ce7bc438a 100644 --- a/python/nx-cugraph/_nx_cugraph/core.py +++ b/python/nx-cugraph/_nx_cugraph/core.py @@ -49,7 +49,7 @@ def dq_repr(s): """Return repr(s) quoted with the double quote preference used by black.""" rs = repr(s) if rs.startswith("'") and '"' not in rs: - rs = rs.strip("'").replace('"', '\\"') + rs = rs.strip("'") return f'"{rs}"' return rs