jwbmisc 0.0.3__py3-none-any.whl → 0.0.4__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.
- jwbmisc/__init__.py +3 -2
- jwbmisc/_version.py +2 -2
- jwbmisc/collection.py +27 -0
- jwbmisc/interactive.py +13 -0
- jwbmisc/keeper.py +1 -1
- jwbmisc/passwd.py +3 -1
- jwbmisc/string.py +20 -0
- {jwbmisc-0.0.3.dist-info → jwbmisc-0.0.4.dist-info}/METADATA +1 -1
- jwbmisc-0.0.4.dist-info/RECORD +15 -0
- jwbmisc/util.py +0 -64
- jwbmisc-0.0.3.dist-info/RECORD +0 -14
- {jwbmisc-0.0.3.dist-info → jwbmisc-0.0.4.dist-info}/WHEEL +0 -0
- {jwbmisc-0.0.3.dist-info → jwbmisc-0.0.4.dist-info}/licenses/LICENSE +0 -0
- {jwbmisc-0.0.3.dist-info → jwbmisc-0.0.4.dist-info}/top_level.txt +0 -0
jwbmisc/__init__.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from .passwd import get_pass
|
|
2
|
-
from .string import jinja_replace
|
|
2
|
+
from .string import jinja_replace, randomsuffix, qw, split_host
|
|
3
3
|
from .exec import run_cmd
|
|
4
4
|
from .json import jsonc_loads, jsonc_read, ndjson_read, ndjson_write, resilient_loads
|
|
5
5
|
from .fs import fzf, find_root
|
|
6
|
-
from .
|
|
6
|
+
from .collection import goo
|
|
7
|
+
from .interactive import ask, confirm
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
9
10
|
"get_pass",
|
jwbmisc/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 4)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
jwbmisc/collection.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def goo(
|
|
5
|
+
d: dict[str, Any],
|
|
6
|
+
*keys: str | int,
|
|
7
|
+
default: Any | None = None,
|
|
8
|
+
raise_on_default: bool = False,
|
|
9
|
+
):
|
|
10
|
+
path = ".".join(str(k) for k in keys)
|
|
11
|
+
parts = path.split(".")
|
|
12
|
+
|
|
13
|
+
res = d
|
|
14
|
+
for p in parts:
|
|
15
|
+
if res is None:
|
|
16
|
+
if raise_on_default:
|
|
17
|
+
raise ValueError(f"'{path}' does not exist")
|
|
18
|
+
return default
|
|
19
|
+
if isinstance(res, (list, set, tuple)):
|
|
20
|
+
res = res[int(p)]
|
|
21
|
+
else:
|
|
22
|
+
res = res.get(p)
|
|
23
|
+
if res is None:
|
|
24
|
+
if raise_on_default:
|
|
25
|
+
raise ValueError(f"'{path}' does not exist")
|
|
26
|
+
return default
|
|
27
|
+
return res
|
jwbmisc/interactive.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
def ask(question: str, default: None | str = None):
|
|
2
|
+
if default is not None:
|
|
3
|
+
question += f" [{default}]"
|
|
4
|
+
answer = input(question.strip() + " ").strip()
|
|
5
|
+
return answer if answer else default
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def confirm(question: str, default: str = "n") -> bool:
|
|
9
|
+
prompt = f"{question} (y/n)"
|
|
10
|
+
answer = ask(prompt, default=default)
|
|
11
|
+
if not answer:
|
|
12
|
+
return False
|
|
13
|
+
return answer.lower().startswith("y")
|
jwbmisc/keeper.py
CHANGED
|
@@ -5,7 +5,7 @@ from time import sleep
|
|
|
5
5
|
from keepercommander.params import KeeperParams
|
|
6
6
|
from keepercommander.config_storage import loader
|
|
7
7
|
import os
|
|
8
|
-
from .
|
|
8
|
+
from .interactive import ask
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
import webbrowser
|
|
11
11
|
from keepercommander.auth import login_steps
|
jwbmisc/passwd.py
CHANGED
|
@@ -2,6 +2,8 @@ import subprocess as sp
|
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
+
PASS_BIN = os.environ.get("JWBMISC_PASS_BIN", "pass")
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
def get_pass(*pass_keys: str):
|
|
7
9
|
if not pass_keys:
|
|
@@ -48,7 +50,7 @@ def get_pass(*pass_keys: str):
|
|
|
48
50
|
|
|
49
51
|
|
|
50
52
|
def _call_unix_pass(key, lnum=1):
|
|
51
|
-
proc = sp.Popen([
|
|
53
|
+
proc = sp.Popen([PASS_BIN, "show", key], stdout=sp.PIPE, stderr=sp.PIPE, encoding="utf-8")
|
|
52
54
|
value, stderr = proc.communicate()
|
|
53
55
|
|
|
54
56
|
if proc.returncode != 0:
|
jwbmisc/string.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import random
|
|
3
|
+
import string
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
def jinja_replace(s, config, relaxed: bool = False, delim: tuple[str, str] = ("{{", "}}")):
|
|
@@ -20,3 +22,21 @@ def jinja_replace(s, config, relaxed: bool = False, delim: tuple[str, str] = ("{
|
|
|
20
22
|
raise KeyError(f"{k} is not in the supplied replacement variables")
|
|
21
23
|
|
|
22
24
|
return re.sub(re.escape(delim[0]) + r"\s*(\w+)\s*" + re.escape(delim[1]), handle_match, s)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def randomsuffix(length: int):
|
|
28
|
+
letters = string.ascii_lowercase
|
|
29
|
+
return "".join(random.choice(letters) for _ in range(length))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def qw(s: str) -> list[str]:
|
|
33
|
+
return s.split()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def split_host(host: str) -> tuple[str | None, int | None]:
|
|
37
|
+
if not host:
|
|
38
|
+
return (None, None)
|
|
39
|
+
res = host.split(":", 1)
|
|
40
|
+
if len(res) == 1:
|
|
41
|
+
return (res[0], None)
|
|
42
|
+
return (res[0], int(res[1]))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
jwbmisc/__init__.py,sha256=5VXxKCMejjLWaiECh64309WJ2LpHHSULxaGOvCAOzyU,581
|
|
2
|
+
jwbmisc/_version.py,sha256=QlXZ5JTjE_pgpDaeHk0GTExkc75xUZFmd0hA7kGYCJ0,704
|
|
3
|
+
jwbmisc/collection.py,sha256=mICHxBFfk2XY8ajdWkLvmQF1R6oo6d0torpRAeDvd1c,663
|
|
4
|
+
jwbmisc/exec.py,sha256=9g1Jc7iDkBj1Y-dn5VhnwH1JqvWSbrFe6Mmvnf-iqag,1177
|
|
5
|
+
jwbmisc/fs.py,sha256=Vf28qbOnBeHEbXNMUZjOQXtMWBurjkzD2KmfV2gJQXM,599
|
|
6
|
+
jwbmisc/interactive.py,sha256=qMgpQNHvUg4AYw-aAAy2qdxri1aKr-mffoLfUgh8TWE,423
|
|
7
|
+
jwbmisc/json.py,sha256=h3CBDNNZjcTDxydViyydPsQufXQLuxqP24wBBAT2nDs,1198
|
|
8
|
+
jwbmisc/keeper.py,sha256=mm3lVUL0UzXzxIBgT3ZM60By-I4Sckozl4t74O3mvQQ,4324
|
|
9
|
+
jwbmisc/passwd.py,sha256=cBCgy3NnLGa2-Fd7S4I_Qos9Taw7UpU-39k0RsKHs0U,2577
|
|
10
|
+
jwbmisc/string.py,sha256=0_AvtAyXUlyVL6yw1iMjs3vMunubTTTWS0PSu_qKgi8,1232
|
|
11
|
+
jwbmisc-0.0.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
12
|
+
jwbmisc-0.0.4.dist-info/METADATA,sha256=aVscIglVdplmuuHuZAfHjbl6gtWSIFegob1-FNbhHec,14507
|
|
13
|
+
jwbmisc-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
14
|
+
jwbmisc-0.0.4.dist-info/top_level.txt,sha256=FqEYs8zdG3iGOJmC6cutDXfGQUNptzfYeKsaG43y1HE,8
|
|
15
|
+
jwbmisc-0.0.4.dist-info/RECORD,,
|
jwbmisc/util.py
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import random
|
|
2
|
-
import string
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def ask(question, default=None):
|
|
7
|
-
if default is not None:
|
|
8
|
-
question += f" [{default}]"
|
|
9
|
-
answer = input(question.strip() + " ").strip()
|
|
10
|
-
return answer if answer else default
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def confirm(question, default="n"):
|
|
14
|
-
prompt = f"{question} (y/n)"
|
|
15
|
-
if default is not None:
|
|
16
|
-
prompt += f" [{default}]"
|
|
17
|
-
answer = input(prompt).strip().lower()
|
|
18
|
-
if not answer:
|
|
19
|
-
answer = default.lower() if default else "n"
|
|
20
|
-
return answer.startswith("y")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def randomsuffix(length):
|
|
24
|
-
letters = string.ascii_lowercase
|
|
25
|
-
return "".join(random.choice(letters) for _ in range(length))
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def qw(s: str) -> list[str]:
|
|
29
|
-
return s.split()
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def split_host(host: str) -> tuple[str | None, int | None]:
|
|
33
|
-
if not host:
|
|
34
|
-
return (None, None)
|
|
35
|
-
res = host.split(":", 1)
|
|
36
|
-
if len(res) == 1:
|
|
37
|
-
return (res[0], None)
|
|
38
|
-
return (res[0], int(res[1]))
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def goo(
|
|
42
|
-
d: dict[str, Any],
|
|
43
|
-
*keys: str | int,
|
|
44
|
-
default: Any | None = None,
|
|
45
|
-
raise_on_default: bool = False,
|
|
46
|
-
):
|
|
47
|
-
path = ".".join(str(k) for k in keys)
|
|
48
|
-
parts = path.split(".")
|
|
49
|
-
|
|
50
|
-
res = d
|
|
51
|
-
for p in parts:
|
|
52
|
-
if res is None:
|
|
53
|
-
if raise_on_default:
|
|
54
|
-
raise ValueError(f"'{path}' does not exist")
|
|
55
|
-
return default
|
|
56
|
-
if isinstance(res, (list, set, tuple)):
|
|
57
|
-
res = res[int(p)]
|
|
58
|
-
else:
|
|
59
|
-
res = res.get(p)
|
|
60
|
-
if res is None:
|
|
61
|
-
if raise_on_default:
|
|
62
|
-
raise ValueError(f"'{path}' does not exist")
|
|
63
|
-
return default
|
|
64
|
-
return res
|
jwbmisc-0.0.3.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
jwbmisc/__init__.py,sha256=VT_f1aG3ufoT7mYV1Ho0ocNtydMTIPbmcvOANwQE-CQ,551
|
|
2
|
-
jwbmisc/_version.py,sha256=pBZsQt6tlL02W-ri--X_4JCubpAK7jjCSnOmUp_isjc,704
|
|
3
|
-
jwbmisc/exec.py,sha256=9g1Jc7iDkBj1Y-dn5VhnwH1JqvWSbrFe6Mmvnf-iqag,1177
|
|
4
|
-
jwbmisc/fs.py,sha256=Vf28qbOnBeHEbXNMUZjOQXtMWBurjkzD2KmfV2gJQXM,599
|
|
5
|
-
jwbmisc/json.py,sha256=h3CBDNNZjcTDxydViyydPsQufXQLuxqP24wBBAT2nDs,1198
|
|
6
|
-
jwbmisc/keeper.py,sha256=nOOfzoAPF7Uy3TuMPPdBdq9DvwNanyrQp6lVFI66LnU,4317
|
|
7
|
-
jwbmisc/passwd.py,sha256=ZcOIT_RrwDR3uZgrcWASRLz8D6gf6iAHOEdyfwTuX4I,2520
|
|
8
|
-
jwbmisc/string.py,sha256=pUNAMaP5531mBy3mrp9GCZ3QRPy6MQwegt5yzcWP1wQ,795
|
|
9
|
-
jwbmisc/util.py,sha256=XCF5LEOLjI4IsYP-FF2ytbzo4J0rlCNJzrdNrtNWSGM,1568
|
|
10
|
-
jwbmisc-0.0.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
11
|
-
jwbmisc-0.0.3.dist-info/METADATA,sha256=U6WTkWiesNELCpjGh0Myaj-Uzd6To1qw7K28--fAWkU,14507
|
|
12
|
-
jwbmisc-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
-
jwbmisc-0.0.3.dist-info/top_level.txt,sha256=FqEYs8zdG3iGOJmC6cutDXfGQUNptzfYeKsaG43y1HE,8
|
|
14
|
-
jwbmisc-0.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|