MainShortcuts2 2.4.0__tar.gz → 2.4.2__tar.gz

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.
Files changed (29) hide show
  1. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/PKG-INFO +1 -1
  2. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/pyproject.toml +1 -1
  3. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/__main__.py +50 -48
  4. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/_module_info.py +1 -1
  5. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/advanced.py +111 -4
  6. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/file.py +32 -0
  7. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/README.md +0 -0
  8. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/__init__.py +0 -0
  9. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/_any2json_regs.py +0 -0
  10. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/any2json.py +0 -0
  11. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/api/base.py +0 -0
  12. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/api/gigachat.py +0 -0
  13. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/api/russian_trusted_root_ca_pem.crt +0 -0
  14. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/api/russian_trusted_sub_ca_pem.crt +0 -0
  15. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/cfg.py +0 -0
  16. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/core.py +0 -0
  17. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/dict.py +0 -0
  18. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/dir.py +0 -0
  19. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/json.py +0 -0
  20. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/list.py +0 -0
  21. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/path.py +0 -0
  22. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/proc.py +0 -0
  23. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/regex.py +0 -0
  24. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/special_chars.py +0 -0
  25. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/str.py +0 -0
  26. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/term.py +0 -0
  27. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/types.py +0 -0
  28. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/utils.py +0 -0
  29. {mainshortcuts2-2.4.0 → mainshortcuts2-2.4.2}/src/MainShortcuts2/win.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MainShortcuts2
3
- Version: 2.4.0
3
+ Version: 2.4.2
4
4
  Summary: Сокращение и улучшение функций + консольные утилиты
5
5
  Home-page: https://github.com/MainPlay-TG/MainShortcuts2.py
6
6
  Author: MainPlay TG
@@ -1,5 +1,5 @@
1
1
  [tool.poetry]
2
- version = "2.4.0"
2
+ version = "2.4.2"
3
3
  name = "MainShortcuts2"
4
4
  description = "Сокращение и улучшение функций + консольные утилиты"
5
5
  authors = [ "MainPlay TG <xbox.roman6666666666@gmail.com>",]
@@ -16,21 +16,21 @@ def nano_json():
16
16
  import subprocess
17
17
  argp = argparse.ArgumentParser("nano-json", description="форматирование JSON файлов и редактирование в GNU NANO")
18
18
  argp.add_argument("files", nargs="+", help="пути к файлам JSON")
19
- argp.add_argument("--encoding", default="utf-8", help="кодировка файлов"
19
+ argp.add_argument("--encoding", default="utf-8", help="кодировка файлов")
20
20
  argp.add_argument("--nano-help", action="store_true", help="показать помощь nano")
21
21
  argp.add_argument("--no-escape", action="store_false", help="не использовать Unicode Escape")
22
22
  argp.add_argument("-f", "--rcfile", help="использовать только этот файл для настройки nano")
23
23
  argp.add_argument("-m", "--mode", choices=ms.json.MODES, default="p", help="режим сохранения редактирования")
24
- args=argp.parse_args()
24
+ args = argp.parse_args()
25
25
  if args.nano_help:
26
26
  return subprocess.call(["nano", "--help"])
27
- nano_args=["nano"]
27
+ nano_args = ["nano"]
28
28
  if args.rcfile:
29
29
  nano_args += ["--rcfile", args.rcfile]
30
30
  nano_args += args.files
31
31
  for i in args.files:
32
32
  try:
33
- data=ms.json.read(i, encoding=args.encoding)
33
+ data = ms.json.read(i, encoding=args.encoding)
34
34
  ms.json.write(i + ms.file.TMP_SUFFIX, data, encoding=args.encoding, ensure_ascii=False, mode="p")
35
35
  ms.file.delete(i)
36
36
  ms.file.move(i + ms.file.TMP_SUFFIX, i)
@@ -39,7 +39,7 @@ def nano_json():
39
39
  subprocess.call(nano_args)
40
40
  for i in args.files:
41
41
  try:
42
- data=ms.json.read(i, encoding=args.encoding)
42
+ data = ms.json.read(i, encoding=args.encoding)
43
43
  ms.json.write(i + ms.file.TMP_SUFFIX, data, encoding=args.encoding, ensure_ascii=args.no_escape, mode=args.mode)
44
44
  ms.file.delete(i)
45
45
  ms.file.move(i + ms.file.TMP_SUFFIX, i)
@@ -50,7 +50,7 @@ def nano_json():
50
50
  def _check_nginx() -> int:
51
51
  import subprocess
52
52
  with subprocess.Popen(["nginx", "-t"], stderr=subprocess.PIPE) as p:
53
- code=p.wait()
53
+ code = p.wait()
54
54
  if code != 0:
55
55
  sys.stderr.buffer.write(p.stderr.read())
56
56
  return code
@@ -59,9 +59,9 @@ def _check_nginx() -> int:
59
59
  def nginx_reload():
60
60
  ms.utils.check_programs("nginx")
61
61
  import subprocess
62
- argp=argparse.ArgumentParser("nginx-reload", description="проверка конфига и перезагрузка Nginx")
62
+ argp = argparse.ArgumentParser("nginx-reload", description="проверка конфига и перезагрузка Nginx")
63
63
  argp.parse_args()
64
- code=_check_nginx()
64
+ code = _check_nginx()
65
65
  if code != 0:
66
66
  sys.exit(code)
67
67
  sys.exit(subprocess.call(["nginx", "-s", "reload"]))
@@ -70,9 +70,9 @@ def nginx_reload():
70
70
  def nginx_restart():
71
71
  ms.utils.check_programs("nginx", "systemctl")
72
72
  import subprocess
73
- argp=argparse.ArgumentParser("nginx-reload", description="проверка конфига и перезапуск Nginx через systemctl")
73
+ argp = argparse.ArgumentParser("nginx-reload", description="проверка конфига и перезапуск Nginx через systemctl")
74
74
  argp.parse_args()
75
- code=_check_nginx()
75
+ code = _check_nginx()
76
76
  if code != 0:
77
77
  sys.exit(code)
78
78
  sys.exit(subprocess.call(["systemctl", "restart", "nginx"]))
@@ -81,36 +81,36 @@ def nginx_restart():
81
81
  def hash_gen():
82
82
  import os
83
83
  import hashlib
84
- argp=argparse.ArgumentParser("ms2-hash-gen", description="создание контрольной суммы для файла")
84
+ argp = argparse.ArgumentParser("ms2-hash-gen", description="создание контрольной суммы для файла")
85
85
  argp.add_argument("files", nargs="+", help="пути к файлам")
86
86
  argp.add_argument("-b", "--bar", action="store_true", help="показывать прогрессбар (нужен модуль progressbar2)")
87
87
  argp.add_argument("-t", "--type", choices=HASH_TYPES, default="sha512", help="тип контрольной суммы")
88
- args=argp.parse_args()
88
+ args = argp.parse_args()
89
89
  if args.bar:
90
90
  import progressbar
91
- pbar_w=[
92
- progressbar.Percentage(),
93
- progressbar.GranularBar(left="(", right=")"),
94
- progressbar.FileTransferSpeed(),
95
- progressbar.ETA(format="%(eta)8s", format_finished="%(elapsed)8s", format_na=" N/A", format_not_started="--:--:--", format_zero="00:00:00"),
91
+ pbar_w = [
92
+ progressbar.Percentage(),
93
+ progressbar.GranularBar(left="(", right=")"),
94
+ progressbar.FileTransferSpeed(),
95
+ progressbar.ETA(format="%(eta)8s", format_finished="%(elapsed)8s", format_na=" N/A", format_not_started="--:--:--", format_zero="00:00:00"),
96
96
  ]
97
- data={}
98
- data["format"]="MainShortcuts2_hash_v1"
99
- data["file"]={}
100
- data["hash"]={}
101
- data["hash"]["type"]=args.type
102
- Hash=getattr(hashlib, args.type)
97
+ data = {}
98
+ data["format"] = "MainShortcuts2_hash_v1"
99
+ data["file"] = {}
100
+ data["hash"] = {}
101
+ data["hash"]["type"] = args.type
102
+ Hash = getattr(hashlib, args.type)
103
103
  for file in args.files:
104
- hash=Hash()
105
- data["file"]["size"]=os.path.getsize(file)
104
+ hash = Hash()
105
+ data["file"]["size"] = os.path.getsize(file)
106
106
  if args.bar:
107
- pbar=progressbar.ProgressBar(
108
- max_error=False,
109
- max_value=data["file"]["size"],
110
- min_value=0,
111
- widgets=[ms.path.Path(file).full_name] + pbar_w,
107
+ pbar = progressbar.ProgressBar(
108
+ max_error=False,
109
+ max_value=data["file"]["size"],
110
+ min_value=0,
111
+ widgets=[ms.path.Path(file).full_name] + pbar_w,
112
112
  )
113
- c=0
113
+ c = 0
114
114
  pbar.start()
115
115
  with open(file, "rb") as f:
116
116
  for chunk in f:
@@ -120,43 +120,45 @@ def hash_gen():
120
120
  pbar.update(c)
121
121
  if args.bar:
122
122
  pbar.finish(dirty=True)
123
- data["hash"]["hex"]=hash.hexdigest()
123
+ data["hash"]["hex"] = hash.hexdigest()
124
124
  ms.json.write(file + HASH_SUFFIX, data)
125
+
126
+
125
127
  def hash_check():
126
128
  import hashlib
127
129
  import os
128
130
  import shlex
129
- argp=argparse.ArgumentParser("ms2-hash-check", description="проверка размера и контрольной суммы файла")
131
+ argp = argparse.ArgumentParser("ms2-hash-check", description="проверка размера и контрольной суммы файла")
130
132
  argp.add_argument("-b", "--bar", action="store_true", help="показывать прогрессбар (нужен модуль progressbar2)")
131
133
  argp.add_argument("files", nargs="+", help="пути к файлам")
132
- args=argp.parse_args()
134
+ args = argp.parse_args()
133
135
  if args.bar:
134
136
  import progressbar
135
- pbar_w=[
136
- progressbar.Percentage(),
137
- progressbar.GranularBar(left="(", right=")"),
138
- progressbar.FileTransferSpeed(),
139
- progressbar.ETA(format="%(eta)8s", format_finished="%(elapsed)8s", format_na=" N/A", format_not_started="--:--:--", format_zero="00:00:00"),
137
+ pbar_w = [
138
+ progressbar.Percentage(),
139
+ progressbar.GranularBar(left="(", right=")"),
140
+ progressbar.FileTransferSpeed(),
141
+ progressbar.ETA(format="%(eta)8s", format_finished="%(elapsed)8s", format_na=" N/A", format_not_started="--:--:--", format_zero="00:00:00"),
140
142
  ]
141
143
  for file in args.files:
142
144
  if file.lower().endswith(HASH_SUFFIX.lower()):
143
- file=file[:0 - len(HASH_SUFFIX)]
145
+ file = file[:0 - len(HASH_SUFFIX)]
144
146
  if not os.path.exists(file + HASH_SUFFIX):
145
147
  print("Ошибка: не найден файл " + shlex.quote(file + HASH_SUFFIX), file=sys.stderr)
146
148
  continue
147
- data=ms.json.read(file + HASH_SUFFIX)
149
+ data = ms.json.read(file + HASH_SUFFIX)
148
150
  if data["file"]["size"] != os.path.getsize(file):
149
151
  print("Ошибка: размер файла " + shlex.quote(file) + " не совпадает")
150
152
  continue
151
- hash=getattr(hashlib, data["hash"]["type"])()
153
+ hash = getattr(hashlib, data["hash"]["type"])()
152
154
  if args.bar:
153
- pbar=progressbar.ProgressBar(
154
- max_error=False,
155
- max_value=data["file"]["size"],
156
- min_value=0,
157
- widgets=[ms.path.Path(file).full_name] + pbar_w,
155
+ pbar = progressbar.ProgressBar(
156
+ max_error=False,
157
+ max_value=data["file"]["size"],
158
+ min_value=0,
159
+ widgets=[ms.path.Path(file).full_name] + pbar_w,
158
160
  )
159
- c=0
161
+ c = 0
160
162
  pbar.start()
161
163
  with open(file, "rb") as f:
162
164
  for chunk in f:
@@ -1,2 +1,2 @@
1
1
  name = "MainShortcuts2"
2
- version = "2.4.0"
2
+ version = "2.4.2"
@@ -18,16 +18,22 @@ class MultiLang:
18
18
  self.files: dict[str, Path] = {}
19
19
  self.langs: dict[Union[None, str], dict[str, dict[str, Any]]] = {}
20
20
 
21
- def cb_lines(text: list[str]) -> str:
21
+ @self.add_cache_builder("lines")
22
+ def _(text: list[str]) -> str:
22
23
  return "\n".join(text)
23
24
 
24
- def cb_normal(text: str) -> str:
25
+ @self.add_cache_builder("normal")
26
+ def _(text: str) -> str:
25
27
  assert type(text) == str
26
28
  return text
27
- self.cache_builders["lines"] = cb_lines
28
- self.cache_builders["normal"] = cb_normal
29
29
  self.add_lang(None, default_lang, load=True)
30
30
 
31
+ def add_cache_builder(self, name: str):
32
+ def deco(func):
33
+ self.cache_builders[name] = func
34
+ return func
35
+ return deco
36
+
31
37
  def add_langs(self, langs: dict[str, Union[dict, Path, str]], check_count: bool = True, load: bool = True):
32
38
  """Добавить языки (`dict`) или пути к языковым файлам (`str`, `ms.path.Path`)"""
33
39
  if check_count:
@@ -252,3 +258,104 @@ class PermissionSystem:
252
258
  del user["perms"][k]
253
259
  else:
254
260
  user["perms"][k] = v
261
+
262
+
263
+ class DictScriptAction:
264
+ def __init__(self, name: str, args: list = None, kwargs: dict = None, save_to: str = None, comment: str = None):
265
+ self.__getitem__ = self.__getattr__
266
+ self.args: list = args
267
+ self.comment: str = comment
268
+ self.kwargs: dict = kwargs
269
+ self.name: str = name
270
+ self.save_to: str = save_to
271
+
272
+ @classmethod
273
+ def from_dict(cls, data: dict):
274
+ kw = {}
275
+ for k in ["args", "comment", "kwargs", "name", "save_to"]:
276
+ kw[k] = data.get(k)
277
+ return cls(**kw)
278
+
279
+ def to_dict(self) -> dict:
280
+ result = {}
281
+ for k in ["args", "comment", "kwargs", "name", "save_to"]:
282
+ v = getattr(self, k)
283
+ if not v is None:
284
+ result[k] = v
285
+ return result
286
+
287
+
288
+ class DictScriptVariable:
289
+ def __init__(self, name: str):
290
+ self.name: str = name
291
+
292
+
293
+ @ms.any2json.reg_decoder(DictScriptVariable)
294
+ def _(obj):
295
+ return DictScriptVariable(obj)
296
+
297
+
298
+ @ms.any2json.reg_encoder(DictScriptVariable)
299
+ def _(obj: DictScriptVariable):
300
+ if isinstance(obj, DictScriptVariable):
301
+ return obj.name
302
+
303
+
304
+ class DictScriptRunner:
305
+ VERSION = 1
306
+
307
+ def __init__(self, functions: dict = None, add_default_functions: bool = True):
308
+ self.globals = {}
309
+ if add_default_functions:
310
+ import time
311
+ for i in [bool, bytes, dict, float, int, list, str, tuple]:
312
+ self.reg_class()(i)
313
+ self.reg_function("sleep")(time.sleep)
314
+ self.reg_function("sum")(sum)
315
+ self.reg_function("time.sleep")(time.sleep)
316
+ self.reg_function("time.time")(time.time)
317
+ if not functions is None:
318
+ for name, func in functions.items():
319
+ self.reg_function(name)(func)
320
+
321
+ def reg_class(self, name: str = None, overwrite: bool = False):
322
+ def deco(cls: type):
323
+ if name is None: # type: ignore
324
+ name = cls.__module__ + "." + cls.__name__
325
+ if callable(cls):
326
+ self.reg_function(name, overwrite=overwrite)(cls) # type: ignore
327
+ for k in dir(cls):
328
+ v = getattr(cls, k)
329
+ if callable(v):
330
+ self.reg_function(name + "." + k, overwrite=overwrite) # type: ignore
331
+ return cls
332
+ return deco
333
+
334
+ def reg_function(self, name: str, overwrite: bool = False):
335
+ if not overwrite:
336
+ if name in self.globals:
337
+ raise ValueError("The %r function already exists. Perhaps you wanted to overwrite it?" % name)
338
+
339
+ def deco(func):
340
+ if not callable(func):
341
+ raise TypeError("Function %r is not callable" % name)
342
+ self.globals[name] = func
343
+ return func
344
+ return deco
345
+
346
+ def run_script(self, script: list[dict]) -> dict:
347
+ """Выполнить скрипт (список действий)"""
348
+ for act in script:
349
+ if not act["name"] in self.globals:
350
+ raise KeyError("Function %r not exists" % act["name"])
351
+ locals = self.globals.copy()
352
+ for act in script:
353
+ if act["name"] == "exit":
354
+ break
355
+ args = act["args"] if "args" in act else []
356
+ func = locals[act["name"]]
357
+ kwargs = act["kwargs"] if "kwargs" in act else {}
358
+ result = func(*args, **kwargs)
359
+ if "save_to" in act:
360
+ locals[act["save_to"]] = result
361
+ return locals
@@ -114,6 +114,38 @@ def rename(path: PATH_TYPES, name: PATH_TYPES, **kw):
114
114
  return ms.path.rename(**kw)
115
115
 
116
116
 
117
+ def compare(path1: PATH_TYPES, path2: PATH_TYPES, method: str = "binary") -> bool:
118
+ """Одинаковые ли файлы"""
119
+ p1 = _check(path1)
120
+ p2 = _check(path2)
121
+ if os.path.getsize(p1) != os.path.getsize(p2):
122
+ return False
123
+ if method == "binary": # Сравнение по байтам
124
+ with open(p1, "rb") as f1:
125
+ with open(p2, "rb") as f2:
126
+ while True:
127
+ b1 = f1.read(1024)
128
+ l = len(b1)
129
+ if l == 0:
130
+ return True
131
+ if b1 != f2.read(l):
132
+ return False
133
+ from .__main__ import HASH_TYPES
134
+ if method in HASH_TYPES: # Сравнение контрольной суммы
135
+ import hashlib
136
+ Hash = getattr(hashlib, method)
137
+ with open(p1, "rb") as f1:
138
+ hash1 = Hash()
139
+ for chunk in f1:
140
+ hash1.update(chunk)
141
+ with open(p2, "rb") as f2:
142
+ hash2 = Hash()
143
+ for chunk in f2:
144
+ hash2.update(chunk)
145
+ return hash1.digest() == hash2.digest()
146
+ raise ValueError("Unknown method: " + repr(method))
147
+
148
+
117
149
  cp = copy
118
150
  ln = link
119
151
  mv = move
File without changes