It works on ranges.
Switch branches/tags
Nothing to show
Latest commit 4b9e05c Nov 26, 2012 @BrianHicks fix tests for python 2.6
Failed to load latest commit information.
cowboy add some nicer methods on MultiSet Nov 26, 2012
.gitignore improve .gitignore Nov 25, 2012
.travis.yml add compatibility for 3.2 Nov 25, 2012
requirements.txt correct author name Nov 25, 2012


Build Status

It works on ranges.


pip install cowboy

Installing for development

git clone
pip install -r requirements.txt
python develop

How to do stuff with Cowboy

Construct a range:

import datetime
from cowboy import DateRange

first_quarter = DateRange(
    start=datetime(2012, 1, 1),
    end=datetime(2012, 3, 31)

See if an arbitrary value is within the range, matching on start and end. O(2):

datetime(2012, 2, 1) in first_quarter # True

Step through all the values in the range. Generator returns O(2n+1) where n is the delta of the start and end:

from cowboy import NumberRange

one_through_ten = NumberRange(1, 10)

one_through_ten.steps(granularity=1) # Generator yielding [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Working with multiple ranges

You can add two ranges in the obvious manner (takes the lesser of the starts and the greater of the ends):

fst, snd = NumberRange(1, 2), NumberRange(3, 4)

fst + snd # <NumberRange: 1 to 4>

In real life, that's not always how you want to combine sets. Take for example, a circus, where we want to quickly see if the circus is showing any particular day:

from cowboy import MultiRange

circus_schedule = MultiRange(
    DateRange(datetime(2012, 1, 1), datetime(2012, 1, 3)),
    DateRange(datetime(2012, 1, 8), datetime(2012, 1, 10))
datetime(2012, 1, 2) in circus_schedule # True
datetime(2012, 1, 9) in circus_schedule # True

You can also get the intersection of two ranges. This works a little bit like set.intersection but might raise a InvalidRangeError if the start is greater than the end. Essentially, this tries to create a new Range with the greater of the starts and the lesser of the ends:

fst, snd = NumberRange(1, 3), NumberRange(2, 4)
fst.intersection(snd) # <NumberRange: 2 to 3>

Make your own ranges

Say you wanted to make your own Range for chars, so that CharRange('a', 'c') made sense. That class would look something like this:

from cowboy.base import Range

class CharRange(Range):
    'a range of characters'
    def steps(self, granularity=1): # most subclasses will override just granularity
        current = ord(self.start)
        while current <= ord(self.end):
            yield chr(current)
            current += granularity

Now you can use all the methods outlined above to operate on ranges of characters.