diff --git a/conservancy_beancount/ranges.py b/conservancy_beancount/ranges.py new file mode 100644 index 0000000000000000000000000000000000000000..aa2348b7fe8fdf6af4e94accdaaf7b9af41ef271 --- /dev/null +++ b/conservancy_beancount/ranges.py @@ -0,0 +1,59 @@ +"""ranges.py - Higher-typed range classes""" +# Copyright © 2020 Brett Smith +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import datetime + +from decimal import Decimal + +from typing import ( + Generic, + TypeVar, + Union, +) + +RangeT = TypeVar( + 'RangeT', + # This is a relatively arbitrary set of types. Feel free to add to it if + # you need; the types just need to support enough comparisons to implement + # _GenericRange.__contains__. + datetime.date, + datetime.datetime, + datetime.time, + Union[int, Decimal], +) + +class _GenericRange(Generic[RangeT]): + """range for higher-level types + + This class knows how to check membership for higher-level types just like + Python's built-in range. It does not know how to iterate or step. + """ + def __init__(self, start: RangeT, stop: RangeT) -> None: + self.start: RangeT = start + self.stop: RangeT = stop + + def __repr__(self) -> str: + return "{clsname}({self.start!r}, {self.stop!r})".format( + clsname=type(self).__name__, + self=self, + ) + + def __contains__(self, item: RangeT) -> bool: + return self.start <= item < self.stop + + +DateRange = _GenericRange[datetime.date] +DecimalCompatRange = _GenericRange[Union[int, Decimal]]