Skip to content

Commit

Permalink
Merge pull request #46 from szykin/feature/query_dates_datetimes
Browse files Browse the repository at this point in the history
dates() and datetimes() support
  • Loading branch information
stphivos authored Apr 8, 2017
2 parents 9cda39e + 35b107a commit cb99ca1
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ $ git push -u origin HEAD

* Add docs as a service like readthedocs with examples for every feature
* Add support for missing QuerySet methods/Field lookups/Aggregation functions:
* Methods that return new QuerySets: annotate, reverse, dates, datetimes, none, extra, raw
* Methods that return new QuerySets: annotate, reverse, none, extra, raw

* Methods that do not return QuerySets: update_or_create, bulk_create, in_bulk, update, delete, as_manager

Expand Down
35 changes: 34 additions & 1 deletion django_mock_queries/query.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import datetime
from mock import Mock, MagicMock, PropertyMock
from operator import attrgetter

from .constants import *
from .exceptions import *
from .utils import matches, merge, intersect, get_attribute, validate_mock_set, is_list_like_iter, flatten_list
from .utils import (
matches, merge, intersect, get_attribute, validate_mock_set, is_list_like_iter, flatten_list, truncate
)


class MockBase(MagicMock):
Expand Down Expand Up @@ -294,6 +297,36 @@ def values_list(*fields, **kwargs):

mock_set.values_list = MagicMock(side_effect=values_list)

def dates(field, kind, order='ASC'):
assert kind in ("year", "month", "day"), "'kind' must be one of 'year', 'month' or 'day'."
assert order in ('ASC', 'DESC'), "'order' must be either 'ASC' or 'DESC'."

initial_values = list(values_list(field, flat=True))

return MockSet(*sorted(
{truncate(x, kind) for x in initial_values},
key=lambda y: datetime.date.timetuple(y)[:3],
reverse=True if order == 'DESC' else False
), clone=mock_set)

mock_set.dates = MagicMock(side_effect=dates)

def datetimes(field, kind, order='ASC'):
# TODO: Handle `tzinfo` parameter
assert kind in ("year", "month", "day", "hour", "minute", "second"), \
"'kind' must be one of 'year', 'month', 'day', 'hour', 'minute' or 'second'."
assert order in ('ASC', 'DESC'), "'order' must be either 'ASC' or 'DESC'."

initial_values = list(values_list(field, flat=True))

return MockSet(*sorted(
{truncate(x, kind) for x in initial_values},
key=lambda y: datetime.datetime.timetuple(y)[:6],
reverse=True if order == 'DESC' else False
), clone=mock_set)

mock_set.datetimes = MagicMock(side_effect=datetimes)

return mock_set


Expand Down
20 changes: 20 additions & 0 deletions django_mock_queries/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,23 @@ def flatten_list(source):
else:
target.extend(flatten_list(x))
return target


def truncate(obj, kind):
trunc_mapping = None
if isinstance(obj, date):
trunc_mapping = {
'year': obj.replace(month=1, day=1),
'month': obj.replace(day=1),
'day': obj
}
if isinstance(obj, datetime):
trunc_mapping = {
'year': obj.replace(month=1, day=1, hour=0, minute=0, second=0),
'month': obj.replace(day=1, hour=0, minute=0, second=0),
'day': obj.replace(hour=0, minute=0, second=0),
'hour': obj.replace(minute=0, second=0),
'minute': obj.replace(second=0),
'second': obj
}
return trunc_mapping[kind]
189 changes: 189 additions & 0 deletions tests/test_query.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import datetime

from mock import MagicMock, ANY
from unittest import TestCase

Expand Down Expand Up @@ -745,3 +747,190 @@ def test_create_model_raises_value_error_with_zero_arguments(self):
def test_query_model_repr_returns_mock_name(self):
model = MockModel(mock_name='model_name')
assert repr(model) == model.mock_name

def test_query_dates_year(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.date(2017, 1, 2))
item2 = MockModel(date_begin=datetime.date(2017, 3, 12))
item3 = MockModel(date_begin=datetime.date(2016, 3, 4))

qs.add(item1, item2, item3)

result = qs.dates('date_begin', 'year', 'ASC')

assert len(result) == 2
assert result[0] == datetime.date(2016, 1, 1)
assert result[1] == datetime.date(2017, 1, 1)

result = qs.dates('date_begin', 'year', 'DESC')

assert len(result) == 2
assert result[0] == datetime.date(2017, 1, 1)
assert result[1] == datetime.date(2016, 1, 1)

def test_query_dates_month(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.date(2017, 1, 2))
item2 = MockModel(date_begin=datetime.date(2017, 1, 19))
item3 = MockModel(date_begin=datetime.date(2017, 2, 4))
qs.add(item1, item2, item3)

result = qs.dates('date_begin', 'month', 'ASC')

assert len(result) == 2
assert result[0] == datetime.date(2017, 1, 1)
assert result[1] == datetime.date(2017, 2, 1)

result = qs.dates('date_begin', 'month', 'DESC')

assert len(result) == 2
assert result[0] == datetime.date(2017, 2, 1)
assert result[1] == datetime.date(2017, 1, 1)

def test_query_dates_day(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.date(2017, 1, 2))
item2 = MockModel(date_begin=datetime.date(2017, 2, 14))
item3 = MockModel(date_begin=datetime.date(2017, 2, 14))

qs.add(item1, item2, item3)

result = qs.dates('date_begin', 'day', 'ASC')

assert len(result) == 2
assert result[0] == datetime.date(2017, 1, 2)
assert result[1] == datetime.date(2017, 2, 14)

result = qs.dates('date_begin', 'day', 'DESC')

assert len(result) == 2
assert result[0] == datetime.date(2017, 2, 14)
assert result[1] == datetime.date(2017, 1, 2)

def test_query_datetimes_year(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.datetime(2017, 1, 2, 1, 2, 3))
item2 = MockModel(date_begin=datetime.datetime(2017, 3, 12, 4, 5, 6))
item3 = MockModel(date_begin=datetime.datetime(2016, 3, 4, 7, 8, 9))

qs.add(item1, item2, item3)

result = qs.datetimes('date_begin', 'year', 'ASC')

assert len(result) == 2
assert result[0] == datetime.datetime(2016, 1, 1, 0, 0, 0)
assert result[1] == datetime.datetime(2017, 1, 1, 0, 0, 0)

result = qs.datetimes('date_begin', 'year', 'DESC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 1, 0, 0, 0)
assert result[1] == datetime.datetime(2016, 1, 1, 0, 0, 0)

def test_query_datetimes_month(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.datetime(2017, 1, 2, 1, 2, 3))
item2 = MockModel(date_begin=datetime.datetime(2017, 1, 19, 4, 5, 6))
item3 = MockModel(date_begin=datetime.datetime(2017, 2, 4, 7, 8, 9))
qs.add(item1, item2, item3)

result = qs.datetimes('date_begin', 'month', 'ASC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 1, 0, 0, 0)
assert result[1] == datetime.datetime(2017, 2, 1, 0, 0, 0)

result = qs.datetimes('date_begin', 'month', 'DESC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 2, 1, 0, 0, 0)
assert result[1] == datetime.datetime(2017, 1, 1, 0, 0, 0)

def test_query_datetimes_day(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.datetime(2017, 1, 2, 1, 2, 3))
item2 = MockModel(date_begin=datetime.datetime(2017, 2, 14, 4, 5, 6))
item3 = MockModel(date_begin=datetime.datetime(2017, 2, 14, 7, 8, 9))

qs.add(item1, item2, item3)

result = qs.datetimes('date_begin', 'day', 'ASC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 2, 0, 0, 0)
assert result[1] == datetime.datetime(2017, 2, 14, 0, 0, 0)

result = qs.datetimes('date_begin', 'day', 'DESC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 2, 14, 0, 0, 0)
assert result[1] == datetime.datetime(2017, 1, 2, 0, 0, 0)

def test_query_datetimes_hour(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 2, 3))
item2 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 5, 6))
item3 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 2, 8, 9))

qs.add(item1, item2, item3)

result = qs.datetimes('date_begin', 'hour', 'ASC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 10, 1, 0, 0)
assert result[1] == datetime.datetime(2017, 1, 10, 2, 0, 0)

result = qs.datetimes('date_begin', 'hour', 'DESC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 10, 2, 0, 0)
assert result[1] == datetime.datetime(2017, 1, 10, 1, 0, 0)

def test_query_datetimes_minute(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 2, 3))
item2 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 2, 6))
item3 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 3, 9))

qs.add(item1, item2, item3)

result = qs.datetimes('date_begin', 'minute', 'ASC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 10, 1, 2, 0)
assert result[1] == datetime.datetime(2017, 1, 10, 1, 3, 0)

result = qs.datetimes('date_begin', 'minute', 'DESC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 10, 1, 3, 0)
assert result[1] == datetime.datetime(2017, 1, 10, 1, 2, 0)

def test_query_datetimes_second(self):
qs = MockSet(model=create_model('date_begin'))

item1 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 2, 3))
item2 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 2, 3))
item3 = MockModel(date_begin=datetime.datetime(2017, 1, 10, 1, 2, 9))

qs.add(item1, item2, item3)

result = qs.datetimes('date_begin', 'second', 'ASC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 10, 1, 2, 3)
assert result[1] == datetime.datetime(2017, 1, 10, 1, 2, 9)

result = qs.datetimes('date_begin', 'second', 'DESC')

assert len(result) == 2
assert result[0] == datetime.datetime(2017, 1, 10, 1, 2, 9)
assert result[1] == datetime.datetime(2017, 1, 10, 1, 2, 3)

0 comments on commit cb99ca1

Please sign in to comment.