Skip to content

Commit e16c710

Browse files
committed
feat: add Singleton metaclass
1 parent 49739b8 commit e16c710

File tree

5 files changed

+42
-12
lines changed

5 files changed

+42
-12
lines changed

examples/service/scripts/demo.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
"""
44
from asyncio import gather, run, sleep
55

6-
from fastapi_esql import timing
6+
from fastapi_esql import Singleton, timing
77

88
from .. import app
99

1010

11+
class Parent(metaclass=Singleton):pass
12+
13+
14+
class Child(Parent):pass
15+
16+
1117
async def work(sec):
1218
print(f"starting sleep {sec}")
1319
await sleep(sec)
@@ -21,6 +27,9 @@ async def main():
2127

2228
await gather(work(1), work(2), work(3))
2329

30+
print(id(Parent()), id(Parent()))
31+
print(id(Child()), id(Child()))
32+
2433

2534
if __name__ == "__main__":
2635
run(main())

fastapi_esql/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Cases,
1515
RawSQL,
1616
SQLizer,
17+
Singleton,
1718
timing,
1819
)
1920

@@ -29,6 +30,7 @@
2930
"Cases",
3031
"RawSQL",
3132
"SQLizer",
33+
"Singleton",
3234
"timing",
3335
]
3436

fastapi_esql/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .cursor_handler import CursorHandler
22
from .decorator import timing
3+
from .metaclass import Singleton
34
from .sqlizer import Cases, RawSQL, SQLizer

fastapi_esql/utils/metaclass.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from abc import ABCMeta
2+
3+
4+
class Singleton(ABCMeta):
5+
"""
6+
Singleton metaclass, using by:
7+
8+
>>> class Parent(BaseClass, metaclass=Singleton):pass
9+
>>> class Child(Parent):pass
10+
"""
11+
def __init__(self, *args, **kwargs):
12+
self.__instance = None
13+
super().__init__(*args, **kwargs)
14+
15+
def __call__(self, *args, **kwargs):
16+
if not self.__instance:
17+
self.__instance = super().__call__(*args, **kwargs)
18+
return self.__instance

fastapi_esql/utils/sqlizer.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from ..const.error import QsParsingError, WrongParamsError
1010

1111
logger = getLogger(__name__)
12-
# ensure the functionality of the RawSQL
12+
# To ensure the functionality of the RawSQL
1313
try:
1414
from tortoise.expressions import RawSQL
1515
except ImportError:
@@ -34,10 +34,10 @@ def __init__(self, field: str, whens: dict, default=None):
3434
@property
3535
def sql(self):
3636
whens = " ".join(
37-
f"WHEN {k} THEN {SQLizer._sqlize_value(v)}"
37+
f"WHEN {k} THEN {SQLizer.sqlize_value(v)}"
3838
for k, v in self.whens.items()
3939
)
40-
else_ = " ELSE " + SQLizer._sqlize_value(self.default) if self.default is not None else ""
40+
else_ = " ELSE " + SQLizer.sqlize_value(self.default) if self.default is not None else ""
4141
return f"CASE {self.field} {whens}{else_} END"
4242

4343

@@ -68,7 +68,7 @@ def resolve_wheres(
6868

6969
modifier = QueryModifier()
7070
for q in qs:
71-
# NOTE method `Q.resolve` changed since V0.18.0
71+
# NOTE Method `Q.resolve` changed since version 0.18.0
7272
# https://github.com/tortoise/tortoise-orm/commit/37178e175bc12bc4767b93142dab0209f9240c55
7373
if __version__ >= "0.18.0":
7474
modifier &= q.resolve(model, model._meta.basetable)
@@ -88,7 +88,7 @@ def resolve_orders(cls, orders: List[str]) -> str:
8888
return ", ".join(orders_)
8989

9090
@classmethod
91-
def _sqlize_value(cls, value, to_json=False) -> str:
91+
def sqlize_value(cls, value, to_json=False) -> str:
9292
"""
9393
Works like aiomysql.connection.Connection.escape
9494
"""
@@ -169,12 +169,12 @@ def update_json_field(
169169
json_obj = f"JSON_REMOVE({json_obj}, {rps})"
170170
if path_value_dict:
171171
pvs = [
172-
f"'{path}',{cls._sqlize_value(value, to_json=True)}"
172+
f"'{path}',{cls.sqlize_value(value, to_json=True)}"
173173
for (path, value) in path_value_dict.items()
174174
]
175175
json_obj = f"JSON_SET({json_obj}, {', '.join(pvs)})"
176176
if merge_dict:
177-
json_obj = f"JSON_MERGE_PATCH({json_obj}, {cls._sqlize_value(merge_dict)})"
177+
json_obj = f"JSON_MERGE_PATCH({json_obj}, {cls.sqlize_value(merge_dict)})"
178178

179179
sql = f"""
180180
UPDATE {table} SET {json_field} =
@@ -196,7 +196,7 @@ def upsert_on_duplicate(
196196
raise WrongParamsError("Please check your params")
197197

198198
values = [
199-
f"({', '.join(cls._sqlize_value(d.get(f)) for f in insert_fields)})"
199+
f"({', '.join(cls.sqlize_value(d.get(f)) for f in insert_fields)})"
200200
for d in dicts
201201
]
202202
# NOTE Beginning with MySQL 8.0.19, it is possible to use an alias for the row
@@ -236,7 +236,7 @@ def insert_into_select(
236236
assign_fields = []
237237
for k, v in assign_field_dict.items():
238238
fields.append(k)
239-
assign_fields.append(f"{cls._sqlize_value(v)} {k}")
239+
assign_fields.append(f"{cls.sqlize_value(v)} {k}")
240240

241241
sql = f"""
242242
INSERT INTO {to_table or table}
@@ -259,14 +259,14 @@ def build_fly_table(
259259

260260
if using_values:
261261
rows = [
262-
f"ROW({', '.join(cls._sqlize_value(d.get(f)) for f in fields)})"
262+
f"ROW({', '.join(cls.sqlize_value(d.get(f)) for f in fields)})"
263263
for d in dicts
264264
]
265265
values = "VALUES\n " + ", ".join(rows)
266266
table = f"fly_table ({', '.join(fields)})"
267267
else:
268268
rows = [
269-
f"SELECT {', '.join(f'{cls._sqlize_value(d.get(f))} {f}' for f in fields)}"
269+
f"SELECT {', '.join(f'{cls.sqlize_value(d.get(f))} {f}' for f in fields)}"
270270
for d in dicts
271271
]
272272
values = " UNION ".join(rows)

0 commit comments

Comments
 (0)