123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- from __future__ import absolute_import, unicode_literals
- from datetime import datetime, timedelta, tzinfo
- import pytest
- import pytz
- from case import Mock, patch
- from pytz import AmbiguousTimeError
- from celery.utils.iso8601 import parse_iso8601
- from celery.utils.time import (LocalTimezone, delta_resolution, ffwd,
- get_exponential_backoff_interval,
- humanize_seconds, localize, make_aware,
- maybe_iso8601, maybe_make_aware,
- maybe_timedelta, rate, remaining, timezone,
- utcoffset)
- class test_LocalTimezone:
- def test_daylight(self, patching):
- time = patching('celery.utils.time._time')
- time.timezone = 3600
- time.daylight = False
- x = LocalTimezone()
- assert x.STDOFFSET == timedelta(seconds=-3600)
- assert x.DSTOFFSET == x.STDOFFSET
- time.daylight = True
- time.altzone = 3600
- y = LocalTimezone()
- assert y.STDOFFSET == timedelta(seconds=-3600)
- assert y.DSTOFFSET == timedelta(seconds=-3600)
- assert repr(y)
- y._isdst = Mock()
- y._isdst.return_value = True
- assert y.utcoffset(datetime.now())
- assert not y.dst(datetime.now())
- y._isdst.return_value = False
- assert y.utcoffset(datetime.now())
- assert not y.dst(datetime.now())
- assert y.tzname(datetime.now())
- class test_iso8601:
- def test_parse_with_timezone(self):
- d = datetime.utcnow().replace(tzinfo=pytz.utc)
- assert parse_iso8601(d.isoformat()) == d
- # 2013-06-07T20:12:51.775877+00:00
- iso = d.isoformat()
- iso1 = iso.replace('+00:00', '-01:00')
- d1 = parse_iso8601(iso1)
- assert d1.tzinfo._minutes == -60
- iso2 = iso.replace('+00:00', '+01:00')
- d2 = parse_iso8601(iso2)
- assert d2.tzinfo._minutes == +60
- iso3 = iso.replace('+00:00', 'Z')
- d3 = parse_iso8601(iso3)
- assert d3.tzinfo == pytz.UTC
- @pytest.mark.parametrize('delta,expected', [
- (timedelta(days=2), datetime(2010, 3, 30, 0, 0)),
- (timedelta(hours=2), datetime(2010, 3, 30, 11, 0)),
- (timedelta(minutes=2), datetime(2010, 3, 30, 11, 50)),
- (timedelta(seconds=2), None),
- ])
- def test_delta_resolution(delta, expected):
- dt = datetime(2010, 3, 30, 11, 50, 58, 41065)
- assert delta_resolution(dt, delta) == expected or dt
- @pytest.mark.parametrize('seconds,expected', [
- (4 * 60 * 60 * 24, '4.00 days'),
- (1 * 60 * 60 * 24, '1.00 day'),
- (4 * 60 * 60, '4.00 hours'),
- (1 * 60 * 60, '1.00 hour'),
- (4 * 60, '4.00 minutes'),
- (1 * 60, '1.00 minute'),
- (4, '4.00 seconds'),
- (1, '1.00 second'),
- (4.3567631221, '4.36 seconds'),
- (0, 'now'),
- ])
- def test_humanize_seconds(seconds, expected):
- assert humanize_seconds(seconds) == expected
- def test_humanize_seconds__prefix():
- assert humanize_seconds(4, prefix='about ') == 'about 4.00 seconds'
- def test_maybe_iso8601_datetime():
- now = datetime.now()
- assert maybe_iso8601(now) is now
- @pytest.mark.parametrize('arg,expected', [
- (30, timedelta(seconds=30)),
- (30.6, timedelta(seconds=30.6)),
- (timedelta(days=2), timedelta(days=2)),
- ])
- def test_maybe_timedelta(arg, expected):
- assert maybe_timedelta(arg) == expected
- def test_remaining_relative():
- remaining(datetime.utcnow(), timedelta(hours=1), relative=True)
- class test_timezone:
- def test_get_timezone_with_pytz(self):
- assert timezone.get_timezone('UTC')
- def test_tz_or_local(self):
- assert timezone.tz_or_local() == timezone.local
- assert timezone.tz_or_local(timezone.utc)
- def test_to_local(self):
- assert timezone.to_local(make_aware(datetime.utcnow(), timezone.utc))
- assert timezone.to_local(datetime.utcnow())
- def test_to_local_fallback(self):
- assert timezone.to_local_fallback(
- make_aware(datetime.utcnow(), timezone.utc))
- assert timezone.to_local_fallback(datetime.utcnow())
- class test_make_aware:
- def test_tz_without_localize(self):
- tz = tzinfo()
- assert not hasattr(tz, 'localize')
- wtz = make_aware(datetime.utcnow(), tz)
- assert wtz.tzinfo == tz
- def test_when_has_localize(self):
- class tzz(tzinfo):
- raises = False
- def localize(self, dt, is_dst=None):
- self.localized = True
- if self.raises and is_dst is None:
- self.raised = True
- raise AmbiguousTimeError()
- return 1 # needed by min() in Python 3 (None not hashable)
- tz = tzz()
- make_aware(datetime.utcnow(), tz)
- assert tz.localized
- tz2 = tzz()
- tz2.raises = True
- make_aware(datetime.utcnow(), tz2)
- assert tz2.localized
- assert tz2.raised
- def test_maybe_make_aware(self):
- aware = datetime.utcnow().replace(tzinfo=timezone.utc)
- assert maybe_make_aware(aware)
- naive = datetime.utcnow()
- assert maybe_make_aware(naive)
- assert maybe_make_aware(naive).tzinfo is pytz.utc
- tz = pytz.timezone('US/Eastern')
- eastern = datetime.utcnow().replace(tzinfo=tz)
- assert maybe_make_aware(eastern).tzinfo is tz
- utcnow = datetime.utcnow()
- assert maybe_make_aware(utcnow, 'UTC').tzinfo is pytz.utc
- class test_localize:
- def test_tz_without_normalize(self):
- class tzz(tzinfo):
- def utcoffset(self, dt):
- return None # Mock no utcoffset specified
- tz = tzz()
- assert not hasattr(tz, 'normalize')
- assert localize(make_aware(datetime.utcnow(), tz), tz)
- def test_when_has_normalize(self):
- class tzz(tzinfo):
- raises = None
- def utcoffset(self, dt):
- return None
- def normalize(self, dt, **kwargs):
- self.normalized = True
- if self.raises and kwargs and kwargs.get('is_dst') is None:
- self.raised = True
- raise self.raises
- return 1 # needed by min() in Python 3 (None not hashable)
- tz = tzz()
- localize(make_aware(datetime.utcnow(), tz), tz)
- assert tz.normalized
- tz2 = tzz()
- tz2.raises = AmbiguousTimeError()
- localize(make_aware(datetime.utcnow(), tz2), tz2)
- assert tz2.normalized
- assert tz2.raised
- tz3 = tzz()
- tz3.raises = TypeError()
- localize(make_aware(datetime.utcnow(), tz3), tz3)
- assert tz3.normalized
- assert tz3.raised
- def test_localize_changes_utc_dt(self):
- now_utc_time = datetime.now(tz=pytz.utc)
- local_tz = pytz.timezone('US/Eastern')
- localized_time = localize(now_utc_time, local_tz)
- assert localized_time == now_utc_time
- def test_localize_aware_dt_idempotent(self):
- t = (2017, 4, 23, 21, 36, 59, 0)
- local_zone = pytz.timezone('America/New_York')
- local_time = datetime(*t)
- local_time_aware = datetime(*t, tzinfo=local_zone)
- alternate_zone = pytz.timezone('America/Detroit')
- localized_time = localize(local_time_aware, alternate_zone)
- assert localized_time == local_time_aware
- assert local_zone.utcoffset(
- local_time) == alternate_zone.utcoffset(local_time)
- localized_utc_offset = localized_time.tzinfo.utcoffset(local_time)
- assert localized_utc_offset == alternate_zone.utcoffset(local_time)
- assert localized_utc_offset == local_zone.utcoffset(local_time)
- @pytest.mark.parametrize('s,expected', [
- (999, 999),
- (7.5, 7.5),
- ('2.5/s', 2.5),
- ('1456/s', 1456),
- ('100/m', 100 / 60.0),
- ('10/h', 10 / 60.0 / 60.0),
- (0, 0),
- (None, 0),
- ('0/m', 0),
- ('0/h', 0),
- ('0/s', 0),
- ('0.0/s', 0),
- ])
- def test_rate_limit_string(s, expected):
- assert rate(s) == expected
- class test_ffwd:
- def test_repr(self):
- x = ffwd(year=2012)
- assert repr(x)
- def test_radd_with_unknown_gives_NotImplemented(self):
- x = ffwd(year=2012)
- assert x.__radd__(object()) == NotImplemented
- class test_utcoffset:
- def test_utcoffset(self, patching):
- _time = patching('celery.utils.time._time')
- _time.daylight = True
- assert utcoffset(time=_time) is not None
- _time.daylight = False
- assert utcoffset(time=_time) is not None
- class test_get_exponential_backoff_interval:
- @patch('random.randrange', lambda n: n - 2)
- def test_with_jitter(self):
- assert get_exponential_backoff_interval(
- factor=4,
- retries=3,
- maximum=100,
- full_jitter=True
- ) == 4 * (2 ** 3) - 1
- def test_without_jitter(self):
- assert get_exponential_backoff_interval(
- factor=4,
- retries=3,
- maximum=100,
- full_jitter=False
- ) == 4 * (2 ** 3)
- def test_bound_by_maximum(self):
- maximum_boundary = 100
- assert get_exponential_backoff_interval(
- factor=40,
- retries=3,
- maximum=maximum_boundary
- ) == maximum_boundary
- @patch('random.randrange', lambda n: n - 1)
- def test_negative_values(self):
- assert get_exponential_backoff_interval(
- factor=-40,
- retries=3,
- maximum=100
- ) == 0
|