halib 0.1.23__py3-none-any.whl → 0.1.25__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.
- halib/__init__.py +2 -2
- halib/filetype/videofile.py +4 -6
- halib/gdrive.py +1 -1
- halib/online/gdrive.py +2 -3
- halib/online/gdrive_mkdir.py +2 -2
- halib/online/gdrive_test.py +1 -4
- halib/online/projectmake.py +2 -4
- halib/projectmake.py +1 -1
- halib/system/__init__.py +0 -0
- halib/system/cmd.py +8 -0
- halib/system/filesys.py +124 -0
- halib/tele_noti.py +123 -0
- halib/videofile.py +1 -1
- {halib-0.1.23.dist-info → halib-0.1.25.dist-info}/METADATA +12 -1
- {halib-0.1.23.dist-info → halib-0.1.25.dist-info}/RECORD +18 -14
- {halib-0.1.23.dist-info → halib-0.1.25.dist-info}/LICENSE.txt +0 -0
- {halib-0.1.23.dist-info → halib-0.1.25.dist-info}/WHEEL +0 -0
- {halib-0.1.23.dist-info → halib-0.1.25.dist-info}/top_level.txt +0 -0
halib/__init__.py
CHANGED
@@ -28,8 +28,8 @@ import numpy as np
|
|
28
28
|
import pandas as pd
|
29
29
|
from .filetype import *
|
30
30
|
from .filetype.yamlfile import load_yaml
|
31
|
-
from .
|
32
|
-
from .
|
31
|
+
from .system import cmd
|
32
|
+
from .system import filesys as fs
|
33
33
|
from .cuda import tcuda
|
34
34
|
|
35
35
|
# for log
|
halib/filetype/videofile.py
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
from enum import Enum
|
2
|
-
|
3
1
|
import cv2
|
2
|
+
import textfile
|
4
3
|
import enlighten
|
5
|
-
from
|
4
|
+
from enum import Enum
|
5
|
+
from ..system import filesys
|
6
6
|
from tube_dl import Youtube, Playlist
|
7
|
-
|
8
|
-
from halib.sys import filesys
|
9
|
-
from halib.filetype import textfile
|
7
|
+
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
|
10
8
|
|
11
9
|
|
12
10
|
class VideoResolution(Enum):
|
halib/gdrive.py
CHANGED
@@ -12,7 +12,7 @@ from pydrive.auth import GoogleAuth
|
|
12
12
|
from pydrive.drive import GoogleDrive
|
13
13
|
from pydrive.files import GoogleDriveFileList
|
14
14
|
|
15
|
-
from halib.
|
15
|
+
from halib.system import filesys
|
16
16
|
from halib.filetype import textfile
|
17
17
|
|
18
18
|
# Import general libraries
|
halib/online/gdrive.py
CHANGED
@@ -15,9 +15,8 @@ from pydrive.auth import GoogleAuth
|
|
15
15
|
from pydrive.drive import GoogleDrive
|
16
16
|
from pydrive.files import GoogleDriveFileList
|
17
17
|
|
18
|
-
|
19
|
-
from
|
20
|
-
from halib.filetype import textfile
|
18
|
+
from ..system import filesys
|
19
|
+
from ..filetype import textfile
|
21
20
|
|
22
21
|
# Import general libraries
|
23
22
|
|
halib/online/gdrive_mkdir.py
CHANGED
halib/online/gdrive_test.py
CHANGED
halib/online/projectmake.py
CHANGED
@@ -8,10 +8,8 @@ import subprocess
|
|
8
8
|
|
9
9
|
import certifi
|
10
10
|
import pycurl
|
11
|
-
|
12
|
-
from
|
13
|
-
from halib.sys import filesys
|
14
|
-
|
11
|
+
from ..filetype import jsonfile
|
12
|
+
from ..system import filesys
|
15
13
|
|
16
14
|
def get_curl(url, user_and_pass, verbose=True):
|
17
15
|
c = pycurl.Curl()
|
halib/projectmake.py
CHANGED
halib/system/__init__.py
ADDED
File without changes
|
halib/system/cmd.py
ADDED
halib/system/filesys.py
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
import glob
|
2
|
+
import os
|
3
|
+
import shutil
|
4
|
+
from distutils.dir_util import copy_tree
|
5
|
+
|
6
|
+
|
7
|
+
def is_exist(path):
|
8
|
+
return os.path.exists(path)
|
9
|
+
|
10
|
+
|
11
|
+
def is_directory(path):
|
12
|
+
return os.path.isdir(path)
|
13
|
+
|
14
|
+
|
15
|
+
def get_current_dir():
|
16
|
+
return os.getcwd()
|
17
|
+
|
18
|
+
|
19
|
+
def change_current_dir(new_dir):
|
20
|
+
if is_directory(new_dir):
|
21
|
+
os.chdir(new_dir)
|
22
|
+
|
23
|
+
|
24
|
+
def get_dir_name(directory):
|
25
|
+
return os.path.basename(os.path.normpath(directory))
|
26
|
+
|
27
|
+
|
28
|
+
def get_parent_dir(directory, return_full_path=False):
|
29
|
+
if not return_full_path:
|
30
|
+
return os.path.basename(os.path.dirname(directory))
|
31
|
+
else:
|
32
|
+
return os.path.dirname(directory)
|
33
|
+
|
34
|
+
|
35
|
+
def make_dir(directory):
|
36
|
+
if not os.path.exists(directory):
|
37
|
+
os.makedirs(directory)
|
38
|
+
|
39
|
+
|
40
|
+
def copy_dir(src_dir, dst_dir, dirs_exist_ok=True, ignore_patterns=None):
|
41
|
+
shutil.copytree(
|
42
|
+
src_dir, dst_dir, dirs_exist_ok=dirs_exist_ok, ignore=ignore_patterns
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
def delete_dir(directory):
|
47
|
+
shutil.rmtree(directory)
|
48
|
+
|
49
|
+
|
50
|
+
def list_dirs(directory):
|
51
|
+
folders = list(
|
52
|
+
filter(
|
53
|
+
lambda x: os.path.isdir(os.path.join(directory, x)), os.listdir(directory)
|
54
|
+
)
|
55
|
+
)
|
56
|
+
return folders
|
57
|
+
|
58
|
+
|
59
|
+
def list_files(directory):
|
60
|
+
files = list(
|
61
|
+
filter(
|
62
|
+
lambda x: os.path.isfile(os.path.join(directory, x)), os.listdir(directory)
|
63
|
+
)
|
64
|
+
)
|
65
|
+
return files
|
66
|
+
|
67
|
+
|
68
|
+
def filter_files_by_extension(directory, ext, recursive=True):
|
69
|
+
if is_directory(directory):
|
70
|
+
result_files = []
|
71
|
+
if isinstance(ext, list):
|
72
|
+
ext_list = ext
|
73
|
+
else:
|
74
|
+
ext_list = [ext]
|
75
|
+
if not recursive:
|
76
|
+
filter_pattern = f"{directory}/*"
|
77
|
+
else:
|
78
|
+
filter_pattern = f"{directory}/**/*"
|
79
|
+
|
80
|
+
for ext_item in ext_list:
|
81
|
+
ext_filter = f"{filter_pattern}.{ext_item}"
|
82
|
+
files = glob.glob(filter_pattern, recursive=True)
|
83
|
+
files = [f for f in files if is_file(f) and f.endswith(ext_item)]
|
84
|
+
result_files.extend(files)
|
85
|
+
return result_files
|
86
|
+
else:
|
87
|
+
raise OSError("Directory not exists")
|
88
|
+
|
89
|
+
|
90
|
+
def is_file(path):
|
91
|
+
return os.path.isfile(path)
|
92
|
+
|
93
|
+
|
94
|
+
def get_file_name(file_path, split_file_ext=False):
|
95
|
+
if is_file(file_path):
|
96
|
+
if split_file_ext:
|
97
|
+
filename, file_extension = os.path.splitext(os.path.basename(file_path))
|
98
|
+
return filename, file_extension
|
99
|
+
else:
|
100
|
+
return os.path.basename(file_path)
|
101
|
+
else:
|
102
|
+
raise OSError("Not a file")
|
103
|
+
|
104
|
+
|
105
|
+
def get_absolute_path(file_path):
|
106
|
+
return os.path.abspath(file_path)
|
107
|
+
|
108
|
+
|
109
|
+
# dest can be a directory
|
110
|
+
def copy_file(source, dest):
|
111
|
+
shutil.copy2(source, dest)
|
112
|
+
|
113
|
+
|
114
|
+
def delete_file(path):
|
115
|
+
if is_file(path):
|
116
|
+
os.remove(path)
|
117
|
+
|
118
|
+
|
119
|
+
def rename_dir_or_file(old, new):
|
120
|
+
os.renames(old, new)
|
121
|
+
|
122
|
+
|
123
|
+
def move_dir_or_file(source, destination):
|
124
|
+
shutil.move(source, destination)
|
halib/tele_noti.py
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# Watch a log file and send a telegram message when train reaches a certain epoch or end
|
2
|
+
|
3
|
+
import os
|
4
|
+
import yaml
|
5
|
+
import asyncio
|
6
|
+
import telegram
|
7
|
+
import pandas as pd
|
8
|
+
|
9
|
+
from rich.pretty import pprint
|
10
|
+
import plotly.graph_objects as go
|
11
|
+
|
12
|
+
from system import filesys as fs
|
13
|
+
from filetype import textfile, csvfile
|
14
|
+
|
15
|
+
from argparse import ArgumentParser
|
16
|
+
|
17
|
+
def parse_args():
|
18
|
+
parser = ArgumentParser(
|
19
|
+
description="desc text")
|
20
|
+
parser.add_argument(
|
21
|
+
"-cfg",
|
22
|
+
"--cfg",
|
23
|
+
type=str,
|
24
|
+
help="yaml file for tele",
|
25
|
+
default=r"E:\Dev\halib\cfg_tele_noti.yaml",
|
26
|
+
)
|
27
|
+
|
28
|
+
return parser.parse_args()
|
29
|
+
|
30
|
+
def get_watcher_message_df(target_file, num_last_lines):
|
31
|
+
file_ext = fs.get_file_name(target_file, split_file_ext=True)[1]
|
32
|
+
supported_ext = ['.txt', '.log', '.csv']
|
33
|
+
assert file_ext in supported_ext, f"File extension {file_ext} not supported. Supported extensions are {supported_ext}"
|
34
|
+
last_lines_df = None
|
35
|
+
if file_ext in ['.txt', '.log']:
|
36
|
+
lines = textfile.read_line_by_line(target_file)
|
37
|
+
if num_last_lines > len(lines):
|
38
|
+
num_last_lines = len(lines)
|
39
|
+
last_line_arr = lines[-num_last_lines:]
|
40
|
+
dfCreator = csvfile.DFCreator()
|
41
|
+
dfCreator.create_table('last_lines', ['line'])
|
42
|
+
last_line_arr = [[line] for line in last_line_arr]
|
43
|
+
dfCreator.insert_rows('last_lines', last_line_arr)
|
44
|
+
dfCreator.fill_table_from_row_pool('last_lines')
|
45
|
+
last_lines_df = dfCreator['last_lines'].copy()
|
46
|
+
else:
|
47
|
+
df = pd.read_csv(target_file)
|
48
|
+
num_rows = len(df)
|
49
|
+
if num_last_lines > num_rows:
|
50
|
+
num_last_lines = num_rows
|
51
|
+
last_lines_df = df.tail(num_last_lines)
|
52
|
+
return last_lines_df
|
53
|
+
|
54
|
+
|
55
|
+
def df2img(df: pd.DataFrame, output_img_dir, decimal_places, out_img_scale):
|
56
|
+
df = df.round(decimal_places)
|
57
|
+
fig = go.Figure(data=[
|
58
|
+
go.Table(
|
59
|
+
header=dict(values=list(df.columns),align='center'),
|
60
|
+
cells=dict(values=df.values.transpose(),
|
61
|
+
fill_color = [["white","lightgrey"]*df.shape[0]],
|
62
|
+
align='center'
|
63
|
+
)
|
64
|
+
)
|
65
|
+
])
|
66
|
+
img_path = os.path.normpath(os.path.join(output_img_dir, "last_lines.png"))
|
67
|
+
fig.write_image(img_path, scale=out_img_scale)
|
68
|
+
return img_path
|
69
|
+
|
70
|
+
|
71
|
+
def compose_message_and_img_path(
|
72
|
+
target_file, project, num_last_lines, decimal_places, out_img_scale, output_img_dir
|
73
|
+
):
|
74
|
+
context_msg = f">> Project: {project} \n>> File: {target_file} \n>> Last {num_last_lines} lines:"
|
75
|
+
msg_df = get_watcher_message_df(target_file, num_last_lines)
|
76
|
+
img_path = df2img(msg_df, output_img_dir, decimal_places, out_img_scale)
|
77
|
+
return context_msg, img_path
|
78
|
+
|
79
|
+
|
80
|
+
async def send_to_telegram(cfg_dict):
|
81
|
+
# pprint(cfg_dict)
|
82
|
+
token = cfg_dict["telegram"]["token"]
|
83
|
+
chat_id = cfg_dict["telegram"]["chat_id"]
|
84
|
+
|
85
|
+
noti_settings = cfg_dict["noti_settings"]
|
86
|
+
project = noti_settings["project"]
|
87
|
+
target_file = noti_settings["target_file"]
|
88
|
+
num_last_lines = noti_settings["num_last_lines"]
|
89
|
+
output_img_dir = noti_settings["output_img_dir"]
|
90
|
+
decimal_places = noti_settings["decimal_places"]
|
91
|
+
out_img_scale = noti_settings["out_img_scale"]
|
92
|
+
|
93
|
+
bot = telegram.Bot(token=token)
|
94
|
+
async with bot:
|
95
|
+
context_msg, img_path = compose_message_and_img_path(
|
96
|
+
target_file,
|
97
|
+
project,
|
98
|
+
num_last_lines,
|
99
|
+
decimal_places,
|
100
|
+
out_img_scale,
|
101
|
+
output_img_dir,
|
102
|
+
)
|
103
|
+
pprint('Sending message to telegram...')
|
104
|
+
await bot.send_message(text=context_msg, chat_id=chat_id)
|
105
|
+
await bot.send_photo(chat_id=chat_id, photo=open(img_path, "rb"))
|
106
|
+
|
107
|
+
|
108
|
+
async def run_forever(cfg_path):
|
109
|
+
cfg_dict = yaml.safe_load(open(cfg_path, "r"))
|
110
|
+
noti_settings = cfg_dict["noti_settings"]
|
111
|
+
interval_in_min = noti_settings["interval_in_min"]
|
112
|
+
interval_in_sec = int(interval_in_min * 60)
|
113
|
+
pprint(f'Message will be sent every {interval_in_min} minutes or {interval_in_sec} seconds')
|
114
|
+
while True:
|
115
|
+
await send_to_telegram(cfg_dict)
|
116
|
+
await asyncio.sleep(interval_in_sec)
|
117
|
+
|
118
|
+
async def main():
|
119
|
+
args = parse_args()
|
120
|
+
await run_forever(args.cfg)
|
121
|
+
|
122
|
+
if __name__ == "__main__":
|
123
|
+
asyncio.run(main())
|
halib/videofile.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: halib
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.25
|
4
4
|
Summary: Small library for common tasks
|
5
5
|
Author: Hoang Van Ha
|
6
6
|
Author-email: hoangvanhauit@gmail.com
|
@@ -19,9 +19,20 @@ Requires-Dist: loguru
|
|
19
19
|
Requires-Dist: omegaconf
|
20
20
|
Requires-Dist: networkx
|
21
21
|
Requires-Dist: click
|
22
|
+
Requires-Dist: python-telegram-bot
|
23
|
+
Requires-Dist: plotly
|
24
|
+
Requires-Dist: moviepy
|
25
|
+
Requires-Dist: tube-dl
|
26
|
+
Requires-Dist: enlighten
|
27
|
+
Requires-Dist: pycurl
|
22
28
|
|
23
29
|
Helper package for coding and automation
|
24
30
|
|
31
|
+
**Version 0.1.24**
|
32
|
+
|
33
|
+
+ rename `sys` to `system` to avoid conflict with built-in `sys` module
|
34
|
+
+ add `tele_noti` module to send notification to telegram after a specific interval for training progress monitoring
|
35
|
+
---
|
25
36
|
**Version 0.1.22**
|
26
37
|
|
27
38
|
+ add `cuda.py` module to check CUDA availability (for both pytorch and tensorflow)
|
@@ -1,32 +1,36 @@
|
|
1
|
-
halib/__init__.py,sha256=
|
1
|
+
halib/__init__.py,sha256=AHuaFyMGLG-jkc082gvnPmx5TtARRMeEDcZcGDkM1Tg,2370
|
2
2
|
halib/csvfile.py,sha256=Eoeni0NIbNG3mB5ESWAvNwhJxOjmCaPd1qqYRHImbvk,1567
|
3
3
|
halib/cuda.py,sha256=gLuQ0l_sm8UhTPWEoAvM8J4Ta91mSvfuSaJ3tzEOWnU,916
|
4
4
|
halib/filesys.py,sha256=r1SftGKM7nyw6QbY5UmcueZLkXEIleSzhui7dQsosPw,2907
|
5
|
-
halib/gdrive.py,sha256
|
5
|
+
halib/gdrive.py,sha256=p302rTv1H4gFsAlmmiUL0iKrbg09_3_dEhtm-N4WGvg,6277
|
6
6
|
halib/gdrive_mkdir.py,sha256=0Gq65i2YaWaGMdJqXX7zthhb0qZnNwrhdoHK6IBIVv8,1456
|
7
7
|
halib/gdrive_test.py,sha256=e8yOYB5MZhdHbeLzjvTcOXbJNKk_DKNWURIRkKxHBMs,1378
|
8
8
|
halib/jsonfile.py,sha256=9XfdFS1wcTdBRmpAGzVu2dVCcJp8RCpsSY16f6KUNts,480
|
9
9
|
halib/listop.py,sha256=Vpa8_2fI0wySpB2-8sfTBkyi_A4FhoFVVvFiuvW8N64,339
|
10
10
|
halib/plot.py,sha256=drLaHL_JVnIeFxsgYYXepJHIECzOmRImX40cWPJJshs,475
|
11
|
-
halib/projectmake.py,sha256=
|
11
|
+
halib/projectmake.py,sha256=8dNTxB2jgQlwvovaOnJcCKgHe5vM0nBwzm46Yc8INEI,4048
|
12
|
+
halib/tele_noti.py,sha256=emmh8sHisdniU0g6bzqIXnTKbDkC-CTzM4yTOzwUk1M,4459
|
12
13
|
halib/textfile.py,sha256=EhVFrit-nRBJx18e6rtIqcE1cSbgsLnMXe_kdhi1EPI,399
|
13
|
-
halib/videofile.py,sha256=
|
14
|
+
halib/videofile.py,sha256=NTLTZ-j6YD47duw2LN2p-lDQDglYFP1LpEU_0gzHLdI,4737
|
14
15
|
halib/filetype/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
16
|
halib/filetype/csvfile.py,sha256=mXqJYcEKyRDLbdkgy68yceJEPhfLV-L2bz5ljrOKwSM,4181
|
16
17
|
halib/filetype/jsonfile.py,sha256=9LBdM7LV9QgJA1bzJRkq69qpWOP22HDXPGirqXTgSCw,480
|
17
18
|
halib/filetype/textfile.py,sha256=QtuI5PdLxu4hAqSeafr3S8vCXwtvgipWV4Nkl7AzDYM,399
|
18
|
-
halib/filetype/videofile.py,sha256=
|
19
|
+
halib/filetype/videofile.py,sha256=4nfVAYYtoT76y8P4WYyxNna4Iv1o2iV6xaMcUzNPC4s,4736
|
19
20
|
halib/filetype/yamlfile.py,sha256=CxiOz2pgFBkP_V8gmPpFWeXyJ3uug-na42m4ydrWtYU,1993
|
20
21
|
halib/online/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
halib/online/gdrive.py,sha256=
|
22
|
-
halib/online/gdrive_mkdir.py,sha256=
|
23
|
-
halib/online/gdrive_test.py,sha256=
|
24
|
-
halib/online/projectmake.py,sha256=
|
22
|
+
halib/online/gdrive.py,sha256=RmF4y6UPxektkKIctmfT-pKWZsBM9FVUeld6zZmJkp0,7787
|
23
|
+
halib/online/gdrive_mkdir.py,sha256=wSJkQMJCDuS1gxQ2lHQHq_IrJ4xR_SEoPSo9n_2WNFU,1474
|
24
|
+
halib/online/gdrive_test.py,sha256=guwj8e08Nb7nkXXhWRTONNPZKdzmmDhRWOtg0HDtW6Q,1338
|
25
|
+
halib/online/projectmake.py,sha256=R9MgcpF4nrqJTUPpelj338n8IBAFI1ZiYw65szEOZn4,4032
|
25
26
|
halib/sys/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
27
|
halib/sys/cmd.py,sha256=b2x7JPcNnFjLGheIESVYvqAb-w2UwBM1PAwYxMZ5YjA,228
|
27
28
|
halib/sys/filesys.py,sha256=ERpnELLDKJoTIIKf-AajgkY62nID4qmqmX5TkE95APU,2931
|
28
|
-
halib
|
29
|
-
halib
|
30
|
-
halib
|
31
|
-
halib-0.1.
|
32
|
-
halib-0.1.
|
29
|
+
halib/system/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
|
+
halib/system/cmd.py,sha256=b2x7JPcNnFjLGheIESVYvqAb-w2UwBM1PAwYxMZ5YjA,228
|
31
|
+
halib/system/filesys.py,sha256=ERpnELLDKJoTIIKf-AajgkY62nID4qmqmX5TkE95APU,2931
|
32
|
+
halib-0.1.25.dist-info/LICENSE.txt,sha256=qZssdna4aETiR8znYsShUjidu-U4jUT9Q-EWNlZ9yBQ,1100
|
33
|
+
halib-0.1.25.dist-info/METADATA,sha256=jMf6PaHFEbIcqdYF8v0an7SzhWmI-wxpRdH5_v4Ps_0,2264
|
34
|
+
halib-0.1.25.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
35
|
+
halib-0.1.25.dist-info/top_level.txt,sha256=7AD6PLaQTreE0Fn44mdZsoHBe_Zdd7GUmjsWPyQ7I-k,6
|
36
|
+
halib-0.1.25.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|