Skip to content

DasKaroWow/loopint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LoopInt

PyPI version Python versions Tests License Typing Downloads Ruff Linter & Formatter basedpyright

LoopInt is a lightweight Python library that provides a cyclic integer type with precise range semantics [left; right) and natural integer-like behavior.

It behaves like a regular integer but wraps around within a fixed interval. This makes it useful for cyclic counters, circular buffers, modular arithmetic, clock-like values, and more.


πŸ”§ Features

  • Fixed interval semantics: [left; right)
  • Modular wrap-around on +, -, +=, -=
  • Behaves like int in:
    • comparisons
    • hashing
    • indexing (__index__)
    • formatting (__format__)
    • int() conversion
  • Safe arithmetic:
    • LoopInt + int supported
    • LoopInt += int supported
    • Adding two LoopInt objects is intentionally forbidden
  • Fully typed (Python β‰₯ 3.12)

πŸ“¦ Installation

pip install loopint

Or with uv:

uv add loopint

πŸš€ Usage

from loopint import LoopInt

x = LoopInt(0, right=5)

print(int(x))      # 0

x += 7
print(int(x))      # 2   (wrap-around: 7 % 5 == 2)

y = x + 10
print(int(y))      # 2   (non-mutating)

assert x == 2
assert y == x

Custom range

x = LoopInt(0, right=2, left=-1)
print(int(x))  # 0

x += 1
print(int(x))  # 1

x += 2         # wraps in [-1; 2)
print(int(x))  # 0

πŸ“š API Overview

LoopInt(current, /, right, *, left=0)

Create a cyclic integer constrained to the interval [left; right) with modular wrap-around.

Parameters:

  • current β€” initial value (any integer-like object supporting __index__)
  • right β€” exclusive upper bound
  • left β€” inclusive lower bound (default: 0)

Interval semantics:

value ∈ [left; right)
span = right βˆ’ left
value = left + ((current βˆ’ left) mod span)

πŸ”Ή Properties

value: int

Returns the visible integer value of the LoopInt instance.

Equivalent to:

int(loopint_instance)

Example:

x = LoopInt(5, right=8, left=2)
assert x.value == 5

left: int

Returns the inclusive lower bound of the interval.

Example:

LoopInt(0, right=5, left=-2).left  # β†’ -2

right: int

Returns the exclusive upper bound of the interval.

Example:

LoopInt(0, right=5).right  # β†’ 5

span: int

Size of the interval:

span = right - left

Example:

LoopInt(0, right=5, left=2).span  # β†’ 3

πŸ”Ή Methods

to_string() -> str

Return the value as a string. Equivalent to:

str(int(self))

Example:

x = LoopInt(4, right=10)
x.to_string()   # β†’ "4"

Arithmetic

__add__(other) -> LoopInt

Non-mutating addition with wrap-around.

x + n  # returns a new LoopInt

__iadd__(other) -> Self

In-place addition (+=) with wrap-around.

x += 3

__sub__(other) -> LoopInt

Non-mutating subtraction.


__isub__(other) -> Self

In-place subtraction (-=).


__neg__() -> LoopInt

Modular negation:

int(-x) == (-int(x)) mod span

Example:

x = LoopInt(1, right=5)
y = -x      # β†’ 4

__radd__(other) -> LoopInt

Enables: int + LoopInt.

Example:

3 + LoopInt(2, right=5)  # β†’ 0

__rsub__(other) -> LoopInt

Implements: other - self using modular arithmetic.

other - x == -(x - other)

Example:

3 - LoopInt(1, right=5)   # β†’ 2
0 - LoopInt(1, right=5)   # β†’ 4

Comparison & hashing

__eq__(other)

LoopInt compares equal to anything whose integer value equals int(self).

Examples:

LoopInt(0, right=5) == 0            # True
LoopInt(3, right=10) == LoopInt(3, right=100)  # True

__hash__() -> int

Hash is consistent with int(self):

hash(LoopInt(3, right=10)) == hash(3)

πŸ§ͺ Testing

pytest .

Both unit tests and property-based tests (Hypothesis) are included.


πŸ“„ License

MIT License.


🀝 Contributing

Contributions are welcome! Feel free to open issues or pull requests.

About

A fully typed cyclic integer type for Python with modular arithmetic and fixed [left; right) interval semantics.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages