1.. _contributing:
2
3Contributing to Trio and related projects
4=========================================
5
6So you're interested in contributing to Trio or `one of our associated
7projects <https://github.com/python-trio>`__? That's awesome! Trio is
8an open-source project maintained by an informal group of
9volunteers. Our goal is to make async I/O in Python more fun, easy,
10and reliable, and we can't do it without help from people like you. We
11welcome contributions from anyone willing to work in good faith with
12other contributors and the community (see also our
13:ref:`code-of-conduct`).
14
15There are many ways to contribute, no contribution is too small, and
16all contributions are valued.  For example, you could:
17
18- Hang out in our `chatroom <https://gitter.im/python-trio/general>`__
19  and help people with questions.
20- Sign up for our `forum <https://trio.discourse.group>`__, set up
21  your notifications so you notice interesting conversations, and join
22  in.
23- Answer questions on StackOverflow (`recent questions
24  <https://stackexchange.com/filters/289914/trio-project-tags-on-stackoverflow-filter>`__).
25- Use Trio in a project, and give us feedback on what worked and what
26  didn't.
27- Write a blog post about your experiences with Trio, good or bad.
28- Release open-source programs and libraries that use Trio.
29- Improve documentation.
30- Comment on issues.
31- Add tests.
32- Fix bugs.
33- Add features.
34
35We want contributing to be enjoyable and mutually beneficial; this
36document tries to give you some tips to help that happen, and applies
37to all of the projects under the `python-trio organization on Github
38<https://github.com/python-trio>`__. If you have thoughts on how it
39can be improved then please let us know.
40
41
42Getting started
43---------------
44
45If you're new to open source in general, you might find it useful to
46check out `opensource.guide's How to Contribute to Open Source
47tutorial <https://opensource.guide/how-to-contribute/>`__, or if
48video's more your thing, `egghead.io has a short free video course
49<https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github>`__.
50
51Trio and associated projects are developed on GitHub, under the
52`python-trio <https://github.com/python-trio>`__ organization. Code
53and documentation changes are made through pull requests (see
54:ref:`preparing-pull-requests` below).
55
56We also have an unusual policy for managing commit rights: anyone
57whose pull request is merged is automatically invited to join the
58GitHub organization, and gets commit rights to all of our
59repositories. See :ref:`joining-the-team` below for more details.
60
61If you're looking for a good place to start, then check out our issues
62labeled `good first issue
63<https://github.com/search?utf8=%E2%9C%93&q=user%3Apython-trio+label%3A%22good+first+issue%22+state%3Aopen&type=Issues&ref=advsearch&l=&l=>`__,
64or feel free to ask `on the forum <https://trio.discourse.group>`__ or
65`in chat <https://gitter.im/python-trio/general>`__.
66
67
68Providing support
69-----------------
70
71When helping others use Trio, please remember that you are
72representing our community, and we want this to be a friendly and
73welcoming place.
74
75Concurrency is *really confusing* when you're first learning. When
76talking to beginners, remember that you were a beginner once too, and
77the whole goal here is to make a top-tier concurrency library that's
78accessible to everyone and a joy to use. If people are showing up with
79beginner questions, *that means we're succeeding*. How we respond to
80questions is part of that developer experience, just as much as our
81API, documentation, or testing tools. And as a bonus, helping
82beginners is often the best way to discover ideas for improvements. If
83you start getting burned out and cranky, we've all been there, and
84it's OK to take a break until you feel better. But it's not OK to take
85that out on random users.
86
87Please remember that the authors and users of competing projects are
88smart, thoughtful people doing their best to balance complicated and
89conflicting requirements, just like us. Of course it's totally fine to
90make specific technical critiques ("In project X, this is handled by
91doing Y, Trio does Z instead, which I prefer because...") or talk
92about your personal experience ("I tried using X but I got super
93frustrated and confused"), but refrain from generic statements like "X
94sucks" or "I can't believe anyone uses X".
95
96Please try not to make assumptions about people's gender, and in
97particular remember that we're not all dudes. If you don't have a
98specific reason to assume otherwise, then `singular they
99<https://en.wikipedia.org/wiki/Third-person_pronoun#Singular_they>`__
100makes a fine pronoun, and there are plenty of gender-neutral
101collective terms: "Hey folks", "Hi all", ...
102
103We also like the Recurse Center's `social rules
104<https://www.recurse.com/manual#sub-sec-social-rules>`__:
105
106* no feigning surprise (also available in a `sweet comic version
107  <https://jvns.ca/blog/2017/04/27/no-feigning-surprise/>`__)
108* no well-actually's
109* no subtle -isms (`more details <https://www.recurse.com/blog/38-subtle-isms-at-hacker-school>`__)
110
111
112.. _preparing-pull-requests:
113
114Preparing pull requests
115-----------------------
116
117If you want to submit a documentation or code change to one of the
118Trio projects, then that's done by preparing a Github pull request (or
119"PR" for short). We'll do our best to review your PR quickly. If it's
120been a week or two and you're still waiting for a response, feel free
121to post a comment poking us. (This can just be a comment with the
122single word "ping"; it's not rude at all.)
123
124Here's a quick checklist for putting together a good PR, with details
125in separate sections below:
126
127* :ref:`pull-request-scope`: Does your PR address a single,
128  self-contained issue?
129
130* :ref:`pull-request-tests`: Are your tests passing? Did you add any
131  necessary tests? Code changes pretty much always require test
132  changes, because if it's worth fixing the code then it's worth
133  adding a test to make sure it stays fixed.
134
135* :ref:`pull-request-formatting`: If you changed Python code, then did
136  you run ``black setup.py trio``? (Or for other packages, replace
137  ``trio`` with the package name.)
138
139* :ref:`pull-request-release-notes`: If your change affects
140  user-visible functionality, then did you add a release note to the
141  ``newsfragments/`` directory?
142
143* :ref:`pull-request-docs`: Did you make any necessary documentation
144  updates?
145
146* License: by submitting a PR to a Trio project, you're offering your
147  changes under that project's license. For most projects, that's dual
148  MIT/Apache 2, except for cookiecutter-trio, which is CC0.
149
150
151.. _pull-request-scope:
152
153What to put in a PR
154~~~~~~~~~~~~~~~~~~~
155
156Each PR should, as much as possible, address just one issue and be
157self-contained. If you have ten small, unrelated changes, then go
158ahead and submit ten PRs – it's much easier to review ten small
159changes than one big change with them all mixed together, and this way
160if there's some problem with one of the changes it won't hold up all
161the others.
162
163If you're uncertain about whether a change is a good idea and want
164some feedback before putting time into it, feel free to ask in an
165issue or in the chat room. If you have a partial change that you want
166to get feedback on, feel free to submit it as a PR. (In this case it's
167traditional to start the PR title with ``[WIP]``, for "work in
168progress".)
169
170When you are submitting your PR, you can include ``Closes #123``,
171``Fixes: #123`` or
172`some variation <https://help.github.com/en/articles/closing-issues-using-keywords>`__
173in either your commit message or the PR description, in order to
174automatically close the referenced issue when the PR is merged.
175This keeps us closer to the desired state where each open issue reflects some
176work that still needs to be done.
177
178
179.. _pull-request-tests:
180
181Tests
182~~~~~
183
184We use `pytest <https://pytest.org/>`__ for testing. To run the tests
185locally, you should run:
186
187.. code-block:: shell
188
189   cd path/to/trio/checkout/
190   pip install -r test-requirements.txt  # possibly using a virtualenv
191   pytest trio
192
193This doesn't try to be completely exhaustive – it only checks that
194things work on your machine, and it may skip some slow tests. But it's
195a good way to quickly check that things seem to be working, and we'll
196automatically run the full test suite when your PR is submitted, so
197you'll have a chance to see and fix any remaining issues then.
198
199Every change should have 100% coverage for both code and tests. But,
200you can use ``# pragma: no cover`` to mark lines where
201lack-of-coverage isn't something that we'd want to fix (as opposed to
202it being merely hard to fix). For example::
203
204    else:  # pragma: no cover
205        raise AssertionError("this can't happen!")
206
207We use Codecov to track coverage, because it makes it easy to combine
208coverage from running in different configurations. Running coverage
209locally can be useful
210(``pytest --cov=PACKAGENAME --cov-report=html``), but don't be
211surprised if you get lower coverage than when looking at Codecov
212reports, because there are some lines that are only executed on
213Windows, or macOS, or PyPy, or CPython, or... you get the idea. After
214you create a PR, Codecov will automatically report back with the
215coverage, so you can check how you're really doing. (But note that the
216results can be inaccurate until all the tests are passing. If the
217tests failed, then fix that before worrying about coverage.)
218
219Some rules for writing good tests:
220
221* `Tests MUST pass deterministically
222  <https://github.com/python-trio/trio/issues/200>`__. Flakey tests
223  make for miserable developers. One common source of indeterminism is
224  scheduler ordering; if you're having trouble with this, then
225  :mod:`trio.testing` provides powerful tools to help control
226  ordering, like :func:`trio.testing.wait_all_tasks_blocked`,
227  :class:`trio.testing.Sequencer`, and :class:`trio.testing.MockClock`
228  (usually used as a fixture: ``async def
229  test_whatever(autojump_clock): ...``). And if you need more tools
230  than this then we should add them.
231
232* (Trio package only) Slow tests – anything that takes more than about
233  0.25 seconds – should be marked with ``@slow``. This makes it so they
234  only run if you do ``pytest trio --run-slow``. Our CI scripts do
235  run slow tests, so you can be sure that the code will still be
236  thoroughly tested, and this way you don't have to sit around waiting
237  for a few irrelevant multi-second tests to run while you're iterating
238  on a change locally.
239
240  You can check for slow tests by passing ``--durations=10`` to
241  pytest. Most tests should take 0.01 seconds or less.
242
243* Speaking of waiting around for tests: Tests should never sleep
244  unless *absolutely* necessary. However, calling :func:`trio.sleep`
245  when using ``autojump_clock`` is fine, because that's not really
246  sleeping, and doesn't waste developers time waiting for the test to
247  run.
248
249* We like tests to exercise real functionality. For example, if you're
250  adding subprocess spawning functionality, then your tests should
251  spawn at least one process! Sometimes this is tricky – for example,
252  Trio's :class:`KeyboardInterrupt` tests have to jump through quite
253  some hoops to generate real SIGINT signals at the right times to
254  exercise different paths. But it's almost always worth it.
255
256* For cases where real testing isn't relevant or sufficient, then we
257  strongly prefer fakes or stubs over mocks. Useful articles:
258
259  * `Test Doubles - Fakes, Mocks and Stubs
260    <https://dev.to/milipski/test-doubles---fakes-mocks-and-stubs>`__
261
262  * `Mocks aren't stubs
263    <https://martinfowler.com/articles/mocksArentStubs.html>`__
264
265  * `Write test doubles you can trust using verified fakes
266    <https://codewithoutrules.com/2016/07/31/verified-fakes/>`__
267
268  Most major features have both real tests and tests using fakes or
269  stubs. For example, :class:`~trio.SSLStream` has some tests that
270  use Trio to make a real socket connection to real SSL server
271  implemented using blocking I/O, because it sure would be
272  embarrassing if that didn't work. And then there are also a bunch of
273  tests that use a fake in-memory transport stream where we have
274  complete control over timing and can make sure all the subtle edge
275  cases work correctly.
276
277Writing reliable tests for obscure corner cases is often harder than
278implementing a feature in the first place, but stick with it: it's
279worth it! And don't be afraid to ask for help. Sometimes a fresh pair
280of eyes can be helpful when trying to come up with devious tricks.
281
282
283.. _pull-request-formatting:
284
285Code formatting
286~~~~~~~~~~~~~~~
287
288Instead of wasting time arguing about code formatting, we use `black
289<https://github.com/psf/black>`__ to automatically format all our
290code to a standard style. While you're editing code you can be as
291sloppy as you like about whitespace; and then before you commit, just
292run::
293
294    pip install -U black
295    black setup.py trio
296
297to fix it up. (And don't worry if you forget – when you submit a pull
298request then we'll automatically check and remind you.) Hopefully this
299will let you focus on more important style issues like choosing good
300names, writing useful comments, and making sure your docstrings are
301nicely formatted. (black doesn't reformat comments or docstrings.)
302
303Very occasionally, you'll want to override black formatting. To do so,
304you can can add ``# fmt: off`` and ``# fmt: on`` comments.
305
306If you want to see what changes black will make, you can use::
307
308    black --diff setup.py trio
309
310(``--diff`` displays a diff, versus the default mode which fixes files
311in-place.)
312
313
314.. _pull-request-release-notes:
315
316Release notes
317~~~~~~~~~~~~~
318
319We use `towncrier <https://github.com/hawkowl/towncrier>`__ to manage
320our `release notes <https://trio.readthedocs.io/en/latest/history.html>`__.
321Basically, every pull request that has a user
322visible effect should add a short file to the ``newsfragments/``
323directory describing the change, with a name like ``<ISSUE
324NUMBER>.<TYPE>.rst``. See `newsfragments/README.rst
325<https://github.com/python-trio/trio/blob/master/newsfragments/README.rst>`__
326for details. This way we can keep a good list of changes as we go,
327which makes the release manager happy, which means we get more
328frequent releases, which means your change gets into users' hands
329faster.
330
331
332.. _pull-request-commit-messages:
333
334Commit messages
335~~~~~~~~~~~~~~~
336
337We don't enforce any particular format on commit messages. In your
338commit messages, try to give the context to explain *why* a change was
339made.
340
341The target audience for release notes is users, who want to find out
342about changes that might affect how they use the library, or who are
343trying to figure out why something changed after they upgraded.
344
345The target audience for commit messages is some hapless developer
346(think: you in six months... or five years) who is trying to figure
347out why some code looks the way it does. Including links to issues and
348any other discussion that led up to the commit is *strongly*
349recommended.
350
351
352.. _pull-request-docs:
353
354Documentation
355~~~~~~~~~~~~~
356
357We take pride in providing friendly and comprehensive documentation.
358Documentation is stored in ``docs/source/*.rst`` and is rendered using
359`Sphinx <http://www.sphinx-doc.org/>`__ with the `sphinxcontrib-trio
360<https://sphinxcontrib-trio.readthedocs.io/en/latest/>`__ extension.
361Documentation is hosted at `Read the Docs
362<https://readthedocs.org/>`__, who take care of automatically
363rebuilding it after every commit.
364
365For docstrings, we use `the Google docstring format
366<https://www.sphinx-doc.org/en/3.x/usage/extensions/example_google.html#example-google-style-python-docstrings>`__.
367If you add a new function or class, there's no mechanism for
368automatically adding that to the docs: you'll have to at least add a
369line like ``.. autofunction:: <your function>`` in the appropriate
370place. In many cases it's also nice to add some longer-form narrative
371documentation around that.
372
373We enable Sphinx's "nitpick mode", which turns dangling references
374into an error – this helps catch typos. (This will be automatically
375checked when your PR is submitted.) If you intentionally want to allow
376a dangling reference, you can add it to the `nitpick_ignore
377<http://www.sphinx-doc.org/en/stable/config.html#confval-nitpick_ignore>`__
378whitelist in ``docs/source/conf.py``.
379
380To build the docs locally, use our handy ``docs-requirements.txt``
381file to install all of the required packages (possibly using a
382virtualenv). After that, build the docs using ``make html`` in the
383docs directory. The whole process might look something like this::
384
385    cd path/to/project/checkout/
386    pip install -r docs-requirements.txt
387    cd docs
388    make html
389
390You can then browse the docs using Python's builtin http server:
391``python -m http.server 8000 --bind 127.0.0.1 --directory build/html``
392and then opening ``http://127.0.0.1:8000/`` in your web browser.
393
394.. _joining-the-team:
395
396Joining the team
397----------------
398
399After your first PR is merged, you should receive a Github invitation
400to join the ``python-trio`` organization. If you don't, that's not
401your fault, it's because we made a mistake on our end. Give us a
402nudge on chat or `send @njsmith an email <mailto:njs@pobox.com>`__ and
403we'll fix it.
404
405It's totally up to you whether you accept or not, and if you do
406accept, you're welcome to participate as much or as little as you
407want. We're offering the invitation because we'd love for you to join
408us in making Python concurrency more friendly and robust, but there's
409no pressure: life is too short to spend volunteer time on things that
410you don't find fulfilling.
411
412At this point people tend to have questions.
413
414**How can you trust me with this kind of power? What if I mess
415everything up?!?**
416
417Relax, you got this! And we've got your back. Remember, it's just
418software, and everything's in version control: worst case we'll just
419roll things back and brainstorm ways to avoid the issue happening
420again. We think it's more important to welcome people and help them
421grow than to worry about the occasional minor mishap.
422
423**I don't think I really deserve this.**
424
425It's up to you, but we wouldn't be offering if we didn't think
426you did.
427
428**What exactly happens if I accept? Does it mean I'll break everything
429if I click the wrong button?**
430
431Concretely, if you accept the invitation, this does three things:
432
433* It lets you manage incoming issues on all of the ``python-trio``
434  projects by labelling them, closing them, etc.
435
436* It lets you merge pull requests on all of the ``python-trio``
437  projects by clicking Github's big green "Merge" button, but only if
438  all their tests have passed.
439
440* It automatically subscribes you to notifications on the
441  ``python-trio`` repositories (but you can unsubscribe again if you
442  want through the Github interface)
443
444Note that it does *not* allow you to push changes directly to Github
445without submitting a PR, and it doesn't let you merge broken PRs –
446this is enforced through Github's "branch protection" feature, and it
447applies to everyone from the newest contributor up to the project
448founder.
449
450**Okay, that's what I CAN do, but what SHOULD I do?**
451
452Short answer: whatever you feel comfortable with.
453
454We do have one rule, which is the same one most F/OSS projects use:
455don't merge your own PRs. We find that having another person look at
456each PR leads to better quality.
457
458Beyond that, it all comes down to what you feel up to. If you don't
459feel like you know enough to review a complex code change, then you
460don't have to – you can just look it over and make some comments, even
461if you don't feel up to making the final merge/no-merge decision. Or
462you can just stick to merging trivial doc fixes and adding tags to
463issues, that's helpful too. If after hanging around for a while you
464start to feel like you have better handle on how things work and want
465to start doing more, that's excellent; if it doesn't happen, that's
466fine too.
467
468If at any point you're unsure about whether doing something would be
469appropriate, feel free to ask. For example, it's *totally OK* if the
470first time you review a PR, you want someone else to check over your
471work before you hit the merge button.
472
473The best essay I know about reviewing pull request's is Sage Sharp's
474`The gentle art of patch review
475<http://sage.thesharps.us/2014/09/01/the-gentle-art-of-patch-review/>`__.
476The `node.js guide
477<https://github.com/nodejs/node/blob/master/doc/guides/contributing/pull-requests.md#reviewing-pull-requests>`__
478also has some good suggestions, and `so does this blog post
479<http://verraes.net/2013/10/pre-merge-code-reviews/>`__.
480
481
482Managing issues
483---------------
484
485As issues come in, they need to be responded to, tracked, and –
486hopefully! – eventually closed.
487
488As a general rule, each open issue should represent some kind of task
489that we need to do. Sometimes that task might be "figure out what to
490do here", or even "figure out whether we want to address this issue";
491sometimes it will be "answer this person's question". But if there's
492no followup to be done, then the issue should be closed.
493
494
495Issue labels
496~~~~~~~~~~~~
497
498The Trio repository in particular uses a number of labels to try and
499keep track of issues. The current list is somewhat ad hoc, and may or
500may not remain useful over time – if you think of a new label that
501would be useful, a better name for an existing label, or think a label
502has outlived its usefulness, then speak up.
503
504* `good first issue
505  <https://github.com/python-trio/trio/labels/good%20first%20issue>`__:
506  Used to mark issues that are relatively straightforward, and could
507  be good places for a new contributor to start.
508
509* `todo soon
510  <https://github.com/python-trio/trio/labels/todo%20soon>`__: This
511  marks issues where there aren't questions left about whether or how
512  to do it, it's just waiting for someone to dig in and do the work.
513
514* `missing piece
515  <https://github.com/python-trio/trio/labels/missing%20piece>`__:
516  This generally marks significant self-contained chunks of missing
517  functionality. If you're looking for a more ambitious project to
518  work on, this might be useful.
519
520* `potential API breaker
521  <https://github.com/python-trio/trio/labels/potential%20API%20breaker>`__:
522  What it says. This is useful because these are issues that we'll
523  want to make sure to review aggressively as Trio starts to
524  stabilize, and certainly before we reach 1.0.
525
526* `design discussion
527  <https://github.com/python-trio/trio/labels/design%20discussion>`__:
528  This marks issues where there's significant design questions to be
529  discussed; if you like meaty theoretical debates and discussions of
530  API design, then browsing this might be interesting.
531
532* `polish <https://github.com/python-trio/trio/labels/polish>`__:
533  Marks issues that it'd be nice to resolve eventually, because it's
534  the Right Thing To Do, but it's addressing a kind of edge case thing
535  that isn't necessary for a minimum viable product. Sometimes
536  overlaps with "user happiness".
537
538* `user happiness
539  <https://github.com/python-trio/trio/labels/user%20happiness>`__:
540  From the name alone, this could apply to any bug (users certainly
541  are happier when you fix bugs!), but that's not what we mean. This
542  label is used for issues involving places where users stub their
543  toes, or for the kinds of quality-of-life features that leave users
544  surprised and excited – e.g. fancy testing tools that Just Work.
545
546
547Governance
548----------
549
550`Nathaniel J. Smith <https://github.com/njsmith>`__ is the Trio `BDFL
551<https://en.wikipedia.org/wiki/Benevolent_dictator_for_life>`__. If
552the project grows to the point where we'd benefit from more structure,
553then we'll figure something out.
554
555
556.. Possible references for future additions:
557
558   """
559   Jumping into an unfamiliar codebase (or any for that matter) for the first time can be scary. Plus, if it’s your first time contributing to open source, it can even be scarier!
560
561   But, we at webpack believe:
562
563       Any (even non-technical) individual should feel welcome to contribute.
564       However you decide to contribute, it should be fun and enjoyable for you!
565       Even after your first commit, you will walk away understanding more about webpack or JavaScript.
566       Consequently, you could become a better developer, writer,
567         designer, etc. along the way, and we are committed to helping
568         foster this growth.
569   """
570
571   imposter syndrome disclaimer
572   https://github.com/Unidata/MetPy#contributing
573
574   checklist
575   https://github.com/nayafia/contributing-template/blob/master/CONTRIBUTING-template.md
576
577   https://medium.com/the-node-js-collection/healthy-open-source-967fa8be7951
578
579   http://sweng.the-davies.net/Home/rustys-api-design-manifesto
580