Skip to content

Commit 155d5c5

Browse files
committed
remove {update,delete}_one: some Python SQLite builds don't support it
It's bad API anyways, as we don't guarantee which document (of potentially multiple matching) is getting updated/removed.
1 parent 2bbec32 commit 155d5c5

8 files changed

+28
-167
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ another database or ORM engine.
4343
print(result["text"])
4444
4545
new_data = {"name": "Virgil", "text": "Hello World!"}
46-
collection.update_one(new_data, name="Dante")
46+
collection.update(new_data, name="Dante")
4747
```
4848

4949
Under the hood, Dante stores each dictionary in a JSON-encoded TEXT column
@@ -79,7 +79,7 @@ print(result.text)
7979
# Find a model in the collection with the attribute name=Dante
8080
# and update (overwrite) it with the new model data
8181
result.name = "Virgil"
82-
collection.update_one(result, name="Dante")
82+
collection.update(result, name="Dante")
8383
```
8484

8585
## Aync Dante
@@ -102,7 +102,7 @@ async def main():
102102
print(result["text"])
103103
104104
new_data = {"name": "Virgil", "text": "Hello World!"}
105-
await collection.update_one(new_data, name="Dante")
105+
await collection.update(new_data, name="Dante")
106106
107107
await db.close()
108108

dante/asyncdante.py

+3-9
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ async def find_one(_self, **kwargs: Any) -> dict | BaseModel | None:
7676
results = await _self.find_many(1, **kwargs)
7777
return results[0] if len(results) > 0 else None
7878

79-
async def update_many(
79+
async def update(
8080
_self,
8181
_data: dict | BaseModel,
8282
_limit: int | None = None,
@@ -90,15 +90,12 @@ async def update_many(
9090

9191
conn: aiosqlite.Connection = await _self.db.get_connection()
9292
await conn.execute(
93-
f"UPDATE {_self.name} SET data = ? {query}",
93+
f"UPDATE {_self.name} SET data = ?{query}",
9494
(_self._to_json(_data), *values),
9595
)
9696
await _self.db._maybe_commit()
9797

98-
async def update_one(_self, _data: dict | BaseModel, /, **kwargs: Any):
99-
await _self.update_many(_data, None, **kwargs)
100-
101-
async def delete_many(_self, _limit: int | None = None, /, **kwargs: Any):
98+
async def delete(_self, _limit: int | None = None, /, **kwargs: Any):
10299
if not kwargs:
103100
raise ValueError("You must provide a filter to delete")
104101

@@ -108,9 +105,6 @@ async def delete_many(_self, _limit: int | None = None, /, **kwargs: Any):
108105
await conn.execute(f"DELETE FROM {_self.name}{query}", values)
109106
await _self.db._maybe_commit()
110107

111-
async def delete_one(_self, /, **kwargs: Any):
112-
await _self.delete_many(None, **kwargs)
113-
114108
async def clear(self):
115109
conn: aiosqlite.Connection = await self.db.get_connection()
116110
await conn.execute(f"DELETE FROM {self.name}")

dante/base.py

+4-22
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ def _build_query(_self, _limit: int | None, /, **kwargs: Any) -> tuple[str, list
184184
query = ""
185185

186186
if _limit:
187-
query += f" LIMIT {_limit}"
187+
query += " LIMIT ?"
188+
values.append(_limit)
188189

189190
return query, values
190191

@@ -224,7 +225,7 @@ def find_one(_self, **kwargs: Any) -> dict | BaseModel | None:
224225
"""
225226

226227
@abstractmethod
227-
def update_many(
228+
def update(
228229
_self,
229230
_data: dict | BaseModel,
230231
_limit: int | None = None,
@@ -242,33 +243,14 @@ def update_many(
242243
"""
243244

244245
@abstractmethod
245-
def update_one(_self, _data: dict | BaseModel, /, **kwargs: Any):
246-
"""
247-
Update one document matching the query.
248-
249-
Note that the data must be a full object, not just the fields to update.
250-
251-
:param _data: Data to update with (must be a full object)
252-
:param kwargs: Fields to match in the document
253-
"""
254-
255-
@abstractmethod
256-
def delete_many(_self, _limit: int | None = None, /, **kwargs: Any):
246+
def delete(_self, _limit: int | None = None, /, **kwargs: Any):
257247
"""
258248
Delete documents matching the query.
259249
260250
:param _limit: Maximum number of documents to delete (default is no limit)
261251
:param kwargs: Fields to match in the documents
262252
"""
263253

264-
@abstractmethod
265-
def delete_one(_self, /, **kwargs: Any):
266-
"""
267-
Delete one document matching the query.
268-
269-
:param kwargs: Fields to match in the document
270-
"""
271-
272254
@abstractmethod
273255
def clear(self):
274256
"""

dante/sync.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def find_one(_self, **kwargs: Any) -> dict | BaseModel | None:
8989
results = _self.find_many(1, **kwargs)
9090
return results[0] if len(results) > 0 else None
9191

92-
def update_many(
92+
def update(
9393
_self,
9494
_data: dict | BaseModel,
9595
_limit: int | None = None,
@@ -108,10 +108,7 @@ def update_many(
108108
)
109109
_self.db._maybe_commit()
110110

111-
def update_one(_self, _data: dict | BaseModel, /, **kwargs: Any):
112-
_self.update_many(_data, 1, **kwargs)
113-
114-
def delete_many(_self, _limit: int | None = None, /, **kwargs: Any):
111+
def delete(_self, _limit: int | None = None, /, **kwargs: Any):
115112
if not kwargs:
116113
raise ValueError("You must provide a filter to delete")
117114

@@ -121,9 +118,6 @@ def delete_many(_self, _limit: int | None = None, /, **kwargs: Any):
121118
cursor.execute(f"DELETE FROM {_self.name}{query}", values)
122119
_self.db._maybe_commit()
123120

124-
def delete_one(_self, /, **kwargs: Any):
125-
_self.delete_many(1, **kwargs)
126-
127121
def clear(self):
128122
cursor = self.conn.cursor()
129123
cursor.execute(f"DELETE FROM {self.name}")

tests/test_async.py

+6-73
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from asyncio import gather
22
from datetime import datetime
3-
from time import time
43

54
import pytest
65

@@ -87,21 +86,11 @@ async def test_iteration(db):
8786

8887

8988
@pytest.mark.asyncio
90-
async def test_update_one(db):
89+
async def test_update(db):
9190
coll = await db["test"]
9291

9392
await coll.insert({"a": 1, "b": 2})
94-
await coll.update_many({"a": 1, "b": 3}, a=1)
95-
result = await coll.find_one(a=1)
96-
assert result["b"] == 3
97-
98-
99-
@pytest.mark.asyncio
100-
async def test_update_many(db):
101-
coll = await db["test"]
102-
103-
await coll.insert({"a": 1, "b": 2})
104-
await coll.update_many({"a": 1, "b": 3}, a=1)
93+
await coll.update({"a": 1, "b": 3}, a=1)
10594
result = await coll.find_one(a=1)
10695
assert result["b"] == 3
10796

@@ -112,28 +101,18 @@ async def test_update_without_filter_fails(db):
112101

113102
await coll.insert({"a": 1, "b": 2})
114103
with pytest.raises(ValueError):
115-
await coll.update_many({})
116-
117-
118-
@pytest.mark.asyncio
119-
async def test_delete_one(db):
120-
coll = await db["test"]
121-
122-
await coll.insert({"a": 1, "b": 2})
123-
await coll.delete_many(a=1)
124-
result = await coll.find_one(a=1)
125-
assert result is None
104+
await coll.update({})
126105

127106

128107
@pytest.mark.asyncio
129-
async def test_delete_many(db):
108+
async def test_delete(db):
130109
coll = await db["test"]
131110

132111
await gather(
133112
coll.insert({"a": 1, "b": 2}),
134113
coll.insert({"a": 1, "b": 3}),
135114
)
136-
await coll.delete_many(a=1)
115+
await coll.delete(a=1)
137116
result = await coll.find_many(a=1)
138117
assert result == []
139118

@@ -143,10 +122,7 @@ async def test_delete_without_filter_fails(db):
143122
coll = await db["test"]
144123

145124
with pytest.raises(ValueError):
146-
await coll.delete_one()
147-
148-
with pytest.raises(ValueError):
149-
await coll.delete_many()
125+
await coll.delete()
150126

151127

152128
@pytest.mark.asyncio
@@ -157,46 +133,3 @@ async def test_clear(db):
157133
await coll.clear()
158134
result = await coll.find_many()
159135
assert result == []
160-
161-
162-
@pytest.mark.asyncio
163-
async def test_insert_performance(tmp_path):
164-
db_path = tmp_path / "test.db"
165-
db = AsyncDante(db_path, auto_commit=False)
166-
167-
coll = await db["test"]
168-
t0 = time()
169-
coros = []
170-
for i in range(100):
171-
coros.append(coll.insert({"a": i, "b": i + 1}))
172-
await gather(*coros)
173-
await db.commit()
174-
t1 = time()
175-
dt = t1 - t0
176-
assert dt < 0.05
177-
await db.close()
178-
179-
180-
@pytest.mark.asyncio
181-
async def test_update_performance(tmp_path):
182-
db_path = tmp_path / "test.db"
183-
db = AsyncDante(db_path, auto_commit=False)
184-
185-
coll = await db["test"]
186-
coros = []
187-
for i in range(100):
188-
coros.append(coll.insert({"a": i, "b": i + 1}))
189-
190-
await gather(*coros)
191-
await db.commit()
192-
193-
t0 = time()
194-
coros = []
195-
for i in range(100):
196-
coros.append(coll.update_one({"a": i, "b": 2 * i + 1}, a=i))
197-
await gather(*coros)
198-
await db.commit()
199-
t1 = time()
200-
dt = t1 - t0
201-
assert dt < 0.1
202-
await db.close()

tests/test_async_models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ async def test_update_model(db):
5151
await coll.insert(obj)
5252

5353
obj.b = "bar"
54-
await coll.update_many(obj, a=1)
54+
await coll.update(obj, a=1)
5555

5656
result = await coll.find_one(a=1)
5757
assert isinstance(result, MyModel)

tests/test_models.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def test_update_model():
5353
coll.insert(obj)
5454

5555
obj.b = "bar"
56-
coll.update_many(obj, a=1)
56+
coll.update(obj, a=1)
5757

5858
result = coll.find_one(a=1)
5959
assert isinstance(result, MyModel)
@@ -69,12 +69,12 @@ def test_update_without_filter_fails():
6969
obj = MyModel(a=1)
7070

7171
with pytest.raises(ValueError):
72-
coll.update_many(obj)
72+
coll.update(obj)
7373

7474

7575
def test_delete_without_filter_fails():
7676
db = Dante()
7777
coll = db[MyModel]
7878

7979
with pytest.raises(ValueError):
80-
coll.delete_many()
80+
coll.delete()

tests/test_sync.py

+6-48
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,12 @@ def test_find_none():
7878
assert result is None
7979

8080

81-
def test_update_one():
81+
def test_update():
8282
db = Dante()
8383
coll = db["test"]
8484

8585
coll.insert({"a": 1, "b": 2})
86-
coll.insert({"a": 1, "b": 3})
87-
coll.update_one({"a": 1, "b": 4}, a=1)
88-
result_bs = set(r["b"] for r in coll)
89-
assert result_bs == {2, 4} or result_bs == {3, 4}
90-
91-
92-
def test_update_many():
93-
db = Dante()
94-
coll = db["test"]
95-
96-
coll.insert({"a": 1, "b": 2})
97-
coll.update_many({"a": 1, "b": 3}, a=1)
86+
coll.update({"a": 1, "b": 3}, a=1)
9887
result = coll.find_one(a=1)
9988
assert result["b"] == 3
10089

@@ -103,27 +92,16 @@ def test_update_without_filter_fails():
10392
db = Dante()
10493
coll = db["test"]
10594
with pytest.raises(ValueError):
106-
coll.update_many({})
107-
108-
109-
def test_delete_one():
110-
db = Dante()
111-
coll = db["test"]
112-
113-
coll.insert({"a": 1, "b": 2})
114-
coll.insert({"a": 1, "b": 2})
115-
coll.delete_one(a=1)
116-
result = coll.find_many(a=1)
117-
assert len(result) == 1
95+
coll.update({})
11896

11997

120-
def test_delete_many():
98+
def test_delete():
12199
db = Dante()
122100
coll = db["test"]
123101

124102
coll.insert({"a": 1, "b": 2})
125103
coll.insert({"a": 1, "b": 3})
126-
coll.delete_many(a=1)
104+
coll.delete(a=1)
127105
result = coll.find_many(a=1)
128106
assert result == []
129107

@@ -132,9 +110,7 @@ def test_delete_without_filter_fails():
132110
db = Dante()
133111
coll = db["test"]
134112
with pytest.raises(ValueError):
135-
coll.delete_many()
136-
with pytest.raises(ValueError):
137-
coll.delete_one()
113+
coll.delete()
138114

139115

140116
def test_clear():
@@ -161,24 +137,6 @@ def test_insert_performance(tmp_path):
161137
assert dt < 0.05
162138

163139

164-
def test_update_performance(tmp_path):
165-
db_path = tmp_path / "test.db"
166-
db = Dante(db_path, auto_commit=False)
167-
168-
coll = db["test"]
169-
for i in range(100):
170-
coll.insert({"a": i, "b": i + 1})
171-
172-
db.commit()
173-
t0 = time()
174-
for i in range(100):
175-
coll.update_one({"a": i, "b": 2 * i + 1}, a=i)
176-
db.commit()
177-
t1 = time()
178-
dt = t1 - t0
179-
assert dt < 0.1
180-
181-
182140
def test_str():
183141
d = Dante()
184142
assert str(d) == '<Dante(":memory:")>'

0 commit comments

Comments
 (0)