Skip to content

Latest commit

 

History

History
299 lines (215 loc) · 12.3 KB

File metadata and controls

299 lines (215 loc) · 12.3 KB

How to contribute?

Contributions of any size are greatly appreciated! You can make a significant impact on UltraPlot by just using it and reporting issues.

The following sections cover some general guidelines regarding UltraPlot development for new contributors. Feel free to suggest improvements or changes to this workflow.

Feature requests

We are eager to hear your requests for new features and suggestions regarding the current API. You can submit these as issues on Github. Please make sure to explain in detail how the feature should work and keep the scope as narrow as possible. This will make it easier to implement in small pull requests.

If you are feeling inspired, feel free to add the feature yourself and submit a pull request!

Report bugs

Bugs should be reported using the Github issues page. When reporting a bug, please follow the template message and include copy-pasteable code that reproduces the issue. This is critical for contributors to fix the bug quickly.

If you can figure out how to fix the bug yourself, feel free to submit a pull request.

Write tests

Most modern python packages have test_*.py scripts that are run by pytest via continuous integration whenever commits are pushed to the repository. Currently, UltraPlot's automated checks focus on the examples that appear on the website User Guide, and Casper van Elteren <https://github.com/cvanelteren> runs additional tests manually. This approach leaves out many use cases and leaves the project more vulnerable to bugs. Improving ultraplot's continuous integration using pytest and pytest-mpl is a critical item on our to-do list.

If you can think of a useful test for ultraplot, feel free to submit a pull request. Your test will be used in the future.

Write documentation

Documentation can always be improved. For minor changes, you can edit docstrings and documentation files directly in the GitHub web interface without using a local copy.

To build the documentation locally, use the following commands:

cd docs
# Install dependencies to the base conda environment..
conda env update -f environment.yml
pip install -e ".[docs]"
# ...or create a new conda environment
# conda env create -n ultraplot-dev --file docs/environment.yml
# source activate ultraplot-dev
# Minimal install (no optional dependencies)
# pip install ultraplot --no-deps
# pip install -r ../requirements-minimal.txt
# Create HTML documentation
make html

The built documentation should be available in docs/_build/html.

Lazy Loading and Adding New Modules

UltraPlot uses a lazy loading mechanism to improve import times. This means that submodules are not imported until they are actually used. This is controlled by the __getattr__ function in ultraplot/__init__.py and the LazyLoader helper in ultraplot/_lazy.py.

When adding a new submodule, make sure it is compatible with the lazy loader:

  1. Add the module file or package: Place your new module in ultraplot/ as my_module.py, or as a package directory with an __init__.py.
  2. Expose public names via `__all__` (optional): The lazy loader inspects __all__ in modules and packages to know which attributes to expose at the top level. If you want uplt.MyClass or uplt.my_function to resolve directly, include them in __all__ in your module. If __all__ is not present, the lazy loader will still expose the module itself as uplt.my_module.
  3. Add explicit exceptions when needed: If a top-level name should map to a different module or attribute (or needs special handling), add it to _LAZY_LOADING_EXCEPTIONS in ultraplot/__init__.py. This mapping controls explicit name-to-module lookups that should override the default discovery behavior.

By following these steps, your module will integrate cleanly with the lazy loading system without requiring manual registry updates.

Preparing pull requests

New features and bug fixes should be addressed using pull requests. Here is a quick guide for submitting pull requests:

  1. Fork the ultraplot GitHub repository. It's fine to keep "ultraplot" as the fork repository name because it will live under your account.

  2. Clone your fork locally using git, connect your repository to the upstream (main project), and create a branch as follows:

    git clone git@github.com:YOUR_GITHUB_USERNAME/ultraplot.git
    cd ultraplot
    git remote add upstream git@github.com:ultraplot/ultraplot.git
    git checkout -b your-branch-name main

    If you need some help with git, follow the quick start guide.

  3. Make an editable install of ultraplot by running:

    pip install -e .

    This way import ultraplot imports your local copy, rather than the stable version you last downloaded from PyPI. You can import ultraplot; print(ultraplot.__file__) to verify your local copy has been imported.

  4. Install pre-commit and its hook on the ultraplot repo as follows:

    pip install --user pre-commit
    pre-commit install

    Afterwards pre-commit will run whenever you commit. pre-commit is a framework for managing and maintaining multi-language pre-commit hooks to ensure code-style and code formatting is consistent.

  5. You can now edit your local working copy as necessary. Please follow the PEP8 style guide. and try to generally adhere to the black subset of the PEP8 style (we may automatically enforce the "black" style in the future). When committing, pre-commit will modify the files as needed, or will generally be clear about what you need to do to pass the pre-commit test.

    Please break your edits up into reasonably sized commits:

    git commit -a -m "<commit message>"
    git push -u

    The commit messages should be short, sweet, and use the imperative mood, e.g. "Fix bug" instead of "Fixed bug".

  6. If you intend to make changes or add examples to the user guide, you may want to open the docs/*.py files as jupyter notebooks. This can be done by installing jupytext, starting a jupyter session, and opening the .py files from the Files page.

  7. When you're finished, create a new changelog entry in CHANGELOG.rst. The entry should be entered as:

    * <description> (:pr:`<PR number>`) by `<author name>`_.
    

    where <description> is the description of the PR related to the change, <PR number> is the pull request number, and <author name> is your first and last name. Make sure to add yourself to the list of authors at the end of CHANGELOG.rst and the list of contributors in docs/authors.rst. Also make sure to add the changelog entry under one of the valid .. rubric:: <heading> headings listed at the top of CHANGELOG.rst.

  8. Finally, submit a pull request through the GitHub website using this data:

    head-fork: YOUR_GITHUB_USERNAME/ultraplot
    compare: your-branch-name
    
    base-fork: ultraplot/ultraplot
    base: main
    

Note that you can create the pull request before you're finished with your feature addition or bug fix. The PR will update as you add more commits. UltraPlot developers and contributors can then review your code and offer suggestions.

Release procedure

Ultraplot follows EffVer (Effectual Versioning). Changes to the version number X.Y.Z will reflect the effect on users: the major version X will be incremented for changes that require user attention (like breaking changes), the minor version Y will be incremented for safe feature additions, and the patch number Z will be incremented for changes users can safely ignore.

While version 1.0 has been released, we are still in the process of ensuring proplot is fully replaced by ultraplot as we continue development under the ultraplot name. During this transition, the versioning scheme reflects both our commitment to stable APIs and the ongoing work to complete this transition. The minor version number is incremented when changes require user attention (like deprecations or style changes), and the patch number is incremented for additions and fixes that users can safely adopt.

For now, Casper van Elteren is the only one who can publish releases on PyPI, but this will change in the future. Releases should be carried out as follows:

  1. Create a new branch release-vX.Y.Z with the version for the release.

  2. Make sure to update CHANGELOG.rst and that all new changes are reflected in the documentation. Before tagging, sync CITATION.cff to the release version and date:

    git add CHANGELOG.rst CITATION.cff
    git commit -m 'Prepare release metadata'
  3. Open a new pull request for this branch targeting main.

  4. After all tests pass and the pull request has been approved, merge into main.

  5. Get the latest version of the main branch:

    git switch main
    git pull
  6. Tag the current commit and push to github:

    git tag -a vX.Y.Z -m "Version X.Y.Z"
    git push origin main --tags

    Pushing a vX.Y.Z tag triggers the release workflow, which publishes the package, creates the corresponding GitHub release, and uploads the same dist/ artifacts to Zenodo through the Zenodo deposit API.

  7. After the workflow completes, confirm that the repository "Cite this repository" panel reflects CITATION.cff, that the release is available on TestPyPI and PyPI, and that Zenodo created a new release record.

    The Zenodo release job uses CITATION.cff as the maintained metadata source and requires a GitHub Actions secret named ZENODO_ACCESS_TOKEN with the Zenodo scopes deposit:write and deposit:actions. To avoid duplicate Zenodo records, disable the repository's Zenodo GitHub auto-archiving integration once the API-based workflow is enabled.