SDS Tools - Simple Data Structures
A comprehensive and educational Python library of fundamental data structures — from linked lists to probabilistic graphical models — and of the classic algorithms that operate on them, implemented with object-oriented programming principles and extensive academic-style documentation.
Package name note: the PyPI/pip distribution is named
pysds-tools(sds-toolscollides with an existing, unrelated package once PyPI normalizes names). The importable module is unaffected — it's stillsds(import sds.linear,import sds.probabilistic, ...).
Goals
- Educational: Clear, well-documented code for learning — not just working code, but code that explains why
- Comprehensive: Exhaustive coverage of classic and advanced data structures
- Typed: Full MyPy strict-mode support, pyright/basedpyright compatible
- Tested: 80–90%+ coverage target per module, enforced via pytest-cov
- Performant:
__slots__on every node and structure class
Installation
pip install pysds-tools
The base install has no dependency. Two optional extras add third-party packages for specific features:
| Extra | Installs | For |
|---|---|---|
image |
matplotlib | Image export of the visualiser |
yaml |
PyYAML | YAML input of the pysds command |
pip install "pysds-tools[image]"
pip install "pysds-tools[image,yaml]"
Using a feature without its extra raises an error that gives the install command.
Quick Start
from sds.linear import Stack
from sds.graph import DirectedGraph, GraphNode, DirectedEdge
from sds.probabilistic import BayesianNetwork, Factor, RandomVariable
# Linear structures
stack = Stack()
stack.push(1)
stack.push(2)
stack.pop() # 2
# Graphs
task_graph = DirectedGraph()
design, backend = GraphNode("Design"), GraphNode("Backend")
task_graph.add_node(design)
task_graph.add_node(backend)
task_graph.add_edge(DirectedEdge(design, backend))
task_graph.is_acyclic() # True
# Probabilistic graphical models
rain = RandomVariable("Rain", ("true", "false"))
bn = BayesianNetwork()
bn.add_variable(rain)
bn.set_cpt(rain, Factor((rain,), {("true",): 0.2, ("false",): 0.8}))
# Algorithms: free functions that take the structure as argument
from sds.algorithms.graph_algorithms import bfs
from sds.algorithms.sorting import merge_sort
[node.data for node in bfs(task_graph, design)] # ['Design', 'Backend']
merge_sort([3, 1, 2]) # [1, 2, 3]
Visualisation
sds.utils.visualizer renders linear structures, trees and graphs as text,
as Mermaid or, for graphs, as Graphviz DOT source, with no dependency;
save_image() draws them with matplotlib (image extra).
from sds.tree import BinarySearchTree
from sds.utils.visualizer import save_image, to_mermaid, to_text
tree = BinarySearchTree()
for key in (50, 30, 70, 20, 40):
tree.insert(key)
print(to_text(tree))
# 50
# ├── L: 30
# │ ├── L: 20
# │ └── R: 40
# └── R: 70
to_mermaid(tree) # "flowchart TD\n n0[\"50\"]\n..."
save_image(tree, "tree.png") # needs pysds-tools[image]
Command Line
Installing the package also installs pysds, which builds a structure
described in a JSON or YAML file and displays it:
$ cat roads.json
{"type": "WeightedGraph",
"nodes": [{"id": "P", "data": "Paris"}, {"id": "L", "data": "Lyon"}],
"edges": [["P", "L", 465]]}
$ pysds show roads.json
Paris -- Lyon (465.0)
Lyon -- Paris (465.0)
$ pysds show roads.json --format mermaid --output roads.mmd
$ pysds show roads.json --image roads.svg # needs pysds-tools[image]
YAML files (.yaml, .yml) need the yaml extra; - reads JSON on
standard input, and python -m sds runs the same command. The
command-line guide
describes the file format of each family of structures.
Architecture
The project is organized into thematic modules, one per family of structures:
src/sds/
├── core/ # Foundations: AbstractNode, AbstractContainer, exceptions
├── linear/ # Linear structures (linked list, stack, queue)
├── tree/ # Tree structures (binary, AVL, heaps, B-tree, trie, segment tree)
├── graph/ # Graph structures (directed, weighted, adjacency representations)
├── advanced/ # Deterministic advanced structures (disjoint set, Bloom filter, ...)
├── probabilistic/ # Probabilistic graphical models (Bayesian networks, MRF, HMM)
├── algorithms/ # Sorting, tree and graph algorithms, probabilistic inference
└── utils/ # Visualizer, pysds command, optional-dependency errors
Available Structures
sds.core — Foundations
Base abstractions shared by every other module: AbstractNode,
AbstractContainer, and the common exception hierarchy. Contains no concrete
data structure by design — every other module imports from here, never the
reverse.
sds.linear — Linear Structures
LinkedList: doubly linked list — O(1) prepend/appendStack: LIFO —push(),pop(),peek(), all O(1)Queue: FIFO —enqueue(),dequeue(), all O(1)
sds.tree — Tree Structures
BinaryTree,AVLTree(self-balancing, guaranteed O(log n)),GeneralTree(n-ary)MinHeap,MaxHeapBTree,Trie(prefix search),SegmentTree(range queries)
sds.graph — Graph Structures
Graph,DirectedGraph,UndirectedGraph(strict wrapper — rejects directed edges explicitly rather than silently converting them)WeightedGraph,WeightedDirectedGraphAdjacencyListGraph(sparse, O(V+E) space),AdjacencyMatrixGraph(dense, O(1) edge lookup)
sds.advanced — Advanced Structures
Deterministic structures that don't fit cleanly into linear/tree/graph:
DisjointSet(Union-Find, path compression + union-by-rank — O(α(n)) amortized)BloomFilter(probabilistic set membership),SkipList(probabilistic sorted structure)HashTableChaining,HashTableOpenAddressingLRUCache,FenwickTree(binary indexed tree),CountMinSketch(frequency estimation over streams)
sds.probabilistic — Probabilistic Graphical Models
Structures encoding probability distributions over discrete random variables.
No inference logic (marginal queries, most-likely-explanation) is implemented
here — inference lives in sds.algorithms.probabilistic_algorithms.
RandomVariable,Factor: shared building blocks (a discrete variable and a potential/CPT table over a scope of variables)BayesianNetwork: directed acyclic graphical model with locally normalized CPTs, composessds.graph.DirectedGraphfor topologyMarkovRandomField: undirected graphical model (cycles allowed) with unnormalized potentials, composessds.graph.GraphHiddenMarkovModel: sequential model over a fixed states/observations pair, with initial/transition/emission components
Available Algorithms
Algorithms are kept out of the structure classes: each one is a free function
of sds.algorithms that receives the structure it works on, typed against the
broadest abstract interface that provides what it needs.
sds.algorithms.sorting
merge_sort(stable, returns a new list),quick_sort(in place, not stable) — both withsorted()-stylekeyandreverse
sds.algorithms.tree_algorithms
inorder,preorder,postorder,level_order: iterative traversals of any binary treeis_balanced,rebalance(rebuilds aBinarySearchTreeto minimum height)
sds.algorithms.graph_algorithms
bfs,dfs: traversals of any graph, in reproducible orderdijkstra: shortest distances and paths, non-negative weightskruskal: minimum spanning forest of an undirected weighted graph
sds.algorithms.probabilistic_algorithms
variable_elimination: exact posterior of query variablesbelief_propagation: every marginal at once (exact on tree-shaped models)forward,viterbi: likelihood, filtering and decoding for hidden Markov models
Deprecation (0.7.0): the
inorder_traversal(),preorder_traversal(),postorder_traversal()andlevel_order_traversal()methods of binary trees are deprecated and will be removed in 1.0.0 — usesds.algorithms.tree_algorithmsinstead, e.g.inorder(tree).
Documentation
Full API reference and user guide, including mathematical foundations, Mermaid diagrams, complexity tables, and real-world examples for every module:
https://pysds-tools.readthedocs.io
Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=sds --cov-report=html
# Run tests for a specific module
pytest tests/06_Probabilistic/
# Run in verbose mode
pytest -v
Test suite layout (mirrors the source tree, one directory per module):
tests/
├── 01_Core/
├── 02_Linear/
├── 03_Tree/
├── 04_Graph/
├── 05_Advanced/
└── 06_Probabilistic/
Static Analysis
The project is fully typed and verified with mypy, flake8, and bandit:
mypy src/sds/
flake8 src/sds/
bandit -r src/sds/
Or, via tox:
tox -e mypy,flake8,bandit
Contributing
Contributions are welcome!
- Fork the project
- Create a branch for your feature (
git checkout -b feature/AmazingFeature) - Commit your changes following Conventional Commits
- Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Full project conventions (labels, issue templates, commit format, versioning,
releases) are documented in
CONVENTIONS.md
in the shared .github repository.
Quality Standards
- ✅ Type-checked with mypy (strict mode)
- ✅ Style-compliant with flake8
- ✅ Security-checked with bandit
- ✅ Tests with pytest (80–90%+ coverage target)
- ✅ NumPy-style docstrings
- ✅
__slots__on all node and structure classes
Roadmap
v0.1.0–v0.5.0 — Foundations through Advanced Structures ✅ Completed
sds.core,sds.linear,sds.tree,sds.graph,sds.advanced— fully implemented, tested, and documented
v0.6.0 — Probabilistic Structures ✅ Completed
sds.probabilistic:BayesianNetwork,MarkovRandomField,HiddenMarkovModel
v0.7.0 — Algorithms ✅ Completed
sds.algorithms: sorting (MergeSort, QuickSort), tree traversals and rebalancing, graph algorithms (BFS, DFS, Dijkstra, Kruskal), probabilistic inference (Variable Elimination, Belief Propagation, Forward, Viterbi)
v0.8.0 — Utilities ✅ Completed (this release)
sds.utils: visualizer (text, Mermaid, DOT, images),pysdscommand, optional extrasimageandyaml- Extended exception hierarchy in
sds.core; Python 3.11 minimum
v0.9.0–v1.0.0 — Quality Consolidation & Stable Release Planned
- Full coverage/mypy sweep, documentation polish, first stable API
v1.1.0–v1.2.0 — French Translation Planned
- Bilingual documentation via a dedicated ReadTheDocs project
License
This project is licensed under the Apache License 2.0 — see the
LICENSE file for details. Documentation is licensed separately
under CC BY-NC 4.0 — see docs/source/license.rst.
Acknowledgments
- Inspired by classic data structures and algorithms courses
- Designed for learning
- Thanks to the Python community for exceptional tools (pytest, mypy, flake8, bandit, Sphinx, Furo)
Resources
- Python Documentation
- Type Hints — PEP 484
- NumPy Docstring Guide
- Probabilistic Graphical Models — Stanford CS228 notes
(open-access reference for
sds.probabilistic)
GitLab mirror: https://gitlab.com/open-works/sds
Metadata
Release files for pysds-tools 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pysds_tools-0.8.0.tar.gz | 177.4 kB | Without provenance | Details for pysds_tools-0.8.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pysds_tools-0.8.0-py3-none-any.whl | Python 3 | none | any | Details for pysds_tools-0.8.0-py3-none-any.whl |
Total release size: 426.8 kB
Release files / pysds_tools-0.8.0.tar.gz
| Download URL | pysds_tools-0.8.0.tar.gz |
|---|---|
| Size | 177.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fac22bf66e3051f642a7d162514642e3370959586b9642356611be2b5c89df95
|
|
BLAKE2b-256 checksum How to use checksums |
645e1a8f36ae8a41ff8a364a5a593dde84f6efe85cc3a5916980d66f6b416f80
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pysds_tools-0.8.0-py3-none-any.whl
| Download URL | pysds_tools-0.8.0-py3-none-any.whl |
|---|---|
| Size | 249.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
89dcca5948a0b36b42f35daaaf3b30c052b9877fbe44d0ec37e3525d52965de3
|
|
BLAKE2b-256 checksum How to use checksums |
88dd50a47657727e93be480843a3688d7088404eb7b060c87c3206ce0f980d6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for pysds-tools 0.8.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.