Skip to content

Commit 629f832

Browse files
authored
Merge pull request #2 from immmdreza/master-entity
Master entity
2 parents 1a635af + dfefea7 commit 629f832

21 files changed

+688
-205
lines changed

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.1.5
3+
version = 0.1.2.5
44
author = immmdreza
55
author_email = ir310022@gmail.com
66
description = A simple and async json database.

src/examples/general_1.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# pylint: skip-file
2+
3+
import asyncio
4+
from datetime import datetime
5+
6+
from sjd import TEntity, Engine, properties as props, make_property, PropertyOptions
7+
8+
9+
@props.auto_collect()
10+
class Order(TEntity):
11+
12+
# A reference to order's owner ( a Customer instance )
13+
customer_id = props.reference()
14+
15+
# Description will be automatically collected from __init__ parameters.
16+
def __init__(self, description: str) -> None:
17+
self.description = description
18+
self._created_at_iso_fmt = datetime.now().isoformat() # private field
19+
20+
# Here our private property _created_at_iso_fmt will be covered by created_at
21+
# property, which is a python property as well as sjd property
22+
@make_property(
23+
str,
24+
options=PropertyOptions(init=False, required=True),
25+
binder="_created_at_iso_fmt", # Get or set from this, but save in created_at
26+
)
27+
def created_at(self):
28+
# _created_at_iso_fmt is an str field which stores an iso format of datetime
29+
return datetime.fromisoformat(self._created_at_iso_fmt)
30+
31+
32+
@props.auto_collect()
33+
class Customer(TEntity):
34+
35+
# A virtual list of orders, saved in a separate collection Order.
36+
orders = props.from_entities(Order, "customer_id")
37+
38+
def __init__(self, username: str, *orders: Order) -> None:
39+
self.username = username
40+
if orders:
41+
self.orders = list(orders)
42+
43+
44+
class AppEngine(Engine):
45+
__db_path__ = "__test_db__"
46+
customers = Engine.set(Customer)
47+
48+
# A custom method to create orders
49+
async def create_order(self, customer_username: str, order_description: str):
50+
customer = await self.customers.get_first_async("username", customer_username)
51+
if customer:
52+
# Iter over virtually saved orders
53+
async for order in self.customers.iter_referenced_by_async(
54+
customer, lambda c: c.orders
55+
):
56+
if order.description == order_description:
57+
return False
58+
59+
customer.orders.append(Order(order_description))
60+
else:
61+
customer = Customer(customer_username, Order(order_description))
62+
self.customers.add(customer)
63+
await self.customers.save_changes_async()
64+
return True
65+
66+
67+
async def main():
68+
69+
engine = AppEngine()
70+
71+
await engine.create_order("immmdreza", "Gimme some faith ...")
72+
await engine.create_order("immmdreza", "Gimme some hope ...")
73+
74+
75+
if __name__ == "__main__":
76+
asyncio.run(main())

src/examples/query_builders.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# pylint: skip-file
2+
3+
import asyncio
4+
import datetime
5+
from typing import Optional
6+
7+
from sjd import TEntity, Engine, properties as props
8+
9+
10+
@props.auto_collect()
11+
class Student(TEntity):
12+
def __init__(
13+
self,
14+
first_name: str,
15+
registered_date: datetime.datetime,
16+
last_name: Optional[str] = None,
17+
):
18+
self.first_name = first_name
19+
self.registered_date = registered_date
20+
self.last_name = last_name
21+
22+
23+
class AppEngine(Engine):
24+
__db_path__ = "__test_db__"
25+
students = Engine.set(Student)
26+
27+
28+
async def main():
29+
30+
engine = AppEngine()
31+
students_col = engine.students
32+
33+
students_col.add_range(
34+
Student("Johnny", datetime.datetime(2001, 7, 20), "Deep"),
35+
Student("Jececa", datetime.datetime(2000, 6, 10), "Doe"),
36+
Student("Jack", datetime.datetime(2001, 6, 5), "Makron"),
37+
)
38+
39+
await engine.save_changes_async()
40+
41+
target_date = datetime.datetime(2001, 1, 1)
42+
async for new_student in students_col.find_all_async(
43+
students_col.qa.gt(lambda s: s.registered_date, target_date)
44+
):
45+
print(new_student.first_name, new_student.last_name)
46+
# Johnny Deep
47+
# Jack Makron
48+
49+
50+
if __name__ == "__main__":
51+
asyncio.run(main())

src/examples/real_properties.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# pylint: skip-file
2+
3+
import asyncio
4+
from typing import Optional
5+
from uuid import uuid4
6+
7+
from sjd import TEntity, Engine, properties as props, make_property, PropertyOptions
8+
9+
10+
@props.auto_collect()
11+
class Student(TEntity):
12+
def __init__(self, first_name: str, last_name: Optional[str] = None):
13+
self.first_name = first_name
14+
self.last_name = last_name
15+
self._private_key = str(uuid4())
16+
17+
@make_property(
18+
str,
19+
options=PropertyOptions(init=False, required=True),
20+
binder="_private_key", # The serializations use this for getting or setting.
21+
)
22+
def private_key(self):
23+
# private_key is an actual property
24+
# Unless you dont define a setter, it's impossible to set value for it.
25+
return self._private_key
26+
27+
@private_key.setter # You can optionally define a setter or even deleter ...
28+
def private_key(self, _):
29+
raise AttributeError(
30+
"Attribute private_key can't be set after it's initialized"
31+
)
32+
33+
34+
class AppEngine(Engine):
35+
__db_path__ = "__test_db__"
36+
students = Engine.set(Student)
37+
38+
39+
async def main():
40+
41+
engine = AppEngine()
42+
students_col = engine.students
43+
44+
students_col.add_range(
45+
Student("Johhny", "Deep"),
46+
Student("Jececa", "Doe"),
47+
Student("Jack", "Makron"),
48+
)
49+
50+
await engine.save_changes_async()
51+
52+
async for student in students_col:
53+
print(student.private_key)
54+
# a77d0534-f09f-4977-81d7-55a0373155bc
55+
student.private_key = "My new blah"
56+
# AttributeError: Attribute private_key can't be set after it's initialized
57+
58+
59+
if __name__ == "__main__":
60+
asyncio.run(main())

src/examples/shifting_syntax.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import asyncio
2+
3+
from sjd import TEntity, Engine, properties as props
4+
5+
6+
@props.auto_collect()
7+
class Customer(TEntity):
8+
def __init__(self, name: str) -> None:
9+
self.name = name
10+
11+
12+
class AppEngine(Engine):
13+
__db_path__ = "__test_db__"
14+
customers = Engine.set(Customer)
15+
16+
17+
async def main():
18+
19+
engine = AppEngine()
20+
customers_collection = engine.customers
21+
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()
42+
43+
# NOTE: no other kind of shifting are allowed only these four!
44+
# ---------------------------------------------
45+
# To add:
46+
# one - Entity >> Collection of Entities
47+
# two - Collection of Entities <<= Entity, Entities
48+
# ---------------------------------------------
49+
# To delete:
50+
# three - Entity << Collection of Entities
51+
# four - Collection of Entities >>= Entity, Entities
52+
53+
# You see? Only four!
54+
55+
56+
if __name__ == "__main__":
57+
asyncio.run(main())

src/sjd/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from .database import Engine, Collection
22
from .entity import TEntity, EmbeddedEntity, properties
3+
from .entity._adv_property import make_property
4+
from .entity._property_options import PropertyOptions, PropertyBinder
35

46

57
__all__ = [
@@ -8,4 +10,7 @@
810
"TEntity",
911
"EmbeddedEntity",
1012
"properties",
13+
"make_property",
14+
"PropertyOptions",
15+
"PropertyBinder"
1116
]

0 commit comments

Comments
 (0)