Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Receives section for generator.send(...) params #145

Merged
merged 5 commits into from
Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 16 additions & 8 deletions doc/format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,21 @@ The sections of a function's docstring are:
Support for the **Yields** section was added in `numpydoc
<https://github.com/numpy/numpydoc>`_ version 0.6.

7. **Other Parameters**
7. **Sent**
Copy link
Contributor

Choose a reason for hiding this comment

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

I am a bit torn about the order of Yields and Sent. Putting Sent first feels more natural to the way you use send (in that the next value to come out probably depends on the value you sent in or you would not be bothering to send anything in!).

On the other hand it yields a non-trivial value before you can send in a non trivial value so it should stay in this order.

On the other other hand, you do send in None first to prime the generator (but that is not what is being documented in this block).

Copy link
Member Author

@jnothman jnothman Nov 29, 2017

Choose a reason for hiding this comment

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

I had thought the idiom was to use next initially, then .send later.

I think the discomfort is partially with the sense of the word "Sent", which connotes a departing aspect (perhaps because it is not agentive). "Receives", in contrast, seems to fit better after "Yields".

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting, I had not seen that idiom. I like sending None as it special-cases the first round less, but that is neither here nor there for this discussion.

"The generator is sent ..." vs "The generator receives ..."

The first is odd because we drop the 'is' in the section title and the second is odd because it feel more passive.

Copy link
Contributor

Choose a reason for hiding this comment

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

"receives" sounds more correct than "sent" in my head.

Choose a reason for hiding this comment

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

I prefer "receives" as well. Another possibility I can think of is "accepts," but I don't think I like that as much as "receives".


Explanation of parameters passed to a generator's ``.send()`` method,
formatted as for Parameters, above. Since, like for Yields and Returns, a
single object is always passed to the method, this may describe either the
single parameter, or positional arguments passed as a tuple. If a docstring
includes Sent it must also include Yields.

8. **Other Parameters**

An optional section used to describe infrequently used parameters.
It should only be used if a function has a large number of keyword
parameters, to prevent cluttering the **Parameters** section.

8. **Raises**
9. **Raises**

An optional section detailing which errors get raised and under
what conditions::
Expand All @@ -269,16 +277,16 @@ The sections of a function's docstring are:
This section should be used judiciously, i.e., only for errors
that are non-obvious or have a large chance of getting raised.

9. **Warns**
10. **Warns**

An optional section detailing which warnings get raised and
under what conditions, formatted similarly to Raises.

10. **Warnings**
11. **Warnings**

An optional section with cautions to the user in free text/reST.

11. **See Also**
12. **See Also**

An optional section used to refer to related code. This section
can be very useful, but should be used judiciously. The goal is to
Expand Down Expand Up @@ -317,7 +325,7 @@ The sections of a function's docstring are:
func_b, func_c_, func_d
func_e

12. **Notes**
13. **Notes**

An optional section that provides additional information about the
code, possibly including a discussion of the algorithm. This
Expand Down Expand Up @@ -362,7 +370,7 @@ The sections of a function's docstring are:
where filename is a path relative to the reference guide source
directory.

13. **References**
14. **References**

References cited in the **notes** section may be listed here,
e.g. if you cited the article below using the text ``[1]_``,
Expand All @@ -387,7 +395,7 @@ The sections of a function's docstring are:
should not be required to understand it. References are numbered, starting
from one, in the order in which they are cited.

14. **Examples**
15. **Examples**

An optional section for examples, using the `doctest
<http://docs.python.org/library/doctest.html>`_ format.
Expand Down
10 changes: 7 additions & 3 deletions numpydoc/docscrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class NumpyDocString(collections.Mapping):
'Parameters': [],
'Returns': [],
'Yields': [],
'Sent': [],
'Raises': [],
'Warns': [],
'Other Parameters': [],
Expand Down Expand Up @@ -342,6 +343,9 @@ def _parse(self):
if has_returns and has_yields:
msg = 'Docstring contains both a Returns and Yields section.'
raise ValueError(msg)
if not has_yields and 'Sent' in section_names:
msg = 'Docstring contains a Sent section but not Yields.'
raise ValueError(msg)

for (section, content) in sections:
if not section.startswith('..'):
Expand All @@ -351,8 +355,8 @@ def _parse(self):
self._error_location("The section %s appears twice"
% section)

if section in ('Parameters', 'Returns', 'Yields', 'Raises',
'Warns', 'Other Parameters', 'Attributes',
if section in ('Parameters', 'Returns', 'Yields', 'Sent',
'Raises', 'Warns', 'Other Parameters', 'Attributes',
'Methods'):
self[section] = self._parse_param_list(content)
elif section.startswith('.. index::'):
Expand Down Expand Up @@ -468,7 +472,7 @@ def __str__(self, func_role=''):
out += self._str_signature()
out += self._str_summary()
out += self._str_extended_summary()
for param_list in ('Parameters', 'Returns', 'Yields',
for param_list in ('Parameters', 'Returns', 'Yields', 'Sent',
'Other Parameters', 'Raises', 'Warns'):
out += self._str_param_list(param_list)
out += self._str_section('Warnings')
Expand Down
1 change: 1 addition & 0 deletions numpydoc/docscrape_sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ def __str__(self, indent=0, func_role="obj"):
'parameters': self._str_param_list('Parameters'),
'returns': self._str_returns('Returns'),
'yields': self._str_returns('Yields'),
'sent': self._str_returns('Sent'),
'other_parameters': self._str_param_list('Other Parameters'),
'raises': self._str_param_list('Raises'),
'warns': self._str_param_list('Warns'),
Expand Down
1 change: 1 addition & 0 deletions numpydoc/templates/numpydoc_docstring.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{{parameters}}
{{returns}}
{{yields}}
{{sent}}
{{other_parameters}}
{{raises}}
{{warns}}
Expand Down
70 changes: 70 additions & 0 deletions numpydoc/tests/test_docscrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,25 @@
doc_yields = NumpyDocString(doc_yields_txt)


doc_sent_txt = """
Test generator

Yields
------
a : int
The number of apples.

Sent
----
b : int
The number of bananas.
c : int
The number of oranges.

"""
doc_sent = NumpyDocString(doc_sent_txt)


def test_signature():
assert doc['Signature'].startswith('numpy.multivariate_normal(')
assert doc['Signature'].endswith('spam=None)')
Expand Down Expand Up @@ -211,6 +230,38 @@ def test_yields():
assert desc[0].endswith(end)


def test_sent():
section = doc_sent['Sent']
assert_equal(len(section), 2)
Copy link
Member

Choose a reason for hiding this comment

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

CI isn't happy: NameError: global name 'assert_equal' is not defined

You can just change this to plain assert

Copy link
Member

Choose a reason for hiding this comment

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

and some more of the same several lines below

truth = [('b', 'int', 'bananas.'),
('c', 'int', 'oranges.')]
for (arg, arg_type, desc), (arg_, arg_type_, end) in zip(section, truth):
assert_equal(arg, arg_)
assert_equal(arg_type, arg_type_)
assert desc[0].startswith('The number of')
assert desc[0].endswith(end)


def test_returnyield():
doc_text = """
Test having returns and yields.

Returns
-------
int
The number of apples.

Yields
------
a : int
The number of apples.
b : int
The number of bananas.

"""
assert_raises(ValueError, NumpyDocString, doc_text)


def test_returnyield():
doc_text = """
Test having returns and yields.
Expand Down Expand Up @@ -462,6 +513,25 @@ def test_yield_str():
.. index:: """)


def test_sent_str():
line_by_line_compare(str(doc_sent),
"""Test generator

Yields
------
a : int
The number of apples.

Sent
----
b : int
The number of bananas.
c : int
The number of oranges.

.. index:: """)


def test_sphinx_str():
sphinx_doc = SphinxDocString(doc_txt)
line_by_line_compare(str(sphinx_doc),
Expand Down