MainShortcuts2 2.8.1__tar.gz → 2.8.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 (56) hide show
  1. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/PKG-INFO +1 -1
  2. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/pyproject.toml +1 -1
  3. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/_module_info.py +1 -1
  4. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/aiohttp_ex/web/__init__.py +1 -1
  5. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/sql/sqlite.py +3 -2
  6. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/utils.py +34 -34
  7. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/README.md +0 -0
  8. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/__init__.py +0 -0
  9. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/__main__.py +0 -0
  10. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/_any2json_regs.py +0 -0
  11. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/_ms2app_regs.py +0 -0
  12. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/_ms2dat_auto.py +0 -0
  13. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/advanced.py +0 -0
  14. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/any2json.py +0 -0
  15. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/api/base.py +0 -0
  16. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/api/gigachat.py +0 -0
  17. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/api/github.py +0 -0
  18. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/api/russian_trusted_root_ca_pem.crt +0 -0
  19. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/api/russian_trusted_sub_ca_pem.crt +0 -0
  20. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/api/webdav.py +0 -0
  21. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/cfg.py +0 -0
  22. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/core.py +0 -0
  23. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/core_config.py +0 -0
  24. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/dict.py +0 -0
  25. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/dir.py +0 -0
  26. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/__init__.py +0 -0
  27. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/aiohttp_ex/web/__main__.py +0 -0
  28. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/datetime_ex.py +0 -0
  29. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/pathlib_ex.py +0 -0
  30. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/pil_ex.py +0 -0
  31. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/psutil_ex.py +0 -0
  32. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/sqlite_ex.py +0 -0
  33. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ex/urlparse_ex.py +0 -0
  34. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/file.py +0 -0
  35. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/gui_scripts/__init__.py +0 -0
  36. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/gui_scripts/ms2_hash_gen.py +0 -0
  37. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/gui_scripts/utils.py +0 -0
  38. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/java_ext/__init__.py +0 -0
  39. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/java_ext/ms2ext.py +0 -0
  40. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/json.py +0 -0
  41. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/linux.py +0 -0
  42. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/list.py +0 -0
  43. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ms2app.py +0 -0
  44. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ms2dat1.py +0 -0
  45. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/ms2hash.py +0 -0
  46. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/path.py +0 -0
  47. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/proc.py +0 -0
  48. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/regex.py +0 -0
  49. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/special_chars.py +0 -0
  50. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/sql/_sql_base.py +0 -0
  51. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/sql/mysql.py +0 -0
  52. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/sql/postgresql.py +0 -0
  53. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/str.py +0 -0
  54. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/term.py +0 -0
  55. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/types.py +0 -0
  56. {mainshortcuts2-2.8.1 → mainshortcuts2-2.8.2}/src/MainShortcuts2/win.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MainShortcuts2
3
- Version: 2.8.1
3
+ Version: 2.8.2
4
4
  Summary: Сокращение и улучшение функций + консольные утилиты
5
5
  Author: MainPlay TG
6
6
  Author-email: xbox.roman6666666666@gmail.com
@@ -1,5 +1,5 @@
1
1
  [tool.poetry]
2
- version = "2.8.1"
2
+ version = "2.8.2"
3
3
  name = "MainShortcuts2"
4
4
  description = "Сокращение и улучшение функций + консольные утилиты"
5
5
  authors = ["MainPlay TG <xbox.roman6666666666@gmail.com>"]
@@ -1,2 +1,2 @@
1
1
  name = 'mainshortcuts2'
2
- version = '2.8.1'
2
+ version = '2.8.2'
@@ -34,7 +34,7 @@ def wrap_handler(app: "Application", handler: Handler):
34
34
  resp = Response(status=500, reason="Internal server error")
35
35
  if app.logger.isEnabledFor(DEBUG):
36
36
  remote = req.remote or "unknown"
37
- if "X-Real-IP" in req.headers:
37
+ if req.headers.get("X-Real-IP"):
38
38
  remote += " (X-Real-IP: %s)" % req.headers["X-Real-IP"]
39
39
  status = resp.status if isinstance(resp, StreamResponse) else repr(resp)
40
40
  app.logger.debug("Request %s %s from %s, return %s", req.method, req.raw_path, remote, status)
@@ -9,6 +9,7 @@ STRICT_SUPPORT = sqlite_version_info >= (3, 37, 0)
9
9
  # float -> REAL (8 байт)
10
10
  # int -> INTEGER (±9.2e18)
11
11
  # str -> TEXT
12
+ # Если strict_schema = False, типы всё равно рекомендуется правильно указывать
12
13
 
13
14
 
14
15
  def _gws(where: dict, sep: str = " AND "):
@@ -28,10 +29,10 @@ class Database(SyncDatabaseBase):
28
29
  kw["autosave"] = False
29
30
  self.db_path = None
30
31
  else:
31
- self.db_path.parent.any_mkdir()
32
32
  self.db_path = Path(path)
33
- DatabaseBase.__init__(self, **kw)
33
+ self.db_path.parent.any_mkdir()
34
34
  self.strict_schema = strict_schema
35
+ DatabaseBase.__init__(self, **kw)
35
36
  if TYPE_CHECKING:
36
37
  def cursor(self) -> Cursor:
37
38
  return super().cursor()
@@ -6,10 +6,10 @@ import logging
6
6
  import os
7
7
  import sys
8
8
  import time
9
+ import typing
9
10
  from .core import ms
10
11
  from contextlib import ExitStack
11
12
  from functools import wraps
12
- from typing import *
13
13
  from warnings import warn
14
14
  cache = {}
15
15
 
@@ -42,7 +42,7 @@ class MiddlewareBase:
42
42
  self._result = None
43
43
  self._time = None
44
44
  self._traceback = None
45
- self.completed_with_exc: Union[None, bool] = None
45
+ self.completed_with_exc: bool | None = None
46
46
  self.completed: bool = False
47
47
  self.func = func
48
48
  self.launched: bool = False
@@ -94,33 +94,33 @@ class MiddlewareBase:
94
94
  return self._args
95
95
 
96
96
  @args.setter
97
- def args(self, value: Iterable):
97
+ def args(self, value):
98
98
  if value is None:
99
99
  value = []
100
100
  self._args = tuple(value)
101
101
 
102
102
  @property
103
- def exception(self) -> None | Exception:
103
+ def exception(self):
104
104
  """Исключение, возникшее в процессе работы функции"""
105
105
  self._check_completed()
106
106
  return self._exception
107
107
 
108
108
  @property
109
- def kwargs(self) -> dict[str, Any]:
109
+ def kwargs(self) -> dict[str, typing.Any]:
110
110
  """Именованные аргументы, переданные функции"""
111
111
  self._check_launched()
112
112
  return self._kwargs
113
113
 
114
114
  @kwargs.setter
115
- def kwargs(self, value: dict[str, Any]):
115
+ def kwargs(self, value):
116
116
  if value is None:
117
117
  value = {}
118
- for k in value.keys():
119
- assert type(k) == str
118
+ for k in value:
119
+ assert isinstance(k, str)
120
120
  self._kwargs = value
121
121
 
122
122
  @property
123
- def result(self) -> Any:
123
+ def result(self):
124
124
  """Результат работы функции"""
125
125
  self._check_completed()
126
126
  if self.completed_with_exc:
@@ -134,7 +134,7 @@ class MiddlewareBase:
134
134
  return self._time
135
135
 
136
136
  @property
137
- def traceback(self) -> None | str:
137
+ def traceback(self):
138
138
  self._check_completed()
139
139
  return self._traceback
140
140
 
@@ -147,7 +147,7 @@ class MiddlewareBase:
147
147
  pass
148
148
 
149
149
 
150
- def args2kwargs(func: Callable, args: Iterable = (), kwargs: dict[str, Any] = {}) -> tuple[tuple, dict[str, Any]]:
150
+ def args2kwargs(func: typing.Callable, args=(), kwargs: dict[str, typing.Any] = {}):
151
151
  """Преобразовать `args` в `kwargs` | `inspect`"""
152
152
  import inspect
153
153
  kw = kwargs.copy()
@@ -164,14 +164,14 @@ def args2kwargs(func: Callable, args: Iterable = (), kwargs: dict[str, Any] = {}
164
164
  return tuple(args), kw
165
165
 
166
166
 
167
- async def async_download_file(url: str, path: str, *, cb_end=return_None, cb_progress=return_None, cb_start=return_None, chunk_size: int = 1024, delete_on_error: bool = True, **kw) -> int:
167
+ async def async_download_file(url: str, path: str, *, cb_end=return_None, cb_progress=return_None, cb_start=return_None, chunk_size: int = 1024, delete_on_error: bool = True, **kw):
168
168
  """Асинхронная функция для скачивания файла | `aiohttp`"""
169
169
  kw.setdefault("method", "GET")
170
170
  kw["url"] = url
171
171
  with ExitStack() as stack:
172
172
  async with async_request(**kw) as resp: # type: ignore
173
173
  if callable(getattr(path, "write", None)):
174
- f: IO[bytes] = path
174
+ f: typing.IO[bytes] = path
175
175
  else:
176
176
  f = stack.enter_context(open(path, "wb"))
177
177
  size = 0
@@ -212,7 +212,7 @@ async def async_request(method: str, url: str, *, ignore_status: bool = False, s
212
212
  return resp
213
213
 
214
214
 
215
- def async2sync(func: Callable) -> Callable:
215
+ def async2sync(func: typing.Callable) -> typing.Callable:
216
216
  """Превратить асинхронную функцию в синхронную | `asyncio`, `concurrent`"""
217
217
  import asyncio
218
218
  import concurrent.futures
@@ -230,13 +230,13 @@ def get_my_ip() -> str:
230
230
  return ip
231
231
 
232
232
 
233
- def is_async(func: Callable) -> bool:
233
+ def is_async(func: typing.Callable) -> bool:
234
234
  """Является ли функция асинхронной | `inspect`"""
235
235
  import inspect
236
236
  return inspect.iscoroutinefunction(func)
237
237
 
238
238
 
239
- def is_sync(func: Callable) -> bool:
239
+ def is_sync(func: typing.Callable) -> bool:
240
240
  """Является ли функция синхронной | `inspect`"""
241
241
  return not is_async(func)
242
242
 
@@ -315,7 +315,7 @@ def sync_download_file(url: str, path: str, *, cb_end=return_None, cb_progress=r
315
315
  with ExitStack() as stack:
316
316
  resp = stack.enter_context(sync_request(**kw))
317
317
  if callable(getattr(path, "write", None)):
318
- f: IO[bytes] = path
318
+ f: typing.IO[bytes] = path
319
319
  else:
320
320
  f = stack.enter_context(open(path, "wb"))
321
321
  size = 0
@@ -367,7 +367,7 @@ def sync_request(method: str, url: str, *, ignore_status: bool = False, session=
367
367
  request = sync_request
368
368
 
369
369
 
370
- def sync2async(func: Callable) -> Callable:
370
+ def sync2async(func: typing.Callable) -> typing.Callable:
371
371
  """Превратить синхронную функцию в асинхронную"""
372
372
  async def wrapper(*args, **kwargs):
373
373
  return func(*args, **kwargs)
@@ -384,7 +384,7 @@ def uuid(format=None, *args, **kwargs) -> str:
384
384
  return str(cls(*args, **kwargs))
385
385
 
386
386
 
387
- def timedelta(time: Union[int, float, dict]):
387
+ def timedelta(time: int | float | dict):
388
388
  """Превратить число/словарь в `timedelta` | `datetime`"""
389
389
  import datetime
390
390
  if isinstance(time, datetime.timedelta):
@@ -394,7 +394,7 @@ def timedelta(time: Union[int, float, dict]):
394
394
  return datetime.timedelta(seconds=time)
395
395
 
396
396
 
397
- def shebang_code(code: str, *, exe_name: Union[None, str] = None, exe_path: Union[None, str] = None, none_if_no_changes: bool = False, use_env: bool = True) -> Union[None, str]:
397
+ def shebang_code(code: str, *, exe_name: str | None = None, exe_path: str | None = None, none_if_no_changes: bool = False, use_env: bool = True) -> str | None:
398
398
  """Вставить/заменить шебанг в коде. Если указать имя интерпретатора, путь будет найден с помощью `shutil.which`"""
399
399
  if (exe_name is None) and (exe_path is None):
400
400
  raise TypeError("Specify exe_name or exe_path")
@@ -418,7 +418,7 @@ def shebang_code(code: str, *, exe_name: Union[None, str] = None, exe_path: Unio
418
418
  return "#!" + exe_path + "\n" + "\n".join(lines)
419
419
 
420
420
 
421
- def shebang_file(path: str, **kw) -> int:
421
+ def shebang_file(path: str, **kw):
422
422
  """Вставить/заменить шебанг в файле кода"""
423
423
  kw["code"] = ms.file.read(path)
424
424
  kw["none_if_no_changes"] = True
@@ -524,21 +524,21 @@ class OnlyOneInstance:
524
524
  pass
525
525
 
526
526
 
527
- def multi_and(*values: bool) -> bool:
527
+ def multi_and(*values: bool):
528
528
  for i in values:
529
529
  if not i:
530
530
  return False
531
531
  return True
532
532
 
533
533
 
534
- def multi_or(*values: bool) -> bool:
534
+ def multi_or(*values: bool):
535
535
  for i in values:
536
536
  if i:
537
537
  return True
538
538
  return False
539
539
 
540
540
 
541
- def is_int(value: float) -> bool:
541
+ def is_int(value: float):
542
542
  return value == int(value)
543
543
 
544
544
 
@@ -546,7 +546,7 @@ def get_self_module(__name__: str):
546
546
  return sys.modules[__name__]
547
547
 
548
548
 
549
- def check_programs(*progs: str, raise_error: bool = True) -> list[str]:
549
+ def check_programs(*progs: str, raise_error=True) -> list[str]:
550
550
  """Проверить наличие программ в `$PATH` | `shutil`"""
551
551
  from shutil import which
552
552
  failed = []
@@ -584,12 +584,12 @@ def disable_warnings():
584
584
  warnings.warn = return_None
585
585
 
586
586
 
587
- def is_instance_of_one(obj, *classes: type) -> bool:
587
+ def is_instance_of_one(obj, *classes: type):
588
588
  """Это экземпляр одного из классов?"""
589
589
  return isinstance(obj, classes)
590
590
 
591
591
 
592
- def is_instance_of_all(obj, *classes: type) -> bool:
592
+ def is_instance_of_all(obj, *classes: type):
593
593
  """Это экземпляр всех классов?"""
594
594
  for i in classes:
595
595
  if not isinstance(obj, i):
@@ -725,7 +725,7 @@ def run_pip(*args: str, internal: bool = False, **kw):
725
725
  raise PipError()
726
726
 
727
727
 
728
- def check_modules(*modules: str, _c: list[str] = None, _m: list[str] = None) -> list[str]:
728
+ def check_modules(*modules: str, _c: list[str] = None, _m: list[str] = None):
729
729
  """Проверить наличие модулей. Не проверяет возможность импорта. Возвращает список отсутствующих модулей"""
730
730
  import pkg_resources
731
731
  checked = [] if _c is None else _c
@@ -761,7 +761,7 @@ def auto_install_modules(*modules, print: bool | str = False, **pip_kw):
761
761
  run_pip(*args, **pip_kw)
762
762
 
763
763
 
764
- def http_check_range_support(url: str, **kw) -> bool:
764
+ def http_check_range_support(url: str, **kw):
765
765
  """Проверить возможность скачать файл по частям"""
766
766
  kw.setdefault("headers", {})
767
767
  kw["headers"]["Range"] = "bytes=0-1"
@@ -773,7 +773,7 @@ def http_check_range_support(url: str, **kw) -> bool:
773
773
  return True
774
774
  if "bytes" in resp.headers.get("Accept-Ranges", "").lower():
775
775
  return True
776
- return False
776
+ return False
777
777
 
778
778
 
779
779
  class MultiContext:
@@ -1042,7 +1042,7 @@ def sleep(seconds: float):
1042
1042
  time.sleep(seconds)
1043
1043
 
1044
1044
 
1045
- def which_real(cmd: str, **kw) -> str | None:
1045
+ def which_real(cmd: str, **kw):
1046
1046
  """Получить реальный путь к исполняемому файлу"""
1047
1047
  from shutil import which
1048
1048
  result = which(cmd, **kw)
@@ -1118,13 +1118,13 @@ def int_size_signed(n: int) -> int:
1118
1118
  return (n.bit_length() + 8) // 8
1119
1119
 
1120
1120
 
1121
- def int2bytes(n: int, byteorder='big', signed=False) -> bytes:
1121
+ def int2bytes(n: int, byteorder='big', signed=False):
1122
1122
  """Конвертировать `int` в `bytes` минимального размера"""
1123
1123
  f = int_size_signed if signed else int_size_unsigned
1124
1124
  return n.to_bytes(f(n), byteorder=byteorder, signed=signed)
1125
1125
 
1126
1126
 
1127
- class SyncSignal(list):
1127
+ class SyncSignal(typing.List[typing.Callable]):
1128
1128
  def __init__(self, ignore_errors=False):
1129
1129
  super().__init__()
1130
1130
  self.ignore_errors = bool(ignore_errors)
@@ -1188,7 +1188,7 @@ class _OrFilter(_AndFilter):
1188
1188
  return self.f1(*a, **b) or self.f2(*a, **b)
1189
1189
 
1190
1190
 
1191
- def create_filter(func: Callable, name: str = None, **d) -> Filter:
1191
+ def create_filter(func: typing.Callable, name: str = None, **d) -> Filter:
1192
1192
  d["__call__"] = func
1193
1193
  return type(name or func.__name__ or "CustomFilter", (Filter,), d)()
1194
1194
 
File without changes