Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

COWList 🐄 -- An Immutable, Copy-on-Write List for Python

An efficient, immutable, type-safe copy-on-write (COW) list implementation for Python 2+.

COWList provides a persistent, immutable list-like data structure where all mutating operations return a new instance, allowing shared storage between list versions until modifications are made. This results in efficient memory use, O(1) indexing, and safe concurrency patterns.

Features

  • ✅ Immutable: All operations return a new instance.
  • 🧠 Copy-on-Write: Physical storage is shared until a mutation is required.
  • ⚡ Efficient:
    • O(1) indexing and slicing
    • O(1) appending (if the current instance is contiguous and not a sliced view)
    • O(k) extending (if the current instance is contiguous and not a sliced view)
  • 🧩 Pythonic: Implements the full collections.abc.Sequence protocol. Fully typed.
  • 🔐 Hashable: Suitable for use as dict keys or set elements (when elements are hashable).
  • 🧪 Testable & Extendable: Clean architecture for experimentation or educational purposes.

Installation

pip install cowlist

Usage

from cowlist import COWList

# --- Construction ---
lst = COWList([1, 2, 3])
assert list(lst) == [1, 2, 3]

empty = COWList()
assert list(empty) == []
assert len(empty) == 0

# --- Immutability ---
lst2 = lst.append(4)
assert list(lst) == [1, 2, 3]         # Original unchanged
assert list(lst2) == [1, 2, 3, 4]     # New list with appended value

# --- Indexing and slicing ---
assert lst[0] == 1
assert lst[-1] == 3
assert list(lst[:2]) == [1, 2]

# --- Equality and hashing ---
lst_copy = COWList([1, 2, 3])
assert lst == lst_copy
assert hash(lst) == hash(lst_copy)

# --- Append ---
lst_app = lst.append(9)
assert list(lst_app) == [1, 2, 3, 9]

# --- Insert ---
lst_ins = lst.insert(1, 99)
assert list(lst_ins) == [1, 99, 2, 3]

# --- Extend ---
lst_ext = lst.extend([4, 5])
assert list(lst_ext) == [1, 2, 3, 4, 5]

# --- Delete by index ---
lst_del = lst.delete(1)
assert list(lst_del) == [1, 3]

# --- Delete by slice ---
lst_del_slice = lst.delete(slice(1, 3))
assert list(lst_del_slice) == [1]

# --- Remove value ---
lst_rem = lst.remove(2)
assert list(lst_rem) == [1, 3]

# --- Set by index ---
lst_set = lst.set(1, 42)
assert list(lst_set) == [1, 42, 3]

# --- Set by slice ---
lst_set_slice = lst.set(slice(1, 3), [7, 8])
assert list(lst_set_slice) == [1, 7, 8]

# --- Reverse ---
lst_rev = lst.reverse()
assert list(lst_rev) == [3, 2, 1]

# --- Pop ---
lst_popped, val = lst.pop()
assert list(lst_popped) == [1, 2]
assert val == 3

# --- Clear ---
lst_clear = lst.clear()
assert list(lst_clear) == []
assert lst_clear == COWList()

# --- Repr ---
assert repr(lst) == 'COWList([1, 2, 3])'

# --- Contains ---
assert 2 in lst
assert 5 not in lst

# --- Comparison ---
assert COWList([1, 2]) < COWList([1, 2, 3])
assert COWList([1, 3]) > COWList([1, 2])

How It Works

Internally, COWList maintains:

  • A shared physical list of elements.
  • A logical offset CanonicalRange into that list.

On mutation, if possible, it reuses storage; otherwise, it copies only the parts it needs.

This strategy enables structural sharing and helps maintain immutability while preserving performance.

API Reference

Method Description
__getitem__(self, index_or_slice: Union[int, slice]) -> Union[T, Self] Get element at index or sliced view of the list. O(1)
append(self, value: T) -> Self Return new instance with value appended to the end. O(1) if current instance is contiguous, O(n) if current instance is a sliced view.
extend(self, iterable: Iterable[T]) -> Self, __add__(self, iterable: Iterable[T]) -> Self Return new instance extended with values in iterable. O(k) if current instance is contiguous, O(n + k) if current instance is a sliced view.
insert(self, index: int, value: T) -> Self Return new instance with value inserted at index. O(n)
delete(self, index_or_slice: Union[int, slice]) -> Self Return new instance with element(s) at specified position(s) deleted. O(n)
set(self, index_or_slice: Union[int, slice], value_or_iterable: Union[T, Iterable[T]]) -> Self Return new instance with element(s) at given position(s) replaced with new value(s). O(n)
pop(self, index: int = -1) -> Tuple[Self, T] Return (new instance with item removed, removed item), where removed item is self[i]. O(n)
clear(self) -> Self Return an empty new instance. O(1)
reverse(self) -> Self Return a sliced view of the list with the elements in reverse order. O(1)

Contributing

Contributions are welcome! Please submit pull requests or open issues on the GitHub repository.

License

This project is licensed under the Apache License.

Release files for cowlist 0.1.0a5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cowlist 0.1.0a5
File Size Uploaded
cowlist-0.1.0a5.tar.gz 10.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cowlist 0.1.0a5
File Interpreter ABI Platform
cowlist-0.1.0a5-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 22.4 kB

Release files / cowlist-0.1.0a5.tar.gz

Download URL cowlist-0.1.0a5.tar.gz
Size 10.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1869d52b855d8a95d2a64f60123a9e8b407713fec2002199396c85b85f3f9ce3
BLAKE2b-256 checksum
How to use checksums
5a724ccc2c219ec82582425f3dc3c89dedab55783ecacc565aedb7ce97fa8401
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Release files / cowlist-0.1.0a5-py2.py3-none-any.whl

Download URL cowlist-0.1.0a5-py2.py3-none-any.whl
Size 11.5 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
595a7c604995e37df21966c86fc1e106e55a324cd7033f70fbca4853c80e3cd5
BLAKE2b-256 checksum
How to use checksums
776d0048f9f9aa3ac9cd068439ca6b516f7d810ab5502a4ecad171760ca5b64a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Release history Release notifications | RSS feed

This release

0.1.0a5 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page