wiederverwendbar 0.8.6__py3-none-any.whl → 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wiederverwendbar/__init__.py +8 -6
- wiederverwendbar/branding/__init__.py +1 -0
- wiederverwendbar/branding/settings.py +85 -0
- wiederverwendbar/console/__init__.py +3 -0
- wiederverwendbar/console/console.py +199 -0
- wiederverwendbar/console/out_files.py +19 -0
- wiederverwendbar/console/settings.py +9 -0
- wiederverwendbar/default.py +4 -1
- wiederverwendbar/fastapi/__init__.py +3 -0
- wiederverwendbar/fastapi/app.py +385 -0
- wiederverwendbar/fastapi/dependencies.py +11 -0
- wiederverwendbar/fastapi/settings.py +39 -0
- wiederverwendbar/functions/is_coroutine_function.py +19 -0
- wiederverwendbar/inspect.py +26 -0
- wiederverwendbar/logger/__init__.py +0 -1
- wiederverwendbar/logger/handlers/rich_console_handler.py +15 -6
- wiederverwendbar/logger/handlers/stream_console_handler.py +3 -16
- wiederverwendbar/logger/log_levels.py +2 -3
- wiederverwendbar/logger/settings.py +15 -20
- wiederverwendbar/rich/__init__.py +2 -0
- wiederverwendbar/rich/console.py +215 -0
- wiederverwendbar/rich/settings.py +26 -0
- wiederverwendbar/typer/__init__.py +3 -1
- wiederverwendbar/typer/app.py +172 -0
- wiederverwendbar/typer/settings.py +14 -0
- {wiederverwendbar-0.8.6.dist-info → wiederverwendbar-0.9.0.dist-info}/METADATA +9 -6
- {wiederverwendbar-0.8.6.dist-info → wiederverwendbar-0.9.0.dist-info}/RECORD +29 -45
- wiederverwendbar/examples/__init__.py +0 -0
- wiederverwendbar/examples/before_after_wrap.py +0 -74
- wiederverwendbar/examples/colors.py +0 -16
- wiederverwendbar/examples/extended_thread.py +0 -28
- wiederverwendbar/examples/file_config.py +0 -11
- wiederverwendbar/examples/indexable_model.py +0 -19
- wiederverwendbar/examples/logger.py +0 -31
- wiederverwendbar/examples/logger_context/__init__.py +0 -0
- wiederverwendbar/examples/logger_context/example.py +0 -58
- wiederverwendbar/examples/logger_context/example_module.py +0 -13
- wiederverwendbar/examples/mongoengine/__init__.py +0 -0
- wiederverwendbar/examples/mongoengine/automatic_reference.py +0 -25
- wiederverwendbar/examples/mongoengine/db.py +0 -7
- wiederverwendbar/examples/mongoengine/log_streamer.py +0 -9
- wiederverwendbar/examples/mongoengine/logger.py +0 -25
- wiederverwendbar/examples/post_init.py +0 -29
- wiederverwendbar/examples/route.py +0 -12
- wiederverwendbar/examples/singletons.py +0 -59
- wiederverwendbar/examples/sqlalchemy/__init__.py +0 -0
- wiederverwendbar/examples/sqlalchemy/db.py +0 -89
- wiederverwendbar/examples/starlette_admin/__init__.py +0 -0
- wiederverwendbar/examples/starlette_admin/action_log.py +0 -126
- wiederverwendbar/examples/starlette_admin/action_log_file_download.py +0 -99
- wiederverwendbar/examples/starlette_admin/action_log_form.py +0 -149
- wiederverwendbar/examples/starlette_admin/action_log_thread.py +0 -192
- wiederverwendbar/examples/starlette_admin/automatic_reference_admin.py +0 -47
- wiederverwendbar/examples/starlette_admin/generic_embedded_document_field.py +0 -74
- wiederverwendbar/examples/starlette_admin/multi_path_admin.py +0 -18
- wiederverwendbar/examples/task_manager.py +0 -55
- wiederverwendbar/examples/test_file.py +0 -14
- wiederverwendbar/examples/typer_resolve_defaults.py +0 -15
- wiederverwendbar/examples/uvicorn_server.py +0 -32
- wiederverwendbar/logger/terminal_out_files.py +0 -10
- {wiederverwendbar-0.8.6.dist-info → wiederverwendbar-0.9.0.dist-info}/WHEEL +0 -0
- {wiederverwendbar-0.8.6.dist-info → wiederverwendbar-0.9.0.dist-info}/entry_points.txt +0 -0
@@ -1,74 +0,0 @@
|
|
1
|
-
from wiederverwendbar.before_after_wrap import WrappedClass, wrap
|
2
|
-
|
3
|
-
|
4
|
-
class BaseClass(metaclass=WrappedClass):
|
5
|
-
def before_cls_test1(self, __ba_before_result__):
|
6
|
-
print("before_cls_test1")
|
7
|
-
|
8
|
-
@wrap(before=before_cls_test1, after="after_cls_test1")
|
9
|
-
def cls_test1(self, __ba_before_result__):
|
10
|
-
print("cls_test1")
|
11
|
-
|
12
|
-
def after_cls_test1(self, __ba_result__):
|
13
|
-
print("after_cls_test1")
|
14
|
-
|
15
|
-
def before_cls_test2(self):
|
16
|
-
print("before_cls_test2")
|
17
|
-
|
18
|
-
@wrap(before=before_cls_test2, after="after_cls_test2")
|
19
|
-
def cls_test2(self):
|
20
|
-
print("cls_test2")
|
21
|
-
|
22
|
-
def after_cls_test2(self):
|
23
|
-
print("after_cls_test2")
|
24
|
-
|
25
|
-
|
26
|
-
class ChildClass(BaseClass):
|
27
|
-
def before_cls_test1A(self):
|
28
|
-
print("before_cls_test1A")
|
29
|
-
|
30
|
-
@wrap(before=before_cls_test1A, after="after_cls_test1A", include_base=False)
|
31
|
-
def cls_test1(self, __ba_before_result__):
|
32
|
-
super().cls_test1(__ba_use__=False)
|
33
|
-
print("cls_test1A")
|
34
|
-
|
35
|
-
def after_cls_test1A(self):
|
36
|
-
print("after_cls_test1A")
|
37
|
-
|
38
|
-
def before_cls_test3(self):
|
39
|
-
print("before_cls_test3")
|
40
|
-
|
41
|
-
@wrap(before=before_cls_test3, after="after_cls_test3")
|
42
|
-
def cls_test3(self):
|
43
|
-
print("cls_test3")
|
44
|
-
|
45
|
-
def after_cls_test3(self):
|
46
|
-
print("after_cls_test3")
|
47
|
-
|
48
|
-
|
49
|
-
def before_test1(*_, **__):
|
50
|
-
print("before_test1")
|
51
|
-
|
52
|
-
|
53
|
-
@wrap(before=before_test1, after="after_test1")
|
54
|
-
def test1(arg1: str):
|
55
|
-
print(f"test1 -> {arg1}")
|
56
|
-
|
57
|
-
|
58
|
-
def after_test1(*_, **__):
|
59
|
-
print("after_test1")
|
60
|
-
|
61
|
-
|
62
|
-
if __name__ == "__main__":
|
63
|
-
base_class = BaseClass()
|
64
|
-
base_class.cls_test1()
|
65
|
-
base_class.cls_test2()
|
66
|
-
|
67
|
-
child_class = ChildClass()
|
68
|
-
child_class.cls_test1()
|
69
|
-
child_class.cls_test2()
|
70
|
-
child_class.cls_test3()
|
71
|
-
|
72
|
-
test1("qwe")
|
73
|
-
|
74
|
-
|
@@ -1,16 +0,0 @@
|
|
1
|
-
from wiederverwendbar.functions.colors import Color
|
2
|
-
|
3
|
-
if __name__ == '__main__':
|
4
|
-
color = Color(red=255, green=0, blue=0, alpha=0.5)
|
5
|
-
color_str_rgb = color.as_rgb()
|
6
|
-
color_str_rgba = color.as_rgba()
|
7
|
-
color_str_hex = color.as_hex()
|
8
|
-
color_str_hex_short = color.from_str("a0a")
|
9
|
-
|
10
|
-
print("Color Class: ", color)
|
11
|
-
print("Color RGB: ", color_str_rgb)
|
12
|
-
print("Color RGBA: ", color_str_rgba)
|
13
|
-
print("Color HEX: ", color_str_hex)
|
14
|
-
print("Color HEX Short: ", color_str_hex_short)
|
15
|
-
|
16
|
-
print()
|
@@ -1,28 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
from typing import Union
|
3
|
-
|
4
|
-
from wiederverwendbar.threading import ExtendedThread
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def test_watchdog(self: ExtendedThread):
|
9
|
-
return True
|
10
|
-
|
11
|
-
|
12
|
-
def thread_target(*args, **kwargs):
|
13
|
-
print("loop", args, kwargs)
|
14
|
-
|
15
|
-
|
16
|
-
if __name__ == '__main__':
|
17
|
-
thread = ExtendedThread(name="test", target=thread_target, args=(1, 2), kwargs={"a": 1}, loop_sleep_time=1, watchdog_target=test_watchdog)
|
18
|
-
|
19
|
-
while True:
|
20
|
-
try:
|
21
|
-
time.sleep(3)
|
22
|
-
with thread.loop_wait():
|
23
|
-
print("main thread")
|
24
|
-
time.sleep(5)
|
25
|
-
except KeyboardInterrupt:
|
26
|
-
break
|
27
|
-
# thread.stop()
|
28
|
-
# thread.raise_exception(Exception("hallo welt"))
|
@@ -1,19 +0,0 @@
|
|
1
|
-
from wiederverwendbar.pydantic.indexable_model import IndexableModel
|
2
|
-
|
3
|
-
|
4
|
-
class Config(IndexableModel):
|
5
|
-
asd: int = 123
|
6
|
-
qwe: str = "qwe"
|
7
|
-
yxc: bool = False
|
8
|
-
|
9
|
-
|
10
|
-
if __name__ == '__main__':
|
11
|
-
config = Config()
|
12
|
-
|
13
|
-
asd = config["asd"]
|
14
|
-
qwe = config["qwe"]
|
15
|
-
yxc = config["yxc"]
|
16
|
-
|
17
|
-
asd_1 = config[0]
|
18
|
-
qwe_1 = config[1]
|
19
|
-
yxc_1 = config[2]
|
@@ -1,31 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
from wiederverwendbar.logger import LoggerSingleton
|
4
|
-
from wiederverwendbar.logger import LoggerSettings
|
5
|
-
|
6
|
-
import uvicorn
|
7
|
-
from fastapi import FastAPI
|
8
|
-
|
9
|
-
|
10
|
-
if __name__ == '__main__':
|
11
|
-
logger = LoggerSingleton(init=True, name="test", settings=LoggerSettings(log_level="DEBUG"), ignored_loggers_like=["uvicorn"])
|
12
|
-
|
13
|
-
sub_logger = logging.getLogger("sub")
|
14
|
-
|
15
|
-
logger.debug("debug")
|
16
|
-
logger.info("info")
|
17
|
-
logger.warning("warning")
|
18
|
-
logger.error("error")
|
19
|
-
logger.critical("critical")
|
20
|
-
|
21
|
-
sub_logger.debug("debug")
|
22
|
-
sub_logger.info("info")
|
23
|
-
sub_logger.warning("warning")
|
24
|
-
sub_logger.error("error")
|
25
|
-
sub_logger.critical("critical")
|
26
|
-
|
27
|
-
app = FastAPI()
|
28
|
-
|
29
|
-
uvicorn.run(app, host="0.0.0.0", port=8000)
|
30
|
-
|
31
|
-
print()
|
File without changes
|
@@ -1,58 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import sys
|
3
|
-
import threading
|
4
|
-
|
5
|
-
from wiederverwendbar.logger import LoggingContext
|
6
|
-
from wiederverwendbar.logger import LoggerSingleton, LoggerSettings
|
7
|
-
|
8
|
-
from wiederverwendbar.examples.logger_context.example_module import example_function
|
9
|
-
|
10
|
-
LoggerSingleton(init=True, name="test", settings=LoggerSettings(log_level="DEBUG"), ignored_loggers_like=["logger1", "logger2"])
|
11
|
-
|
12
|
-
logger1 = logging.getLogger("logger1")
|
13
|
-
ch = logging.StreamHandler()
|
14
|
-
ch.setLevel(logging.DEBUG)
|
15
|
-
ch.setFormatter(logging.Formatter('logger1 - %(name)s - %(levelname)s - %(message)s'))
|
16
|
-
logger1.addHandler(ch)
|
17
|
-
logger1.setLevel(logging.DEBUG)
|
18
|
-
|
19
|
-
logger2 = logging.getLogger("logger2")
|
20
|
-
ch = logging.StreamHandler()
|
21
|
-
ch.setLevel(logging.DEBUG)
|
22
|
-
ch.setFormatter(logging.Formatter('logger2 - %(name)s - %(levelname)s - %(message)s'))
|
23
|
-
logger2.addHandler(ch)
|
24
|
-
logger2.setLevel(logging.DEBUG)
|
25
|
-
|
26
|
-
|
27
|
-
def test_thread():
|
28
|
-
while True:
|
29
|
-
# generate log messages on different loggers
|
30
|
-
example_function()
|
31
|
-
|
32
|
-
|
33
|
-
# start test thread
|
34
|
-
thread = threading.Thread(target=test_thread, daemon=True)
|
35
|
-
thread.start()
|
36
|
-
|
37
|
-
if __name__ == '__main__':
|
38
|
-
# no context
|
39
|
-
logger1.debug("no context")
|
40
|
-
logger2.debug("no context")
|
41
|
-
|
42
|
-
with LoggingContext(logger1, handle_origin_logger=False) as context1_a:
|
43
|
-
with LoggingContext(logger2, handle_origin_logger=False) as context2_a:
|
44
|
-
example_function()
|
45
|
-
example_function()
|
46
|
-
example_function()
|
47
|
-
|
48
|
-
with LoggingContext(logger1):
|
49
|
-
with LoggingContext(logger2):
|
50
|
-
example_function()
|
51
|
-
example_function()
|
52
|
-
example_function()
|
53
|
-
|
54
|
-
# again no context
|
55
|
-
logger1.debug("again no context")
|
56
|
-
logger2.debug("again no context")
|
57
|
-
|
58
|
-
sys.exit(0)
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import time
|
3
|
-
|
4
|
-
logger = logging.getLogger(__name__)
|
5
|
-
|
6
|
-
|
7
|
-
def example_function():
|
8
|
-
logger.debug("example_function")
|
9
|
-
func_logger = logging.getLogger(__name__ + ".example_function")
|
10
|
-
time.sleep(1)
|
11
|
-
func_logger.debug("debug")
|
12
|
-
time.sleep(1)
|
13
|
-
return
|
File without changes
|
@@ -1,25 +0,0 @@
|
|
1
|
-
from mongoengine import ListField, ReferenceField, StringField
|
2
|
-
|
3
|
-
from wiederverwendbar.mongoengine import AutomaticReferenceDocument
|
4
|
-
|
5
|
-
|
6
|
-
# --- example classes ---
|
7
|
-
|
8
|
-
class Test1(AutomaticReferenceDocument):
|
9
|
-
meta = {"collection": "test1"}
|
10
|
-
|
11
|
-
name = StringField(required=True)
|
12
|
-
test2_one_to_one = ReferenceField("Test2", automatic_reference="test1_one_to_one")
|
13
|
-
test2_one_to_many = ReferenceField("Test2", automatic_reference="test1_many_to_one")
|
14
|
-
test2_many_to_one = ListField(ReferenceField("Test2"), automatic_reference="test1_one_to_many")
|
15
|
-
test2_many_to_many = ListField(ReferenceField("Test2"), automatic_reference="test1_many_to_many")
|
16
|
-
|
17
|
-
|
18
|
-
class Test2(AutomaticReferenceDocument):
|
19
|
-
meta = {"collection": "test2"}
|
20
|
-
|
21
|
-
name = StringField(required=True)
|
22
|
-
test1_one_to_one = ReferenceField("Test1", automatic_reference="test2_one_to_one")
|
23
|
-
test1_one_to_many = ReferenceField("Test1", automatic_reference="test2_many_to_one")
|
24
|
-
test1_many_to_one = ListField(ReferenceField("Test1"), automatic_reference="test2_one_to_many")
|
25
|
-
test1_many_to_many = ListField(ReferenceField("Test1"), automatic_reference="test2_many_to_many")
|
@@ -1,7 +0,0 @@
|
|
1
|
-
from wiederverwendbar.logger import LoggerSingleton, LoggerSettings
|
2
|
-
from wiederverwendbar.mongoengine import MongoengineDbSingleton
|
3
|
-
|
4
|
-
LoggerSingleton(name="test", settings=LoggerSettings(log_level=LoggerSettings.LogLevels.DEBUG), init=True)
|
5
|
-
|
6
|
-
if __name__ == '__main__':
|
7
|
-
MongoengineDbSingleton(init=True)
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
|
3
|
-
from wiederverwendbar.examples.mongoengine.logger import MyMongoengineLogDocument
|
4
|
-
from wiederverwendbar.mongoengine import MongoengineLogStreamer
|
5
|
-
|
6
|
-
if __name__ == '__main__':
|
7
|
-
with MongoengineLogStreamer(MyMongoengineLogDocument) as streamer:
|
8
|
-
while True:
|
9
|
-
time.sleep(1)
|
@@ -1,25 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
from mongoengine import StringField
|
4
|
-
|
5
|
-
from wiederverwendbar.mongoengine import MongoengineDbSingleton, MongoengineLogDocument, MongoengineLogHandler
|
6
|
-
|
7
|
-
MongoengineDbSingleton(init=True)
|
8
|
-
|
9
|
-
|
10
|
-
class MyMongoengineLogDocument(MongoengineLogDocument):
|
11
|
-
meta = {"collection": "log.test"}
|
12
|
-
|
13
|
-
test = StringField(required=True)
|
14
|
-
|
15
|
-
|
16
|
-
logger = logging.getLogger("test123")
|
17
|
-
|
18
|
-
logger.addHandler(logging.StreamHandler())
|
19
|
-
logger.addHandler(MongoengineLogHandler(document=MyMongoengineLogDocument, document_kwargs={"test": "test"}))
|
20
|
-
|
21
|
-
logger.setLevel(logging.DEBUG)
|
22
|
-
|
23
|
-
if __name__ == '__main__':
|
24
|
-
logger.debug("Hello")
|
25
|
-
logger.debug("Hello")
|
@@ -1,29 +0,0 @@
|
|
1
|
-
from wiederverwendbar.post_init import PostInit
|
2
|
-
|
3
|
-
class MyParentClass(PostInit):
|
4
|
-
def __init__(self, parent_attr: str):
|
5
|
-
super().__init__()
|
6
|
-
|
7
|
-
self.parent_attr = parent_attr
|
8
|
-
|
9
|
-
print(f"Parent attribute: {parent_attr}")
|
10
|
-
|
11
|
-
def __post_init__(self):
|
12
|
-
print(f"Parent post init attribute: {self.parent_attr}")
|
13
|
-
|
14
|
-
|
15
|
-
class MyClass(MyParentClass):
|
16
|
-
def __init__(self, my_attr: str, parent_attr: str):
|
17
|
-
super().__init__(parent_attr=parent_attr)
|
18
|
-
|
19
|
-
self.my_attr = my_attr
|
20
|
-
|
21
|
-
print(f"My attribute: {my_attr}")
|
22
|
-
|
23
|
-
def __post_init__(self):
|
24
|
-
super().__post_init__()
|
25
|
-
print(f"My post init attribute: {self.my_attr}")
|
26
|
-
|
27
|
-
|
28
|
-
if __name__ == '__main__':
|
29
|
-
my_class = MyClass(my_attr="My attribute", parent_attr="Parent attribute")
|
@@ -1,12 +0,0 @@
|
|
1
|
-
from ipaddress import IPv4Network, IPv4Address
|
2
|
-
|
3
|
-
from wiederverwendbar.route import RouteManager, Route
|
4
|
-
|
5
|
-
if __name__ == '__main__':
|
6
|
-
route_manager = RouteManager()
|
7
|
-
test_route = Route(target=IPv4Network("192.168.200.0/24"), gateway=IPv4Address("192.168.65.1"))
|
8
|
-
result_add = route_manager.create(test_route)
|
9
|
-
all_routes = route_manager.get_all()
|
10
|
-
result_delete = route_manager.delete(test_route)
|
11
|
-
|
12
|
-
print()
|
@@ -1,59 +0,0 @@
|
|
1
|
-
from pydantic import BaseModel
|
2
|
-
|
3
|
-
from wiederverwendbar.logger import LoggerSingleton, LoggerSettings
|
4
|
-
from wiederverwendbar.pydantic import ModelSingleton
|
5
|
-
from wiederverwendbar.singleton import Singleton
|
6
|
-
|
7
|
-
logger = LoggerSingleton(init=True, name="test", settings=LoggerSettings(log_level="DEBUG"), ignored_loggers_like=["uvicorn"])
|
8
|
-
|
9
|
-
|
10
|
-
class A(metaclass=Singleton, order=3):
|
11
|
-
def __init__(self):
|
12
|
-
print("A created")
|
13
|
-
|
14
|
-
def __del__(self):
|
15
|
-
print("A deleted")
|
16
|
-
|
17
|
-
|
18
|
-
class B(metaclass=Singleton, order=2):
|
19
|
-
def __init__(self):
|
20
|
-
print("B created")
|
21
|
-
|
22
|
-
def __del__(self):
|
23
|
-
print("B deleted")
|
24
|
-
|
25
|
-
|
26
|
-
class C(metaclass=Singleton, order=1):
|
27
|
-
def __init__(self):
|
28
|
-
print("C created")
|
29
|
-
|
30
|
-
def __del__(self):
|
31
|
-
print("C deleted")
|
32
|
-
|
33
|
-
|
34
|
-
class Model(BaseModel, metaclass=ModelSingleton):
|
35
|
-
qwe: str
|
36
|
-
|
37
|
-
|
38
|
-
Model(qwe="qwe", init=True)
|
39
|
-
|
40
|
-
|
41
|
-
def init():
|
42
|
-
A(init=True)
|
43
|
-
B(init=True)
|
44
|
-
C(init=True)
|
45
|
-
print("init")
|
46
|
-
|
47
|
-
|
48
|
-
def main():
|
49
|
-
a = A()
|
50
|
-
b = B()
|
51
|
-
c = C()
|
52
|
-
|
53
|
-
print("main")
|
54
|
-
|
55
|
-
|
56
|
-
if __name__ == '__main__':
|
57
|
-
Singleton.delete_ordered_on_exit = True
|
58
|
-
init()
|
59
|
-
main()
|
File without changes
|
@@ -1,89 +0,0 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from typing import Optional
|
3
|
-
|
4
|
-
from sqlalchemy import Column, ForeignKey, Integer, Text
|
5
|
-
|
6
|
-
from sqlalchemy.orm import relationship
|
7
|
-
|
8
|
-
from wiederverwendbar.logger import LoggerSingleton, LoggerSettings, LogLevels
|
9
|
-
from wiederverwendbar.sqlalchemy import Base, SqlalchemySettings, SqlalchemyDbSingleton
|
10
|
-
|
11
|
-
LoggerSingleton(name="test", settings=LoggerSettings(log_level=LogLevels.DEBUG), init=True)
|
12
|
-
SqlalchemyDbSingleton(settings=SqlalchemySettings(db_file=Path("test.db")), init=True)
|
13
|
-
|
14
|
-
|
15
|
-
class MyBase(Base, SqlalchemyDbSingleton().Base):
|
16
|
-
__abstract__ = True
|
17
|
-
|
18
|
-
|
19
|
-
class Parent(MyBase):
|
20
|
-
__tablename__ = "parent"
|
21
|
-
__str_columns__: list[str] = ["id", "name"]
|
22
|
-
|
23
|
-
id: int = Column(Integer(), primary_key=True, autoincrement=True, name="parent_id")
|
24
|
-
name: str = Column(Text(50), nullable=False, unique=True)
|
25
|
-
children: list["Child"] = relationship("Child",
|
26
|
-
foreign_keys="Child.parent_id",
|
27
|
-
primaryjoin="Parent.id == Child.parent_id",
|
28
|
-
viewonly=True)
|
29
|
-
|
30
|
-
|
31
|
-
class Child(MyBase):
|
32
|
-
__tablename__ = "child"
|
33
|
-
__str_columns__: list[str] = ["id", "name"]
|
34
|
-
|
35
|
-
id: int = Column(Integer(), primary_key=True, autoincrement=True, name="parent_id")
|
36
|
-
name: str = Column(Text(50), nullable=False, unique=True)
|
37
|
-
parent_id: int = Column(Integer(), ForeignKey("parent.parent_id"), nullable=False, name="child_parent_id")
|
38
|
-
parent: Optional[Parent] = relationship("Parent",
|
39
|
-
foreign_keys="Parent.id",
|
40
|
-
primaryjoin="Child.parent_id == Parent.id")
|
41
|
-
|
42
|
-
|
43
|
-
if __name__ == '__main__':
|
44
|
-
SqlalchemyDbSingleton().create_all()
|
45
|
-
|
46
|
-
parent1 = Parent.get(name="parent1")
|
47
|
-
if parent1 is None:
|
48
|
-
parent1 = Parent(name="parent1")
|
49
|
-
parent1.save()
|
50
|
-
|
51
|
-
child1 = Child.get(name="child1")
|
52
|
-
if child1 is None:
|
53
|
-
child1 = Child(name="child1", parent_id=parent1.id)
|
54
|
-
child1.save()
|
55
|
-
|
56
|
-
child2 = Child.get(name="child2")
|
57
|
-
if child2 is None:
|
58
|
-
child2 = Child(name="child2", parent_id=parent1.id)
|
59
|
-
child2.save()
|
60
|
-
|
61
|
-
child3 = Child.get(name="child3")
|
62
|
-
if child3 is None:
|
63
|
-
child3 = Child(name="child3", parent_id=parent1.id)
|
64
|
-
child3.save()
|
65
|
-
|
66
|
-
parent2 = Parent.get(name="parent2")
|
67
|
-
if parent2 is None:
|
68
|
-
parent2 = Parent(name="parent2")
|
69
|
-
parent2.save()
|
70
|
-
|
71
|
-
child4 = Child.get(name="child4")
|
72
|
-
if child4 is None:
|
73
|
-
child4 = Child(name="child4", parent_id=parent2.id)
|
74
|
-
child4.save()
|
75
|
-
|
76
|
-
child5 = Child.get(name="child5")
|
77
|
-
if child5 is None:
|
78
|
-
child5 = Child(name="child5", parent_id=parent2.id)
|
79
|
-
child5.save()
|
80
|
-
|
81
|
-
child6 = Child.get(name="child6")
|
82
|
-
if child6 is None:
|
83
|
-
child6 = Child(name="child6", parent_id=parent2.id)
|
84
|
-
child6.save()
|
85
|
-
|
86
|
-
Parent.delete_all() # Should raise an IntegrityError --> FOREIGN KEY constraint failed
|
87
|
-
parent2.delete() # Should raise an IntegrityError --> FOREIGN KEY constraint failed
|
88
|
-
|
89
|
-
print()
|
File without changes
|
@@ -1,126 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import asyncio
|
3
|
-
|
4
|
-
import uvicorn
|
5
|
-
from starlette.applications import Starlette
|
6
|
-
from starlette.responses import HTMLResponse
|
7
|
-
from starlette.routing import Route
|
8
|
-
from starlette.requests import Request
|
9
|
-
from starlette_admin.contrib.mongoengine import Admin, ModelView
|
10
|
-
from starlette_admin.actions import action
|
11
|
-
from mongoengine import Document, StringField
|
12
|
-
from kombu import Connection
|
13
|
-
|
14
|
-
from wiederverwendbar.mongoengine import MongoengineDbSingleton
|
15
|
-
from wiederverwendbar.starlette_admin import ActionLogAdmin, ActionLogger
|
16
|
-
|
17
|
-
logger = logging.getLogger(__name__)
|
18
|
-
ch = logging.StreamHandler()
|
19
|
-
ch.setLevel(logging.DEBUG)
|
20
|
-
logger.addHandler(ch)
|
21
|
-
logger.setLevel(logging.DEBUG)
|
22
|
-
|
23
|
-
# connect to database
|
24
|
-
MongoengineDbSingleton(init=True)
|
25
|
-
|
26
|
-
# create kombu connection
|
27
|
-
kombu_connection = Connection(MongoengineDbSingleton().connection_string)
|
28
|
-
|
29
|
-
|
30
|
-
# Create starlette app
|
31
|
-
app = Starlette(
|
32
|
-
routes=[
|
33
|
-
Route(
|
34
|
-
"/",
|
35
|
-
lambda r: HTMLResponse("<a href=/admin/>Click me to get to Admin!</a>"),
|
36
|
-
),
|
37
|
-
],
|
38
|
-
)
|
39
|
-
|
40
|
-
|
41
|
-
class MyAdmin(Admin, ActionLogAdmin):
|
42
|
-
...
|
43
|
-
|
44
|
-
|
45
|
-
# Create admin
|
46
|
-
admin = MyAdmin(title="Test Admin", kombu_connection=kombu_connection)
|
47
|
-
|
48
|
-
|
49
|
-
class Test(Document):
|
50
|
-
meta = {"collection": "test"}
|
51
|
-
|
52
|
-
test_str = StringField()
|
53
|
-
|
54
|
-
|
55
|
-
class TestView(ModelView):
|
56
|
-
def __init__(self):
|
57
|
-
super().__init__(document=Test, icon="fa fa-server", name="Test", label="Test")
|
58
|
-
|
59
|
-
actions = ["delete", "test_action_normal", "test_action_action_log"]
|
60
|
-
|
61
|
-
@action(name="test_action_normal",
|
62
|
-
text="Test Action - Normal")
|
63
|
-
# confirmation="Möchtest du die Test Aktion durchführen?",
|
64
|
-
# icon_class="fa-regular fa-network-wired",
|
65
|
-
# submit_btn_text="Ja, fortsetzen",
|
66
|
-
# submit_btn_class="btn-success")
|
67
|
-
async def test_action_normal(self, request: Request, pk: list[str]) -> str:
|
68
|
-
await asyncio.sleep(2)
|
69
|
-
|
70
|
-
return "Test Aktion erfolgreich."
|
71
|
-
|
72
|
-
@action(name="test_action_action_log",
|
73
|
-
text="Test Action - Action Log")
|
74
|
-
# confirmation="Möchtest du die Test Aktion durchführen?",
|
75
|
-
# icon_class="fa-regular fa-network-wired",
|
76
|
-
# submit_btn_text="Ja, fortsetzen",
|
77
|
-
# submit_btn_class="btn-success")
|
78
|
-
async def test_action_action_log(self, request: Request, pk: list[str]) -> str:
|
79
|
-
with ActionLogger(request, parent=logger) as action_logger:
|
80
|
-
# use context manager to ensure that the logger is finalized
|
81
|
-
with action_logger.sub_logger("sub_action_1", "Sub Action 1", steps=3, ignore_loggers_like=["pymongo"]) as sub_logger:
|
82
|
-
sub_logger.info("Test Aktion startet ...")
|
83
|
-
sub_logger.debug("Debug")
|
84
|
-
sub_logger.info("Test Aktion step 1")
|
85
|
-
await asyncio.sleep(2)
|
86
|
-
sub_logger.next_step()
|
87
|
-
sub_logger.info("Test Aktion step 2")
|
88
|
-
_ = 1 / 0 # raise exception
|
89
|
-
# raise ActionFailed("Test Aktion fehlgeschlagen.")
|
90
|
-
await asyncio.sleep(2)
|
91
|
-
sub_logger.next_step()
|
92
|
-
sub_logger.steps += 100
|
93
|
-
for i in range(1, 100):
|
94
|
-
sub_logger.info(f"Test Aktion step 2 - {i}")
|
95
|
-
sub_logger.next_step()
|
96
|
-
await asyncio.sleep(0.1)
|
97
|
-
sub_logger.info("Test Aktion step 3")
|
98
|
-
await asyncio.sleep(2)
|
99
|
-
|
100
|
-
sub_action_2_logger = action_logger.new_sub_logger("sub_action_2", "Sub Action 2")
|
101
|
-
sub_action_2_logger.start(steps=3)
|
102
|
-
sub_action_3_logger = action_logger.new_sub_logger("sub_action_3", "Sub Action 3")
|
103
|
-
sub_action_3_logger.start()
|
104
|
-
sub_action_3_logger.steps = 3
|
105
|
-
sub_action_2_logger.info("Test Aktion startet ...")
|
106
|
-
sub_action_3_logger.info("Test Aktion startet ...")
|
107
|
-
await asyncio.sleep(2)
|
108
|
-
sub_action_2_logger.next_step()
|
109
|
-
sub_action_3_logger.next_step()
|
110
|
-
await asyncio.sleep(2)
|
111
|
-
sub_action_2_logger.next_step()
|
112
|
-
sub_action_3_logger.next_step()
|
113
|
-
sub_action_2_logger.finalize(success=False, on_error_msg="Test Aktion fehlgeschlagen.")
|
114
|
-
sub_action_3_logger.finalize(success=True, on_success_msg="Test Aktion erfolgreich.")
|
115
|
-
|
116
|
-
return "Test Aktion erfolgreich."
|
117
|
-
|
118
|
-
|
119
|
-
# Add views to admin#
|
120
|
-
admin.add_view(TestView())
|
121
|
-
|
122
|
-
# Mount admin to app
|
123
|
-
admin.mount_to(app)
|
124
|
-
|
125
|
-
if __name__ == "__main__":
|
126
|
-
uvicorn.run(app, host="0.0.0.0", port=8000)
|