Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for Python 2.6.
-Import backported libraries where necessary.
-Refactor set literal and dictionary comprehension usage (not py2.6 compatible).
-Skip 2 tests in py2.6 that don't seem to be compatible. These tests use certain imaginary literals that don't parse in py2.6.
-Skip hypothesis-django tests for py2.6 since hypothesis-django is not py2.6 compatible.
  • Loading branch information
Jeff-Meadows authored and DRMacIver committed Jun 28, 2015
1 parent 603aa6b commit a09ca5f
Show file tree
Hide file tree
Showing 24 changed files with 130 additions and 55 deletions.
Expand Up @@ -29,9 +29,9 @@

DatetimeSpec = namedtuple('DatetimeSpec', ('naive_options',))

naive_datetime = DatetimeSpec({True})
timezone_aware_datetime = DatetimeSpec({False})
any_datetime = DatetimeSpec({False, True})
naive_datetime = DatetimeSpec(set((True,)))
timezone_aware_datetime = DatetimeSpec(set((False,)))
any_datetime = DatetimeSpec(set((False, True)))


def draw_day_for_month(random, year, month):
Expand Down Expand Up @@ -180,7 +180,7 @@ def year_in_bounds(self, year):

def simplify_towards_2000(self, random, value):
value = self.reify(value)
s = {value}
s = set((value,))
s.add(value.replace(microsecond=0))
s.add(value.replace(second=0))
s.add(value.replace(minute=0))
Expand Down
Expand Up @@ -72,8 +72,7 @@ def test_custom_field(self, x):
assert x.customish == "a"

def test_mandatory_fields_are_mandatory(self):
with self.assertRaises(InvalidArgument):
models(Store)
self.assertRaises(InvalidArgument, models, Store)


class TestsNeedingRollback(TransactionTestCase):
Expand Down
13 changes: 7 additions & 6 deletions scripts/basic-test.sh
Expand Up @@ -6,7 +6,7 @@ import os
for k, v in sorted(dict(os.environ).items()):
print("%s=%s" % (k, v))
'
python -u -m pytest tests
python -u setup.py test

for extra in datetime fakefactory pytest ; do
pip install --upgrade hypothesis-extra/hypothesis-$extra/
Expand All @@ -21,9 +21,10 @@ if [ "$(python -c 'import platform; print(platform.python_implementation())')" !
python -u -m pytest hypothesis-extra/hypothesis-numpy/tests --durations=20
fi

pip install --upgrade hypothesis-extra/hypothesis-django/

pushd hypothesis-extra/hypothesis-django
python -u manage.py test
popd
if [ "$(python -c 'import sys; print(sys.version_info <= (2, 6))')" ] ; then
pip install --upgrade hypothesis-extra/hypothesis-django/
pushd hypothesis-extra/hypothesis-django
python -u manage.py test
popd
fi

3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -60,6 +60,7 @@ def run_tests(self):
license='MPL v2',
description='A library for property based testing',
zip_safe=False,
install_requires=['importlib', 'ordereddict'],
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
Expand All @@ -78,6 +79,6 @@ def run_tests(self):
],
long_description=open(README).read(),
tests_require=[
'pytest', 'flake8'],
'pytest', 'flake8', 'Counter'],
cmdclass={'test': PyTest},
)
4 changes: 2 additions & 2 deletions src/hypothesis/core.py
Expand Up @@ -466,8 +466,8 @@ def convert_to_specifier(v):

given_specifier = sd.tuples(
sd.tuples(*map(convert_to_specifier, arguments)),
sd.fixed_dictionaries({
k: convert_to_specifier(v) for k, v in kwargs.items()})
sd.fixed_dictionaries(dict(
(k, convert_to_specifier(v)) for (k, v) in kwargs.items()))
)

search_strategy = strategy(given_specifier, settings)
Expand Down
6 changes: 5 additions & 1 deletion src/hypothesis/searchstrategy/collections.py
Expand Up @@ -18,7 +18,11 @@
unicode_literals

from random import Random
from collections import OrderedDict, namedtuple
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
from collections import namedtuple

import hypothesis.internal.distributions as dist
from hypothesis.settings import Settings
Expand Down
2 changes: 1 addition & 1 deletion src/hypothesis/searchstrategy/numbers.py
Expand Up @@ -361,7 +361,7 @@ def from_basic(self, value):
return (
struct.unpack(b'!d', struct.pack(b'!Q', value))[0]
)
except (struct.error, ValueError, OverflowError) as e:
except (struct.error, ValueError, OverflowError, TypeError) as e:
raise BadData(e.args[0])

def reify(self, value):
Expand Down
14 changes: 12 additions & 2 deletions src/hypothesis/settings.py
Expand Up @@ -26,7 +26,6 @@
import os
import inspect
import threading
from functools import total_ordering
from collections import namedtuple

from hypothesis.errors import InvalidArgument
Expand Down Expand Up @@ -345,7 +344,6 @@ def __exit__(self, *args, **kwargs):
)


@total_ordering
class Verbosity(object):

def __repr__(self):
Expand All @@ -360,12 +358,24 @@ def __eq__(self, other):
self.level == other.level
)

def __ne__(self, other):
return not self.__eq__(other)

def __hash__(self):
return self.level

def __lt__(self, other):
return self.level < other.level

def __le__(self, other):
return self.level <= other.level

def __gt__(self, other):
return self.level > other.level

def __ge__(self, other):
return self.level >= other.level

@classmethod
def by_name(cls, key):
result = getattr(cls, key, None)
Expand Down
28 changes: 25 additions & 3 deletions src/hypothesis/strategies.py
Expand Up @@ -19,7 +19,7 @@

import math
from random import Random
from decimal import Decimal
from decimal import Context, Decimal, Inexact
from fractions import Fraction

import hypothesis.specifiers as spec
Expand Down Expand Up @@ -454,11 +454,33 @@ def fractions():
)


_special_floats = {
float('inf'): Decimal('Infinity'),
float('-inf'): Decimal('-Infinity'),
}


def float_to_decimal(f):
"Convert a floating point number to a Decimal with no loss of information"
if f in _special_floats:
return _special_floats[f]
elif math.isnan(f):
return Decimal('NaN')
n, d = f.as_integer_ratio()
numerator, denominator = Decimal(n), Decimal(d)
ctx = Context(prec=60)
result = ctx.divide(numerator, denominator)
while ctx.flags[Inexact]:
ctx.flags[Inexact] = False
ctx.prec *= 2
result = ctx.divide(numerator, denominator)
return result


def decimals():
"""Generates instances of decimals.Decimal."""
from decimal import Decimal
return (
floats().map(Decimal) |
floats().map(float_to_decimal) |
fractions().map(
lambda f: Decimal(f.numerator) / f.denominator
)
Expand Down
9 changes: 3 additions & 6 deletions src/hypothesis/strategytests.py
Expand Up @@ -193,15 +193,13 @@ def test_will_give_unsatisfiable_if_all_rejected(self):
@given(specifier, settings=settings)
def nope(x):
assume(False)
with self.assertRaises(Unsatisfiable):
nope()
self.assertRaises(Unsatisfiable, nope)

def test_will_find_a_constant_failure(self):
@given(specifier, settings=settings)
def nope(x):
raise Rejected()
with self.assertRaises(Rejected):
nope()
self.assertRaises(Rejected, nope)

def test_will_find_a_failure_from_the_database(self):
db = ExampleDatabase()
Expand All @@ -211,8 +209,7 @@ def nope(x):
raise Rejected()
try:
for i in hrange(3):
with self.assertRaises(Rejected):
nope() # pragma: no branch
self.assertRaises(Rejected, nope) # pragma: no cover
finally:
db.close()

Expand Down
2 changes: 1 addition & 1 deletion tests/cover/test_converter.py
Expand Up @@ -27,7 +27,7 @@

@pytest.mark.parametrize(('specifier', 'data'), [
(sets(text()), 0j),
(complex_numbers(), {'hi'}),
(complex_numbers(), set('hi')),
(lists(sets(booleans())), 0),
(just(1), 'hi'),
(binary(), 0.0),
Expand Down
2 changes: 1 addition & 1 deletion tests/cover/test_deprecated_api.py
Expand Up @@ -159,7 +159,7 @@ def test_float_ranges(r):

def test_strings():
x = strategy(s.strings('a')).example()
assert set(x).issubset({'a'})
assert set(x).issubset(set('a'))


def test_empty_strings():
Expand Down
3 changes: 1 addition & 2 deletions tests/cover/test_direct_strategies.py
Expand Up @@ -18,7 +18,6 @@
unicode_literals

import math
from decimal import Decimal

import pytest
import hypothesis.strategies as ds
Expand Down Expand Up @@ -211,7 +210,7 @@ def test_decimals():


def test_non_float_decimal():
find(ds.decimals(), lambda d: Decimal(float(d)) != d)
find(ds.decimals(), lambda d: ds.float_to_decimal(float(d)) != d)


def test_validates_min_size_for_sets():
Expand Down
2 changes: 1 addition & 1 deletion tests/cover/test_explicit_examples.py
Expand Up @@ -112,7 +112,7 @@ def test_not_long_str(x):
seen.append(x)

test_not_long_str()
assert set(seen[:2]) == {long_str, short_str}
assert set(seen[:2]) == set((long_str, short_str))


@pytest.mark.parametrize(('x', 'y'), [(1, False), (2, True)])
Expand Down
8 changes: 6 additions & 2 deletions tests/cover/test_nice_string.py
Expand Up @@ -19,6 +19,8 @@
from __future__ import division, print_function, absolute_import, \
unicode_literals

import pytest
import sys
import unittest
from collections import namedtuple

Expand All @@ -45,6 +47,7 @@ def test_show_for_nasty_complex():
complex(float('inf'), 0.0)) == "complex('inf+0j')"


@pytest.mark.skipif(sys.version_info < (2,7), reason='complex is picky in python 2.6')
def test_show_for_nasty_in_just():
assert show(
specifiers.just(complex('inf+1.9j'))
Expand Down Expand Up @@ -81,6 +84,7 @@ def test_uses_show_inside_unnamed_tuples():
assert show((1, float('nan'))) == "(1, float('nan'))"


@pytest.mark.skipif(sys.version_info < (2,7), reason='complex is picky in python 2.6')
def test_does_not_strip_brackets_when_not_present():
assert show(complex('nanj')) == "complex('nanj')"

Expand Down Expand Up @@ -142,11 +146,11 @@ def test_list_str_is_repr():


def test_set_str_is_sorted_repr():
assert show({4, 3, 2, 1}) == '{1, 2, 3, 4}'
assert show(set((4, 3, 2, 1))) == '{1, 2, 3, 4}'


def test_frozenset_str_is_sorted_repr():
assert show(frozenset({4, 3, 2, 1})) == 'frozenset({1, 2, 3, 4})'
assert show(frozenset(set((4, 3, 2, 1)))) == 'frozenset({1, 2, 3, 4})'


def test_dict_str_is_sorted_repr():
Expand Down
6 changes: 2 additions & 4 deletions tests/cover/test_numerics.py
Expand Up @@ -17,18 +17,16 @@
from __future__ import division, print_function, absolute_import, \
unicode_literals

from decimal import Decimal

from hypothesis import given, assume
from tests.common.utils import fails
from hypothesis.strategies import decimals, fractions
from hypothesis.strategies import decimals, fractions, float_to_decimal


@fails
@given(decimals())
def test_all_decimals_can_be_exact_floats(x):
assume(x.is_finite())
assert Decimal(float(x)) == x
assert float_to_decimal(float(x)) == x


@given(fractions(), fractions(), fractions())
Expand Down
8 changes: 6 additions & 2 deletions tests/cover/test_simple_collections.py
Expand Up @@ -19,7 +19,11 @@

from random import Random
from itertools import islice
from collections import OrderedDict, namedtuple
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
from collections import namedtuple

import pytest
from hypothesis import Settings, find, given, strategy
Expand Down Expand Up @@ -120,7 +124,7 @@ def test_minimize_list_of_sets():
assert find(
lists(sets(booleans())),
lambda x: len(list(filter(None, x))) >= 3) == (
[{False}] * 3
[set((False,))] * 3
)


Expand Down
6 changes: 3 additions & 3 deletions tests/cover/test_simple_numbers.py
Expand Up @@ -148,9 +148,9 @@ def test_list_of_fractional_float():
assert set(find(
lists(floats()), lambda x: len([t for t in x if t >= 1.5]) >= 10
)) in (
{1.5},
{1.5, 2.0},
{2.0},
set((1.5,)),
set((1.5, 2.0)),
set((2.0,)),
)


Expand Down
2 changes: 1 addition & 1 deletion tests/cover/test_streams.py
Expand Up @@ -125,7 +125,7 @@ def test_template_equality():
t5 = StreamTemplate(t.seed, t.parameter_seed + 1, Stream(t.stream))
assert t2 != t5

assert len({t, t2, t3, t4, t5}) == 4
assert len(set((t, t2, t3, t4, t5))) == 4


def test_streams_copy_as_self():
Expand Down
2 changes: 1 addition & 1 deletion tests/cover/test_testdecorators.py
Expand Up @@ -455,7 +455,7 @@ def test_fails_in_reify(x):

@given(text('a'))
def test_a_text(x):
assert set(x).issubset({'a'})
assert set(x).issubset(set('a'))


@given(text(''))
Expand Down
2 changes: 1 addition & 1 deletion tests/cover/test_tracker.py
Expand Up @@ -64,7 +64,7 @@ def test_track_dict():

def test_nested_unhashables():
t = Tracker()
x = {'foo': [1, 2, {3, 4, 5, 6}], 'bar': 10}
x = {'foo': [1, 2, set((3, 4, 5, 6))], 'bar': 10}
assert t.track(x) == 1
assert t.track(x) == 2

Expand Down
6 changes: 5 additions & 1 deletion tests/nocover/test_descriptortests.py
Expand Up @@ -18,7 +18,11 @@
unicode_literals

from random import Random
from collections import OrderedDict, namedtuple
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
from collections import namedtuple

from hypothesis import Settings, strategy
from tests.common.basic import Bitfields, BoringBitfields, \
Expand Down

0 comments on commit a09ca5f

Please sign in to comment.