# Path: picraft/compat.py
# class range(Sequence):
#     def __init__(self, start, stop=None, step=1):
#         if stop is None:
#             start, stop = 0, start
#         if (start != start // 1) or (stop != stop // 1) or (step != step // 1):
#             raise TypeError('integer arguments are required')
#         if step == 0:
#             raise ValueError('step must not be zero')
#         elif step < 0:
#             stop = min(stop, start)
#         else:
#             stop = max(stop, start)
#         self._start = start
#         self._stop = stop
#         self._step = step
#         q, r = divmod(self.stop - self.start, self.step)
#         self._len = q + (1 if r else 0)
# 
#     @property
#     def start(self):
#         return self._start
# 
#     @property
#     def stop(self):
#         return self._stop
# 
#     @property
#     def step(self):
#         return self._step
# 
#     def __repr__(self):
#         if self.step == 1:
#             return 'range(%d, %d)' % (self.start, self.stop)
#         else:
#             return 'range(%d, %d, %d)' % (self.start, self.stop, self.step)
# 
#     def __eq__(self, other):
#         if isinstance(other, range):
#             if len(self) == 0:
#                 return len(other) == 0
#             elif len(self) == len(other) == 1:
#                 return self.start == other.start
#             else:
#                 # If the other object is a (non-degenerate) range with
#                 # equivalent start, last value and step, it's equal. Note
#                 # that it's not enough to just test stop here as range(0,
#                 # 10, 3) == range(0, 11, 3).
#                 self_last = self.start + (len(self) * self.step)
#                 other_last = other.start + (len(other) * other.step)
#                 return (
#                         self.start == other.start and
#                         self_last == other_last and
#                         self.step == other.step
#                         )
#         return False
# 
#     def __ne__(self, other):
#         return not self.__eq__(other)
# 
#     def __len__(self):
#         return self._len
# 
#     def __nonzero__(self):
#         return len(self) > 0
# 
#     def index(self, value):
#         q, r = divmod(value - self.start, self.step)
#         if r == 0 and (0 <= q < len(self)):
#             return abs(q)
#         raise ValueError('%r is not in range' % value)
# 
#     def count(self, value):
#         return 1 if value in self else 0
# 
#     def __contains__(self, value):
#         try:
#             self.index(value)
#         except ValueError:
#             return False
#         else:
#             return True
# 
#     def __iter__(self):
#         count = 0
#         value = self.start
#         while count < len(self):
#             yield value
#             count += 1
#             value += self.step
# 
#     def __reversed__(self):
#         last = self.start + ((len(self) - 1) * self.step)
#         return range(last, self.start - self.step, -self.step)
# 
#     def __getitem__(self, index):
#         if isinstance(index, slice):
#             return self._get_slice(index)
#         if index < 0:
#             # negative indexes access from the end
#             index += len(self)
#         if not (0 <= index < len(self)):
#             raise IndexError('range object index out of range')
#         return self.start + index * self.step
# 
#     def _get_slice(self, s):
#         start, stop, step = s.start, s.stop, s.step
# 
#         # Calculate the step of the new range
#         if step == 0:
#             raise ValueError('slice step cannot be 0')
#         elif step is None:
#             step = 1
#         range_step = step * self.step
# 
#         # Calculate the start of the new range
#         last = self.start + ((len(self) - 1) * self.step)
#         if start is None:
#             if step > 0:
#                 range_start = self.start
#             else:
#                 range_start = last
#         else:
#             if start < 0:
#                 start = max(0, start + len(self))
#             if start < len(self):
#                 range_start = self[start]
#             else:
#                 range_start = last + self.step
# 
#         # Calculate the stop of the new range
#         last += self.step
#         if stop is None:
#             if step > 0:
#                 range_stop = last
#             else:
#                 range_stop = self.start - self.step
#         else:
#             if stop < 0:
#                 stop = max(0, stop + len(self))
#             if stop < len(self):
#                 range_stop = self[stop]
#             else:
#                 range_stop = last
# 
#         return range(range_start, range_stop, range_step)


import pytest
from picraft.compat import range
    from itertools import izip_longest as zip_longest
    from itertools import zip_longest
    assert len(range(10)) == 10
    assert len(range(10, 10)) == 0
    assert len(range(10)[::-1]) == 10
    assert len(range(3, 10, 3)) == 3

def test_range_bool():
    assert range(10)
    assert not range(10, 10)
    assert range(3, 10, 3)

def test_range_index():
    assert range(10).index(0) == 0
    assert range(10).index(9) == 9
    assert range(3, 10, 3).index(3) == 0
    assert range(3, 10, 3).index(9) == 2
    assert range(3, 10, 3)[::-1].index(9) == 0
    with pytest.raises(ValueError):
        range(10).index(10)

def test_range_count():
    assert range(10).count(0) == 1
    assert range(10).count(10) == 0
    assert range(3, 10, 3).count(4) == 0
    assert range(3, 10, 3).count(6) == 1

def test_range_contains():
    assert 0 in range(10)
    assert 10 not in range(10)
    assert 3 in range(3, 10, 3)
    assert 3 in range(3, 10, 3)[::-1]

# Path: picraft/compat.py
# class range(Sequence):
#     def __init__(self, start, stop=None, step=1):
#         if stop is None:
#             start, stop = 0, start
#         if (start != start // 1) or (stop != stop // 1) or (step != step // 1):
#             raise TypeError('integer arguments are required')
#         if step == 0:
#             raise ValueError('step must not be zero')
#         elif step < 0:
#             stop = min(stop, start)
#         else:
#             stop = max(stop, start)
#         self._start = start
#         self._stop = stop
#         self._step = step
#         q, r = divmod(self.stop - self.start, self.step)
#         self._len = q + (1 if r else 0)
# 
#     @property
#     def start(self):
#         return self._start
# 
#     @property
#     def stop(self):
#         return self._stop
# 
#     @property
#     def step(self):
#         return self._step
# 
#     def __repr__(self):
#         if self.step == 1:
#             return 'range(%d, %d)' % (self.start, self.stop)
#         else:
#             return 'range(%d, %d, %d)' % (self.start, self.stop, self.step)
# 
#     def __eq__(self, other):
#         if isinstance(other, range):
#             if len(self) == 0:
#                 return len(other) == 0
#             elif len(self) == len(other) == 1:
#                 return self.start == other.start
#             else:
#                 # If the other object is a (non-degenerate) range with
#                 # equivalent start, last value and step, it's equal. Note
#                 # that it's not enough to just test stop here as range(0,
#                 # 10, 3) == range(0, 11, 3).
#                 self_last = self.start + (len(self) * self.step)
#                 other_last = other.start + (len(other) * other.step)
#                 return (
#                         self.start == other.start and
#                         self_last == other_last and
#                         self.step == other.step
#                         )
#         return False
# 
#     def __ne__(self, other):
#         return not self.__eq__(other)
# 
#     def __len__(self):
#         return self._len
# 
#     def __nonzero__(self):
#         return len(self) > 0
# 
#     def index(self, value):
#         q, r = divmod(value - self.start, self.step)
#         if r == 0 and (0 <= q < len(self)):
#             return abs(q)
#         raise ValueError('%r is not in range' % value)
# 
#     def count(self, value):
#         return 1 if value in self else 0
# 
#     def __contains__(self, value):
#         try:
#             self.index(value)
#         except ValueError:
#             return False
#         else:
#             return True
# 
#     def __iter__(self):
#         count = 0
#         value = self.start
#         while count < len(self):
#             yield value
#             count += 1
#             value += self.step
# 
#     def __reversed__(self):
#         last = self.start + ((len(self) - 1) * self.step)
#         return range(last, self.start - self.step, -self.step)
# 
#     def __getitem__(self, index):
#         if isinstance(index, slice):
#             return self._get_slice(index)
#         if index < 0:
#             # negative indexes access from the end
#             index += len(self)
#         if not (0 <= index < len(self)):
#             raise IndexError('range object index out of range')
#         return self.start + index * self.step
# 
#     def _get_slice(self, s):
#         start, stop, step = s.start, s.stop, s.step
# 
#         # Calculate the step of the new range
#         if step == 0:
#             raise ValueError('slice step cannot be 0')
#         elif step is None:
#             step = 1
#         range_step = step * self.step
# 
#         # Calculate the start of the new range
#         last = self.start + ((len(self) - 1) * self.step)
#         if start is None:
#             if step > 0:
#                 range_start = self.start
#             else:
#                 range_start = last
#         else:
#             if start < 0:
#                 start = max(0, start + len(self))
#             if start < len(self):
#                 range_start = self[start]
#             else:
#                 range_start = last + self.step
# 
#         # Calculate the stop of the new range
#         last += self.step
#         if stop is None:
#             if step > 0:
#                 range_stop = last
#             else:
#                 range_stop = self.start - self.step
#         else:
#             if stop < 0:
#                 stop = max(0, stop + len(self))
#             if stop < len(self):
#                 range_stop = self[stop]
#             else:
#                 range_stop = last
# 
#         return range(range_start, range_stop, range_step)


# Path: tests/test_compat.py
import pytest
from picraft.compat import range
    from itertools import izip_longest as zip_longest
    from itertools import zip_longest

    assert len(range(10)) == 10
    assert len(range(10, 10)) == 0
    assert len(range(10)[::-1]) == 10
    assert len(range(3, 10, 3)) == 3

def test_range_bool():
    assert range(10)
    assert not range(10, 10)
    assert range(3, 10, 3)

def test_range_index():
    assert range(10).index(0) == 0
    assert range(10).index(9) == 9
    assert range(3, 10, 3).index(3) == 0
    assert range(3, 10, 3).index(9) == 2
    assert range(3, 10, 3)[::-1].index(9) == 0
    with pytest.raises(ValueError):
        range(10).index(10)

def test_range_count():
    assert range(10).count(0) == 1
    assert range(10).count(10) == 0
    assert range(3, 10, 3).count(4) == 0
    assert range(3, 10, 3).count(6) == 1

def test_range_contains():
    assert 0 in range(10)
    assert 10 not in range(10)
    assert 3 in range(3, 10, 3)
    assert 3 in range(3, 10, 3)[::-1]

    assert 0 not in range(3, 10, 3)