1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
|
.. _contributor_guide:
Contributor Guide
=================
.. note::
This document assumes some familiarity with contributing to open source
scientific Python projects using GitHub pull requests. If this does not
describe you, you may first want to see the :ref:`contributing_faq`.
If you are using a LLM or any other AI model, you will still need to
follow the process described here.
.. _dev_workflow:
Development Workflow
--------------------
1. If you are a first-time contributor:
* Go to `https://github.com/networkx/networkx
<https://github.com/networkx/networkx>`_ and click the
"fork" button to create your own copy of the project.
* Clone the project to your local computer::
git clone git@github.com:your-username/networkx.git
* Navigate to the folder networkx and add the upstream repository::
git remote add upstream git@github.com:networkx/networkx.git
* Now, you have remote repositories named:
- ``upstream``, which refers to the ``networkx`` repository
- ``origin``, which refers to your personal fork
* Next, you need to set up your build environment.
Here are instructions for two popular environment managers:
* ``venv`` (pip based)
::
# Create a virtualenv named ``networkx-dev`` that lives in the directory of
# the same name
python -m venv networkx-dev
# Activate it
source networkx-dev/bin/activate
# Install main development and runtime dependencies of networkx
pip install -r requirements/default.txt -r requirements/test.txt -r requirements/developer.txt
#
# (Optional) Install pygraphviz and pydot packages
# These packages require that you have your system properly configured
# and what that involves differs on various systems.
# pip install -r requirements/extra.txt
#
# Build and install networkx from source
pip install -e .
# Test your installation
pytest --pyargs networkx
* ``conda`` (Anaconda or Miniconda)
::
# Create a conda environment named ``networkx-dev``
conda create --name networkx-dev
# Activate it
conda activate networkx-dev
# Install main development and runtime dependencies of networkx
conda install -c conda-forge --file requirements/default.txt --file requirements/test.txt --file requirements/developer.txt
#
# (Optional) Install pygraphviz and pydot packages
# These packages require that you have your system properly configured
# and what that involves differs on various systems.
# conda install -c conda-forge --file requirements/extra.txt
#
# Install networkx from source
pip install -e .
# Test your installation
pytest --pyargs networkx
* Finally, we recommend you install pre-commit which checks
that your code matches formatting guidelines::
pre-commit install
2. Develop your contribution:
* Pull the latest changes from upstream::
git checkout main
git pull upstream main
* Create a branch for the feature you want to work on. Since the
branch name will appear in the merge message, use a sensible name
such as 'bugfix-for-issue-1480'::
git checkout -b bugfix-for-issue-1480 main
* Commit locally as you progress (``git add`` and ``git commit``)
3. Test your contribution:
* Run the test suite locally (see `Testing`_ for details)::
PYTHONPATH=. pytest networkx
* Running the tests locally *before* submitting a pull request helps catch
problems early and reduces the load on the continuous integration
system.
4. Ensure your contribution is properly formatted.
* If you installed ``pre-commit`` as recommended in step 1, all necessary
linting should run automatically at commit time. If there are any
formatting issues, the commit will not be successful and linting
suggestions will be applied to the patch automatically.
Simply ``git add`` and ``git commit`` a second time to accept the proposed
formatting changes.
* If the above fails for whatever reason, you can also run the linter over
the entire codebase with::
pre-commit run --all-files
5. Submit your contribution:
* Push your changes back to your fork on GitHub::
git push origin bugfix-for-issue-1480
* Go to GitHub. The new branch will show up with a green Pull Request
button---click it.
* If you want, post on the `mailing list
<http://groups.google.com/group/networkx-discuss>`_ to explain your changes or
to ask for review.
6. Review process:
* Every Pull Request (PR) update triggers a set of `continuous integration
<https://en.wikipedia.org/wiki/Continuous_integration>`_ services
that check that the code is up to standards and passes all our tests.
These checks must pass before your PR can be merged. If one of the
checks fails, you can find out why by clicking on the "failed" icon (red
cross) and inspecting the build and test log.
* Reviewers (the other developers and interested community members) will
write inline and/or general comments on your PR to help
you improve its implementation, documentation, and style. Every single
developer working on the project has their code reviewed, and we've come
to see it as friendly conversation from which we all learn and the
overall code quality benefits. Therefore, please don't let the review
discourage you from contributing: its only aim is to improve the quality
of project, not to criticize (we are, after all, very grateful for the
time you're donating!).
* To update your PR, make your changes on your local repository
and commit. As soon as those changes are pushed up (to the same branch as
before) the PR will update automatically.
.. note::
If the PR closes an issue, make sure that GitHub knows to automatically
close the issue when the PR is merged. For example, if the PR closes
issue number 1480, you could use the phrase "Fixes #1480" in the PR
description or commit message.
7. Document deprecations and API changes
If your change introduces any API modifications including deprecations,
please make sure the PR has the ``type: API`` label.
To set up a function for deprecation:
- Use a deprecation warning to warn users. For example::
msg = "curly_hair is deprecated and will be removed in v3.0. Use sum() instead."
warnings.warn(msg, DeprecationWarning)
- Add a warnings filter to ``networkx/conftest.py``::
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message=<start of message>
)
- Add a reminder to ``doc/developer/deprecations.rst`` for the team
to remove the deprecated functionality in the future. For example:
.. code-block:: rst
* In ``utils/misc.py`` remove ``generate_unique_node`` and related tests.
.. note::
To reviewers: make sure the merge message has a brief description of the
change(s) and if the PR closes an issue add, for example, "Closes #123"
where 123 is the issue number.
Divergence from ``upstream main``
---------------------------------
If GitHub indicates that the branch of your Pull Request can no longer
be merged automatically, merge the main branch into yours::
git fetch upstream main
git merge upstream/main
If any conflicts occur, they need to be fixed before continuing. See
which files are in conflict using::
git status
Which displays a message like::
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: file_with_conflict.txt
Inside the conflicted file, you'll find sections like these::
<<<<<<< HEAD
The way the text looks in your branch
=======
The way the text looks in the main branch
>>>>>>> main
Choose one version of the text that should be kept, and delete the
rest::
The way the text looks in your branch
Now, add the fixed file::
git add file_with_conflict.txt
Once you've fixed all merge conflicts, do::
git commit
.. note::
Advanced Git users may want to rebase instead of merge,
but we squash and merge PRs either way.
Guidelines
----------
* All code should have tests.
* All code should be documented, to the same
`standard <https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard>`_
as NumPy and SciPy.
* All changes are reviewed. Ask on the
`mailing list <http://groups.google.com/group/networkx-discuss>`_ if
you get no response to your pull request.
* Default dependencies are listed in ``requirements/default.txt`` and extra
(i.e., optional) dependencies are listed in ``requirements/extra.txt``.
We don't often add new default and extra dependencies. If you are considering
adding code that has a dependency, you should first consider adding a gallery
example. Typically, new proposed dependencies would first be added as extra
dependencies. Extra dependencies should be easy to install on all platforms
and widely-used. New default dependencies should be easy to install on all
platforms, widely-used in the community, and have demonstrated potential for
wide-spread use in NetworkX.
* Use the following import conventions::
import numpy as np
import scipy as sp
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import networkx as nx
After importing ``sp`` for ``scipy``::
import scipy as sp
access the relevant scipy subpackages from the top-level ``sp`` namespace, e.g.::
sp.sparse.linalg
Instead of ``from scipy.sparse import linalg`` or
``import scipy.sparse.linalg as spla``.
For example, many libraries have a ``linalg`` subpackage: ``nx.linalg``,
``np.linalg``, ``sp.linalg``, ``sp.sparse.linalg``. The above import
pattern makes the origin of any particular instance of ``linalg`` explicit.
* Use the decorator ``not_implemented_for`` in ``networkx/utils/decorators.py``
to designate that a function doesn't accept 'directed', 'undirected',
'multigraph' or 'graph'. The first argument of the decorated function should
be the graph object to be checked.
.. code-block:: python
@nx.not_implemented_for("directed", "multigraph")
def function_not_for_MultiDiGraph(G, others):
# function not for graphs that are directed *and* multigraph
pass
@nx.not_implemented_for("directed")
@nx.not_implemented_for("multigraph")
def function_only_for_Graph(G, others):
# function not for directed graphs *or* for multigraphs
pass
Testing
-------
``networkx`` has an extensive test suite that ensures correct
execution on your system. The test suite has to pass before a pull
request can be merged, and tests should be added to cover any
modifications to the code base.
We make use of the `pytest <https://docs.pytest.org/en/latest/>`__
testing framework, with tests located in the various
``networkx/submodule/tests`` folders.
To run all tests::
$ PYTHONPATH=. pytest networkx
Or the tests for a specific submodule::
$ PYTHONPATH=. pytest networkx/readwrite
Or tests from a specific file::
$ PYTHONPATH=. pytest networkx/readwrite/tests/test_edgelist.py
Or a single test within that file::
$ PYTHONPATH=. pytest networkx/readwrite/tests/test_edgelist.py::test_parse_edgelist_with_data_list
Use ``--doctest-modules`` to run doctests.
For example, run all tests and all doctests using::
$ PYTHONPATH=. pytest --doctest-modules networkx
Tests for a module should ideally cover all code in that module,
i.e., statement coverage should be at 100%.
To measure the test coverage, run::
$ PYTHONPATH=. pytest --cov=networkx networkx
This will print a report with one line for each file in `networkx`,
detailing the test coverage::
Name Stmts Miss Branch BrPart Cover
----------------------------------------------------------------------------------
networkx/__init__.py 33 2 2 1 91%
networkx/algorithms/__init__.py 114 0 0 0 100%
networkx/algorithms/approximation/__init__.py 12 0 0 0 100%
networkx/algorithms/approximation/clique.py 42 1 18 1 97%
...
Adding tests
~~~~~~~~~~~~
If you're **new to testing**, see existing test files for examples of things to do.
**Don't let the tests keep you from submitting your contribution!**
If you're not sure how to do this or are having trouble, submit your pull request
anyway.
We will help you create the tests and sort out any kind of problem during code review.
Image comparison
~~~~~~~~~~~~~~~~
To run image comparisons::
$ PYTHONPATH=. pytest --mpl --pyargs networkx.drawing
The ``--mpl`` tells ``pytest`` to use ``pytest-mpl`` to compare the generated plots
with baseline ones stored in ``networkx/drawing/tests/baseline``.
To add a new test, add a test function to ``networkx/drawing/tests`` that
returns a Matplotlib figure (or any figure object that has a savefig method)
and decorate it as follows::
@pytest.mark.mpl_image_compare
def test_barbell():
fig = plt.figure()
barbell = nx.barbell_graph(4, 6)
# make sure to fix any randomness
pos = nx.spring_layout(barbell, seed=42)
nx.draw(barbell, pos=pos)
return fig
Then create a baseline image to compare against later::
$ pytest -k test_barbell --mpl-generate-path=networkx/drawing/tests/baseline
.. note:: In order to keep the size of the repository from becoming too large, we
prefer to limit the size and number of baseline images we include.
And test::
$ pytest -k test_barbell --mpl
Documentation
-------------
.. include:: ../README.rst
Adding examples
~~~~~~~~~~~~~~~
The gallery examples are managed by
`sphinx-gallery <https://sphinx-gallery.readthedocs.io/>`_.
The source files for the example gallery are ``.py`` scripts in ``examples/`` that
generate one or more figures. They are executed automatically by sphinx-gallery when the
documentation is built. The output is gathered and assembled into the gallery.
Building the example gallery locally requires that the additional dependencies
in ``requirements/example.txt`` be installed in your development environment.
You can **add a new** plot by placing a new ``.py`` file in one of the directories inside the
``examples`` directory of the repository. See the other examples to get an idea for the
format.
.. note:: Gallery examples should start with ``plot_``, e.g. ``plot_new_example.py``
General guidelines for making a good gallery plot:
* Examples should highlight a single feature/command.
* Try to make the example as simple as possible.
* Data needed by examples should be included in the same directory and the example script.
* Add comments to explain things that aren't obvious from reading the code.
* Describe the feature that you're showcasing and link to other relevant parts of the
documentation.
Adding References
~~~~~~~~~~~~~~~~~
If you are contributing a new algorithm (or an improvement to a current algorithm),
a reference paper or resource should also be provided in the function docstring.
For references to published papers, we try to follow the
`Chicago Citation Style <https://en.wikipedia.org/wiki/The_Chicago_Manual_of_Style>`__.
The quickest way of generating citation in this style is
by searching for the paper on `Google Scholar <https://scholar.google.com/>`_ and clicking on
the ``cite`` button. It will pop up the citation of the paper in multiple formats, and copy the
``Chicago`` style.
We prefer adding DOI links for URLs. If the DOI link resolves to a paywalled version of
the article, we prefer adding a link to the arXiv version (if available) or any other
publicly accessible copy of the paper.
An example of a reference::
.. [1] Cheong, Se-Hang, and Yain-Whar Si. "Force-directed algorithms for schematic drawings and
placement: A survey." Information Visualization 19, no. 1 (2020): 65-91.
https://doi.org/10.1177%2F1473871618821740
If the resource is uploaded as a PDF/DOCX/PPT on the web (lecture notes, presentations) it is better
to use the `wayback machine <https://web.archive.org/>`_ to create a snapshot of the resource
and link the internet archive link. The URL of the resource can change, and it creates unreachable
links from the documentation.
Using Math Formulae and Latex Formatting in Documentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When working with docstrings that contain math symbols or formulae
use raw strings (``r"""``) to ensure proper rendering.
While LaTeX formatting can improve the appearance of the rendered documentation,
it's best to keep it simple and readable.
An example of a math formula::
.. math::
Ax = \lambda x
.. math::
Ax = \lambda x
Some inline math::
These are Cheeger's Inequalities for \d-Regular graphs:
$\frac{d- \lambda_2}{2} \leq h(G) \leq \sqrt{2d(d- \lambda_2)}$
These are Cheeger's Inequalities for \d-Regular graphs:
$\frac{d- \lambda_2}{2} \leq h(G) \leq \sqrt{2d(d- \lambda_2)}$
Bugs
----
Please `report bugs on GitHub <https://github.com/networkx/networkx/issues>`_.
Policies
--------
All interactions with the project are subject to the
:doc:`NetworkX code of conduct <code_of_conduct>`.
We also follow these policies:
* :doc:`NetworkX deprecation policy <deprecations>`
* :external+neps:doc:`Python version support <nep-0029-deprecation_policy>`
|