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 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 .sys import cmd
32
- from .sys import filesys as fs
31
+ from .system import cmd
32
+ from .system import filesys as fs
33
33
  from .cuda import tcuda
34
34
 
35
35
  # for log
@@ -1,12 +1,10 @@
1
- from enum import Enum
2
-
3
1
  import cv2
2
+ import textfile
4
3
  import enlighten
5
- from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
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.sys import filesys
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 halib.sys import filesys
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
 
@@ -1,8 +1,8 @@
1
1
  from argparse import ArgumentParser
2
2
  from datetime import datetime
3
3
 
4
- from halib.online import gdrive
5
- from halib.filetype import textfile
4
+ import gdrive
5
+ from ..filetype import textfile
6
6
 
7
7
 
8
8
  def parse_args():
@@ -1,8 +1,5 @@
1
1
  from argparse import ArgumentParser
2
-
3
- from halib.online import gdrive
4
-
5
-
2
+ import gdrive
6
3
  def parse_args():
7
4
  parser = ArgumentParser(description="Upload local folder to Google Drive")
8
5
  parser.add_argument(
@@ -8,10 +8,8 @@ import subprocess
8
8
 
9
9
  import certifi
10
10
  import pycurl
11
-
12
- from halib.filetype import jsonfile
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
@@ -10,7 +10,7 @@ import certifi
10
10
  import pycurl
11
11
 
12
12
  from halib.filetype import jsonfile
13
- from halib.sys import filesys
13
+ from halib.system import filesys
14
14
 
15
15
 
16
16
  def get_curl(url, user_and_pass, verbose=True):
File without changes
halib/system/cmd.py ADDED
@@ -0,0 +1,8 @@
1
+ import subprocess
2
+
3
+
4
+ # @link: https://geekflare.com/learn-python-subprocess/
5
+ # subprocess.run(['ls', '-la'])
6
+ def run(args):
7
+ process = subprocess.run(args, capture_output=True, text=True)
8
+ return process.returncode
@@ -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
@@ -5,7 +5,7 @@ import enlighten
5
5
  from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
6
6
  from tube_dl import Youtube, Playlist
7
7
 
8
- from halib.sys import filesys
8
+ from halib.system import filesys
9
9
  from halib.filetype import textfile
10
10
 
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: halib
3
- Version: 0.1.23
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=x7N0Wlt_VvG9-4CygKTXUNibbHUIOBnik8sZ9EydX9I,2364
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=-dx8hbknor1stIXhAzCnCfOHAPWm9a9z7L0epsOBHjA,6274
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=EOj_CADQBUfQX35JNRdF3nZepnB_ruJFoQeXmwfhh0w,4045
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=HVRijfyPN_VJ4HnichUHNLGPWS-jhCHBhA2LHB5Xgjo,4734
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=n4lRKhQH8uRxVrhvdw_NUfrnChocflv3LfGlGya0WUs,4761
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=tiVCJpJKci0wQ7H9iKti0K3AxsTp_q8e9uBSxPOBB6s,7794
22
- halib/online/gdrive_mkdir.py,sha256=Ur9-J1uzaM9qgpWF-d6md3gjkrFdPiMNLmbJtpQjXDI,1496
23
- halib/online/gdrive_test.py,sha256=njzCzd__exYp-0yPyGsznG0Sm3GfPWLicxgSmm4V37o,1362
24
- halib/online/projectmake.py,sha256=r9vPID23o_GG7TJy32PIUMvjtl2f-M9nlYJq63GL6ZA,4041
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-0.1.23.dist-info/LICENSE.txt,sha256=qZssdna4aETiR8znYsShUjidu-U4jUT9Q-EWNlZ9yBQ,1100
29
- halib-0.1.23.dist-info/METADATA,sha256=FDYPO0PaIZf4en5PmwaIxOxN6uAdyLLSyoewMT20U2s,1901
30
- halib-0.1.23.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
31
- halib-0.1.23.dist-info/top_level.txt,sha256=7AD6PLaQTreE0Fn44mdZsoHBe_Zdd7GUmjsWPyQ7I-k,6
32
- halib-0.1.23.dist-info/RECORD,,
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