Repository: HypothesisWorks/hypothesis

Issue:
pytest's switch to setuptools-scm breaks version check
With the latest pytest `features` branch with https://github.com/pytest-dev/pytest/pull/1834 in, I get:

```
Traceback (most recent call last):
  File "./.venv/bin/pytest", line 11, in <module>
    load_entry_point('pytest', 'console_scripts', 'pytest')()
  File "/home/florian/proj/pytest/_pytest/config.py", line 48, in main
    config = _prepareconfig(args, plugins)
  File "/home/florian/proj/pytest/_pytest/config.py", line 157, in _prepareconfig
    pluginmanager=pluginmanager, args=args)
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 745, in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 339, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 334, in <lambda>
    _MultiCall(methods, kwargs, hook.spec_opts).execute()
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 613, in execute
    return _wrapped_call(hook_impl.function(*args), self.execute)
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 250, in _wrapped_call
    wrap_controller.send(call_outcome)
  File "/home/florian/proj/pytest/_pytest/helpconfig.py", line 34, in pytest_cmdline_parse
    config = outcome.get_result()
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 279, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 265, in __init__
    self.result = func()
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 614, in execute
    res = hook_impl.function(*args)
  File "/home/florian/proj/pytest/_pytest/config.py", line 926, in pytest_cmdline_parse
    self.parse(args)
  File "/home/florian/proj/pytest/_pytest/config.py", line 1084, in parse
    self._preparse(args, addopts=addopts)
  File "/home/florian/proj/pytest/_pytest/config.py", line 1046, in _preparse
    self.pluginmanager.load_setuptools_entrypoints(entrypoint_name)
  File "/home/florian/proj/pytest/_pytest/vendored_packages/pluggy.py", line 510, in load_setuptools_entrypoints
    plugin = ep.load()
  File "/home/florian/proj/qutebrowser/git/.venv/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2302, in load
    return self.resolve()
  File "/home/florian/proj/qutebrowser/git/.venv/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2308, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 646, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 616, in _load_backward_compatible
  File "/home/florian/proj/pytest/_pytest/assertion/rewrite.py", line 216, in load_module
    py.builtin.exec_(co, mod.__dict__)
  File "/home/florian/proj/qutebrowser/git/.venv/lib/python3.6/site-packages/hypothesis/extra/pytestplugin.py", line 32, in <module>
    re.sub('-.+', '', pytest.__version__).split('.')[:3]
ValueError: invalid literal for int() with base 10: 'unknown'
```


Discussion:
Hmmm are you using a development version @The-Compiler? Because regardless it should work if you do a `pip install -e .` on Pytest; this will generate the `_version.py` file... 

Resolving patch:
diff --git a/src/hypothesis/extra/pytestplugin.py b/src/hypothesis/extra/pytestplugin.py
--- a/src/hypothesis/extra/pytestplugin.py
+++ b/src/hypothesis/extra/pytestplugin.py
@@ -17,8 +17,6 @@
 
 from __future__ import division, print_function, absolute_import
 
-import re
-
 import pytest
 
 from hypothesis.reporting import default as default_reporter
@@ -27,116 +25,119 @@
 from hypothesis.internal.compat import OrderedDict, text_type
 from hypothesis.internal.detection import is_hypothesis_test
 
-PYTEST_VERSION = tuple(map(
-    int,
-    re.sub('-.+', '', pytest.__version__).split('.')[:3]
-))
-
 LOAD_PROFILE_OPTION = '--hypothesis-profile'
 PRINT_STATISTICS_OPTION = '--hypothesis-show-statistics'
 
-if PYTEST_VERSION >= (2, 7, 0):
-    class StoringReporter(object):
-
-        def __init__(self, config):
-            self.config = config
-            self.results = []
-
-        def __call__(self, msg):
-            if self.config.getoption('capture', 'fd') == 'no':
-                default_reporter(msg)
-            if not isinstance(msg, text_type):
-                msg = repr(msg)
-            self.results.append(msg)
-
-    def pytest_addoption(parser):
-        group = parser.getgroup('hypothesis', 'Hypothesis')
-        group.addoption(
-            LOAD_PROFILE_OPTION,
-            action='store',
-            help='Load in a registered hypothesis.settings profile'
+
+class StoringReporter(object):
+
+    def __init__(self, config):
+        self.config = config
+        self.results = []
+
+    def __call__(self, msg):
+        if self.config.getoption('capture', 'fd') == 'no':
+            default_reporter(msg)
+        if not isinstance(msg, text_type):
+            msg = repr(msg)
+        self.results.append(msg)
+
+
+def pytest_addoption(parser):
+    group = parser.getgroup('hypothesis', 'Hypothesis')
+    group.addoption(
+        LOAD_PROFILE_OPTION,
+        action='store',
+        help='Load in a registered hypothesis.settings profile'
+    )
+    group.addoption(
+        PRINT_STATISTICS_OPTION,
+        action='store_true',
+        help='Configure when statistics are printed',
+        default=False
+    )
+
+
+def pytest_configure(config):
+    from hypothesis import settings
+    profile = config.getoption(LOAD_PROFILE_OPTION)
+    if profile:
+        settings.load_profile(profile)
+    config.addinivalue_line(
+        'markers',
+        'hypothesis: Tests which use hypothesis.')
+
+
+gathered_statistics = OrderedDict()
+
+
+@pytest.mark.hookwrapper
+def pytest_runtest_call(item):
+    if not (hasattr(item, 'obj') and is_hypothesis_test(item.obj)):
+        yield
+    else:
+        store = StoringReporter(item.config)
+
+        def note_statistics(stats):
+            gathered_statistics[item.nodeid] = stats
+
+        with collector.with_value(note_statistics):
+            with with_reporter(store):
+                yield
+        if store.results:
+            item.hypothesis_report_information = list(store.results)
+
+
+@pytest.mark.hookwrapper
+def pytest_runtest_makereport(item, call):
+    report = (yield).get_result()
+    if hasattr(item, 'hypothesis_report_information'):
+        report.sections.append((
+            'Hypothesis',
+            '\n'.join(item.hypothesis_report_information)
+        ))
+
+
+def pytest_terminal_summary(terminalreporter):
+    if not terminalreporter.config.getoption(PRINT_STATISTICS_OPTION):
+        return
+    terminalreporter.section('Hypothesis Statistics')
+    for name, statistics in gathered_statistics.items():
+        terminalreporter.write_line(name + ':')
+        terminalreporter.write_line('')
+
+        if not statistics.has_runs:
+            terminalreporter.write_line('  - Test was never run')
+            continue
+
+        terminalreporter.write_line((
+            '  - %d passing examples, %d failing examples,'
+            ' %d invalid examples') % (
+            statistics.passing_examples, statistics.failing_examples,
+            statistics.invalid_examples,
+        ))
+        terminalreporter.write_line(
+            '  - Typical runtimes: %s' % (statistics.runtimes,)
         )
-        group.addoption(
-            PRINT_STATISTICS_OPTION,
-            action='store_true',
-            help='Configure when statistics are printed',
-            default=False
+        terminalreporter.write_line(
+            '  - Stopped because %s' % (statistics.exit_reason,)
         )
+        if statistics.events:
+            terminalreporter.write_line('  - Events:')
+            for event in statistics.events:
+                terminalreporter.write_line(
+                    '    * %s' % (event,)
+                )
+        terminalreporter.write_line('')
+
+
+def pytest_collection_modifyitems(items):
+    for item in items:
+        if not isinstance(item, pytest.Function):
+            continue
+        if getattr(item.function, 'is_hypothesis_test', False):
+            item.add_marker('hypothesis')
+
 
-    def pytest_configure(config):
-        from hypothesis import settings
-        profile = config.getoption(LOAD_PROFILE_OPTION)
-        if profile:
-            settings.load_profile(profile)
-        config.addinivalue_line(
-            'markers',
-            'hypothesis: Tests which use hypothesis.')
-
-    gathered_statistics = OrderedDict()
-
-    @pytest.mark.hookwrapper
-    def pytest_runtest_call(item):
-        if not (hasattr(item, 'obj') and is_hypothesis_test(item.obj)):
-            yield
-        else:
-            store = StoringReporter(item.config)
-
-            def note_statistics(stats):
-                gathered_statistics[item.nodeid] = stats
-
-            with collector.with_value(note_statistics):
-                with with_reporter(store):
-                    yield
-            if store.results:
-                item.hypothesis_report_information = list(store.results)
-
-    @pytest.mark.hookwrapper
-    def pytest_runtest_makereport(item, call):
-        report = (yield).get_result()
-        if hasattr(item, 'hypothesis_report_information'):
-            report.sections.append((
-                'Hypothesis',
-                '\n'.join(item.hypothesis_report_information)
-            ))
-
-    def pytest_terminal_summary(terminalreporter):
-        if not terminalreporter.config.getoption(PRINT_STATISTICS_OPTION):
-            return
-        terminalreporter.section('Hypothesis Statistics')
-        for name, statistics in gathered_statistics.items():
-            terminalreporter.write_line(name + ':')
-            terminalreporter.write_line('')
-
-            if not statistics.has_runs:
-                terminalreporter.write_line('  - Test was never run')
-                continue
-
-            terminalreporter.write_line((
-                '  - %d passing examples, %d failing examples,'
-                ' %d invalid examples') % (
-                statistics.passing_examples, statistics.failing_examples,
-                statistics.invalid_examples,
-            ))
-            terminalreporter.write_line(
-                '  - Typical runtimes: %s' % (statistics.runtimes,)
-            )
-            terminalreporter.write_line(
-                '  - Stopped because %s' % (statistics.exit_reason,)
-            )
-            if statistics.events:
-                terminalreporter.write_line('  - Events:')
-                for event in statistics.events:
-                    terminalreporter.write_line(
-                        '    * %s' % (event,)
-                    )
-            terminalreporter.write_line('')
-
-    def pytest_collection_modifyitems(items):
-        for item in items:
-            if not isinstance(item, pytest.Function):
-                continue
-            if getattr(item.function, 'is_hypothesis_test', False):
-                item.add_marker('hypothesis')
-
-    def load():
-        pass
+def load():
+    pass
diff --git a/src/hypothesis/version.py b/src/hypothesis/version.py
--- a/src/hypothesis/version.py
+++ b/src/hypothesis/version.py
@@ -17,5 +17,5 @@
 
 from __future__ import division, print_function, absolute_import
 
-__version_info__ = (3, 8, 2)
+__version_info__ = (3, 8, 3)
 __version__ = '.'.join(map(str, __version_info__))


Test patch: