Skip to content

Latest commit

 

History

History
477 lines (324 loc) · 17.5 KB

CONTRIBUTING.rst

File metadata and controls

477 lines (324 loc) · 17.5 KB

Contributing to pyiron

The following is a set of guidelines for contributing to pyiron, which is hosted and maintained by the Max Planck Institut für Eisenforschung on GitHub. These are mostly guidelines to facilitate an efficient development workflow, and not necessarily rules. Use your best judgment, and feel free to propose changes even to this document in a pull request.

You can find all the pyiron packages at our github page . To create pull requests, you will need to become part of the pyiron organization. Please email us if you would like to join.

Wait I don't want to read this; I just have a quick question/bugfix!

  1. Check out our FAQ page; your question might already be answered there.
  2. If your question relates to a bug in pyiron, please briefly search the issues page and open a new labeled issue if you don't see anything related to your question there.
  3. Please feel free just to send one of us a brief, descriptive email with your question, and we'll do our best to get back to you as ASAP as possible.

Table of Contents

License

What should I know before I get started?
How can I contribute?
Styleguides
Additional Notes
Debugging

License

pyiron is released as an open-source project under the BSD 3-Clause License. Code contributions should also be considered open-source.

What should I know before I get started?

pyiron developer meetings

If you are interested in discussing pyiron's development, we encourage you to virtually participate in the weekly pyiron developer meeting at 14:00 german time (GMT+2). Check the discussion page for details.

How can I contribute?

Reporting bugs

Note: If you find a closed issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.

Before Submitting A Bug Report

Check if you can reproduce the problem in the latest version of pyiron. Check the FAQ page for a list of common questions and problems. Briefly search the issues page for bugs to see if the problem has already been reported. If it has and the issue is still open, add a comment to the existing issue instead of opening a new one.

How Do I Submit A (Good) Bug Report?

Bugs are tracked as GitHub issues. You can create an issue on the pyiron repository by including the following information:

  • Use a clear and descriptive title for the issue to identify the problem.
  • Describe the exact steps you took so we can reproduce the problem as closely as possible.
  • Provide sample code that causes the problem. Include code snippets as markdown code blocks.
  • Include information about the environment (OS, python version, how packages were installed) in which you were running pyiron.
  • Explain what you expected to happen, and what happened instead.

Suggesting Enhancements

How Do I Submit A (Good) Enhancement Suggestion?

Enhancement suggestions are tracked as GitHub issues. You can create an issue on the pyiron repository by including the following information:

  • Use a clear and descriptive title for the issue to identify the suggestion.
  • Describe the exact behavior you would expect the suggested feature to produce.
  • Provide sample code that you would use to access the feature. If possible, include code for how you think the feature could be built into pyiron's codebase. Include code snippets as markdown code blocks.

Your first code contribution

Unsure where to begin contributing to pyiron? You can start by looking through these good-first-issue and help-wanted issues:

  • Good first issues - issues which should only require a few lines of code, and a test or two.
  • Help wanted issues - issues which should be a bit more involved than beginner issues.

Local development

pyiron can be developed and tested locally. If you are using pyiron to run an external software package, e.g. VASP or LAMMPS, you might also need to install those packages locally to run certain integration tests in pyiron.

To get the developmental (git) version of pyiron,

git clone https://github.com/pyiron/pyiron.git
conda env update --name pyiron_dev --file pyiron/.ci_support/environment.yml
conda activate pyiron_dev
conda install conda-build
conda develop pyiron

Deploy development version to a managed environment

If you want to use a development version of pyiron in a managed environment where a version of pyiron is already installed outside of your control (e.g. on the cmti/cmfe cluster), you can still preload a local checkout of the repo, while using the dependencies already installed. Assuming pyiron and dependencies are already installed and setup, clone the repository to a location of your choice

mkdir -p ~/software
cd ~/software
git clone https://github.com/pyiron/pyiron.git

add this folder to your python path by adding this line to your ~/.profile

export PYTHONPATH="$HOME/software/pyiron:$PYTHONPATH"

and finally restart any jupyter or jupyterhub session you might still have running. Within this folder you can then check out any local branchen, push your own dev branches, etc and python will automatically use this version over the system-wide installation. Check that it works by running the following cell

import pyiron
print(pyiron.__file__)

If it doesn't print the path of your checkout, check that you restarted all the relevant shell sessions and that the environment variables are correctly updated.

Local Testing

The full test suite is always run automatically when you open a new pull request. Still it sometimes nice to run all or only specific tests on your machine. To do that run from the repo root, e.g.

python -m unittest discover tests
python -m unittest discover tests/sphinx
python -m unittest tests/sphinx/test_base.py

Where the first line runs all tests, the second all the sphinx tests and the final line only the tests in that file. Keep in mind that to run the tests your repository needs to be inside your pyiron project folder and you need to have at least the basic resources installed from tests/static. A neat trick when testing/debugging is to combine the pdb and unittest modules like this

python -m pdb -m unittest ...

This allows you to re-use the sometimes complicated setups for your interactive debugging that might be otherwise difficult to replicate in a REPL.

Pull requests

The process described here has several goals:

  • Maintain pyiron's quality
  • Fix problems that are important to users
  • Engage the community in working toward the best possible tools
  • Enable a sustainable system for pyiron's maintainers to review contributions

Please follow these steps to have your contribution considered by the maintainers:

  • Keep the changes in your pull request as focused as possible - only address one issue per pull request wherever possible.
  • Follow the Styleguides
  • Assign the appropriate label (see Issue and pull request labels) to your pull request. If you are fixing a specific Github issue, reference the issue directly in the pull request comments.
  • If you are aware which maintainer is most closely related to the code you've edited, feel free to request their review.
  • After you submit your pull request, verify that all status checks are passing.
  • If a status check fails and it seems to be unrelated to your changes, explain why the failure is unrelated as a comment in your pull request.
  • If you add a new external dependency, please check it is up to date. Packages which have not been updated for five years are considered outdated.
  • If you rename an existing python module, please open a separate pull request to simplify the review process.

While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted.

Styleguides

Git commit messages

  • Use the present tense ("Add feature" not "Added feature")
  • Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
  • Limit the first line to 72 characters or less
  • Reference issues and pull requests liberally after the first line
  • When only changing documentation, include [ci skip] in the commit title
  • Consider starting the commit message with an applicable emoji:

🎨 (:art:) improves the format/structure of the code

⚡ (:zap:) improves performance

📝 (:memo:) adds documentation

🐛 (:bug:) fixes a bug

🔥 (:fire:) removes code or files

💚 (:green_heart:) fixes the CI build

✅ (:white_check_mark:) adds tests

Managing git commits is much easier using an IDE (we recommend PyCharm).

Python styleguide

Please follow PEP8 conventions for all python code added to pyiron. Pull requests will be checked for PEP8 plus a few other security issues with Codacy, and will be rejected if they do not meet the specified formatting criteria.

Any new features should include coverage with a unit test, such that your pull request does not decrease pyiron's overall coverage. This will be automatically tested within the ci test suite and Coveralls.

Deprecation warning template

XXX is deprecated as of vers. A.B.C. It is not guaranteed to be in service in vers. D.E.F. Use YYY instead.

Documentation styleguide

All new/modified functions should include a docstring that follows the Google Python Docstring format.

Documentation is built automatically with Sphinx; any manually created documentation should be added as a restructured text (.rst) file under pyiron/docs/source.

Notebooks created to exemplify features in pyiron are very useful, and can even be used as integration tests. If you have added a major feature, consider creating a notebook to show its usage under pyiron/notebooks/. See the other examples that are already there.

Additional notes

Issue and pull request labels

We use the following tags to organize pyiron Github issues and pull requests:

  • bug: something isn't working
  • duplicate: this issue/pull request already existed
  • enhancement: new feature or request
  • good first issue: easy fix for beginners
  • help wanted: extra attention is needed
  • invalid: this doesn't seem right
  • question: further information is requested
  • wontfix: this will not be worked on
  • stale: inactive after 2 weeks

Build status

The build status for pyiron and all sub packages are given below

Coverage Status Codacy Badge Release_Date Build Status Build status

pyiron releases

Downloads

For the pyiron release management we use git tags:

https://git-scm.com/book/en/v2/Git-Basics-Tagging

The tag format consists of a tag_prefix (<package name>-) and the release version, for example:

pyiron-0.2.0

For the automated versioning we use:

https://github.com/warner/python-versioneer/

So the configuration of the release is included in setup.cfg:

https://github.com/pyiron/pyiron_base/blob/master/setup.cfg

As the pyiron packages are pure python packages – we use only the Linux Python 3.7 job to build the packages, as defined in the .travis.yml file:

https://github.com/pyiron/pyiron_base/blob/master/.travis.yml

The python 3.7 linux tests therefore takes more time, compared to the other tests on travis.

Just like each other commit to the master branch the tagged releases are pushed to pypi.org and anaconda.org:

https://pypi.org/project/pyiron-base/#history
https://anaconda.org/pyiron/pyiron_base

The major difference for pypi (pip) is that tagged releases are the default for pip while installing prerelease versions using pip requires the --pre flag. pip install --pre pyiron

Those pre-release versions are named <version_number>.post0.dev<release number>

0.2.0.post0.dev1

For anaconda the prereleases are pushed to the pyiron channel and can be installed using: conda install -c pyiron pyiron

On the other hand the tagged releases are available through conda-forge, as soon as the corresponding packages are merged:

https://github.com/conda-forge/pyiron-feedstock
conda install -c conda-forge pyiron

So for both conda and pip both the prereleases as well as the official releases are available.

Debugging

My job does not run on the queue

In case a job runs properly while executing it locally (or on the head node), but not when you submit it to a queue,

1. Check if the job class is available in the project:

In this example, we want a custom job class ProtoMD from the module pyiron_contrib:

from pyiron import Project
import pyiron_contrib  # only if importing a custom job class

pr = Project("debug")
dir(pr.job_type)

This should output:

>>> ['AtomisticExampleJob',
 'Atoms',
 'ConvEncutParallel',
 ...
 ...
 'ProtoMD']

If you see your job class in the list, proceed to step 3. If not,

2. Check if the job class in initialized in ``__init__.py`` of the module

Make sure that the __init__.py of your module (here, pyiron_contrib) initializes the job class in the following format:

from pyiron import Project
from pyiron.base.job.jobtype import JOB_CLASS_DICT

# Make classes available for new pyiron version
JOB_CLASS_DICT['ProtoMD'] = 'pyiron_contrib.protocol.compound.md'  # the path of your job class

3. Confirm that the job class can be instantiatied

Create a new job, but instead of running it, save it:

job = pr.create_job(job_type = pr.job_type.ProtoMD, job_name = 'job')
...  # input parameters that the job requires
...
job.save()

>>> 98  # this is the job id of the saved job

Note down the job id, then run the following line:

job["TYPE"]

This should output an instance of the job class:

>>> "<class 'pyiron_contrib.protocol.compound.md.ProtoMD'>"

Now we know that the job class is indeed available in the project and can be instantiated.

4. Debug using a second notebook

Submitting and running a job on the queue, is essentially the same as saving a job in one notebook, but loading and executing it in another notebook.

In a new notebook , load the job that you just saved, using its job id. You may or may not import the module (here, pyiron_conntirb):

from pyiron import Project
# we do not import pyiron_contrib here, becasue it should not be necessary

pr = Project("second_notebook")
reloaded_job = pr.load(98)  # 98 is the job id of the previously saved job
reloaded_job.run(run_again=True)

If the job loads and runs properly, the job should also run properly on the queue. This also means that there may be a bug in your custom job class. Debug the job class, and repeat steps 3 and 4 till you no longer get an error in step 4.