mukimov
A small cross-platform Python library with masked password input, terminal colors, Markdown and typed environment settings.
Developed by Mukimov Studio
- ⭐ Hidden password input with
stars() - 🎨 12 terminal colors with
mukimov.color - 📝 Terminal Markdown rendering with
mukimov.text.markdown - ⚙️ Typed environment settings and explicit
.envloading withmukimov.env(since 0.1.8)
What is mukimov?
mukimov lets you read a password or any other secret text in the terminal
while showing a mask character instead of the real keystrokes.
For example, the user really types:
123456
but the terminal shows:
Password: ******
And the function returns the real text "123456".
Starting with mukimov 0.1.4, the library also provides mukimov.color
with 12 terminal colors — see the Colors sections below.
Starting with mukimov 0.1.6, the library also provides mukimov.text.markdown,
a Markdown → ANSI terminal renderer — see the Markdown section below.
Starting with mukimov 0.1.7, the package also ships a mukimov CLI
with --version and a cached self-updater — see the CLI / Updates section below.
Important: this is NOT hashing and NOT encryption. The library only visually hides input from people who may be looking at the screen. The real password is still returned to your program as a plain string.
Installation
pip install mukimov
Upgrade to the latest version:
pip install --upgrade mukimov
Or with the built-in updater (uses the same Python/pip that runs mukimov):
mukimov update
Check the installed version:
mukimov --version
pip show mukimov
Quick Start
The simplest possible example:
from mukimov import stars
password = stars("Password: ")
What the user sees:
Password: ******
If the user typed 123456, the variable password contains:
"123456"
Custom Mask ✨
The second argument controls which character is shown for every typed symbol:
stars("Password: ", "*") # Password: ******
stars("Password: ", "/") # Password: //////
stars("Password: ", "#") # Password: ######
stars("Password: ", "•") # Password: ••••••
API:
stars(prompt, mask="*")
| Parameter | Type | Description |
|---|---|---|
prompt |
str |
Text displayed before input. |
mask |
str |
Character shown instead of each typed symbol. Defaults to "*". |
Important:
maskmust contain exactly ONE character.
Full Example
A realistic login prompt:
from mukimov import stars
username = input("Username: ")
password = stars("Password: ")
print(f"Welcome, {username}!")
Example terminal session:
Username: Mukimov
Password: ********
Welcome, Mukimov!
Note that the real password is never printed — only the mask is shown.
Colors 🎨
Available since
mukimov 0.1.4.
mukimov.color provides 12 terminal colors for your CLI output.
Установка актуальной версии:
pip install -U mukimov
Простой пример:
from mukimov.color import red, green, blue
print(red("Error"))
print(green("Success"))
print(blue("Information"))
red(), green() и остальные функции НЕ вызывают print() самостоятельно.
Они возвращают ANSI-цветную строку, которую можно передавать
в print(), input(), stars() и другие функции.
Пример:
message = red("Error")
print(message)
Все 12 цветов
| Function | Color |
|---|---|
red() |
Red |
green() |
Green |
blue() |
Blue |
yellow() |
Yellow |
orange() |
Orange |
purple() |
Purple |
pink() |
Pink |
cyan() |
Cyan |
lime() |
Lime |
gray() |
Gray |
white() |
White |
gold() |
Gold |
Полный импорт:
from mukimov.color import (
red,
green,
blue,
yellow,
orange,
purple,
pink,
cyan,
lime,
gray,
white,
gold,
)
Colors + input()
from mukimov.color import red, green
username = input(red("Username: "))
password = input(green("Password: "))
Цвет применяется к prompt терминала: текст приглашения отображается цветным, а введённое пользователем значение остаётся обычным.
Colors + stars()
Один из главных примеров README:
from mukimov import stars
from mukimov.color import cyan, green, red
print(cyan("=== LOGIN ==="))
username = input(green("Username: "))
password = stars(green("Password: "))
if username == "Mukimov":
print(green("Login successful!"))
else:
print(red("Invalid username!"))
stars() продолжает скрывать ввод пароля (показывает mask-символы
вместо реальных нажатий), а цветовая функция отвечает только
за цвет prompt.
Validation
Функции цветов принимают только str.
Например:
red(123)
результат:
TypeError: red() expected str, got int
Также запрещены пустые строки и строки только из whitespace:
red("")
red(" ")
red("\t")
red("\n")
Ожидается:
ValueError: red() text cannot be empty
При этом:
red("Username: ")
полностью корректно.
Исходный текст сохраняется без .strip() — пробелы внутри
нормального текста разрешены и не изменяются.
ANSI / RESET
Цвет реализован через ANSI escape sequences: каждая функция оборачивает
текст в код своего цвета и автоматически добавляет RESET (\x1b[0m)
в конец строки, поэтому цвет не распространяется на последующий вывод.
Например:
print(red("Error"))
print("Normal text")
Normal text отображается обычным цветом терминала.
Поддержка:
- Windows Terminal
- PowerShell
- Linux terminals
Для цветов не требуются сторонние зависимости — только чистый Python.
Markdown 🎨
Available since
mukimov 0.1.6.
mukimov.text.markdown renders Markdown as beautiful ANSI output
directly in your terminal:
from mukimov.text import markdown
markdown.print("# Hello")
markdown.print("**Bold text**")
markdown.print("*Italic text*")
Two functions, two different jobs:
markdown.render(...) # → returns `str` (prints nothing by itself)
markdown.print(...) # → prints the rendered result to the terminal
Example:
text = markdown.render("**Hello**")
print(text)
Supported Markdown: headings H1–H6, **bold**, __bold__,
*italic*, _italic_, ***bold + italic***, ~~strikethrough~~,
`inline code`, > quotes, unordered lists (-, *, +),
ordered lists (1.), --- rules, [links](https://...), fenced code
blocks with language, and GitHub-style tables with alignment.
Tables are drawn with box characters and correct column widths (Unicode-aware, ANSI-aware):
markdown.print("""
| Name | Language |
|------|----------|
| Mukimov | Python |
| Alex | Go |
""")
Code blocks keep their content untouched (no Markdown inside is interpreted) and show the language when it is given:
markdown.print("""
```python
def hello(name):
if name:
print(f"Hello {name}")
```
""")
Markdown combines with mukimov.color — your color stays, Markdown
styling is applied on top:
from mukimov.text import markdown
from mukimov.color import green
markdown.print(green("**Success!**"))
Success! stays green and becomes bold at the same time.
Notes:
- Markdown parsing is done by the small, stable
markdown-it-pydependency (installed automatically withmukimov); the ANSI terminal renderer itself is implemented insidemukimov. - Full LaTeX math support is planned for a future release:
$...$syntax currently passes through as plain text and never crashes. markdown.render()/markdown.print()accept onlystr(otherwiseTypeError) and return""/ print an empty line for an empty string.
Environment settings / .env ⚙️
Available since
mukimov 0.1.8.
from mukimov import env
env.load(".env")
DEBUG = env.boolean("DEBUG", default=False)
PORT = env.integer("PORT", default=8000)
SECRET_KEY = env.required("SECRET_KEY")
Пример файла .env (это настройки, Python-код пишется в .py):
DEBUG=true
PORT=8000
SECRET_KEY=your-secret-key
env.load(path=".env", override=False)явно загружает UTF-8 файл относительно текущей рабочей директории. Возвращает кортеж имён переменных без значений. Системные переменные имеют приоритет;override=Trueразрешает заменить их. Кавычки, комментарии,exportи многострочные значения поддерживаются. Подстановка${NAME}отключена: значения сохраняются буквально. Повторное имя в одном файле получает последнее значение.env.boolean(name, default=...)принимаетtrue/false,1/0,yes/no,on/off, без учёта регистра и окружающих пробелов.env.integer(name, default=...)читает целое десятичное число, включая знак.env.required(name)возвращает непустую строку без изменения её содержимого. Отсутствующее, пустое или состоящее только из пробелов значение вызываетenv.EnvError(подклассValueError).defaultиспользуется только для отсутствующей переменной. Пустое или неправильное значение вызывает ошибку даже при наличииdefault. Безdefaultпеременная обязательна. Default должен иметь правильный тип.- Без
env.load()функции читают только системное окружение. Импорт библиотеки сам по себе не читает.env. Отсутствующий файл вызываетFileNotFoundError. - Ошибка синтаксиса содержит номер строки, но не её содержимое; файл с ошибкой
не загружается частично. Имена должны соответствовать
[A-Za-z_][A-Za-z0-9_]*.
Если после загрузки .env в файле есть только:
DB_PASS=some-password
SUPER_KEY=some-key
и SECRET_KEY отсутствует также в системном окружении:
env.required("SECRET_KEY")
ошибка содержит только имена, без паролей и других значений:
Переменная SECRET_KEY в .env отсутствует!
Переменные в .env:
DB_PASS
SUPER_KEY
Если нужная переменная существует в системном окружении, она будет использована,
даже если её нет в файле. Список в ошибке относится только к последнему успешно
загруженному файлу, а не ко всем переменным компьютера. При пустом значении ошибка
явно сообщает об этом. .env с секретами не следует добавлять в Git или пакет.
Для Django можно указать путь независимо от текущей директории:
from pathlib import Path
from mukimov import env
BASE_DIR = Path(__file__).resolve().parent.parent
env.load(BASE_DIR / ".env")
DEBUG = env.boolean("DEBUG", default=False)
SECRET_KEY = env.required("SECRET_KEY")
Errors
mukimov raises clear, descriptive errors in Russian.
Each message tells you which parameter is wrong, what value was passed,
why it is wrong, what was expected, and shows a correct example.
Wrong usage:
stars("Password: ", "//")
Error:
ValueError: Параметр mask='//' содержит 2 символа. Допускается только 1 символ.
Пример: stars("Password: ", "*")
More examples (real messages from the library):
stars("Password: ", "")
ValueError: Параметр mask='' пустой. Укажите ровно 1 символ для маскировки.
Пример: stars("Password: ", "*")
stars("Password: ", 123)
TypeError: Параметр mask должен быть строкой (str), но получен int: 123.
Пример: stars("Password: ", "*")
stars(123)
TypeError: Параметр prompt должен быть строкой (str), но получен int: 123.
Пример: stars("Password: ")
Platform Support
Only systems actually supported by the current code are listed:
| OS | Backend |
|---|---|
| Windows | msvcrt |
| Linux | termios / tty |
| macOS | termios / tty |
Password input and colors use only the Python standard library.
Markdown uses markdown-it-py and wcwidth; .env loading uses python-dotenv. When standard input is not a TTY (pipes, IDE consoles, CI),
it safely falls back to getpass with no echo.
Extra behavior worth knowing:
- Backspace deletes the last mask character and the last symbol.
- Enter finishes input.
Ctrl+CraisesKeyboardInterrupt,Ctrl+Don empty input raisesEOFError.
Why mukimov?
The goal of mukimov is a simple, short API for masked terminal input.
mukimov:
from mukimov import stars
password = stars("Password: ", "•")
And the standard-library alternative, where your Python version
supports echo_char:
from getpass import getpass
password = getpass("Password: ", echo_char="•")
If you like the classic getpass, keep using it — mukimov is just
a compact option when you want per-character masking with a tiny API.
Security 🔒
mukimov hides the password only visually, while it is being typed.
It does NOT:
- hash the password
- encrypt the password
- store the password securely by itself
- protect the process from malware
- protect the contents of the process memory
After input, the function returns the real password as a regular Python string. To store passwords, developers must separately use a reliable password-hashing solution.
Also, error messages and logs of this library never include
the typed password — only configuration values (prompt, mask)
may appear in validation errors.
API
stars(prompt="Password: ", mask="*")
Parameters:
prompt: str— text displayed before input.mask: str— exactly one character shown instead of each typed symbol.
Returns:
str— the real text the user typed.
Exceptions:
TypeError—promptormaskis not a string.ValueError—maskis empty or longer than one character.
Color API
red(text: str) -> str
green(text: str) -> str
blue(text: str) -> str
yellow(text: str) -> str
orange(text: str) -> str
purple(text: str) -> str
pink(text: str) -> str
cyan(text: str) -> str
lime(text: str) -> str
gray(text: str) -> str
white(text: str) -> str
gold(text: str) -> str
Each color function takes a string and returns it wrapped in its ANSI
color code with RESET applied at the end. Raises TypeError for
non-string input and ValueError for empty/whitespace-only strings.
Markdown API
from mukimov.text import markdown
markdown.render(text: str) -> str # render Markdown to an ANSI string
markdown.print(text: str) -> None # render and print to the terminal
render() returns the styled string without printing anything;
print() writes the rendered result to the terminal.
Both raise TypeError for non-string input
(e.g. markdown.render() expected str, got int).
LaTeX math rendering is planned for a future release.
CLI / Updates 🔄
Available since
mukimov 0.1.7.
Show the installed version:
mukimov --version
mukimov 0.1.7
Check PyPI and upgrade to the latest release (no confirmation asked):
mukimov update
If a newer version exists, mukimov upgrades the current installation with
the same interpreter that runs it (python -m pip install --upgrade mukimov)
and prints the old and new versions:
Updated mukimov: 0.1.6 → 0.1.7
If the latest version is already installed:
Already up to date (обновление не требуется): mukimov 0.1.7
When a new release is known, other CLI invocations print a reminder to stderr (stdout stays script-friendly):
⚠ New mukimov version available: 0.1.7
Run: mukimov update
Notes:
- The PyPI check is cached on disk for 24 hours (
%LOCALAPPDATA%\mukimovon Windows,~/.cache/mukimovelsewhere), so repeated CLI calls do not hammer PyPI. - Plain
import mukimovnever touches the network. - The library is never upgraded automatically — only
mukimov updatedoes. - Network/PyPI/pip problems print a clear error and exit with code
1without tracebacks.
Project
- PyPI: https://pypi.org/project/mukimov/
- GitHub: https://github.com/mukimov/mukimov
- Author: mukimov
- Organization: Mukimov Studio
- Email: mukimov.shop@gmail.com
- License: MIT
Metadata
Release files for mukimov 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mukimov-0.1.8.tar.gz | 42.3 kB | Without provenance | Details for mukimov-0.1.8.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mukimov-0.1.8-py3-none-any.whl | Python 3 | none | any | Details for mukimov-0.1.8-py3-none-any.whl |
Total release size: 69.8 kB
Release files / mukimov-0.1.8.tar.gz
| Download URL | mukimov-0.1.8.tar.gz |
|---|---|
| Size | 42.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
182ab741242fd2e1d6f1eb880afcad913fa1c46f76d467950d39802449b3e53f
|
|
BLAKE2b-256 checksum How to use checksums |
983a579d66f39ad087c14852ed10feed7f0945a8f275a2305a586c53bbec9a0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / mukimov-0.1.8-py3-none-any.whl
| Download URL | mukimov-0.1.8-py3-none-any.whl |
|---|---|
| Size | 27.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c83472fa57e1bc2119ac4399ae2945f21e85e7789737c654484df0b4af466ae9
|
|
BLAKE2b-256 checksum How to use checksums |
1df97400141f953495d33bd7704bee4b6244abf146b267a3851b19f672aa0e93
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Security for mukimov 0.1.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.