Skip to content

Commit c2cc10c

Browse files
authored
Merge pull request #3 from immmdreza/master-entity
Change how __aenter__ works on collections ( now saves on exit ).
2 parents 27d3d7f + ca624fa commit c2cc10c

File tree

5 files changed

+51
-47
lines changed

5 files changed

+51
-47
lines changed

README.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ This is a simple json database.
44
The package provides a simple ORM between python objects and
55
json objects with a well type-hinted schema.
66

7+
```py
8+
engine = AppEngine()
9+
10+
async with engine.students as students:
11+
students.add_range(Student("John", "Doe"), Student("Jane", "Doe"))
12+
13+
async for student in engine.students:
14+
print(student.first_name, student.last_name)
15+
# Can you guess ? )
16+
```
17+
718
This package maps your python objects to json and then you can save, get,
819
modify or delete them using async methods.
920

@@ -64,7 +75,8 @@ the model will automatically collect properties form `__init__` method.
6475

6576
### Creating collection ?
6677

67-
It's really not necessary to create a collection by your own! And maybe you better )
78+
It's really not necessary to create a collection by your own!
79+
And maybe you better )
6880

6981
Let us do that for ya ( Of course you can create customized Collections ).
7082

@@ -76,11 +88,8 @@ Now you need to setup database's engine and define your collections there.
7688
# ---- sniff ----
7789

7890
class AppEngine(Engine):
79-
91+
__db_path__ = "my_database"
8092
persons = Engine.set(Person)
81-
82-
def __init__(self):
83-
super().__init__("MoyDatabase")
8493
```
8594

8695
That's all you need to do for now.
@@ -112,13 +121,13 @@ async def main():
112121
engine = AppEngine()
113122
collection = engine.persons
114123

115-
collection.add_range(
116-
Person("John", "Doe", 20),
117-
Person("Jane", "Doe", 21),
118-
Person("Jack", "jones", 22),
119-
Person("Jill", "jones", 23),
120-
)
121-
await collection.save_changes_async()
124+
async with collection:
125+
collection.add_range(
126+
Person("John", "Doe", 20),
127+
Person("Jane", "Doe", 21),
128+
Person("Jack", "jones", 22),
129+
Person("Jill", "jones", 23),
130+
)
122131

123132
```
124133

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = json-entity
3-
version = 0.1.2.5
3+
version = 0.1.3.1
44
author = immmdreza
55
author_email = ir310022@gmail.com
66
description = A simple and async json database.

src/examples/shifting_syntax.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,24 @@ async def main():
1919
engine = AppEngine()
2020
customers_collection = engine.customers
2121

22-
customers_collection <<= Customer("Arash"), Customer("Sara")
23-
tracked = Customer("Kiarash") >> customers_collection
24-
# Both of above ways will call add() method of customers_collection
25-
# using second way, you can only add one! but you receive a free tracking instance
26-
# which contains information about changes in entity, and entity id.
27-
print("A new entity will be added with id:", tracked.key)
28-
29-
await customers_collection.save_changes_async()
30-
31-
async for customer in customers_collection:
32-
customers_collection >>= customer
33-
# Using above syntax is same as calling: customers_collection.delete(customer)
34-
break
35-
36-
# Again, using below syntax, you can get tracking instance as well.
37-
async for customer in customers_collection:
38-
tracked = customer << customers_collection
39-
print(f"An entity with id {tracked.key}, is going to be deleted!")
40-
41-
await customers_collection.save_changes_async()
22+
async with customers_collection: # <-- this will save changes automatically on exit
23+
customers_collection <<= Customer("Arash"), Customer("Sara")
24+
tracked = Customer("Kiarash") >> customers_collection
25+
# Both of above ways will call add() method of customers_collection
26+
# using second way, you can only add one! but you receive a free tracking instance
27+
# which contains information about changes in entity, and entity id.
28+
print("A new entity will be added with id:", tracked.key)
29+
30+
async with customers_collection:
31+
async for customer in customers_collection:
32+
customers_collection >>= customer
33+
# Using above syntax is same as calling: customers_collection.delete(customer)
34+
break
35+
36+
# Again, using below syntax, you can get tracking instance as well.
37+
async for customer in customers_collection:
38+
tracked = customer << customers_collection
39+
print(f"An entity with id {tracked.key}, is going to be deleted!")
4240

4341
# NOTE: no other kind of shifting are allowed only these four!
4442
# ---------------------------------------------

src/examples/very_simple.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ def __init__(self, first_name: str, last_name: Optional[str] = None):
1515

1616
class AppEngine(Engine):
1717
__db_path__ = "__test_db__"
18-
1918
students = Engine.set(Student)
2019

2120

2221
async def main():
2322

2423
engine = AppEngine()
2524

26-
engine.students.add(Student("John", "Doe"))
27-
await engine.save_changes_async()
25+
async with engine.students as students:
26+
students.add_range(Student("John", "Doe"), Student("Jane", "Doe"))
27+
28+
async for student in engine.students:
29+
print(student.first_name, student.last_name)
2830

2931

3032
if __name__ == "__main__":

src/sjd/database/_collection.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,15 @@ def __init__(self, engine: "Engine", /) -> None:
143143
self._engine = engine
144144

145145
self._main_file_lock = asyncio.Lock()
146-
self._main_iter_ctx: Optional[
147-
_CollectionQueryableContext[_TMasterEntity, _TKey, T]
148-
] = None
149146
self._entity_trackers: dict[_TKey, _EntityTracker[_TKey, T]] = {}
150147

151148
async def __aenter__(self):
152-
self._main_iter_ctx = self.get_queryable()
153-
return self._main_iter_ctx
149+
"""Enters a context that will save all changes when it is closed."""
150+
return self
154151

155-
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any):
156-
if self._main_iter_ctx is not None:
157-
if not self._main_iter_ctx.closed:
158-
await self._main_iter_ctx.close()
159-
self._main_iter_ctx = None
152+
async def __aexit__(self, exc_type, exc_val, exc_tb):
153+
"""Saves all changes made to the collection."""
154+
await self.save_changes_async()
160155

161156
async def __aiter__(self):
162157
async with self.get_queryable() as tmp_file:
@@ -706,7 +701,7 @@ async def count_async(self) -> int:
706701
"""Count the number of entities in the collection."""
707702

708703
await self._ensure_collection_exists()
709-
async with self as iter_ctx:
704+
async with self.get_queryable() as iter_ctx:
710705
count = 0
711706
async for _ in iter_ctx.iter_lines():
712707
count += 1

0 commit comments

Comments
 (0)