Repository: HypothesisWorks/hypothesis

Issue:
TypeError in renaming.py
I don't have time to dig into this right now I'm afraid, but it looks like the newest release broke pytest's build:

```
[...]
  File "/home/travis/build/pytest-dev/pytest/.tox/py35/lib/python3.5/site-packages/_pytest/assertion/rewrite.py", line 213, in load_module
    py.builtin.exec_(co, mod.__dict__)
  File "/home/travis/build/pytest-dev/pytest/.tox/py35/lib/python3.5/site-packages/hypothesis/strategies.py", line 1232, in <module>
    min_datetime=None, max_datetime=None,
  File "/home/travis/build/pytest-dev/pytest/.tox/py35/lib/python3.5/site-packages/hypothesis/internal/renaming.py", line 52, in accept
    'in a future version of Hypothesis.'
TypeError: unsupported operand type(s) for +=: 'NoneType' and 'str'
```

Travis build: https://travis-ci.org/pytest-dev/pytest/jobs/268491937#L653

Affected code which I don't really understand right now:

https://github.com/HypothesisWorks/hypothesis-python/blob/ea8f3a125adf98d90b7a9de1809f596b41880f8b/src/hypothesis/internal/renaming.py#L42-L54


Discussion:

Resolving patch:
diff --git a/src/hypothesis/internal/renaming.py b/src/hypothesis/internal/renaming.py
--- a/src/hypothesis/internal/renaming.py
+++ b/src/hypothesis/internal/renaming.py
@@ -39,18 +39,28 @@ def with_name_check(**kwargs):
                     kwargs[t] = kwargs.pop(k)
             return f(**kwargs)
 
-        with_name_check.__doc__ += '\n'.join((
-            '', '',
-            'The following arguments have been renamed:',
-            '',
-        ) + tuple(
-            '  * %s has been renamed to %s' % s
-            for s in rename_mapping.items()
-        ) + (
-            '',
-            'Use of the old names has been deprecated and will be removed',
-            'in a future version of Hypothesis.'
-        )
-        )
+        # This decorates things in the public API, which all have docstrings.
+        # (If they're not in the public API, we don't need a deprecation path.)
+        # But docstrings are stripped when running with PYTHONOPTIMIZE=2.
+        #
+        # If somebody's running with that flag, they don't expect any
+        # docstrings to be present, so this message isn't useful.  Absence of
+        # a docstring is a strong indicator that they're running in this mode,
+        # so skip adding this message if that's the case.
+        if with_name_check.__doc__ is not None:
+            with_name_check.__doc__ += '\n'.join((
+                '', '',
+                'The following arguments have been renamed:',
+                '',
+            ) + tuple(
+                '  * %s has been renamed to %s' % s
+                for s in rename_mapping.items()
+            ) + (
+                '',
+                'Use of the old names has been deprecated and will be removed',
+                'in a future version of Hypothesis.'
+            )
+            )
+
         return with_name_check
     return accept


Test patch:
diff --git a/tests/cover/test_renaming.py b/tests/cover/test_renaming.py
new file mode 100644
--- /dev/null
+++ b/tests/cover/test_renaming.py
@@ -0,0 +1,39 @@
+# coding=utf-8
+#
+# This file is part of Hypothesis, which may be found at
+# https://github.com/HypothesisWorks/hypothesis-python
+#
+# Most of this work is copyright (C) 2013-2017 David R. MacIver
+# (david@drmaciver.com), but it contains contributions by others. See
+# CONTRIBUTING.rst for a full list of people who may hold copyright, and
+# consult the git log if you need to determine who owns an individual
+# contribution.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License,
+# v. 2.0. If a copy of the MPL was not distributed with this file, You can
+# obtain one at http://mozilla.org/MPL/2.0/.
+#
+# END HEADER
+
+from __future__ import division, print_function, absolute_import
+
+from tests.common.utils import checks_deprecated_behaviour
+from hypothesis.internal.renaming import renamed_arguments
+
+
+@renamed_arguments(old_arg='new_arg')
+def f(new_arg=None, old_arg=None):
+    return new_arg
+
+
+def test_using_new_args():
+    new_arg = 'A number of numbats at night'
+    assert f(new_arg=new_arg) == new_arg
+    assert f.__doc__ is None
+
+
+@checks_deprecated_behaviour
+def test_using_old_args():
+    old_arg = 'An order of otters on the Ouse'
+    assert f(old_arg=old_arg) == old_arg
+    assert f.__doc__ is None