Repository: numpy/numpydoc

Issue:
Parsing `returns` section with several types and no name
According to numpydoc [return value specification](https://numpydoc.readthedocs.io/en/latest/format.html#returns), the name for each return value may be optional. If the return value is omitted and the return type can take several types (if the actual type depends on user input, for example), then if the second type contains `" :"` as part of the type description (as in the following example) it is incorrectly identified as parameter type separator. This prevents sphinx recognition of the referenced type. 

```python
from numpydoc.docscrape import NumpyDocString
docstr="""
Returns
-------
str or :class:`NumpyDocString`
"""
print(NumpyDocString(docstr))
```
Results with:
```



Returns
-------
str or : class:`NumpyDocString`

```

I would expect getting the following result:
```



Returns
-------
str or :class:`NumpyDocString`

```

The example is using version 1.4.0.
I think this was changed in #286 .

Thanks!

Discussion:
larsoner: Looks great, thanks for the quick fix @rossbar !

Patch:
diff --git a/numpydoc/docscrape.py b/numpydoc/docscrape.py
index 6bdaa84..9496f9d 100644
--- a/numpydoc/docscrape.py
+++ b/numpydoc/docscrape.py
@@ -226,10 +226,14 @@ class NumpyDocString(Mapping):
         params = []
         while not r.eof():
             header = r.read().strip()
-            if " :" in header:
-                arg_name, arg_type = header.split(" :", maxsplit=1)
-                arg_name, arg_type = arg_name.strip(), arg_type.strip()
+            if " : " in header:
+                arg_name, arg_type = header.split(" : ", maxsplit=1)
             else:
+                # NOTE: param line with single element should never have a
+                # a " :" before the description line, so this should probably
+                # warn.
+                if header.endswith(" :"):
+                    header = header[:-2]
                 if single_element_is_type:
                     arg_name, arg_type = "", header
                 else:


Test patch:
diff --git a/numpydoc/tests/test_docscrape.py b/numpydoc/tests/test_docscrape.py
index 55ccf92..049d2a2 100644
--- a/numpydoc/tests/test_docscrape.py
+++ b/numpydoc/tests/test_docscrape.py
@@ -980,6 +980,21 @@ doc8 = NumpyDocString(
 )
 
 
+def test_returns_with_roles_no_names():
+    """Make sure colons that are part of sphinx roles are not misinterpreted
+    as type separator in returns section. See gh-428."""
+    docstring = NumpyDocString(
+        """
+        Returns
+        -------
+        str or :class:`NumpyDocString`
+        """
+    )
+    expected = "str or :class:`NumpyDocString`"  # not "str or : class:...
+    assert docstring["Returns"][0].type == expected
+    assert expected in str(docstring)
+
+
 def test_trailing_colon():
     assert doc8["Parameters"][0].name == "data"