Skip to main content

A professional and extensible Stack implementation in Python

Project description

stack-lab

stack-lab

Production-grade, feature-rich Stack for Python — small, battle-tested, and built to impress.

Python Version License CI

TL;DR

stack-lab is a modern Stack[T] implementation for Python with:

  • Optional O(1) min() / max() tracking.
  • Capacity control + multiple overflow strategies.
  • Transactions (with support), snapshots, and observers.
  • Bulk ops, functional helpers, rotation, dedup, and more.
  • Clean, typed API ready for production, teaching, or portfolio demos.

Table of contents


Installation

Development / local install:

git clone https://github.com/anbukumaran1/stack-lab.git
cd stack-lab
python -m venv .venv
# macOS / Linux:
source .venv/bin/activate
# Windows PowerShell:
# .\.venv\Scripts\Activate.ps1

pip install -e .
pip install -r requirements.txt   # installs pytest
When published to PyPI (future):

bash
Copy
Edit
pip install stack-lab
Quick start
python
Copy
Edit
from stack_lab import Stack, OverflowStrategy

# Simple stack
s = Stack[int]()
s.push(3)
s.push(7)
print(s.pop())   # -> 7

# Stack with min/max tracking
s2 = Stack[int](track_minmax=True)
s2.push_many([5, 2, 9])
print(s2.min(), s2.max())  # -> 2 9
Full API & Examples
NOTE: in examples, # -> comments show expected outputs.

Construction
Signature
Stack(*items, track_minmax=False, maxsize=None, overflow=OverflowStrategy.ERROR, on_change=None)

items: initial elements (left  right = bottom  top).

track_minmax: enable O(1) min() / max() (maintained internally).

maxsize: integer capacity (optional).

overflow: behaviour when capacity reached (see OverflowStrategy).

on_change: iterable of callables or 'print' to attach a console observer.

python
Copy
Edit
s = Stack(1, 2, 3)  # bottom=1, top=3
s = Stack(track_minmax=True)
Core methods
push(item)
Push an item onto the top.

python
Copy
Edit
s = Stack()
s.push(10)
s.push(20)
print(s.peek())  # -> 20
push_many(iterable)
Push many items in order.

python
Copy
Edit
s.push_many([1,2,3])  # pushes 1 then 2 then 3 (3 is top)
pop() -> T
Pop and return top element. Raises StackEmptyError if empty.

python
Copy
Edit
s = Stack()
s.push("a")
print(s.pop())  # -> "a"
pop_many(k) -> List[T]
Pop up to k items; returns list of popped items (top-first).

python
Copy
Edit
s.push_many([1,2,3,4])
print(s.pop_many(2))  # -> [4, 3]
peek() -> T
Return top item without removing. Raises StackEmptyError if empty.

safe_peek() -> Optional[T]
Return top item or None if empty.

clear()
Remove all elements.

to_list() -> List[T]
Shallow copy of the stack data (bottom  top).

from_iterable(iterable, **kwargs) -> Stack
Build a stack from any iterable.

len(stack), item in stack, repr(stack) are supported.

Min / Max tracking (O(1))
To enable fast min() and max():

python
Copy
Edit
s = Stack[int](track_minmax=True)
s.push_many([3, 1, 4])
print(s.min(), s.max())  # -> 1 4
Notes & edge cases

min() / max() require track_minmax=True and a non-empty stack, otherwise raises StackError.

Implementation uses auxiliary stacks to preserve O(1) per operation.

Capacity & OverflowStrategy
maxsize limits stack size. overflow controls what happens when full:

OverflowStrategy.ERROR  raise StackCapacityError.

OverflowStrategy.DROP_OLDEST  remove bottom element(s) to make room for new pushes.

OverflowStrategy.DROP_NEWEST  refuse the incoming push (no-op).

OverflowStrategy.GROW  ignore maxsize and grow (effectively unbounded).

Examples:

python
Copy
Edit
from stack_lab import Stack, OverflowStrategy

s = Stack[int](maxsize=3, overflow=OverflowStrategy.DROP_OLDEST)
s.push_many([1,2,3])  # stack = [1,2,3]
s.push(4)             # drops 1 -> stack = [2,3,4]

s2 = Stack[int](maxsize=2, overflow=OverflowStrategy.ERROR)
s2.push_many([1,2])
# s2.push(3)  # raises StackCapacityError
Tip: Choose DROP_OLDEST for rolling buffers, ERROR when capacity must be enforced strictly.

Transactions and rollback
Transaction support allows multi-step changes to be committed or automatically rolled back on exception.

Context-manager style (recommended):

python
Copy
Edit
s = Stack([1,2,3])
try:
    with s.transaction():
        s.push(99)
        raise RuntimeError("abort")  # causes rollback
except RuntimeError:
    pass

print(s.to_list())  # -> [1,2,3]  (99 rolled back)
Manual API (begin/commit/rollback):

python
Copy
Edit
s.begin()
s.push(4)
s.rollback()  # undoes the push
Behavioral notes

push operations are rolled back by popping them.

pop operations are rolled back by re-pushing popped payloads (attempts to respect capacity).

clear during a transaction does not fully preserve pre-clear state  avoid clear inside transactions if you need precise restores.

Snapshots & clone
Snapshot  immutable capture of stack state (fast, safe):

python
Copy
Edit
snap = s.snapshot()
s.push(5)
s.restore(snap)
Clone / copy  shallow copy:

python
Copy
Edit
s2 = s.copy()   # or s.clone()
Utilities: rotate / unique / map_new / filter_new / find
rotate(k)  cyclically rotate the stack (top moves to bottom for positive k):

python
Copy
Edit
s = Stack.from_iterable([1,2,3,4])  # top=4
s.rotate(1)
print(s.to_list())  # -> [4,1,2,3]
unique(keep="last"|"first")  deduplicate preserving order:

python
Copy
Edit
s = Stack.from_iterable([1,2,3,2,1])
s.unique(keep="last")   # top-most duplicates kept by default
print(s.to_list())      # -> [3,2,1]
map_new(fn) and filter_new(pred)  functional helpers that return new Stack instances:

python
Copy
Edit
s = Stack.from_iterable([1,2,3])
s2 = s.map_new(lambda x: x * 2)   # -> Stack([2,4,6])
s3 = s.filter_new(lambda x: x % 2 == 1)  # -> Stack([1,3])
count(item) and find(item):

python
Copy
Edit
s.count(2)   # number of occurrences
s.find(3)    # index from bottom or None
Observers (hooks)
Attach callbacks to respond to 'push', 'pop', and 'clear' events. A built-in "print" observer is provided for quick logging.

python
Copy
Edit
def logger(event, st):
    print(f"EVENT={event} size={len(st)} top={st.safe_peek()}")

s = Stack(on_change=[logger, "print"])
s.push(10)  # triggers logger and the built-in print observer
Observers are guaranteed not to break core behavior (exceptions inside observers are caught).

Exceptions
StackError  base class

StackEmptyError  operations on empty stack (peek/pop)

StackCapacityError  capacity enforcement errors

StackTransactionError  transaction misuse

Use try/except to handle these in production code.

Testing
We use pytest. Example commands:

bash
Copy
Edit
# inside your venv
pip install -r requirements.txt
pytest -q
Sample unit tests included in tests/test_core.py cover:

basic push/pop/peek

errors on empty pops/peeks

transaction semantics

min/max behavior (when enabled)

Publishing & CI notes
Use pyproject.toml + setuptools for packaging.

Recommended workflow:

Bump version in pyproject.toml and stack_lab/__init__.py.

python -m build

twine upload dist/*

Use a GitHub Actions workflow to run tests and build on push and to publish on tags (protect secrets  store PyPI token in repo settings).

Contributing
Fork, create a branch, add tests, and open a PR.

Keep API backward-compatible or provide a clear migration note in CHANGELOG.md.

Run tests and lint before opening PRs.

Changelog (v1.0.0)
Initial public release: Stack with transactions, min/max tracking, capacity control, snapshots, functional helpers, observers, and utilities.

License & Contact
License: MIT  see LICENSE.
Author: Anbu Kumaran
GitHub: https://github.com/anbukumaran1
Email: anbuku12345@gmail.com

<p align="center"> Built with ❤️ by Anbu  go make something legendary. </p> ```

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stack_lab-1.0.0.tar.gz (16.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stack_lab-1.0.0-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file stack_lab-1.0.0.tar.gz.

File metadata

  • Download URL: stack_lab-1.0.0.tar.gz
  • Upload date:
  • Size: 16.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for stack_lab-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a28cabaf7ce144b3d53a605266ff382389cd666731b8bf3d5a14113e7dc25961
MD5 ba32128f732e3f415d92008a036ff09e
BLAKE2b-256 6c3a8ba3ff20e04b1a966a54b69914e5ba64d6d0daaa2b0cc83c54587c3ec702

See more details on using hashes here.

File details

Details for the file stack_lab-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: stack_lab-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for stack_lab-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 939ec241dddb5b11153360b0ed6d0d03b0dbddd83015c8e24cdb6f8764b1b66a
MD5 5ae83600128fcd9d39d4bbcb94a4fce3
BLAKE2b-256 e1e159fc732860b3362589c722afbc781d6dfcf518dccc82772eb3e275c7411f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page