A professional and extensible Stack implementation in Python
Project description
stack-lab
Production-grade, feature-rich Stack for Python — small, battle-tested, and built to impress.
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 (
withsupport), 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
- Quick start
- Full API & Examples
- Testing
- Publishing & CI notes
- Contributing
- License & Contact
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
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
stack_lab-1.0.0.tar.gz
(16.8 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
stack_lab-1.0.0-py3-none-any.whl
(14.6 kB
view details)
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a28cabaf7ce144b3d53a605266ff382389cd666731b8bf3d5a14113e7dc25961
|
|
| MD5 |
ba32128f732e3f415d92008a036ff09e
|
|
| BLAKE2b-256 |
6c3a8ba3ff20e04b1a966a54b69914e5ba64d6d0daaa2b0cc83c54587c3ec702
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
939ec241dddb5b11153360b0ed6d0d03b0dbddd83015c8e24cdb6f8764b1b66a
|
|
| MD5 |
5ae83600128fcd9d39d4bbcb94a4fce3
|
|
| BLAKE2b-256 |
e1e159fc732860b3362589c722afbc781d6dfcf518dccc82772eb3e275c7411f
|