Skip to content

Commit

Permalink
Conform datetime to the new template regime
Browse files Browse the repository at this point in the history
  • Loading branch information
DRMacIver committed Mar 18, 2015
1 parent 5297e4a commit 8410cf4
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 49 deletions.
7 changes: 4 additions & 3 deletions basic-test.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/bin/bash
set -e -o xtrace

pip install --upgrade hypothesis-extra/*/
python -m pytest --capture=no --strict tests/
python -m pytest --capture=no --strict hypothesis-extra/*/tests/
python setup.py develop
pip install --upgrade hypothesis-extra/hypothesis-datetime/
#python -m pytest --capture=no --strict tests/
python -m pytest --capture=no --strict hypothesis-extra/hypothesis-datetime/tests/
for f in hypothesis-extra/*/manage.py; do
d=$(dirname $f)
pushd $d
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import pytz
import hypothesis.internal.distributions as dist
from hypothesis.internal.compat import hrange, text_type
from hypothesis.internal.fixers import equal
from hypothesis.searchstrategy.strategies import SearchStrategy, \
strategy, check_data_type

Expand All @@ -30,11 +29,6 @@
any_datetime = DatetimeSpec({False, True})


@equal.extend(dt.datetime)
def equal_datetimes(x, y, fuzzy=False):
return (x.tzinfo == y.tzinfo) and (x == y)


def draw_day_for_month(random, year, month):
# Validate that we've not got a bad year or month
dt.datetime(year=year, month=month, day=27)
Expand Down Expand Up @@ -108,25 +102,48 @@ def produce_template(self, context, pv):
microsecond=random.randint(0, 1000000 - 1),
)
if not self.supports_timezones():
return base
return self.templateize(base)

if random.random() <= pv.utc_chance:
timezone = pytz.UTC
else:
timezone = random.choice(pv.timezones)

if not self.supports_naive():
return timezone.localize(base)
return self.templateize(timezone.localize(base))

if len(pv.naive_options) == 1:
naive = list(pv.naive_options)[0]
else:
naive = random.random() <= pv.naive_chance

if naive:
return base
return self.templateize(base)
else:
return timezone.localize(base)
return self.templateize(timezone.localize(base))

def templateize(self, dt):
return (
dt.year,
dt.month,
dt.day,
dt.hour,
dt.minute,
dt.second,
dt.microsecond,
text_type(dt.tzinfo.zone) if dt.tzinfo else None,
)

def reify(self, template):
tz = template[-1]
d = dt.datetime(
year=template[0], month=template[1], day=template[2],
hour=template[3], minute=template[4], second=template[5],
microsecond=template[6]
)
if tz:
d = pytz.timezone(tz).localize(d)
return d

def supports_timezones(self):
return False in self.naive_options
Expand All @@ -135,11 +152,13 @@ def supports_naive(self):
return True in self.naive_options

def simplify(self, value):
value = self.reify(value)
if self.supports_timezones():
if not value.tzinfo:
yield pytz.UTC.localize(value)
yield self.templateize(pytz.UTC.localize(value))
elif value.tzinfo != pytz.UTC:
yield pytz.UTC.normalize(value.astimezone(pytz.UTC))
yield self.templateize(
pytz.UTC.normalize(value.astimezone(pytz.UTC)))
s = {value}
s.add(value.replace(microsecond=0))
s.add(value.replace(second=0))
Expand All @@ -150,7 +169,7 @@ def simplify(self, value):
s.add(value.replace(year=2000))
s.remove(value)
for t in s:
yield t
yield self.templateize(t)
year = value.year
if year == 2000:
return
Expand All @@ -161,7 +180,7 @@ def simplify(self, value):
mid = (year + 2000) // 2
if mid != 2000 and mid != year:
try:
yield value.replace(year=mid)
yield self.templateize(value.replace(year=mid))
except ValueError:
pass
direction = -1 if year > 2000 else 1
Expand All @@ -170,34 +189,20 @@ def simplify(self, value):
if year == mid:
continue
try:
yield value.replace(year)
yield self.templateize(value.replace(year))
except ValueError:
pass

def to_basic(self, value):
return [
value.year, value.month, value.day,
value.hour, value.minute, value.second,
value.microsecond,
text_type(value.tzinfo.zone) if value.tzinfo else None
]
return list(value)

def from_basic(self, values):
check_data_type(list, values)
for d in values[:-1]:
check_data_type(int, d)
timezone = None
if values[-1] is not None:
check_data_type(text_type, values[-1])
timezone = pytz.timezone(values[-1])
base = dt.datetime(
year=values[0], month=values[1], day=values[2],
hour=values[3], minute=values[4], second=values[5],
microsecond=values[6]
)
if timezone is not None:
base = timezone.localize(base)
return base
return tuple(values)


@strategy.extend_static(dt.datetime)
Expand Down
20 changes: 5 additions & 15 deletions hypothesis-extra/hypothesis-datetime/tests/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,19 @@ def test_can_find_christmas():


def test_simplifies_towards_midnight():
d = falsify(lambda x: False, datetime)[0]
d = strategy(datetime).reify(falsify(lambda x: False, datetime)[0])
assert d.hour == 0
assert d.minute == 0
assert d.second == 0
assert d.microsecond == 0


def test_simplifies_towards_2000():
d = falsify(lambda x: x.year <= 2000, datetime)[0]
d = strategy(datetime).reify(
falsify(lambda x: x.year <= 2000, datetime)[0])
assert d.year == 2001
d = falsify(lambda x: x.year >= 2000, datetime)[0]
d = strategy(datetime).reify(
falsify(lambda x: x.year >= 2000, datetime)[0])
assert d.year == 1999


Expand All @@ -112,18 +114,6 @@ def test_can_generate_utc():
falsify(lambda d: assume(d.tzinfo) and d.tzinfo.zone != 'UTC', datetime)


def test_can_simplify_leap_years():
s = strategy(datetime)
d = datetime(
year=2012, month=2, day=29
)
t = list(
s.simplify_such_that(
d, lambda x: (x.month == 2) and (x.day == 29) and (x.year > 2000))
)[-1]
assert t.year == 2004


@given(naive_datetime)
def test_naive_datetimes_are_naive(dt):
assert not dt.tzinfo
Expand Down

0 comments on commit 8410cf4

Please sign in to comment.