Repository: HypothesisWorks/hypothesis

Issue:
Deprecation warning does not blame user code correctly
From IRC:
```
<idnar> …/hypothesis/searchstrategy/deferred.py:81: HypothesisDeprecationWarning: Use hypothesis.strategies.datetimes, which supports full-precision bounds and has a simpler API.
<idnar> that message doesn't actually tell me _what_ is deprecated
<tos9> idnar: It's hypothesis.extras.datetime.datetimes that's deprecated
<tos9> But I think all the warnings are possibly missing a stacklevel
<tos9> because they don't point at the calling code
```


Discussion:
    from hypothesis.extra.datetime import datetimes
    datetimes().example()

gives a warning pointing into Hypothesis internals.

However, I think this is due to lazy evaluation rather than a stack error as such; and the proper fix is probably to address the deeper issue of misattributed exceptions in deferred strategy creation.
Nope, turns out it's a lot simpler than that - purely a presentation issue where we should pass `stacklevel=2` but currently have `stacklevel=3`; the traceback is fine but we've told the warnings machinery not to display the relevant frame!  Fix incoming :smile: 

Resolving patch:
diff --git a/hypothesis-python/src/hypothesis/_settings.py b/hypothesis-python/src/hypothesis/_settings.py
--- a/hypothesis-python/src/hypothesis/_settings.py
+++ b/hypothesis-python/src/hypothesis/_settings.py
@@ -845,7 +845,7 @@ def note_deprecation(message, s=None):
     verbosity = s.verbosity
     warning = HypothesisDeprecationWarning(message)
     if verbosity > Verbosity.quiet:
-        warnings.warn(warning, stacklevel=3)
+        warnings.warn(warning, stacklevel=2)
 
 
 settings.register_profile('default', settings())


Test patch:
diff --git a/hypothesis-python/tests/nocover/test_regressions.py b/hypothesis-python/tests/nocover/test_regressions.py
new file mode 100644
--- /dev/null
+++ b/hypothesis-python/tests/nocover/test_regressions.py
@@ -0,0 +1,44 @@
+# 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-2018 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
+
+import warnings
+
+from hypothesis.errors import HypothesisDeprecationWarning
+from hypothesis._settings import note_deprecation
+from hypothesis.strategies import integers, composite
+
+
+def test_note_deprecation_blames_right_code_issue_652():
+    msg = 'this is an arbitrary deprecation warning message'
+
+    @composite
+    def deprecated_strategy(draw):
+        draw(integers())
+        note_deprecation(msg)
+
+    with warnings.catch_warnings(record=True) as log:
+        warnings.simplefilter('always')
+        deprecated_strategy().example()
+
+    assert len(log) == 1
+    record, = log
+    # We got the warning we expected, from the right file
+    assert isinstance(record.message, HypothesisDeprecationWarning)
+    assert record.message.args == (msg,)
+    assert record.filename == __file__