tensorneko-util 0.3.14__py3-none-any.whl → 0.3.15__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.
- tensorneko_util/__init__.py +7 -0
- tensorneko_util/_rich.py +2 -0
- tensorneko_util/io/json/json_writer.py +2 -1
- tensorneko_util/io/video/video_writer.py +2 -1
- tensorneko_util/msg/__init__.py +3 -0
- tensorneko_util/msg/gotify.py +48 -0
- tensorneko_util/util/eventbus/bus.py +16 -13
- tensorneko_util/util/eventbus/event.py +1 -16
- tensorneko_util/version.txt +1 -1
- tensorneko_util/visualization/watcher/web/dist/assets/index.9f626faa.js +188 -0
- tensorneko_util/visualization/watcher/web/dist/index.html +1 -1
- {tensorneko_util-0.3.14.dist-info → tensorneko_util-0.3.15.dist-info}/METADATA +3 -2
- {tensorneko_util-0.3.14.dist-info → tensorneko_util-0.3.15.dist-info}/RECORD +16 -13
- tensorneko_util/visualization/watcher/web/dist/assets/index.493c52c5.js +0 -188
- {tensorneko_util-0.3.14.dist-info → tensorneko_util-0.3.15.dist-info}/LICENSE +0 -0
- {tensorneko_util-0.3.14.dist-info → tensorneko_util-0.3.15.dist-info}/WHEEL +0 -0
- {tensorneko_util-0.3.14.dist-info → tensorneko_util-0.3.15.dist-info}/top_level.txt +0 -0
tensorneko_util/__init__.py
CHANGED
|
@@ -7,6 +7,7 @@ from . import visualization
|
|
|
7
7
|
from . import preprocess
|
|
8
8
|
from . import io
|
|
9
9
|
from . import debug
|
|
10
|
+
from . import msg
|
|
10
11
|
from .io import read, write
|
|
11
12
|
|
|
12
13
|
__all__ = [
|
|
@@ -16,9 +17,15 @@ __all__ = [
|
|
|
16
17
|
"preprocess",
|
|
17
18
|
"io",
|
|
18
19
|
"debug",
|
|
20
|
+
"msg",
|
|
19
21
|
"read",
|
|
20
22
|
"write",
|
|
21
23
|
]
|
|
22
24
|
|
|
25
|
+
try:
|
|
26
|
+
from . import _rich
|
|
27
|
+
except ImportError:
|
|
28
|
+
pass
|
|
29
|
+
|
|
23
30
|
with open(os.path.join(dirname(__file__), "version.txt"), "r", encoding="UTF-8") as file:
|
|
24
31
|
__version__ = file.read()
|
tensorneko_util/_rich.py
ADDED
|
@@ -16,7 +16,8 @@ class JsonWriter:
|
|
|
16
16
|
import orjson
|
|
17
17
|
with open(path, "w", encoding=encoding) as file:
|
|
18
18
|
if indent == 4:
|
|
19
|
-
|
|
19
|
+
warnings.warn("orjson does not support indent 4, will use indent 2 instead.")
|
|
20
|
+
option = orjson.OPT_INDENT_2
|
|
20
21
|
elif indent == 2:
|
|
21
22
|
option = orjson.OPT_INDENT_2
|
|
22
23
|
else:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pathlib
|
|
2
2
|
import warnings
|
|
3
|
+
from subprocess import Popen
|
|
3
4
|
from typing import Optional, Union
|
|
4
5
|
|
|
5
6
|
import numpy as np
|
|
@@ -116,7 +117,7 @@ class VideoWriter:
|
|
|
116
117
|
if not VisualLib.ffmpeg_available():
|
|
117
118
|
raise ValueError("FFMPEG is not installed.")
|
|
118
119
|
import ffmpeg
|
|
119
|
-
pipe = ffmpeg.input("pipe:", format="rawvideo", pix_fmt="rgb24", s=f"{video.shape[2]}x{video.shape[1]}") \
|
|
120
|
+
pipe: Popen = ffmpeg.input("pipe:", format="rawvideo", pix_fmt="rgb24", s=f"{video.shape[2]}x{video.shape[1]}") \
|
|
120
121
|
.output(path, format=ext[1:], pix_fmt="rgb24", r=video_fps) \
|
|
121
122
|
.overwrite_output() \
|
|
122
123
|
.run_async(pipe_stdin=True)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import socket
|
|
4
|
+
import urllib.request
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from urllib.error import HTTPError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def push_gotify(message: str, url: Optional[str] = None, token: Optional[str] = None, title: Optional[str] = None,
|
|
10
|
+
priority: int = 0
|
|
11
|
+
):
|
|
12
|
+
"""
|
|
13
|
+
Push a message to a Gotify server.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
message (``str``): The message to be sent.
|
|
17
|
+
url (``str``, optional): The URL of the Gotify server. If not provided, it will be read from the environment variable GOTIFY_URL.
|
|
18
|
+
token (``str``, optional): The token for the Gotify server. If not provided, it will be read from the environment variable GOTIFY_TOKEN.
|
|
19
|
+
title (``str``, optional): The title of the message. Default is the hostname of the machine.
|
|
20
|
+
priority (``int``, optional): The priority of the message. Default is 0.
|
|
21
|
+
|
|
22
|
+
Examples::
|
|
23
|
+
|
|
24
|
+
push_gotify("This is a test message", "<URL>", "<APP_TOKEN>")
|
|
25
|
+
# then the message will be sent to the Gotify server.
|
|
26
|
+
# title = "<HOST_NAME>", message = "This is a test message", priority = 0
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
title = title or socket.gethostname()
|
|
30
|
+
url = url or os.environ.get("GOTIFY_URL")
|
|
31
|
+
if url is None:
|
|
32
|
+
raise ValueError("URL is not provided. Input url argument or set the environment variable GOTIFY_URL.")
|
|
33
|
+
token = token or os.environ.get("GOTIFY_TOKEN")
|
|
34
|
+
if token is None:
|
|
35
|
+
raise ValueError("Token is not provided. Input token argument or set the environment variable GOTIFY_TOKEN.")
|
|
36
|
+
url = f"{url.rstrip('/')}/message?token={token}"
|
|
37
|
+
data = json.dumps(
|
|
38
|
+
{"title": title, "message": message, "priority": priority}
|
|
39
|
+
).encode("utf-8")
|
|
40
|
+
req = urllib.request.Request(url, data=data, method="POST", headers={
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
"User-Agent": "TensorNeko"
|
|
43
|
+
})
|
|
44
|
+
try:
|
|
45
|
+
with urllib.request.urlopen(req) as res:
|
|
46
|
+
pass
|
|
47
|
+
except HTTPError as e:
|
|
48
|
+
print(e.read().decode("utf-8"))
|
|
@@ -6,7 +6,8 @@ from abc import ABC, abstractmethod
|
|
|
6
6
|
from concurrent.futures import wait
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from enum import Enum
|
|
9
|
-
from typing import Dict, Type, Callable, TYPE_CHECKING, Any, Coroutine, Union, Set, TypeVar
|
|
9
|
+
from typing import Dict, Type, Callable, TYPE_CHECKING, Any, Coroutine, Union, Set, TypeVar, List
|
|
10
|
+
from concurrent.futures import Future
|
|
10
11
|
|
|
11
12
|
from ...backend.parallel import ExecutorPool, ParallelType
|
|
12
13
|
|
|
@@ -99,12 +100,7 @@ class EventBus:
|
|
|
99
100
|
.. code-block:: python
|
|
100
101
|
|
|
101
102
|
# useful decorators for default event bus
|
|
102
|
-
from tensorneko.util import
|
|
103
|
-
subscribe, # run in the main thread
|
|
104
|
-
subscribe_thread, # run in a new thread
|
|
105
|
-
subscribe_async, # run async
|
|
106
|
-
subscribe_process # run in a new process
|
|
107
|
-
)
|
|
103
|
+
from tensorneko.util import subscribe
|
|
108
104
|
# Event base type
|
|
109
105
|
from tensorneko.util import Event
|
|
110
106
|
|
|
@@ -117,15 +113,15 @@ class EventBus:
|
|
|
117
113
|
def log_information(event: LogEvent):
|
|
118
114
|
print(event.message)
|
|
119
115
|
|
|
120
|
-
@
|
|
116
|
+
@subscribe.thread
|
|
121
117
|
def log_information_thread(event: LogEvent):
|
|
122
118
|
print(event.message, "in another thread")
|
|
123
119
|
|
|
124
|
-
@
|
|
120
|
+
@subscribe.coro
|
|
125
121
|
async def log_information_async(event: LogEvent):
|
|
126
122
|
print(event.message, "async")
|
|
127
123
|
|
|
128
|
-
@
|
|
124
|
+
@subscribe.process
|
|
129
125
|
def log_information_process(event: LogEvent):
|
|
130
126
|
print(event.message, "in a new process")
|
|
131
127
|
|
|
@@ -171,6 +167,7 @@ class EventBus:
|
|
|
171
167
|
|
|
172
168
|
def __init__(self):
|
|
173
169
|
self.listeners: Dict[Type[E], Set[Listener]] = {}
|
|
170
|
+
self.futures: List[Future] = []
|
|
174
171
|
|
|
175
172
|
def register(self,
|
|
176
173
|
event_type: Type[E],
|
|
@@ -185,7 +182,7 @@ class EventBus:
|
|
|
185
182
|
self.listeners[event_type] = set()
|
|
186
183
|
self.listeners[event_type].add(Listener(func, func_name, emit_type))
|
|
187
184
|
|
|
188
|
-
def emit(self, event: E
|
|
185
|
+
def emit(self, event: E) -> None:
|
|
189
186
|
event_type: Type[E] = type(event)
|
|
190
187
|
if event_type in self.listeners:
|
|
191
188
|
normal_listeners = set()
|
|
@@ -216,8 +213,14 @@ class EventBus:
|
|
|
216
213
|
for listener in normal_listeners:
|
|
217
214
|
listener.func(event)
|
|
218
215
|
|
|
219
|
-
|
|
220
|
-
|
|
216
|
+
self.futures.extend(futures)
|
|
217
|
+
|
|
218
|
+
def wait(self):
|
|
219
|
+
"""
|
|
220
|
+
Wait for all the futures to be completed.
|
|
221
|
+
"""
|
|
222
|
+
wait(self.futures)
|
|
223
|
+
self.futures.clear()
|
|
221
224
|
|
|
222
225
|
@staticmethod
|
|
223
226
|
async def emit_async(async_listeners: Set[Listener], event: E) -> None:
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from contextlib import contextmanager
|
|
2
1
|
from typing import TypeVar
|
|
3
2
|
|
|
4
3
|
from .bus import EventBus
|
|
@@ -9,24 +8,10 @@ class EventMeta(type):
|
|
|
9
8
|
def __call__(cls, *args, **kwargs):
|
|
10
9
|
event = super().__call__(*args, **kwargs)
|
|
11
10
|
event.bus = kwargs.get("bus", EventBus.default)
|
|
12
|
-
event.bus.emit(event
|
|
11
|
+
event.bus.emit(event)
|
|
13
12
|
return event
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
_blocking_flag = True
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@contextmanager
|
|
20
|
-
def no_blocking():
|
|
21
|
-
"""
|
|
22
|
-
Context manager to disable blocking event handler.
|
|
23
|
-
"""
|
|
24
|
-
global _blocking_flag
|
|
25
|
-
_blocking_flag = False
|
|
26
|
-
yield
|
|
27
|
-
_blocking_flag = True
|
|
28
|
-
|
|
29
|
-
|
|
30
15
|
class Event(metaclass=EventMeta):
|
|
31
16
|
bus: EventBus
|
|
32
17
|
|
tensorneko_util/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.3.
|
|
1
|
+
0.3.15
|