Metadata-Version: 2.4
Name: mukimov
Version: 0.1.2
Summary: Tiny cross-platform password prompt with customizable masking
Author-email: mukimov <mukimov.shop@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/mukimov/mukimov
Keywords: password,getpass,stars,prompt,cli
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# mukimov

Tiny cross-platform Python library: password prompt that shows `*` for each typed character — like `getpass()`, but with visual feedback.

```python
from mukimov import stars

password = stars("Password: ")
print(password)
```

Terminal:

```text
Password: ********
```

`password` contains the real text (`"12345678"`), only `*` are shown on screen.

## Features

- Only standard library, zero dependencies
- Windows (`msvcrt`) + Linux/macOS (`termios`/`tty`)
- Each character is immediately replaced with `*`
- Backspace correctly deletes the last `*`
- Enter finishes input
- Real password is never printed
- Ctrl+C → `KeyboardInterrupt`, Ctrl+D on empty input → `EOFError`
- Falls back to `getpass` (no echo) when stdin is not a TTY (pipes, IDE, CI)

## Install

```bash
pip install .
```

For development:

```bash
pip install -e .[test]  # or: pip install -e . && pip install pytest
pytest -q
```

## Usage

```python
from mukimov import stars

username = input("Username: ")
password = stars("Password: ")

print(username)
```

```text
Username: mukimov
Password: ********
```

Custom mask character:

```python
password = stars("Password: ", mask="#")
```

More examples — each typed character is echoed with your symbol,
but the returned value is always the real password:

```python
from mukimov import stars

password = stars("Password: ")       # input 12345 -> shows: Password: *****
password = stars("Password: ", "/")  # input 12345 -> shows: Password: /////
password = stars("Secret: ", "#")    # input hello -> shows: Secret: #####
password = stars("Password: ", "•")  # unicode masks work too
```

`mask` must be exactly one character, otherwise `ValueError` is raised:

```python
stars("Password: ", "")    # ValueError: Параметр mask='' пустой...
stars("Password: ", "/*")  # ValueError: Параметр mask='/*' содержит 2 символа...
```

## Ошибки

Сообщения об ошибках — на русском. В них указано: какой параметр неверный,
что передано (через `repr()`), почему это неправильно, что ожидалось и пример
правильного вызова. Введённый пароль никогда не попадает в сообщения об ошибках.

Неправильно → ошибка → правильно:

```python
stars("Password: ", "")
# ValueError: Параметр mask='' пустой. Укажите ровно 1 символ для маскировки.
# Пример: stars("Password: ", "*")
stars("Password: ", "*")  # правильно
```

```python
stars("Password: ", "//")
# ValueError: Параметр mask='//' содержит 2 символа. Допускается только 1 символ.
# Пример: stars("Password: ", "*")
stars("Password: ", "/")  # правильно
```

```python
stars("Password: ", "hello")
# ValueError: Параметр mask='hello' содержит 5 символов. Допускается только 1 символ.
# Пример: stars("Password: ", "*")
stars("Password: ", "*")  # правильно
```

```python
stars("Password: ", 123)
# TypeError: Параметр mask должен быть строкой (str), но получен int: 123.
# Пример: stars("Password: ", "*")
stars("Password: ", "#")  # правильно
```

```python
stars(123)
# TypeError: Параметр prompt должен быть строкой (str), но получен int: 123.
# Пример: stars("Password: ")
stars("Password: ")  # правильно
```

## Build & publish to PyPI

```bash
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
python -m twine upload dist/*
```

Test PyPI first:

```bash
python -m twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ mukimov
```

## License

MIT

---

Developed by [Mukimov Studio](https://github.com/mukimov/mukimov).
