basic-password-manager 0.2.3__tar.gz → 0.2.4__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.
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/PKG-INFO +1 -1
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/basic_password_manager.egg-info/PKG-INFO +1 -1
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pw_manager/cli.py +3 -4
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pw_manager/logo.py +44 -2
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pw_manager/tui.py +12 -2
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pyproject.toml +1 -1
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/LICENSE +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/README.md +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/basic_password_manager.egg-info/SOURCES.txt +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/basic_password_manager.egg-info/dependency_links.txt +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/basic_password_manager.egg-info/entry_points.txt +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/basic_password_manager.egg-info/requires.txt +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/basic_password_manager.egg-info/top_level.txt +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pw_manager/__init__.py +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pw_manager/crypto.py +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/pw_manager/vault.py +0 -0
- {basic_password_manager-0.2.3 → basic_password_manager-0.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-password-manager
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: The Paladin — a local encrypted password manager that lives in your terminal
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/Daisentaur/password-manager
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-password-manager
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: The Paladin — a local encrypted password manager that lives in your terminal
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/Daisentaur/password-manager
|
|
@@ -62,11 +62,10 @@ def cmd_about(args):
|
|
|
62
62
|
v = version("basic-password-manager")
|
|
63
63
|
except PackageNotFoundError:
|
|
64
64
|
v = "dev" # running from source without an install
|
|
65
|
-
|
|
66
|
-
from . import logo
|
|
65
|
+
from . import logo
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
print(f"The Paladin
|
|
67
|
+
print(logo.ascii_art())
|
|
68
|
+
print(f"The Paladin ⚔ v{v}")
|
|
70
69
|
print("your passwords, guarded locally — no browser, no cloud, no mercy")
|
|
71
70
|
print("https://github.com/Daisentaur/password-manager")
|
|
72
71
|
|
|
@@ -62,11 +62,34 @@ def ansi(indent: str = "") -> str:
|
|
|
62
62
|
return "\n".join(out)
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
_ORANGE = (PALETTE["b"], PALETTE["r"])
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _tinted(pixel, tint, accent):
|
|
69
|
+
"""Recolor a pixel: keep its brightness, take its hue from the theme —
|
|
70
|
+
the accent color for the sword guard, the tint for everything else."""
|
|
71
|
+
if tint is None or pixel is None:
|
|
72
|
+
return pixel
|
|
73
|
+
base = accent if pixel in _ORANGE else tint
|
|
74
|
+
lum = sum(pixel) / 765
|
|
75
|
+
return tuple(int(c * lum) for c in base)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _hex_rgb(color: str) -> tuple:
|
|
79
|
+
color = color.lstrip("#")
|
|
80
|
+
return tuple(int(color[i : i + 2], 16) for i in (0, 2, 4))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def rich_text(tint: str | None = None, accent: str | None = None) -> Text:
|
|
84
|
+
"""The knight as a Rich Text, for Textual widgets. Pass theme colors as
|
|
85
|
+
hex strings to render him in the theme's livery instead of silver."""
|
|
86
|
+
tint_rgb = _hex_rgb(tint) if tint else None
|
|
87
|
+
accent_rgb = _hex_rgb(accent) if accent else tint_rgb
|
|
67
88
|
text = Text()
|
|
68
89
|
for row in _pixel_pairs():
|
|
69
90
|
for top, bottom in row:
|
|
91
|
+
top = _tinted(top, tint_rgb, accent_rgb)
|
|
92
|
+
bottom = _tinted(bottom, tint_rgb, accent_rgb)
|
|
70
93
|
if top is None and bottom is None:
|
|
71
94
|
text.append(" ")
|
|
72
95
|
elif bottom is None:
|
|
@@ -79,6 +102,25 @@ def rich_text() -> Text:
|
|
|
79
102
|
return text
|
|
80
103
|
|
|
81
104
|
|
|
105
|
+
def ascii_art() -> str:
|
|
106
|
+
"""The knight as plain monochrome ASCII — two chars per pixel to keep
|
|
107
|
+
his proportions in terminal cells, denser glyphs for brighter armor."""
|
|
108
|
+
lines = []
|
|
109
|
+
for row in ROWS:
|
|
110
|
+
line = ""
|
|
111
|
+
for ch in row:
|
|
112
|
+
pixel = PALETTE.get(ch)
|
|
113
|
+
if pixel is None:
|
|
114
|
+
line += " "
|
|
115
|
+
elif pixel in _ORANGE:
|
|
116
|
+
line += "%%"
|
|
117
|
+
else:
|
|
118
|
+
lum = sum(pixel) / 765
|
|
119
|
+
line += "::" if lum < 0.15 else "++" if lum < 0.45 else "==" if lum < 0.8 else "##"
|
|
120
|
+
lines.append(line.rstrip())
|
|
121
|
+
return "\n".join(lines)
|
|
122
|
+
|
|
123
|
+
|
|
82
124
|
def says(message: str) -> str:
|
|
83
125
|
"""Cowsay, but it's a knight."""
|
|
84
126
|
border = "_" * (len(message) + 2)
|
|
@@ -23,7 +23,7 @@ from .cli import VAULT_PATH, generate, import_csv, to_clipboard
|
|
|
23
23
|
THEME_FILE = os.path.expanduser("~/.local/share/pw-manager/theme")
|
|
24
24
|
|
|
25
25
|
APP_NAME = "The Paladin"
|
|
26
|
-
APP_ICON = "
|
|
26
|
+
APP_ICON = "⚔"
|
|
27
27
|
|
|
28
28
|
TUXEDO_THEMES = [
|
|
29
29
|
Theme(
|
|
@@ -76,11 +76,21 @@ class UnlockScreen(Screen):
|
|
|
76
76
|
|
|
77
77
|
def compose(self) -> ComposeResult:
|
|
78
78
|
with Vertical(id="unlock-box"):
|
|
79
|
-
yield Static(
|
|
79
|
+
yield Static(id="unlock-logo")
|
|
80
80
|
yield Label(f"{APP_ICON} {APP_NAME}", id="unlock-title")
|
|
81
81
|
yield Input(password=True, placeholder="master password", id="master")
|
|
82
82
|
yield Static("", id="unlock-error")
|
|
83
83
|
|
|
84
|
+
def on_mount(self) -> None:
|
|
85
|
+
self._paint_logo()
|
|
86
|
+
self.app.theme_changed_signal.subscribe(self, self._paint_logo)
|
|
87
|
+
|
|
88
|
+
def _paint_logo(self, _theme: Theme | None = None) -> None:
|
|
89
|
+
theme = self.app.current_theme
|
|
90
|
+
self.query_one("#unlock-logo", Static).update(
|
|
91
|
+
logo.rich_text(tint=theme.primary, accent=theme.warning or theme.primary)
|
|
92
|
+
)
|
|
93
|
+
|
|
84
94
|
def on_input_submitted(self, event: Input.Submitted) -> None:
|
|
85
95
|
self.query_one("#unlock-error", Static).update("unlocking…")
|
|
86
96
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|