Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dates() and datetimes() support #46

Merged
merged 2 commits into from
Apr 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)