MainShortcuts2 2.0.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.
@@ -0,0 +1,9 @@
1
+ """Упрощение и сокращение вашего кода благодаря этой библиотеке
2
+ Разработчик: MainPlay TG
3
+ https://t.me/MainPlayCh"""
4
+ __all__ = ["ms", "MS2"]
5
+ __scripts__ = ["ms2-import_example"]
6
+ from ._module_info import version as __version__
7
+ # 2.0.0
8
+ from .core import MS2
9
+ ms = MS2()
@@ -0,0 +1,2 @@
1
+ name = "MainShortcuts2"
2
+ version = "2.0.0"
MainShortcuts2/cfg.py ADDED
@@ -0,0 +1,125 @@
1
+ import os
2
+ from .core import MS2
3
+ from .path import PATH_TYPES, path2str
4
+ from typing import *
5
+ ms: MS2 = None
6
+ # 2.0.0
7
+ types = ["json", "json5", "pickle", "toml"]
8
+ ext2type = {
9
+ "json": "json",
10
+ "json5": "json5",
11
+ "pickle": "pickle",
12
+ "pkl": "pickle",
13
+ "toml": "toml",
14
+ }
15
+
16
+
17
+ def _check_type(path: str, type: Union[str, None]):
18
+ type = type.lower()
19
+ if not type is None:
20
+ if not type in types:
21
+ raise Exception("Type %r not supported" % type)
22
+ return type
23
+ _, ext = os.path.splitext(path).lower()
24
+ if ext in ext2type:
25
+ return ext2type[ext]
26
+ raise Exception("Cannot determine type by extension %r" % ext)
27
+
28
+
29
+ def _load_type(cfg):
30
+ path: str = cfg.path
31
+ type: str = cfg.type
32
+ if type == "json":
33
+ def load(**kw):
34
+ kw["like_json5"] = False
35
+ kw["path"] = path
36
+ return ms.json.read(**kw)
37
+
38
+ def save(**kw):
39
+ kw["data"] = cfg.data
40
+ kw["path"] = path
41
+ return ms.json.write(**kw)
42
+ if type == "json5":
43
+ def load(**kw):
44
+ kw["like_json5"] = True
45
+ kw["path"] = path
46
+ return ms.json.read(**kw)
47
+
48
+ def save(**kw):
49
+ kw["data"] = cfg.data
50
+ kw["path"] = path
51
+ return ms.json.write(**kw)
52
+ if type == "pickle":
53
+ import pickle
54
+
55
+ def load(**kw):
56
+ with open(path, "rb") as f:
57
+ kw["file"] = f
58
+ return pickle.load(**kw)
59
+
60
+ def save(**kw):
61
+ buf = pickle.dumps(**kw)
62
+ with open(path, "wb") as f:
63
+ return f.write(buf)
64
+ if type == "toml":
65
+ import toml
66
+
67
+ def load(encoding="utf-8", **kw):
68
+ with open(path, "r", encoding=encoding) as f:
69
+ kw["f"] = f
70
+ return toml.load(**kw)
71
+
72
+ def save(encoding="utf-8", **kw):
73
+ kw["o"] = cfg.data
74
+ buf = toml.dumps(**kw)
75
+ with open(path, "w", encoding=encoding) as f:
76
+ return f.write(buf)
77
+ return load, save
78
+
79
+
80
+ class cfg:
81
+ # 2.0.0
82
+ def __init__(self, path: PATH_TYPES, data: dict = None, default: dict = None, type=None):
83
+ self.data = {} if data is None else data
84
+ self.default = {} if default is None else default
85
+ self.path = path2str(path, True)
86
+ self.type = _check_type(path, type)
87
+ self._load_func, self._save_func = _load_type(self)
88
+
89
+ def load(self, **kw):
90
+ self.data = self._load_func(**kw)
91
+ read = load
92
+
93
+ def save(self, **kw) -> int:
94
+ return self._save_func(**kw)
95
+ write = save
96
+
97
+ def fill_defaults(self):
98
+ for i in self.default:
99
+ if not i in self:
100
+ self[i] = self.default[i]
101
+
102
+ def dload(self, **kw):
103
+ self.load(**kw)
104
+ self.fill_defaults()
105
+
106
+ def __contains__(self, k):
107
+ return k in self.data
108
+
109
+ def __delitem__(self, k):
110
+ del self.data[k]
111
+
112
+ def __getitem__(self, k):
113
+ return self.data[k]
114
+
115
+ def __setitem__(self, k, v):
116
+ self.data[k] = v
117
+
118
+ def items(self):
119
+ return self.data.items()
120
+
121
+ def keys(self):
122
+ return self.data.keys()
123
+
124
+ def values(self):
125
+ return self.data.values()
MainShortcuts2/core.py ADDED
@@ -0,0 +1,142 @@
1
+ import os
2
+ import sys
3
+ from logging import Logger
4
+ # 2.0.0
5
+
6
+
7
+ class NoLogger:
8
+ def __init__(*a, **b):
9
+ pass
10
+
11
+ def __getattr__(self, k):
12
+ return lambda *a, **b: None
13
+
14
+
15
+ class MS2:
16
+ def __init__(self, *,
17
+ __file__: str = None,
18
+ __name__: str = None,
19
+ logger: Logger = None,
20
+ **kw):
21
+ self._cfg = None
22
+ self._dict = None
23
+ self._dir = None
24
+ self._file = None
25
+ self._json = None
26
+ self._list = None
27
+ self._path = None
28
+ self._proc = None
29
+ self._str = None
30
+ self._term = None
31
+ self._utils = None
32
+ self._win = None
33
+ self.encoding = "utf-8"
34
+ self.env = os.environ
35
+ self.log: Logger = NoLogger() if logger is None else logger
36
+ self.prog_file = __file__
37
+ self.prog_name = __name__
38
+ self.reload()
39
+
40
+ def reload(self):
41
+ self.args = sys.argv
42
+ self.import_code = "from MainShortcuts2 import ms\nms.prog_file,ms.prog_name=__file__,__name__\nms.reload()"
43
+ self.imported = self.prog_name != "__main__"
44
+ self.pid = os.getpid()
45
+ self.prog_dir = os.path.dirname(self.prog_file)
46
+ self.running = self.prog_name == "__main__"
47
+
48
+ @property
49
+ def cfg(self):
50
+ if self._cfg is None:
51
+ from .cfg import cfg
52
+ self._cfg = cfg
53
+ self._cfg.ms = self
54
+ return self._cfg
55
+
56
+ @property
57
+ def dict(self):
58
+ if self._dict is None:
59
+ from . import dict
60
+ self._dict = dict
61
+ self._dict.ms = self
62
+ return self._dict
63
+
64
+ @property
65
+ def dir(self):
66
+ if self._dir is None:
67
+ from . import dir
68
+ self._dir = dir
69
+ self._dir.ms = self
70
+ return self._dir
71
+
72
+ @property
73
+ def file(self):
74
+ if self._file is None:
75
+ from . import file
76
+ self._file = file
77
+ self._file.ms = self
78
+ return self._file
79
+
80
+ @property
81
+ def json(self):
82
+ if self._json is None:
83
+ from . import json
84
+ self._json = json
85
+ self._json.ms = self
86
+ return self._json
87
+
88
+ @property
89
+ def list(self):
90
+ if self._list is None:
91
+ from . import list
92
+ self._list = list
93
+ self._list.ms = self
94
+ return self._list
95
+
96
+ @property
97
+ def path(self):
98
+ if self._path is None:
99
+ from . import path
100
+ self._path = path
101
+ self._path.ms = self
102
+ return self._path
103
+
104
+ @property
105
+ def proc(self):
106
+ if self._proc is None:
107
+ from . import proc
108
+ self._proc = proc
109
+ self._proc.ms = self
110
+ return self._proc
111
+
112
+ @property
113
+ def str(self):
114
+ if self._str is None:
115
+ from . import str
116
+ self._str = str
117
+ self._str.ms = self
118
+ return self._str
119
+
120
+ @property
121
+ def term(self):
122
+ if self._term is None:
123
+ from . import term
124
+ self._term = term
125
+ self._term.ms = self
126
+ return self._term
127
+
128
+ @property
129
+ def utils(self):
130
+ if self._utils is None:
131
+ from . import utils
132
+ self._utils = utils
133
+ self._utils.ms = self
134
+ return self._utils
135
+
136
+ @property
137
+ def win(self):
138
+ if self._win is None:
139
+ from . import win
140
+ self._win = win
141
+ self._win.ms = self
142
+ return self._win
MainShortcuts2/dict.py ADDED
@@ -0,0 +1,45 @@
1
+ from .core import MS2
2
+ from typing import *
3
+ ms: MS2 = None
4
+ # 2.0.0
5
+
6
+
7
+ def merge(old: dict, new: dict) -> dict:
8
+ """Рекурсиво объединить словари"""
9
+ out = old.copy()
10
+ for k, v in new.items():
11
+ if k in out:
12
+ if type(out[k]) == dict and type(v) == dict:
13
+ out[k] = merge(out[k], v)
14
+ else:
15
+ out[k] = v
16
+ else:
17
+ out[k] = v
18
+ return out
19
+
20
+
21
+ def reverse(d: dict) -> dict:
22
+ """Развернуть порядок ключей"""
23
+ keys = list(d.keys())[::-1]
24
+ r = {}
25
+ for k in keys:
26
+ r[k] = d[k]
27
+ return r
28
+
29
+
30
+ def sort(d: dict, *, key: None = None, reverse: bool = False) -> dict:
31
+ """Сортировать порядок ключей"""
32
+ keys = list(d.keys)
33
+ keys.sort(key=key, reverse=reverse)
34
+ r = {}
35
+ for k in keys:
36
+ r[k] = d[k]
37
+ return r
38
+
39
+
40
+ def swap(d: dict) -> dict:
41
+ """Вывернуть словарь (повторяющиеся значения будут перезаписаны)"""
42
+ r = {}
43
+ for k, v in d.items():
44
+ r[v] = k
45
+ return r
MainShortcuts2/dir.py ADDED
@@ -0,0 +1,102 @@
1
+ import os
2
+ from .core import MS2
3
+ from .path import Path, PATH_TYPES, path2str
4
+ from typing import *
5
+ ms: MS2 = None
6
+ # 2.0.0
7
+
8
+
9
+ class NotADirError(Exception):
10
+ pass
11
+
12
+
13
+ def _check(path, **kw) -> str:
14
+ kw["path"] = path
15
+ path = path2str(**kw)
16
+ if os.path.exists(path):
17
+ if not os.path.isdir(path):
18
+ raise NotADirError(path)
19
+ return path
20
+
21
+
22
+ def create(path: PATH_TYPES, force: bool = True, **kw):
23
+ path = path2str(path)
24
+ if os.path.isdir(path):
25
+ return
26
+ if force:
27
+ if os.path.isfile(path):
28
+ ms.path.delete(path)
29
+ kw["name"] = _check(path)
30
+ os.makedirs(**kw)
31
+
32
+
33
+ def _list_filter(path: Path, *, exts: Iterable[str], func: Callable[[Path], bool], links: bool, type: str):
34
+ if not exts is None:
35
+ if not path.ext in exts:
36
+ return False
37
+ if not func is None:
38
+ if not func(path):
39
+ return False
40
+ if not links is None:
41
+ if os.path.islink(path.path) != links:
42
+ return False
43
+ if not type is None:
44
+ if path.type != type:
45
+ return False
46
+ return True
47
+
48
+
49
+ def list(path: PATH_TYPES = ".", *, exts: Iterable[str] = None, func: Callable[[Path], bool] = None, links: bool = None, type: str = None) -> list[Path]:
50
+ r = []
51
+ kw = {}
52
+ kw["exts"] = list(exts)
53
+ kw["func"] = func
54
+ kw["links"] = bool(links)
55
+ kw["type"] = type
56
+ for i in os.listdir(_check(path)):
57
+ i = Path(i)
58
+ if _list_filter(i, **kw):
59
+ r.append(i)
60
+ return i
61
+
62
+
63
+ def copy(path: PATH_TYPES, dest: PATH_TYPES, **kw):
64
+ kw["dest"] = dest
65
+ kw["path"] = _check(path)
66
+ return ms.path.copy(**kw)
67
+
68
+
69
+ def delete(path: PATH_TYPES, **kw):
70
+ kw["path"] = _check(path)
71
+ return ms.path.delete(**kw)
72
+
73
+
74
+ def in_dir(path: str, dir: str, **kw) -> bool:
75
+ kw["dir"] = dir
76
+ kw["path"] = _check(path)
77
+ return ms.path.in_dir(**kw)
78
+
79
+
80
+ def link(path: PATH_TYPES, dest: PATH_TYPES, **kw):
81
+ kw["dest"] = dest
82
+ kw["path"] = _check(path)
83
+ return ms.path.link(**kw)
84
+
85
+
86
+ def move(path: PATH_TYPES, dest: PATH_TYPES, **kw):
87
+ kw["dest"] = dest
88
+ kw["path"] = _check(path)
89
+ return ms.path.move(**kw)
90
+
91
+
92
+ def rename(path: PATH_TYPES, name: PATH_TYPES, **kw):
93
+ kw["name"] = name
94
+ kw["path"] = _check(path)
95
+ return ms.path.rename(**kw)
96
+
97
+
98
+ cp = copy
99
+ ln = link
100
+ mv = move
101
+ rm = delete
102
+ rn = rename
MainShortcuts2/file.py ADDED
@@ -0,0 +1,92 @@
1
+ import builtins
2
+ import os
3
+ from .core import MS2
4
+ from .path import PATH_TYPES, path2str
5
+ from typing import *
6
+ ms: MS2 = None
7
+ # 2.0.0
8
+
9
+
10
+ class NotAFileError(Exception):
11
+ pass
12
+
13
+
14
+ def _check(path, **kw) -> str:
15
+ kw["path"] = path
16
+ path = path2str(**kw)
17
+ if os.path.exists(path):
18
+ if not os.path.isfile(path):
19
+ raise NotAFileError(path)
20
+ return path
21
+
22
+
23
+ def read(path: PATH_TYPES, encoding: str = None, **kw) -> str:
24
+ kw["encoding"] = ms.encoding if encoding is None else encoding
25
+ kw["file"] = _check(path)
26
+ kw["mode"] = "r"
27
+ with builtins.open(**kw) as f:
28
+ return f.read()
29
+
30
+
31
+ def write(path: PATH_TYPES, data: str, encoding: str = None, **kw) -> int:
32
+ kw["encoding"] = ms.encoding if encoding is None else encoding
33
+ kw["file"] = _check(path)
34
+ kw["mode"] = "w"
35
+ with builtins.open(**kw) as f:
36
+ return f.write(data)
37
+
38
+
39
+ def load(path: PATH_TYPES, **kw) -> bytes:
40
+ kw["file"] = _check(path)
41
+ kw["mode"] = "rb"
42
+ with builtins.open(**kw) as f:
43
+ return f.read()
44
+
45
+
46
+ def save(path: PATH_TYPES, data: bytes, **kw) -> int:
47
+ kw["file"] = _check(path)
48
+ kw["mode"] = "wb"
49
+ with builtins.open(**kw) as f:
50
+ return f.write(data)
51
+
52
+
53
+ def copy(path: PATH_TYPES, dest: PATH_TYPES, **kw):
54
+ kw["dest"] = dest
55
+ kw["path"] = _check(path)
56
+ return ms.path.copy(**kw)
57
+
58
+
59
+ def delete(path: PATH_TYPES, **kw):
60
+ kw["path"] = _check(path)
61
+ return ms.path.delete(**kw)
62
+
63
+
64
+ def in_dir(path: str, dir: str, **kw) -> bool:
65
+ kw["dir"] = dir
66
+ kw["path"] = _check(path)
67
+ return ms.path.in_dir(**kw)
68
+
69
+
70
+ def link(path: PATH_TYPES, dest: PATH_TYPES, **kw):
71
+ kw["dest"] = dest
72
+ kw["path"] = _check(path)
73
+ return ms.path.link(**kw)
74
+
75
+
76
+ def move(path: PATH_TYPES, dest: PATH_TYPES, **kw):
77
+ kw["dest"] = dest
78
+ kw["path"] = _check(path)
79
+ return ms.path.move(**kw)
80
+
81
+
82
+ def rename(path: PATH_TYPES, name: PATH_TYPES, **kw):
83
+ kw["name"] = name
84
+ kw["path"] = _check(path)
85
+ return ms.path.rename(**kw)
86
+
87
+
88
+ cp = copy
89
+ ln = link
90
+ mv = move
91
+ rm = delete
92
+ rn = rename
MainShortcuts2/json.py ADDED
@@ -0,0 +1,90 @@
1
+ import json
2
+ import builtins
3
+ from .core import MS2
4
+ from .path import PATH_TYPES
5
+ from typing import *
6
+ try:
7
+ import json5
8
+ except Exception:
9
+ json5 = None
10
+ ms: MS2 = None
11
+ # 2.0.0
12
+ JSON_TYPES = Union[bool, dict, float, int, list, None, str]
13
+
14
+
15
+ def decode(text: str, *, like_json5: bool = False, **kw) -> JSON_TYPES:
16
+ kw["s"] = text
17
+ if like_json5:
18
+ if not json5 is None:
19
+ return json5.loads(**kw)
20
+ return json.loads(**kw)
21
+
22
+
23
+ def encode(data: JSON_TYPES, mode: str = "c", **kw):
24
+ kw["obj"] = data
25
+ mode = mode.lower()
26
+ if "force" in kw:
27
+ del kw["force"]
28
+ if "sort" in kw:
29
+ kw["sort_keys"] = kw.pop("sort")
30
+ if mode in ["c", "compress", "min", "zip"]: # Сжатый
31
+ kw["indent"] = None
32
+ kw["separators"] = [",", ":"]
33
+ if mode in ["p", "pretty", "max", "print"]: # Развёрнутый
34
+ if not "indent" in kw:
35
+ kw["indent"] = 2
36
+ kw["separators"] = None
37
+ if mode in ["mp", "mp_tg", "mainplay", "mainplay_tg"]: # Стиль MainPlay TG
38
+ kw["indent"] = 2
39
+ kw["separators"] = [",", ":"]
40
+ return json.dumps(**kw)
41
+
42
+
43
+ def print(data: JSON_TYPES, mode: str = "p", **kw):
44
+ pr_kw = {}
45
+ for i in ["end", "file", "flush", "sep"]:
46
+ if i in kw:
47
+ pr_kw[i] = kw.pop(i)
48
+ kw["data"] = data
49
+ kw["mode"] = mode
50
+ builtins.print(encode(**kw), **pr_kw)
51
+
52
+
53
+ def read(path: PATH_TYPES, **kw) -> JSON_TYPES:
54
+ f_kw = {}
55
+ if "encoding" in kw:
56
+ f_kw["encoding"] = kw.pop("encoding")
57
+ f_kw["path"] = path
58
+ kw["text"] = ms.file.read(**f_kw)
59
+ return decode(**kw)
60
+
61
+
62
+ def rebuild(text: str, **kw) -> str:
63
+ de_kw = {}
64
+ if "like_json5" in kw:
65
+ de_kw["like_json5"] = kw.pop("like_json5")
66
+ de_kw["text"] = text
67
+ kw["data"] = decode(**de_kw)
68
+ return encode(**kw)
69
+
70
+
71
+ def rewrite(path: PATH_TYPES, **kw) -> int:
72
+ de_kw = {}
73
+ if "encoding" in kw:
74
+ de_kw["encoding"] = kw["encoding"]
75
+ if "like_json5" in kw:
76
+ de_kw["like_json5"] = kw.pop("like_json5")
77
+ de_kw["path"] = path
78
+ kw["path"] = path
79
+ kw["text"] = read(**de_kw)
80
+ return write(**kw)
81
+
82
+
83
+ def write(path: PATH_TYPES, data: JSON_TYPES, **kw) -> int:
84
+ f_kw = {}
85
+ for i in ["encoding", "force"]:
86
+ if i in kw:
87
+ f_kw[i] = kw.pop(i)
88
+ f_kw["path"] = path
89
+ f_kw["text"] = encode(**kw)
90
+ return ms.file.write(**f_kw)
MainShortcuts2/list.py ADDED
@@ -0,0 +1,84 @@
1
+ import re
2
+ from .core import MS2
3
+ from typing import *
4
+ ms: MS2 = None
5
+ # 2.0.0
6
+
7
+
8
+ def filter(a: list, whitelist: list = None, blacklist: list = [], regex: str = False, begin: str = None, end: str = None):
9
+ """Фильтровать список
10
+ whitelist - удалить всё, чего нет в этом списке
11
+ blacklist - удалить всё, что есть в этом списке
12
+ regex - сортировка с регулярным выражением (строки)"""
13
+ a = list(a)
14
+ if whitelist == None:
15
+ whitelist = a
16
+ if type(whitelist) == str:
17
+ whitelist = [whitelist]
18
+ if type(blacklist) == str:
19
+ blacklist = [blacklist]
20
+ b = []
21
+ for i in a:
22
+ add = True
23
+ if begin != None:
24
+ if str(i).startswith(str(begin)):
25
+ add = True
26
+ else:
27
+ add = False
28
+ if end != None and add:
29
+ if str(i).endswith(str(end)):
30
+ add = True
31
+ else:
32
+ add = False
33
+ if regex and add:
34
+ reW = False
35
+ for i2 in whitelist:
36
+ if re.match(str(i2), str(i)) != None:
37
+ reW = True
38
+ break
39
+ reB = False
40
+ for i2 in blacklist:
41
+ if re.match(str(i2), str(i)) != None:
42
+ reB = True
43
+ break
44
+ if reW and not reB:
45
+ add = True
46
+ else:
47
+ add = False
48
+ if add and not regex:
49
+ if (i in whitelist) and (not i in blacklist):
50
+ add = True
51
+ else:
52
+ add = False
53
+ if add:
54
+ b.append(i)
55
+ return b
56
+
57
+
58
+ def rm_duplicates(a: list, trim: bool = False, case: bool = False, func=lambda i: i):
59
+ """Удалить дублирующиеся элементы
60
+ trim - True: использовать strip()
61
+ l: использовать lstrip()
62
+ r: использовать rstrip()
63
+ case - lower/upper/capitalize
64
+ func - обработать каждый элемент этой функцией"""
65
+ b = []
66
+ trim = str(trim).lower()
67
+ case = str(case).lower()
68
+ for i in a:
69
+ if trim in ["true", "lr", "rl", "all"]:
70
+ i = i.strip()
71
+ elif trim in ["l", "left"]:
72
+ i = i.lstrip()
73
+ elif trim in ["r", "right"]:
74
+ i = i.rstrip()
75
+ if case in ["l", "lower", "low"]:
76
+ i = i.lower()
77
+ elif case in ["u", "upper", "up"]:
78
+ i = i.upper()
79
+ elif case in ["capitalize", "cap"]:
80
+ i = i.capitalize()
81
+ i = func(i)
82
+ if not i in b:
83
+ b.append(i)
84
+ return b