============
Contributing
============


.. important::
   When contributing to this repository, please adhere to our :ref:`code-of-conduct` and
   first discuss the change you wish to make via an issue **before** submitting a pull
   request.


.. _local-development:

Local Development
=================

The following sections will guide you through setting up a local development environment
for working on this project package.
**At the very least**, make sure that you have the necessary pre-commit hooks installed
to make sure that all commits are pristine before they make it into the change history.

Installing Python
-----------------

.. note::
   If you already have Python 3.7+ installed on your local system, you can skip this
   step completely.


Installing Python should be done through `pyenv <https://github.com/pyenv/pyenv>`_.
To first install ``pyenv`` please follow the guide they provided at
https://github.com/pyenv/pyenv#installation. When you finally have ``pyenv`` you should
be good to continue on.

.. code-block:: console

   $ pyenv --version
   pyenv x.x.x


Now that you have ``pyenv`` we can install the necessary Python version. This project's
package depends on Python 3.7+, so we can request that through ``pyenv``.

.. code-block:: console

   $ pyenv install 3.7  # to install Python 3.7+
   ...

   $ pwd
   /PATH/TO/CLONED/REPOSITORY/project-name
   $ pyenv local 3.7  # to mark the project directory as needing Python 3.7+
   ...

   $ pyenv global 3.7  # if you wish Python 3.7 to be aliased to `python` everywhere
   ...


After installing and marking the repository as requiring Python 3.7+ you should be good
to continue on installing the project's dependencies.

Virtual Environment
-------------------

We use `Poetry <https://python-poetry.org/>`_ to manage both our dependencies and
virtual environments. Setting up ``poetry`` just involves installing it through ``pip``
as a user-level dependency.

.. code-block:: console

   $ pip install --user poetry
   Collecting poetry
   Downloading poetry-x.x.x-py2.py3-non-any.whl
   ...


You can quickly setup your entire development environment by running the installation
process from poetry.

.. code-block:: console

   $ poetry install
   Installing dependencies from lock file
   ...


This with create a virtual environment for you and install the necesary development
dependencies. From there you can jump into a subshell using the newly created virtual
environment using the ``shell`` subcommand.

.. code-block:: console

   $ poetry shell
   pawning shell within ~/.local/share/virtualenvs/my-project-py3.7
   ...

   $ exit # when you wish to exit the subshell


From this shell you have access to all the necessary development dependencies installed
in the virutal environment and can start actually writing and running code within the
client package.


Style Enforcement
-----------------

This project's preferred styles are fully enforced through
`pre-commit <https://pre-commit.com/>`_ hooks. In order to take advantage of these hooks
please make sure that you have ``pre-commit`` and the configured hooks installed in your
local environment.

Installing ``pre-commit`` is done through ``pip`` and should be installed as a
user-level dependency as it adds some console scripts that all projects using
``pre-commit`` will need.

.. code-block:: console

   $ pip install --user pre-commit
   Collecting pre-commit
   Downloading pre_commit-x.x.x-py2.py3-none-any.whl
   ...

   $ pre-commit --version
   pre-commit 2.4.0


Once ``pre-commit`` is installed you should also install the hooks into the cloned
repository.

.. code-block:: console

   $ pwd
   /PATH/TO/CLONED/REPOSITORY/project-name

   $ pre-commit install
   pre-commit installed at .git/hooks/pre-commit


After this you should be good to continue on. These installed hooks will do a first-time
setup when you attempt your next commit to build hook environments. Changes that violate
the defined style specifications in ``setup.cfg`` and ``pyproject.toml`` will cause the
commit to fail and will likely make the necessary changes to added / changed files to
be written to the failing files.

This will give you the opportunity to view the changes the hooks made to the failing
files and add the new changes to the commit in order to make the commit pass. It also
gives you the opportunity to make tweaks to the autogenerated changes to make them more
human accessible (only if necessary).

Editor Configuration
--------------------

We also have some specific settings for editor configuration via
`editorconfig <https://editorconfig.org/#download>`_. We recommend you install the
appropriate plugin for your editor of choice if your editor doesn't already natively
support ``.editorconfig`` configuration files.

Project Tasking
---------------

All of our tasks are built and run through `invoke <http://www.pyinvoke.org/>`_ which is
basically just a more advanced (a little too advanced) Python alternative to
`make <http://man7.org/linux/man-pages/man1/make.1.html>`_. The only reason we are using
this utility is because I know how it works and I already had most of the necessary
tasks defined from other projects.

From within the Poetry subshell, you can access and run these commands through the
provided ``invoke`` development dependency.

.. code-block:: console

   $ invoke --list
   Available tasks:

      build                  Build the project.
      clean                  Clean the project.
      lint                   Lint the project.
      profile                Run and profile a given Python script.
      test                   Test the project.
      docs.build             Build docs.
      docs.build-news        Build towncrier newsfragments.
      docs.clean             Clean built docs.
      docs.view              Build and view docs.
      linter.black           Run Black tool check against source.
      linter.flake8          Run Flake8 tool against source.
      linter.isort           Run ISort tool check against source.
      linter.mypy            Run MyPy tool check against source.
      package.build          Build package source files.
      package.check          Check built package is valid.
      package.clean          Clean previously built package artifacts.
      package.coverage       Build coverage report for test run.
      package.format         Auto format package source files.
      package.requirements   Generate requirements.txt from Poetry's lock.
      package.stub           Generate typing stubs for the package.
      package.test           Run package tests.
      package.typecheck      Run type checking with generated package stubs.


You can run these tasks to do many miscellaneous project tasks such as building
documentation.

.. code-block:: console

   $ invoke docs.build
   [docs.build] ... building 'html' documentation
   Running Sphinx v3.0.3
   loading pickled environment... done
   building [mo]: targets for 0 po files that are out of date
   building [html]: targets for 0 source files that are out of date
   updating environment: 0 added, 0 changed, 0 removed
   looking for now-outdated files... none found
   no targets are out of date.
   build succeeded.

   The HTML pages are in build/html.


All of these tasks should just work right out of the box, but something might break
eventually after required tooling gets enough major updates.

Opening Issues
==============

Issues should follow the included ``ISSUE_TEMPLATE`` found in
``.github/ISSUE_TEMPLATE.md``.

- Issues should contain the following sections:
   - Expected Behavior
   - Current Behavior
   - Possible Solution
   - Steps to Reproduce (for bugs)
   - Context
   - Your Environment

These sections help the developers greatly by providing a large understanding of the
context of the bug or requested feature without having to launch a full fledged
discussion inside of the issue.

Creating Pull Requests
======================

Pull requests should follow the included ``PULL_REQUEST_TEMPLATE`` found in
``.github/PULL_REQUEST_TEMPLATE.md``.

- | Pull requests should always be from a ``topic`` / ``feature`` / ``bugfix``
    (left side) branch.
  | **Pull requests from master branches will not be merged.**
- Pull requests should not fail our requested style guidelines or linting checks.
