-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add report range functions for chunking requests and diffing cache by…
… month
- Loading branch information
Showing
4 changed files
with
110 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from datetime import date | ||
from typing import Tuple | ||
from typing import NamedTuple | ||
from typing import Union | ||
from typing import Iterator | ||
from .date import DateInterval | ||
|
||
# Load Algorithm... | ||
# given a date range... | ||
# create a ReportMonth for each month in the request range | ||
# Retrieve report months from table's fetched attribute that match the requested ReportMonth | ||
# Find the date difference between each requested report range and the corresponding fetched report range | ||
# Request the report for those dates and save it into the table | ||
# Replace the fetched report month with the requested report month in table's fetched attribute | ||
|
||
Month = Tuple[int, int] | ||
|
||
|
||
class ReportMonth(NamedTuple): | ||
year: int | ||
month: int | ||
end: int = None | ||
|
||
@property | ||
def dates(self) -> DateInterval: | ||
year = self.year | ||
month = self.month | ||
end = self.end | ||
last = date(year, month, end) if end else min(date(*next_month(year, month), 1), date.today()) | ||
return date(year, month, 1), last | ||
|
||
def __hash__(self) -> int: | ||
return hash((self.year, self.month)) | ||
|
||
def __eq__(self, other) -> bool: | ||
return isinstance(other, ReportMonth) and hash(self) == hash(other) and self.end == other.end | ||
|
||
|
||
def next_month(year: int, month: int) -> Month: | ||
return (year, month + 1) if month < 12 else (year + 1, 1) | ||
|
||
|
||
def get_months(start: date, end: date) -> Iterator[Month]: | ||
current = (start.year, start.month) | ||
last = (end.year, end.month) | ||
|
||
while current <= last: | ||
yield current | ||
current = next_month(*current) | ||
|
||
|
||
def report_months(start: date, end: date) -> Iterator[ReportMonth]: | ||
return map(lambda it: ReportMonth(*it), get_months(start, end)) | ||
|
||
|
||
def report_diff(requested: ReportMonth, fetched: ReportMonth) -> Union[DateInterval, None]: | ||
assert requested.month == fetched.month, "Reports must be the same month" | ||
|
||
if requested == fetched: | ||
return None | ||
|
||
first = fetched.dates[1] | ||
second = requested.dates[1] | ||
return min(first, second), max(first, second) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
from datetime import date | ||
from unittest import TestCase | ||
|
||
from mpr.report_range import ReportMonth, next_month, report_months, get_months, report_diff | ||
|
||
|
||
class ReportRangeTest(TestCase): | ||
def test_equals(self): | ||
first = ReportMonth(2019, 1) | ||
second = ReportMonth(2019, 1) | ||
self.assertEqual(first, second) | ||
|
||
def test_not_equal(self): | ||
first = ReportMonth(2019, 1) | ||
second = ReportMonth(2019, 1, 15) | ||
self.assertEqual(hash(first), hash(second)) | ||
self.assertNotEqual(first, second) | ||
|
||
def test_next_month(self): | ||
self.assertEqual(next_month(2018, 12), (2019, 1)) | ||
self.assertEqual(next_month(2019, 1), (2019, 2)) | ||
|
||
def test_months(self): | ||
months = list(get_months(date(2018, 10, 1), date(2019, 2, 15))) | ||
self.assertEqual(months, [(2018, 10), (2018, 11), (2018, 12), (2019, 1), (2019, 2)]) | ||
|
||
def test_report_months(self): | ||
today = date.today() | ||
year = today.year | ||
month = today.month | ||
first, *_, last = report_months(date(2019, 6, 1), today) | ||
|
||
self.assertEqual(first, ReportMonth(2019, 6)) | ||
self.assertEqual(last.year, year) | ||
self.assertEqual(last.month, month) | ||
self.assertEqual(last.dates, (date(year, month, 1), today)) | ||
|
||
def test_report_diff(self): | ||
with self.assertRaises(AssertionError): | ||
report_diff(ReportMonth(2019, 1), ReportMonth(2019, 2)) | ||
|
||
self.assertIsNone(report_diff(ReportMonth(2019, 1), ReportMonth(2019, 1))) | ||
|
||
start, end = report_diff(ReportMonth(2019, 1), ReportMonth(2019, 1, 15)) | ||
self.assertEqual(start, date(2019, 1, 15)) | ||
self.assertEqual(end, date(2019, 2, 1)) |