Continuous set support for Python
Project description
Spans
Spans is a pure Python implementation of PostgreSQL’s range types [1]. Range types are conveinent when working with intervals of any kind. Every time you’ve found yourself working with date_start and date_end, an interval may have been what you were actually looking for.
Spans has successfully been used in production since its first release 30th August, 2013.
Here is an example on how to use ranges to determine if something happened in the 90s.
>>> from spans import daterange
>>> from datetime import date
>>> the90s = daterange(date(1990, 1, 1), date(2000, 1, 1))
>>> date(1996, 12, 4) in the90s
True
>>> date(2000, 1, 1) in the90s
False
>>> the90s.union(daterange(date(2000, 1, 1), date(2010, 1, 1)))
daterange([datetime.date(1990, 1, 1), datetime.date(2010, 1, 1))))
If you are making a booking application for a bed and breakfast hotel and want to ensure no room gets double booked:
from collections import defaultdict
from datetime import date
from spans import daterange
# Add a booking from 2013-01-14 through 2013-01-15
bookings = defaultdict(list, {
1 : [daterange(date(2013, 1, 14), date(2013, 1, 16))]
}
def is_valid_booking(bookings, room, new_booking):
return not any(booking.overlap(new_booking for booking in bookings[room])
print is_valid_booking(
bookings, 1, daterange(date(2013, 1, 14), date(2013, 1, 18))) # False
print is_valid_booking(
bookings, 1, daterange(date(2013, 1, 16), date(2013, 1, 18))) # True
The library supports ranges and sets of ranges. A range has no discontinuities between its endpoints. For some applications this is a requirement and hence the rangeset type exists.
Apart from the above mentioned overlap operation; ranges support union, difference, intersection, contains, startswith, endswith, left_of and right_of.
Built-in ranges:
intrange
floatrange
strrangerange - For unicode strings
daterange
datetimerange
timedeltarange
For each one of the range types a rangeset type exists as well:
intrangeset
floatrangeset
strrangerangeset
daterangeset
datetimerangeset
timedeltarangeset
Motivation
For a recent project of mine I started using PostgreSQL’s tsrange type and needed an equivalent in Python. These range types attempt to mimick PostgreSQL’s behavior in every way. Deviating from it is considered as a bug and should be reported.
Installation
Spans exists on PyPI.
$ pip install Spans
Documentation
Documentation is hosted on Read the Docs.
Use with Psycopg2
To use these range types with Psycopg2 the PsycoSpans library exists [2].
Custom range types
Using your own types for ranges are easy, just extend a base class and you’re good to go:
from spans.types import range_, discreterange
from spans.settypes import rangeset, discreterangeset
class intrange(discreterange):
__slots__ = ()
type = int
step = 1
class intrangeset(discreterangeset):
__slots__ = ()
type = intrange
class floatrange(range_):
__slots__ = ()
type = float
class floatrangeset(rangeset):
__slots__ = ()
type = floatrange
For a deeper set of examples please refer to types.py and settypes.py.
Changelog
Version are structured like the following: <major>.<minor>.<bugfix>. The first 0.1 release does not properly adhere to this. Unless explicitly stated, changes are made by Andreas Runfalk.
Version 0.2.0
Released 22nd December, 2015
Added __len__() to range sets (Michael Krate)
Added contains() to range sets (Michael Krate)
Added Sphinx style doc strings to all methods
Added proper Sphinx documentation
Added unit tests for uncovered parts, mostly error checking
Added wheel to PyPI along with source distribution
Fixed a potential bug where comparing ranges of different types would result in an infinite loop
Changed meta class implementation for range sets to allow more mixins for custom range sets
Version 0.1.4
Released on 15th May, 2015
Added .last property to discreterange
Added from_date() helper to daterange
Added more unit tests
Improved pickle implementation
Made type checking more strict for date ranges to prevent datetime from being allowed in daterange
Version 0.1.3
Released on 27th February, 2015
Added offset() to some range types
Added offset() to some range set types
Added sanity checks to range boundaries
Fixed incorrect __slots__ usage, resulting in __slots__ not being used on most ranges
Fixed pickling of ranges and range sets
Simplified creation of new rangesets, by the use of the meta class metarangeset
Version 0.1.2
Released on 13th June, 2014
Fix for inproper version detection on Ubuntu’s bundled Python interpreter
Version 0.1.1
Released on 12th June, 2014
Readme fixes
Syntax highlighting for PyPI page
Version 0.1.0
Released on 30th August, 2013
Initial release
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for Spans-0.2.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8f090cbad7ac727e55fcb20b3e20dea26c4948186f38796e0dc3815cb110ac2c |
|
MD5 | 2ca2e03edf165fece9f21b8754f30849 |
|
BLAKE2b-256 | c98e1bec791b858295cbf82468bea88755c74ba090d866a7909a9a2785774576 |