We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Avoid "impossible" ZeroDivisionError we keep seeing
https://github.com/HypothesisWorks/hypothesis/blob/592bc7cd2c642bf273113083457444b4823021c9/hypothesis-python/src/hypothesis/statistics.py#L88-L95

This snippet occasionally leads to problems, when `total_drawtime` is nonzero but `total_runtime` *is* zero, causing test failures [like this one](https://ci.appveyor.com/project/DRMacIver/hypothesis/build/1.0.458/job/hl2d74810901ttf5#L926).  I'm not sure why this happens - it's been observed on Python 2 (without) and Python 3 (with) a monotonic clock, so there might be multiple causes - but the solution is pretty simple.  All you need to do to fix this is to change the first conditional to

```python
if total_drawtime <= 0.0 or total_runtime <= 0.0:
```

Then write up a short changelog (see guides/documentation.rst), add your name to the contributors list (in - and read! - contributing.rst), and open a pull request!  If you have any questions, just let me know and I'd be happy to help out.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `hypothesis-python/src/hypothesis/statistics.py`
Content:
```
1 # coding=utf-8
2 #
3 # This file is part of Hypothesis, which may be found at
4 # https://github.com/HypothesisWorks/hypothesis-python
5 #
6 # Most of this work is copyright (C) 2013-2018 David R. MacIver
7 # (david@drmaciver.com), but it contains contributions by others. See
8 # CONTRIBUTING.rst for a full list of people who may hold copyright, and
9 # consult the git log if you need to determine who owns an individual
10 # contribution.
11 #
12 # This Source Code Form is subject to the terms of the Mozilla Public License,
13 # v. 2.0. If a copy of the MPL was not distributed with this file, You can
14 # obtain one at http://mozilla.org/MPL/2.0/.
15 #
16 # END HEADER
17 
18 from __future__ import division, print_function, absolute_import
19 
20 import math
21 
22 from hypothesis.utils.dynamicvariables import DynamicVariable
23 from hypothesis.internal.conjecture.data import Status
24 from hypothesis.internal.conjecture.engine import MAX_SHRINKS, ExitReason
25 
26 collector = DynamicVariable(None)
27 
28 
29 class Statistics(object):
30 
31     def __init__(self, engine):
32         self.passing_examples = len(
33             engine.status_runtimes.get(Status.VALID, ()))
34         self.invalid_examples = len(
35             engine.status_runtimes.get(Status.INVALID, []) +
36             engine.status_runtimes.get(Status.OVERRUN, [])
37         )
38         self.failing_examples = len(engine.status_runtimes.get(
39             Status.INTERESTING, ()))
40 
41         runtimes = sorted(
42             engine.status_runtimes.get(Status.VALID, []) +
43             engine.status_runtimes.get(Status.INVALID, []) +
44             engine.status_runtimes.get(Status.INTERESTING, [])
45         )
46 
47         self.has_runs = bool(runtimes)
48         if not self.has_runs:
49             return
50 
51         n = max(0, len(runtimes) - 1)
52         lower = int(runtimes[int(math.floor(n * 0.05))] * 1000)
53         upper = int(runtimes[int(math.ceil(n * 0.95))] * 1000)
54         if upper == 0:
55             self.runtimes = '< 1ms'
56         elif lower == upper:
57             self.runtimes = '~ %dms' % (lower,)
58         else:
59             self.runtimes = '%d-%d ms' % (lower, upper)
60 
61         if engine.exit_reason == ExitReason.finished:
62             self.exit_reason = 'nothing left to do'
63         elif engine.exit_reason == ExitReason.flaky:
64             self.exit_reason = 'test was flaky'
65         elif engine.exit_reason == ExitReason.max_shrinks:
66             self.exit_reason = 'shrunk example %s times' % (MAX_SHRINKS,)
67         elif engine.exit_reason == ExitReason.max_iterations:
68             self.exit_reason = ((
69                 'settings.max_examples={}, but < 10% of examples satisfied '
70                 'assumptions').format(engine.settings.max_examples)
71             )
72         else:
73             self.exit_reason = (
74                 'settings.%s=%r' % (
75                     engine.exit_reason.name,
76                     getattr(engine.settings, engine.exit_reason.name)
77                 )
78             )
79 
80         self.events = [
81             '%.2f%%, %s' % (
82                 c / engine.call_count * 100, e
83             ) for e, c in sorted(
84                 engine.event_call_counts.items(), key=lambda x: -x[1])
85         ]
86 
87         total_runtime = math.fsum(engine.all_runtimes)
88         total_drawtime = math.fsum(engine.all_drawtimes)
89 
90         if total_drawtime == 0.0:
91             self.draw_time_percentage = '~ 0%'
92         else:
93             draw_time_percentage = 100.0 * min(
94                 1, total_drawtime / total_runtime)
95 
96             self.draw_time_percentage = '~ %d%%' % (
97                 round(draw_time_percentage),)
98 
99 
100 def note_engine_for_statistics(engine):
101     callback = collector.value
102     if callback is not None:
103         callback(Statistics(engine))
104
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/hypothesis-python/src/hypothesis/statistics.py b/hypothesis-python/src/hypothesis/statistics.py
--- a/hypothesis-python/src/hypothesis/statistics.py
+++ b/hypothesis-python/src/hypothesis/statistics.py
@@ -87,8 +87,15 @@
         total_runtime = math.fsum(engine.all_runtimes)
         total_drawtime = math.fsum(engine.all_drawtimes)
 
-        if total_drawtime == 0.0:
+        if total_drawtime == 0.0 and total_runtime >= 0.0:
             self.draw_time_percentage = '~ 0%'
+        elif total_drawtime < 0.0 or total_runtime <= 0.0:
+            # This weird condition is possible in two ways:
+            # 1.  drawtime and/or runtime are negative, due to clock changes
+            #     on Python 2 or old OSs (we use monotonic() where available)
+            # 2.  floating-point issues *very rarely* cause math.fsum to be
+            #     off by the lowest bit, so drawtime==0 and runtime!=0, eek!
+            self.draw_time_percentage = 'NaN'
         else:
             draw_time_percentage = 100.0 * min(
                 1, total_drawtime / total_runtime)

{"golden_diff": "diff --git a/hypothesis-python/src/hypothesis/statistics.py b/hypothesis-python/src/hypothesis/statistics.py\n--- a/hypothesis-python/src/hypothesis/statistics.py\n+++ b/hypothesis-python/src/hypothesis/statistics.py\n@@ -87,8 +87,15 @@\n         total_runtime = math.fsum(engine.all_runtimes)\n         total_drawtime = math.fsum(engine.all_drawtimes)\n \n-        if total_drawtime == 0.0:\n+        if total_drawtime == 0.0 and total_runtime >= 0.0:\n             self.draw_time_percentage = '~ 0%'\n+        elif total_drawtime < 0.0 or total_runtime <= 0.0:\n+            # This weird condition is possible in two ways:\n+            # 1.  drawtime and/or runtime are negative, due to clock changes\n+            #     on Python 2 or old OSs (we use monotonic() where available)\n+            # 2.  floating-point issues *very rarely* cause math.fsum to be\n+            #     off by the lowest bit, so drawtime==0 and runtime!=0, eek!\n+            self.draw_time_percentage = 'NaN'\n         else:\n             draw_time_percentage = 100.0 * min(\n                 1, total_drawtime / total_runtime)\n", "issue": "Avoid \"impossible\" ZeroDivisionError we keep seeing\nhttps://github.com/HypothesisWorks/hypothesis/blob/592bc7cd2c642bf273113083457444b4823021c9/hypothesis-python/src/hypothesis/statistics.py#L88-L95\r\n\r\nThis snippet occasionally leads to problems, when `total_drawtime` is nonzero but `total_runtime` *is* zero, causing test failures [like this one](https://ci.appveyor.com/project/DRMacIver/hypothesis/build/1.0.458/job/hl2d74810901ttf5#L926).  I'm not sure why this happens - it's been observed on Python 2 (without) and Python 3 (with) a monotonic clock, so there might be multiple causes - but the solution is pretty simple.  All you need to do to fix this is to change the first conditional to\r\n\r\n```python\r\nif total_drawtime <= 0.0 or total_runtime <= 0.0:\r\n```\r\n\r\nThen write up a short changelog (see guides/documentation.rst), add your name to the contributors list (in - and read! - contributing.rst), and open a pull request!  If you have any questions, just let me know and I'd be happy to help out.\n", "before_files": [{"content": "# coding=utf-8\n#\n# This file is part of Hypothesis, which may be found at\n# https://github.com/HypothesisWorks/hypothesis-python\n#\n# Most of this work is copyright (C) 2013-2018 David R. MacIver\n# (david@drmaciver.com), but it contains contributions by others. See\n# CONTRIBUTING.rst for a full list of people who may hold copyright, and\n# consult the git log if you need to determine who owns an individual\n# contribution.\n#\n# This Source Code Form is subject to the terms of the Mozilla Public License,\n# v. 2.0. If a copy of the MPL was not distributed with this file, You can\n# obtain one at http://mozilla.org/MPL/2.0/.\n#\n# END HEADER\n\nfrom __future__ import division, print_function, absolute_import\n\nimport math\n\nfrom hypothesis.utils.dynamicvariables import DynamicVariable\nfrom hypothesis.internal.conjecture.data import Status\nfrom hypothesis.internal.conjecture.engine import MAX_SHRINKS, ExitReason\n\ncollector = DynamicVariable(None)\n\n\nclass Statistics(object):\n\n    def __init__(self, engine):\n        self.passing_examples = len(\n            engine.status_runtimes.get(Status.VALID, ()))\n        self.invalid_examples = len(\n            engine.status_runtimes.get(Status.INVALID, []) +\n            engine.status_runtimes.get(Status.OVERRUN, [])\n        )\n        self.failing_examples = len(engine.status_runtimes.get(\n            Status.INTERESTING, ()))\n\n        runtimes = sorted(\n            engine.status_runtimes.get(Status.VALID, []) +\n            engine.status_runtimes.get(Status.INVALID, []) +\n            engine.status_runtimes.get(Status.INTERESTING, [])\n        )\n\n        self.has_runs = bool(runtimes)\n        if not self.has_runs:\n            return\n\n        n = max(0, len(runtimes) - 1)\n        lower = int(runtimes[int(math.floor(n * 0.05))] * 1000)\n        upper = int(runtimes[int(math.ceil(n * 0.95))] * 1000)\n        if upper == 0:\n            self.runtimes = '< 1ms'\n        elif lower == upper:\n            self.runtimes = '~ %dms' % (lower,)\n        else:\n            self.runtimes = '%d-%d ms' % (lower, upper)\n\n        if engine.exit_reason == ExitReason.finished:\n            self.exit_reason = 'nothing left to do'\n        elif engine.exit_reason == ExitReason.flaky:\n            self.exit_reason = 'test was flaky'\n        elif engine.exit_reason == ExitReason.max_shrinks:\n            self.exit_reason = 'shrunk example %s times' % (MAX_SHRINKS,)\n        elif engine.exit_reason == ExitReason.max_iterations:\n            self.exit_reason = ((\n                'settings.max_examples={}, but < 10% of examples satisfied '\n                'assumptions').format(engine.settings.max_examples)\n            )\n        else:\n            self.exit_reason = (\n                'settings.%s=%r' % (\n                    engine.exit_reason.name,\n                    getattr(engine.settings, engine.exit_reason.name)\n                )\n            )\n\n        self.events = [\n            '%.2f%%, %s' % (\n                c / engine.call_count * 100, e\n            ) for e, c in sorted(\n                engine.event_call_counts.items(), key=lambda x: -x[1])\n        ]\n\n        total_runtime = math.fsum(engine.all_runtimes)\n        total_drawtime = math.fsum(engine.all_drawtimes)\n\n        if total_drawtime == 0.0:\n            self.draw_time_percentage = '~ 0%'\n        else:\n            draw_time_percentage = 100.0 * min(\n                1, total_drawtime / total_runtime)\n\n            self.draw_time_percentage = '~ %d%%' % (\n                round(draw_time_percentage),)\n\n\ndef note_engine_for_statistics(engine):\n    callback = collector.value\n    if callback is not None:\n        callback(Statistics(engine))\n", "path": "hypothesis-python/src/hypothesis/statistics.py"}], "after_files": [{"content": "# coding=utf-8\n#\n# This file is part of Hypothesis, which may be found at\n# https://github.com/HypothesisWorks/hypothesis-python\n#\n# Most of this work is copyright (C) 2013-2018 David R. MacIver\n# (david@drmaciver.com), but it contains contributions by others. See\n# CONTRIBUTING.rst for a full list of people who may hold copyright, and\n# consult the git log if you need to determine who owns an individual\n# contribution.\n#\n# This Source Code Form is subject to the terms of the Mozilla Public License,\n# v. 2.0. If a copy of the MPL was not distributed with this file, You can\n# obtain one at http://mozilla.org/MPL/2.0/.\n#\n# END HEADER\n\nfrom __future__ import division, print_function, absolute_import\n\nimport math\n\nfrom hypothesis.utils.dynamicvariables import DynamicVariable\nfrom hypothesis.internal.conjecture.data import Status\nfrom hypothesis.internal.conjecture.engine import MAX_SHRINKS, ExitReason\n\ncollector = DynamicVariable(None)\n\n\nclass Statistics(object):\n\n    def __init__(self, engine):\n        self.passing_examples = len(\n            engine.status_runtimes.get(Status.VALID, ()))\n        self.invalid_examples = len(\n            engine.status_runtimes.get(Status.INVALID, []) +\n            engine.status_runtimes.get(Status.OVERRUN, [])\n        )\n        self.failing_examples = len(engine.status_runtimes.get(\n            Status.INTERESTING, ()))\n\n        runtimes = sorted(\n            engine.status_runtimes.get(Status.VALID, []) +\n            engine.status_runtimes.get(Status.INVALID, []) +\n            engine.status_runtimes.get(Status.INTERESTING, [])\n        )\n\n        self.has_runs = bool(runtimes)\n        if not self.has_runs:\n            return\n\n        n = max(0, len(runtimes) - 1)\n        lower = int(runtimes[int(math.floor(n * 0.05))] * 1000)\n        upper = int(runtimes[int(math.ceil(n * 0.95))] * 1000)\n        if upper == 0:\n            self.runtimes = '< 1ms'\n        elif lower == upper:\n            self.runtimes = '~ %dms' % (lower,)\n        else:\n            self.runtimes = '%d-%d ms' % (lower, upper)\n\n        if engine.exit_reason == ExitReason.finished:\n            self.exit_reason = 'nothing left to do'\n        elif engine.exit_reason == ExitReason.flaky:\n            self.exit_reason = 'test was flaky'\n        elif engine.exit_reason == ExitReason.max_shrinks:\n            self.exit_reason = 'shrunk example %s times' % (MAX_SHRINKS,)\n        elif engine.exit_reason == ExitReason.max_iterations:\n            self.exit_reason = ((\n                'settings.max_examples={}, but < 10% of examples satisfied '\n                'assumptions').format(engine.settings.max_examples)\n            )\n        else:\n            self.exit_reason = (\n                'settings.%s=%r' % (\n                    engine.exit_reason.name,\n                    getattr(engine.settings, engine.exit_reason.name)\n                )\n            )\n\n        self.events = [\n            '%.2f%%, %s' % (\n                c / engine.call_count * 100, e\n            ) for e, c in sorted(\n                engine.event_call_counts.items(), key=lambda x: -x[1])\n        ]\n\n        total_runtime = math.fsum(engine.all_runtimes)\n        total_drawtime = math.fsum(engine.all_drawtimes)\n\n        if total_drawtime == 0.0 and total_runtime >= 0.0:\n            self.draw_time_percentage = '~ 0%'\n        elif total_drawtime < 0.0 or total_runtime <= 0.0:\n            # This weird condition is possible in two ways:\n            # 1.  drawtime and/or runtime are negative, due to clock changes\n            #     on Python 2 or old OSs (we use monotonic() where available)\n            # 2.  floating-point issues *very rarely* cause math.fsum to be\n            #     off by the lowest bit, so drawtime==0 and runtime!=0, eek!\n            self.draw_time_percentage = 'NaN'\n        else:\n            draw_time_percentage = 100.0 * min(\n                1, total_drawtime / total_runtime)\n\n            self.draw_time_percentage = '~ %d%%' % (\n                round(draw_time_percentage),)\n\n\ndef note_engine_for_statistics(engine):\n    callback = collector.value\n    if callback is not None:\n        callback(Statistics(engine))\n", "path": "hypothesis-python/src/hypothesis/statistics.py"}]}