Custom range types¶
The built in range types may not suffice for your particular application. It is very easy to extend with your own classes. The only requirement is that the type supports rich comparison PEP 207 and is immutable.
Standard range types¶
A normal range can be implemented by extending spans.types.Range
.
from spans.types import Range
class floatrange(Range):
__slots__ = ()
type = float
span = floatrange(1.0, 5.0)
assert span.lower == 1.0
assert span.upper == 5.0
Note
The __slots__ = ()
is a performance optimization that is used for all ranges. It lowers the memory footprint for every instance. It is not mandatory but encourgaged.
Offsetable range types¶
An offsetable range can be implemented using the mixin spans.types.OffsetableRangeMixin
. The class still needs to extend spans.types.Range
.
from spans.types import Range, OffsetableRangeMixin
class floatrange(Range, OffsetableRangeMixin):
__slots__ = ()
type = float
If the offset type is not the same as the range type (such as date
that is offsetable with timedelta
) the attribute offset_type
can be used.
from spans.types import DiscreteRange, OffsetableRangeMixin
from datetime import date, timedelta
class daterange(DiscreteRange, OffsetableRangeMixin):
__slots__ = ()
type = date
offset_type = timedelta
span = daterange(date(2000, 1, 1), date(2000, 2, 1))
assert span.offset(timedelta(14)).upper == date(2000, 2, 15)
Discrete range types¶
Discrete ranges (such as intrange
and daterange
) can be implemented by extending spans.types.DiscreteRange
.
from spans.types import DiscreteRange, OffsetableRangeMixin
class intrange(DiscreteRange, OffsetableRangeMixin):
__slots__ = ()
type = intrange
step = 1
assert list(intrange(1, 5)) == [1, 2, 3, 4]
Note the step
attribute. It must always be the smallest possible unit. Using 2
for intranges would not have expected behavior.
Range sets¶
Range sets are conveinient to implement regardless of the mixins used. This is due to the metaclass spans.settypes.MetaRangeSet
. The metaclass automatically adds required mixins to the range set type.
from spans.types import intrange
from spans.settypes import RangeSet
class intrangeset(RangeSet):
__slots__ = ()
type = intrange
assert intrangeset(
[intrange(1, 5), intrange(10, 15)]).span() == intrange(1, 15)
Custom mixins¶
It is possible to create custom mixins for range sets by adding mappings to spans.settypes.MetaRangeSet
. The mapping has to be added before the range set class is created or it will not be used.