MainShortcuts2 2.0.0__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.
- mainshortcuts2-2.0.0/PKG-INFO +79 -0
- mainshortcuts2-2.0.0/README.md +60 -0
- mainshortcuts2-2.0.0/pyproject.toml +20 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/__init__.py +9 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/_module_info.py +2 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/cfg.py +125 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/core.py +142 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/dict.py +45 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/dir.py +102 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/file.py +92 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/json.py +90 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/list.py +84 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/path.py +306 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/proc.py +30 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/str.py +48 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/term.py +93 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/utils.py +295 -0
- mainshortcuts2-2.0.0/src/MainShortcuts2/win.py +39 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: MainShortcuts2
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Сокращение и улучшение функций
|
|
5
|
+
Home-page: https://github.com/MainPlay-TG/MainShortcuts2.py
|
|
6
|
+
Author: MainPlay TG
|
|
7
|
+
Author-email: xbox.roman6666666666@gmail.com
|
|
8
|
+
Requires-Python: >=3.6,<4.0
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Project-URL: Repository, https://github.com/MainPlay-TG/MainShortcuts2.py
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# MainShortcuts
|
|
21
|
+
## Описание
|
|
22
|
+
Сокращение и упрощение встроенных операций Python
|
|
23
|
+
## Установка
|
|
24
|
+
Для установки через PIP используйте
|
|
25
|
+
```bash
|
|
26
|
+
pip install -U mainshortcuts
|
|
27
|
+
```
|
|
28
|
+
## Использование
|
|
29
|
+
Для импорта рекомендуется сокращённое название
|
|
30
|
+
```python
|
|
31
|
+
import MainShortcuts as ms
|
|
32
|
+
```
|
|
33
|
+
Или же создайте/добавьте импорт MainCore в вашу программу
|
|
34
|
+
```bash
|
|
35
|
+
MS-getCoreMini program.py
|
|
36
|
+
```
|
|
37
|
+
Встроенная информация о модуле
|
|
38
|
+
```python
|
|
39
|
+
ms.__version__ -> str # Версия модуля
|
|
40
|
+
ms.__depends__ -> dict # Обязательные и необязательные зависимости
|
|
41
|
+
```
|
|
42
|
+
### Выход с кодом ошибки
|
|
43
|
+
Закрывает процесс программы с указанным кодом ошибки
|
|
44
|
+
```python
|
|
45
|
+
# Любой ненулевой код означает ошибку
|
|
46
|
+
ms.exit() # Выход с кодом 0 (нет ошибки)
|
|
47
|
+
ms.exit(1) # Выход с кодом 1
|
|
48
|
+
```
|
|
49
|
+
### Очистка терминала
|
|
50
|
+
Очищает окно терминала от всего текста
|
|
51
|
+
```python
|
|
52
|
+
ms.clear() # Очистить окно терминала
|
|
53
|
+
mc.cls() # То же самое, но с названием из Windows CMD
|
|
54
|
+
```
|
|
55
|
+
**Поддерживается только на Windows и Linux**
|
|
56
|
+
### Загрузка/сохранение данных
|
|
57
|
+
Для удобной загрузки или сохранения данных можно использовать класс `cfg`
|
|
58
|
+
```python
|
|
59
|
+
cfg=ms.cfg("config.json",json_args={"mode":"p"})
|
|
60
|
+
cfg.load() # Загрузить данные
|
|
61
|
+
print(cfg.data) # Вывести данные
|
|
62
|
+
cfg.data={"example":"Пример данных"} # Изменить данные
|
|
63
|
+
cfg.save() # Сохранить данные
|
|
64
|
+
```
|
|
65
|
+
Тип сохранения определяется по расширению, но можно это изменить
|
|
66
|
+
```python
|
|
67
|
+
cfg=ms.cfg("data",type="pickle") # Использовать Pickle для файла данных
|
|
68
|
+
# Предупреждение: использование Pickle может быть не безопасным!
|
|
69
|
+
```
|
|
70
|
+
Чтобы посмотреть поддерживаемые типы сохранения, импортируйте часть модуля
|
|
71
|
+
```python
|
|
72
|
+
from MainShortcuts.cfg import types
|
|
73
|
+
print(", ".join(types))
|
|
74
|
+
```
|
|
75
|
+
Также можно изменить расположение файла, тип и аргументы во время любой загрузки или сохранения, это не повлияет на обычные настройки
|
|
76
|
+
```python
|
|
77
|
+
cfg.load("data.toml",toml_args={"encoding":"utf-8"})
|
|
78
|
+
cfg.save("data.pkl")
|
|
79
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# MainShortcuts
|
|
2
|
+
## Описание
|
|
3
|
+
Сокращение и упрощение встроенных операций Python
|
|
4
|
+
## Установка
|
|
5
|
+
Для установки через PIP используйте
|
|
6
|
+
```bash
|
|
7
|
+
pip install -U mainshortcuts
|
|
8
|
+
```
|
|
9
|
+
## Использование
|
|
10
|
+
Для импорта рекомендуется сокращённое название
|
|
11
|
+
```python
|
|
12
|
+
import MainShortcuts as ms
|
|
13
|
+
```
|
|
14
|
+
Или же создайте/добавьте импорт MainCore в вашу программу
|
|
15
|
+
```bash
|
|
16
|
+
MS-getCoreMini program.py
|
|
17
|
+
```
|
|
18
|
+
Встроенная информация о модуле
|
|
19
|
+
```python
|
|
20
|
+
ms.__version__ -> str # Версия модуля
|
|
21
|
+
ms.__depends__ -> dict # Обязательные и необязательные зависимости
|
|
22
|
+
```
|
|
23
|
+
### Выход с кодом ошибки
|
|
24
|
+
Закрывает процесс программы с указанным кодом ошибки
|
|
25
|
+
```python
|
|
26
|
+
# Любой ненулевой код означает ошибку
|
|
27
|
+
ms.exit() # Выход с кодом 0 (нет ошибки)
|
|
28
|
+
ms.exit(1) # Выход с кодом 1
|
|
29
|
+
```
|
|
30
|
+
### Очистка терминала
|
|
31
|
+
Очищает окно терминала от всего текста
|
|
32
|
+
```python
|
|
33
|
+
ms.clear() # Очистить окно терминала
|
|
34
|
+
mc.cls() # То же самое, но с названием из Windows CMD
|
|
35
|
+
```
|
|
36
|
+
**Поддерживается только на Windows и Linux**
|
|
37
|
+
### Загрузка/сохранение данных
|
|
38
|
+
Для удобной загрузки или сохранения данных можно использовать класс `cfg`
|
|
39
|
+
```python
|
|
40
|
+
cfg=ms.cfg("config.json",json_args={"mode":"p"})
|
|
41
|
+
cfg.load() # Загрузить данные
|
|
42
|
+
print(cfg.data) # Вывести данные
|
|
43
|
+
cfg.data={"example":"Пример данных"} # Изменить данные
|
|
44
|
+
cfg.save() # Сохранить данные
|
|
45
|
+
```
|
|
46
|
+
Тип сохранения определяется по расширению, но можно это изменить
|
|
47
|
+
```python
|
|
48
|
+
cfg=ms.cfg("data",type="pickle") # Использовать Pickle для файла данных
|
|
49
|
+
# Предупреждение: использование Pickle может быть не безопасным!
|
|
50
|
+
```
|
|
51
|
+
Чтобы посмотреть поддерживаемые типы сохранения, импортируйте часть модуля
|
|
52
|
+
```python
|
|
53
|
+
from MainShortcuts.cfg import types
|
|
54
|
+
print(", ".join(types))
|
|
55
|
+
```
|
|
56
|
+
Также можно изменить расположение файла, тип и аргументы во время любой загрузки или сохранения, это не повлияет на обычные настройки
|
|
57
|
+
```python
|
|
58
|
+
cfg.load("data.toml",toml_args={"encoding":"utf-8"})
|
|
59
|
+
cfg.save("data.pkl")
|
|
60
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
version = "2.0.0"
|
|
3
|
+
name = "MainShortcuts2"
|
|
4
|
+
description = "Сокращение и улучшение функций"
|
|
5
|
+
authors = [ "MainPlay TG <xbox.roman6666666666@gmail.com>",]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
repository = "https://github.com/MainPlay-TG/MainShortcuts2.py"
|
|
8
|
+
packages = [
|
|
9
|
+
{ include = "MainShortcuts2", from = "src" },
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[tool.poetry.scripts]
|
|
13
|
+
ms2-import_example = "MainShortcuts2.__main__:import_example"
|
|
14
|
+
|
|
15
|
+
[tool.poetry.dependencies]
|
|
16
|
+
python = "^3.6"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = [ "poetry-core",]
|
|
20
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -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,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()
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|