Skip to content

Commit

Permalink
Add DateTime index in contrib
Browse files Browse the repository at this point in the history
  • Loading branch information
twidi committed Jan 26, 2018
1 parent 7b314cc commit e1f4cde
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 2 deletions.
44 changes: 43 additions & 1 deletion limpyd/contrib/indexes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
from __future__ import unicode_literals

from limpyd.indexes import BaseIndex
from limpyd.indexes import BaseIndex, NumberRangeIndex, TextRangeIndex
from limpyd.utils import cached_property


Expand Down Expand Up @@ -208,3 +208,45 @@ def get_filtered_keys(self, suffix, *args, **kwargs):
for index in self._indexes:
if index.can_handle_suffix(suffix):
return index.get_filtered_keys(suffix, *args, **kwargs)


# This is a multi-indexes managing the different parts of a date in the format YYYY-MM-SS
DateIndexParts = MultiIndexes.compose([
NumberRangeIndex.configure(prefix='year', transform=lambda value: value[:4], handle_uniqueness=False, name='YearIndex'),
NumberRangeIndex.configure(prefix='month', transform=lambda value: value[5:7], handle_uniqueness=False, name='MonthIndex'),
NumberRangeIndex.configure(prefix='day', transform=lambda value: value[8:10], handle_uniqueness=False, name='DayIndex'),
], name='DateIndexParts')

# A simple TextRangeIndex to filter on a date in the format YYYY-MM-SS
DateRangeIndex = TextRangeIndex.configure(key='date', transform=lambda value: value[:10], name='DateRangeIndex')

# A full usable index for fields holding dates (without time)
DateIndex = MultiIndexes.compose([DateRangeIndex, DateIndexParts], name='DateIndex')

# This is a multi-indexes managing the different parts of a tine in the format HH:MM:SS
TimeIndexParts = MultiIndexes.compose([
NumberRangeIndex.configure(prefix='hour', transform=lambda value: value[0:2], handle_uniqueness=False, name='HourIndex'),
NumberRangeIndex.configure(prefix='minute', transform=lambda value: value[3:5], handle_uniqueness=False, name='MinuteIndex'),
NumberRangeIndex.configure(prefix='second', transform=lambda value: value[6:8], handle_uniqueness=False, name='SecondIndex'),
], name='TimeIndexParts')

# A simple TextRangeIndex to filter on a date in the format HH:MM:SS
TimeRangeIndex = TextRangeIndex.configure(key='time', transform=lambda value: value[:8], name='TimeRangeIndex')

# A full usable index for fields holding times (without date)
TimeIndex = MultiIndexes.compose([TimeRangeIndex, TimeIndexParts], name='TimeIndex')

# A full usable index for fields holding dates+times, without filtering on hour/min/sec
# but only full field, full date and full time, and year, month, day
DateSimpleTimeIndex = MultiIndexes.compose([
TextRangeIndex.configure(key='full', name='FullDateTimeRangeIndex'),
DateRangeIndex.configure(prefix='date'),
DateIndexParts,
TimeRangeIndex.configure(prefix='time', transform=lambda value: value[11:]) # pass only time
], name='DateSimpleTimeIndex', transform=lambda value: value[:19])

# A full usable index for fields holding dates+times, with full filtering capabilities
DateTimeIndex = MultiIndexes.compose([
DateSimpleTimeIndex,
TimeIndexParts.configure(transform=lambda value: value[11:]),
], name='DateTimeIndex')
207 changes: 206 additions & 1 deletion tests/contrib/indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import unicode_literals

from limpyd import fields
from limpyd.contrib.indexes import MultiIndexes
from limpyd.contrib.indexes import MultiIndexes, DateIndex, DateTimeIndex, TimeIndex
from limpyd.exceptions import ImplementationError, UniquenessError
from limpyd.indexes import BaseIndex, NumberRangeIndex, TextRangeIndex, EqualIndex

Expand Down Expand Up @@ -166,3 +166,208 @@ class MultiIndexTestModel(TestRedisModel):
set(MultiIndexTestModel.collection(name__first_letter='b', name='bar')),
{pk2}
)


class DateTimeModelTest(TestRedisModel):
date = fields.InstanceHashField(indexable=True, indexes=[DateIndex])
unique_date = fields.InstanceHashField(indexable=True, indexes=[DateIndex], unique=True)
time = fields.InstanceHashField(indexable=True, indexes=[TimeIndex])
unique_time = fields.InstanceHashField(indexable=True, indexes=[TimeIndex], unique=True)
datetime = fields.InstanceHashField(indexable=True, indexes=[DateTimeIndex])
unique_datetime = fields.InstanceHashField(indexable=True, indexes=[DateTimeIndex], unique=True)


class DateTimeIndexesTestCase(LimpydBaseTest):

def test_date_index(self):
obj1 = DateTimeModelTest(date='2015-12-16')
pk1 = obj1.pk.get()
obj2 = DateTimeModelTest(date='2014-09-07')
pk2 = obj2.pk.get()
obj3 = DateTimeModelTest(date='2015-06-12')
pk3 = obj3.pk.get()
obj4 = DateTimeModelTest(date='2016-12-31')
pk4 = obj4.pk.get()

# not unique so same date is ok
obj5 = DateTimeModelTest(date='2015-12-16')
pk5 = obj5.pk.get()

# EqualIndex
self.assertSetEqual(
set(DateTimeModelTest.collection(date='2015-12-16')),
{pk1, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(date__gte='2015-06-12')),
{pk1, pk3, pk4, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(date__gt='2015')),
{pk1, pk3, pk4, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(date__lt='2015-07')),
{pk2, pk3}
)

# year index
self.assertSetEqual(
set(DateTimeModelTest.collection(date__year=2015)),
{pk1, pk3, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(date__year__lt=2015)),
{pk2}
)

# month index
self.assertSetEqual(
set(DateTimeModelTest.collection(date__month=12)),
{pk1, pk4, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(date__year=2015, date__month=12)),
{pk1, pk5}
)

def test_date_unique_index(self):
DateTimeModelTest(unique_date='2001-01-01')
# can add on same year (diff month/day)
DateTimeModelTest(unique_date='2001-02-02')
# can add on same month (diff year/day)
DateTimeModelTest(unique_date='2002-02-03')
# can add on same day (diff year/month)
DateTimeModelTest(unique_date='2003-03-03')

# cannot add on same date
with self.assertRaises(UniquenessError):
DateTimeModelTest(unique_date='2003-03-03')

def test_time_index(self):
# constructed the same as DateIndex so only test for transforms

obj1 = DateTimeModelTest(time='15:16:17')
pk1 = obj1.pk.get()
obj2 = DateTimeModelTest(time='05:06:07')
pk2 = obj2.pk.get()

self.assertSetEqual(
set(DateTimeModelTest.collection(time__hour='15')),
{pk1}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(time__minute='06')),
{pk2}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(time__second='17')),
{pk1}
)

def test_datetime_index(self):
obj1 = DateTimeModelTest(datetime='2015-12-16 15:16:17')
pk1 = obj1.pk.get()
obj2 = DateTimeModelTest(datetime='2014-09-07 05:06:07')
pk2 = obj2.pk.get()
obj3 = DateTimeModelTest(datetime='2015-06-12 15:16:17')
pk3 = obj3.pk.get()
obj4 = DateTimeModelTest(datetime='2016-12-31 05:06:07')
pk4 = obj4.pk.get()

# not unique so same date is ok
obj5 = DateTimeModelTest(datetime='2015-12-16 15:16:17')
pk5 = obj5.pk.get()

# check full date
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime='2015-12-16 15:16:17')),
{pk1, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__gte='2015-06-12 1')),
{pk1, pk3, pk4, pk5}
)

# check date
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__date='2015-12-16')),
{pk1, pk5}
)

self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__date__lt='2015-07')),
{pk2, pk3}
)

# check year
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__year=2015)),
{pk1, pk3, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__year__lt=2015)),
{pk2}
)

# check time
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__time='15:16:17')),
{pk1, pk3, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__time__lt='15')),
{pk2, pk4}
)

# check hour
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__hour=15)),
{pk1, pk3, pk5}
)
self.assertSetEqual(
set(DateTimeModelTest.collection(datetime__hour__lt=15)),
{pk2, pk4}
)

# be crazy, check all for '2015-12-16 15:16:17'
# All are ended so it should work
self.assertSetEqual(
set(DateTimeModelTest.collection(
datetime='2015-12-16 15:16:17',
datetime__date='2015-12-16',
datetime__year=2015,
datetime__month=12,
datetime__day=16,
datetime__time='15:16:17',
datetime__hour=15,
datetime__minute=16,
datetime__second=17
)),
{pk1, pk5}
)

def test_datetime_unique_index(self):

DateTimeModelTest(unique_datetime='2001-01-01 01:01:01')
# can add on same year (diff month/day/hour/min/sec)
DateTimeModelTest(unique_datetime='2001-02-02 02:02:02')
# can add on same month (diff year/day/hour/min/sec)
DateTimeModelTest(unique_datetime='2002-02-03 03:03:03')
# can add on same day (diff year/month/hour/min/sec)
DateTimeModelTest(unique_datetime='2003-03-03 04:04:04')
# can add on same hour (diff year/month/day/min/sec)
DateTimeModelTest(unique_datetime='2004-04-04 04:05:05')
# can add on same minute (diff year/month/day/hour/sec)
DateTimeModelTest(unique_datetime='2005-05-05 05:05:06')
# can add on same second (diff year/month/day/hour/min)
DateTimeModelTest(unique_datetime='2006-06-06 06:06:06')

# can add on same date (diff time)
DateTimeModelTest(unique_datetime='2006-06-06 07:07:07')
# can add on same time (diff date)
DateTimeModelTest(unique_datetime='2007-07-07 07:07:07')

# but cannot add the same full datetime
with self.assertRaises(UniquenessError):
DateTimeModelTest(unique_datetime='2007-07-07 07:07:07')

0 comments on commit e1f4cde

Please sign in to comment.