Skip to content

Commit 73b7682

Browse files
authored
Merge pull request #1 from rundef/feat/indexes_support
Indexes support
2 parents f8ee2bf + 299ee55 commit 73b7682

27 files changed

Lines changed: 1131 additions & 196 deletions

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.2.2
2+
current_version = 0.3.0
33
commit = True
44
tag = True
55

.readthedocs.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Read the Docs configuration file
2+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3+
4+
# Required
5+
version: 2
6+
7+
# Set the OS, Python version, and other tools you might need
8+
build:
9+
os: ubuntu-24.04
10+
tools:
11+
python: "3.13"
12+
13+
# Build documentation in the "docs/" directory with Sphinx
14+
sphinx:
15+
configuration: docs/conf.py
16+
17+
python:
18+
install:
19+
- method: pip
20+
path: .
21+
- requirements: docs/requirements.txt
22+

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.PHONY: docs tests
2+
3+
TESTS_PATH?=tests
4+
5+
docs:
6+
rm -rf docs/_build && $(MAKE) -C docs html
7+
8+
tests:
9+
PYTHONPATH=. pytest -s -vvvv -x $(TESTS_PATH)
10+

README.md

Lines changed: 7 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
[![PyPI - Version](https://img.shields.io/pypi/v/sqlalchemy-memory)](https://pypi.org/project/sqlalchemy-memory/)
44
[![CI](https://github.com/rundef/sqlalchemy-memory/actions/workflows/ci.yml/badge.svg)](https://github.com/rundef/sqlalchemy-memory/actions/workflows/ci.yml)
5+
[![Documentation](https://app.readthedocs.org/projects/sqlalchemy-memory/badge/?version=latest)](https://sqlalchemy-memory.readthedocs.io/en/latest/)
56
[![PyPI - Downloads](https://img.shields.io/pypi/dm/sqlalchemy-memory)](https://pypistats.org/packages/sqlalchemy-memory)
67

78

@@ -34,6 +35,7 @@ Data is kept purely in RAM and is **volatile**: it is **not persisted across app
3435
- **SQLAlchemy 2.0 support**: ORM & Core expressions, sync & async modes
3536
- **Zero I/O overhead**: pure in‑RAM storage (`dict`/`list` under the hood)
3637
- **Commit/rollback support**
38+
- **Index support**: indexes are recognized and used for faster lookups
3739
- **Merge and `get()` support**: like real SQLAlchemy behavior
3840

3941
## Installation
@@ -42,104 +44,10 @@ Data is kept purely in RAM and is **volatile**: it is **not persisted across app
4244
pip install sqlalchemy-memory
4345
```
4446

45-
## Quickstart
47+
## Documentation
4648

47-
```python
48-
from sqlalchemy import create_engine, select
49-
from sqlalchemy.orm import sessionmaker, declarative_base, Mapped, mapped_column
50-
from sqlalchemy_memory import MemorySession
49+
[See the official documentation for usage examples](https://sqlalchemy-memory.readthedocs.io/en/latest/)
5150

52-
engine = create_engine("memory://")
53-
Session = sessionmaker(
54-
engine,
55-
class_=MemorySession,
56-
expire_on_commit=False,
57-
)
58-
59-
Base = declarative_base()
60-
61-
class Item(Base):
62-
__tablename__ = "items"
63-
id: Mapped[int] = mapped_column(primary_key=True)
64-
name: Mapped[str] = mapped_column()
65-
def __repr__(self):
66-
return f"Item(id={self.id} name={self.name})"
67-
68-
Base.metadata.create_all(engine)
69-
70-
# Use just like any other SQLAlchemy engine:
71-
session = Session()
72-
73-
# Add & commit
74-
item = Item(id=1, name="foo")
75-
session.add(item)
76-
session.commit()
77-
78-
# Query (no SQL under the hood: objects come straight back)
79-
items = session.scalars(select(Item)).all()
80-
print("Items", items)
81-
assert items[0] is item
82-
assert items[0].name == "foo"
83-
84-
# Delete & commit
85-
session.delete(item)
86-
session.commit()
87-
88-
# Confirm gone
89-
assert session.scalars(select(Item)).all() == []
90-
```
91-
92-
## Quickstart (async)
93-
94-
```python
95-
import asyncio
96-
from sqlalchemy import select
97-
from sqlalchemy.ext.asyncio import create_async_engine
98-
from sqlalchemy.orm import sessionmaker, declarative_base, Mapped, mapped_column
99-
from sqlalchemy_memory import MemorySession, AsyncMemorySession
100-
101-
engine = create_async_engine("memory+asyncio://")
102-
Session = sessionmaker(
103-
engine,
104-
class_=AsyncMemorySession,
105-
sync_session_class=MemorySession,
106-
expire_on_commit=False,
107-
)
108-
109-
Base = declarative_base()
110-
111-
class Item(Base):
112-
__tablename__ = "items"
113-
id: Mapped[int] = mapped_column(primary_key=True)
114-
name: Mapped[str] = mapped_column()
115-
116-
def __repr__(self):
117-
return f"Item(id={self.id} name={self.name})"
118-
119-
Base.metadata.create_all(engine.sync_engine)
120-
121-
async def main():
122-
async with Session() as session:
123-
# Add & commit
124-
item = Item(id=1, name="foo")
125-
session.add(item)
126-
await session.commit()
127-
128-
# Query (no SQL under the hood: objects come straight back)
129-
items = (await session.scalars(select(Item))).all()
130-
print("Items", items)
131-
assert items[0] is item
132-
assert items[0].name == "foo"
133-
134-
# Delete & commit
135-
await session.delete(item)
136-
await session.commit()
137-
138-
# Confirm gone
139-
assert (await session.scalars(select(Item))).all() == []
140-
141-
asyncio.run(main())
142-
```
14351

14452
## Status
14553

@@ -155,11 +63,13 @@ Coming soon:
15563

15664
- Joins and relationships (limited)
15765

66+
- Compound indexes
67+
15868
- Better expression support in `update(...).values()` (e.g., +=)
15969

16070
## Testing
16171

162-
Simply run `pytest`
72+
Simply run `make tests`
16373

16474
## License
16575

docs/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Minimal makefile for Sphinx documentation
2+
#
3+
4+
# You can set these variables from the command line, and also
5+
# from the environment for the first two.
6+
SPHINXOPTS ?=
7+
SPHINXBUILD ?= sphinx-build
8+
SOURCEDIR = .
9+
BUILDDIR = _build
10+
11+
# Put it first so that "make" without argument is like "make help".
12+
help:
13+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14+
15+
.PHONY: help Makefile
16+
17+
# Catch-all target: route all unknown targets to Sphinx using the new
18+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19+
%: Makefile
20+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

docs/commit_rollback.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
Commit / Rollback
2+
=================
3+
4+
sqlalchemy-memory fully supports transactional behavior, including commit and rollback operations. Changes are staged until committed, and can be safely reverted using rollback().
5+
6+
Commit
7+
------
8+
9+
.. code-block:: python
10+
11+
with SessionFactory() as session:
12+
session.add(Item(id=1, name="foo"))
13+
session.commit()
14+
15+
item = session.get(Item, 1)
16+
print(item.name) # foo
17+
item.name = "updated"
18+
session.commit()
19+
20+
print(item.name) # updated
21+
22+
Rollback
23+
--------
24+
25+
Use `rollback()` to undo uncommitted changes:
26+
27+
.. code-block:: python
28+
29+
with SessionFactory() as session:
30+
session.add(Item(id=1, name="foo"))
31+
session.commit()
32+
33+
item = session.get(Item, 1)
34+
print(item.name) # foo
35+
item.name = "updated"
36+
session.rollback()
37+
38+
print(item.name) # foo

docs/conf.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Configuration file for the Sphinx documentation builder.
2+
#
3+
# For the full list of built-in configuration values, see the documentation:
4+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
5+
import os
6+
import sys
7+
sys.path.insert(0, os.path.abspath('..'))
8+
9+
10+
# -- Project information -----------------------------------------------------
11+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
12+
13+
project = 'sqlalchemy_memory'
14+
copyright = '2025, rundef'
15+
author = 'rundef'
16+
17+
# -- General configuration ---------------------------------------------------
18+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
19+
20+
extensions = [
21+
"sphinx.ext.autodoc",
22+
"sphinx.ext.napoleon", # for Google/NumPy-style docstrings
23+
"sphinx.ext.viewcode",
24+
"sphinx.ext.autosummary",
25+
]
26+
#autosummary_generate = True
27+
28+
templates_path = ['_templates']
29+
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
30+
31+
32+
33+
# -- Options for HTML output -------------------------------------------------
34+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
35+
36+
#html_theme = 'furo'
37+
#html_static_path = ['_static']
38+
39+
40+
html_theme = 'sphinx_rtd_theme'
41+
html_theme_options = {
42+
'logo_only': False,
43+
'prev_next_buttons_location': 'bottom',
44+
# Toc options
45+
'collapse_navigation': True,
46+
'sticky_navigation': True,
47+
'navigation_depth': 4,
48+
'includehidden': True,
49+
'titles_only': False,
50+
'navigation_with_keys': True,
51+
'style_external_links': True,
52+
}
53+

docs/delete.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Delete
2+
======
3+
4+
Deleting objects from the memory store uses standard SQLAlchemy syntax.
5+
6+
.. code-block:: python
7+
8+
session.delete(obj) # orm style
9+
10+
stmt = delete(Item).where(Item.id < 3) # core style
11+
result = session.execute(stmt)
12+
print(result.rowcount)

0 commit comments

Comments
 (0)