Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
b8e1c29
change default to using simple pytest call
obestwalter Apr 12, 2018
c7dd288
cleaned up the code a bit
obestwalter Apr 12, 2018
b9d44e5
Improve plugin docs
obestwalter Apr 13, 2018
7f4aeea
Merge branch 'tox-quickstart-updates' into spring-cleaning
obestwalter Apr 13, 2018
bda2966
spring cleaning / refactoring
obestwalter Apr 14, 2018
c64e636
_exit_code_str -> exit_code_str
obestwalter Apr 14, 2018
591532e
fix docs to use pluggy API instead of import
obestwalter Apr 14, 2018
50d6230
fix test to use pluggy API instead of import
obestwalter Apr 14, 2018
0e05f36
use tmpdir right - thanks @asottile
obestwalter Apr 14, 2018
e2f97fc
fix redundant formulation - thanks @rpkilby
obestwalter Apr 14, 2018
a80fe9f
Imprve packaging and release orientation - thanks @rpkilby
obestwalter Apr 14, 2018
fb13e94
missed a word
obestwalter Apr 14, 2018
fc9fba2
finish up quickstart testing
obestwalter Apr 15, 2018
f179e5f
improve docstrings
obestwalter Apr 15, 2018
76b8205
exception object is usually called simply 'e'
obestwalter Apr 15, 2018
48cae31
fix some typos and make string formatting consistent within function
obestwalter Apr 15, 2018
ebd5835
remove spaces after class statement for consistency
obestwalter Apr 15, 2018
f9825d1
refactorings
obestwalter Apr 15, 2018
dc62bd6
own module for constants
obestwalter Apr 15, 2018
c44c7d4
json is part of stdlib since Python 2.6
obestwalter Apr 15, 2018
3b6bd01
There should only be one hookimpl object per project
obestwalter Apr 15, 2018
7cdf048
tidy up imports, unused fixtures, unused hook params
obestwalter Apr 15, 2018
3822793
no creation of hookimpl needed, check param types
obestwalter Apr 15, 2018
5b63777
fix imports
obestwalter Apr 15, 2018
a620048
naming things, imports, comments -> docstrings for attributes
obestwalter Apr 15, 2018
470149a
docstring fixes
obestwalter Apr 15, 2018
b8eee01
remove unnecessary monkeypatching
obestwalter Apr 15, 2018
1eecd5f
revert accidental test duplication
obestwalter Apr 15, 2018
f3412d6
clean up
obestwalter Apr 15, 2018
6f96ca2
clean up
obestwalter Apr 15, 2018
1dffe50
more fixes and "modernizations"
obestwalter Apr 15, 2018
8d8cd81
move more constants to shared constants module
obestwalter Apr 15, 2018
4d3193a
fix test bug introduced by switching to version tuples from shared const
obestwalter Apr 17, 2018
dffae55
The new PyPi is out! Update links.
obestwalter Apr 17, 2018
db57931
update some more pypi links - should be all now
obestwalter Apr 17, 2018
bc950dd
remove unstable API warning session class seems quite stable by now.
obestwalter Apr 17, 2018
d4cdf11
add platform = linux to make clear pra is only tested/used there
obestwalter Apr 20, 2018
5a6743b
formatting, whitelist sphinx-build command
obestwalter Apr 20, 2018
cdb6680
enhance plugin docs, small link and example fixes
obestwalter Apr 20, 2018
acdbd48
Do not use reorder imports - uses too much vertical space
obestwalter Apr 20, 2018
82a32bb
change imports to import needed objects directly
obestwalter Apr 20, 2018
7d139e5
revert to using format
obestwalter Apr 20, 2018
4969c57
prevent building messy packages - fixes #754
obestwalter Apr 20, 2018
7327c89
remove wrong docstring for hookspecs, add pluggy docs link
obestwalter Apr 22, 2018
61498c2
add new tox framework classifier to example and rephrase the naming part
obestwalter Apr 25, 2018
bdb0d17
remove unused links
obestwalter Apr 28, 2018
2d1f2a2
fix typo
obestwalter Apr 28, 2018
5a5b3dc
fix formatting error
obestwalter Apr 28, 2018
9662011
fix redundancy in title
obestwalter Apr 28, 2018
e3bba6b
fix API (hookspec is NOT part of API, but hookimpl is)
obestwalter Apr 28, 2018
5058cc9
some fixmes/todos about the pytestplugin
obestwalter Apr 28, 2018
a6c3ff6
some fixmes/todos about the pytestplugin
obestwalter Apr 28, 2018
d136a4f
add link to packaging guide
obestwalter Apr 28, 2018
98cbcd9
update marker handling
obestwalter Apr 28, 2018
84c5884
remove docstrings (don't work like that) - they're redundant anyway
obestwalter Apr 28, 2018
753fe55
add a doc example, more explanation and fix formatting
obestwalter Apr 28, 2018
b5944ca
add changelog entries
obestwalter Apr 28, 2018
40d2583
add a little constructor instead of building factors in namespace
obestwalter Apr 28, 2018
558000c
API: add docstring and mark elements appropriately
obestwalter Apr 28, 2018
1f995b3
add changelog entries
obestwalter Apr 28, 2018
2683477
fix import formatting
obestwalter Apr 28, 2018
e59afae
fix import formatting
obestwalter Apr 28, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 62 additions & 42 deletions doc/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,74 +5,90 @@ tox plugins

.. versionadded:: 2.0

With tox-2.0 a few aspects of tox running can be experimentally modified
by writing hook functions. The list of of available hook function is
to grow over time on a per-need basis.
A growing number of `pluggy`_ hooks make tox extendable by writing plugins.


writing a setuptools entrypoints plugin
Writing a setuptools entrypoints plugin
---------------------------------------

If you have a ``tox_MYPLUGIN.py`` module you could use the following
rough ``setup.py`` to make it into a package which you can upload to the
Python packaging index:
You can create a new tox plugin with all bells and whistles via a `Cookiecutter`_ template (see `cookiecutter-tox-plugin <https://github.com/tox-dev/cookiecutter-tox-plugin>`_) - this will create a complete pypi-releasable, documented project with license, documentation and CI.

.. code-block:: python

# content of setup.py
from setuptools import setup
.. code-block:: console

if __name__ == "__main__":
setup(
name='tox-MYPLUGIN',
description='tox plugin decsription',
license="MIT license",
version='0.1',
py_modules=['tox_MYPLUGIN'],
entry_points={'tox': ['MYPLUGIN = tox_MYPLUGIN']},
install_requires=['tox>=2.0'],
)
$ pip install -U cookiecutter
$ cookiecutter gh:tox-dev/cookiecutter-tox-plugin

If installed, the ``entry_points`` part will make tox see and integrate
your plugin during startup.

You can install the plugin for development ("in-place") via:
Tutorial: a minimal tox plugin
------------------------------

.. code-block:: shell
To create a working plugin you need at least a python project with a tox entry point and a python
module implementing one or more of the pluggy based hooks tox specifies (using the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should have a link here to a page that lists all available hooks

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I misunderstand what you mean: they are already documented at the end of the same page.

``@tox.hookimpl`` decorator as marker).

pip install -e .
Let us consider you want to extent tox behaviour by displaying fireworks at the end of a
successful tox run (we won't go into the details of how to display fireworks though).

and later publish it via something like:
minimal structure:

.. code-block:: shell
.. code-block:: console

python setup.py sdist register upload
$ mkdir tox-fireworks
$ cd tox-fireworks
$ touch tox_fireworks.py
$ touch setup.py


Writing hook implementations
----------------------------

A plugin module defines one or more hook implementation functions
by decorating them with tox's ``hookimpl`` marker:
contents of ``tox_fireworks.py``:

.. code-block:: python

from tox import hookimpl
import pluggy

hookimpl = pluggy.HookimplMarker("tox")

@hookimpl
def tox_addoption(parser):
# add your own command line options

"""Add command line option to display fireworks on request."""

@hookimpl
def tox_configure(config):
# post process tox configuration after cmdline/ini file have
# been parsed
"""Post process config after parsing."""

@hookimpl
def tox_runenvreport(config):
"""Display fireworks if all was fine and requested."""

If you put this into a module and make it pypi-installable with the ``tox``
entry point you'll get your code executed as part of a tox run.

contents of ``setup.py``:

.. code-block:: python

from setuptools import setup

setup(name='tox-fireworks', py_modules=['tox_fireworks'],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be more comfortable if this would follow the structure of what we generate with the cookiecutter, but at least add tox-dev/cookiecutter-tox-plugin#4

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here is to explain the minimal implementation to show how things basically work. In the cookiecutter introduced the package structure, because I think it is a better structure. I was already thinking that this could also be made configurable in the cookiecutter (adding a choice, if you want to create a single module plugin or a a package based one).

entry_points={'tox': ['fireworks = tox_fireworks']})

Using the **tox-** prefix in ``tox-fireworks`` is necessary for it to be an official plugin and
makes finding it easy with e.g. ``pip search 'tox-'`` once it is released on PyPi.

To make your new plugin discoverable by tox, you need to install it. During development you should
install it with ``-e`` or ``--editable``, so that changes to the code are immediately active:

.. code-block:: console

pip install -e </path/to/tox-fireworks>

If you think the rest of the world could profit using your plugin you can publish it to PyPi.
Add some more meta data to ``setup.py`` (see the cookiecutter for a complete example) and publish

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see the cookiecutter template

link the cookiectutter template to the github repo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

it like:

.. code-block:: console

$ cd </path/to/tox-fireworks>
$ python setup.py sdist bdist_wheel upload

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a typo in this commit message, can be left as it is if you do a squash merge, otherwise I suggest a reword 😄

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imprve definitely needs improving :)

For more information about packaging Python projects see the
`Python Packaging User Guide <https://packaging.python.org/>`_.

tox hook specifications and related API
---------------------------------------
Expand All @@ -94,3 +110,7 @@ tox hook specifications and related API

.. autoclass:: tox.session.Session()
:members:


.. _`Cookiecutter`: https://cookiecutter.readthedocs.io
.. _`pluggy`: https://pluggy.readthedocs.io
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def main():
author='holger krekel',
author_email='holger@merlinux.eu',
packages=['tox'],
entry_points={'console_scripts': ['tox=tox.session:run_main',
entry_points={'console_scripts': ['tox=tox:cmdline',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this rename; the cmdline actually shows up as not a valid dictionary entry, hence why I renamed it to run_main instead, to be more explicit

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by valid dictionary entry? Idea here is to remove an unnecessary proxy name. Why should we have a run_main at all, when it is imported and used as cmdline everywhere and is also the name of the de-facto API function?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. in the English dictionary the word cmdline does not exist

I would consider this bad naming in the past, having the proxy names help correct it internally imho, although if you really insist we can keep it as such

'tox-quickstart=tox._quickstart:main']},
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
setup_requires=['setuptools_scm'],
Expand Down
Loading