Metadata-Version: 2.4
Name: vcoder
Version: 0.2.0
Summary: Make safe input handling effortless: validated prompts, composable validators, and honest security helpers.
Project-URL: Homepage, https://github.com/bitilia/vcoder
Project-URL: Repository, https://github.com/bitilia/vcoder
Project-URL: Documentation, https://github.com/bitilia/vcoder/tree/main/docs
Project-URL: Changelog, https://github.com/bitilia/vcoder/blob/main/CHANGELOG.md
Project-URL: Bug Tracker, https://github.com/bitilia/vcoder/issues
Author: VCoder contributors
License: MIT
License-File: LICENSE
Keywords: cli,input,password,prompt,sanitization,security,validation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: black>=24.1; extra == 'dev'
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: hypothesis>=6.90; extra == 'dev'
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# VCoder

**Make safe input handling effortless.**

VCoder is a zero-dependency Python library for validated input prompts,
composable validators, and honest security helpers. It does **not** claim to
magically sanitize all input or to "prevent injection". Instead, it makes the
*safe* path the *easy* path.

```python
from vcoder import vc

name = vc.text("Name: ")
age = vc.int("Age: ", min=0, max=120)
email = vc.email("Email: ")
password = vc.password("Password: ", min_length=12)
choice = vc.choice("Language: ", ["Python", "Rust", "Go"])
numbers = vc.list("Numbers: ", parser=int)
```

Every prompt validates, reprompts on failure, supports defaults and optional
input, accepts custom validators and custom error messages — so you never write
a validation loop by hand.

## Why VCoder?

- **Pythonic & discoverable.** One import (`vc`) surfaces everything.
- **Strongly typed.** Fully annotated; passes `mypy --strict` and `pyright`.
- **Zero dependencies.** Standard library only.
- **Composable validators.** `Validator(MinLength(8), Regex(...), NoControlCharacters())`.
- **Honest security helpers.** For paths, filenames, shell, SQL, HTML and passwords —
  with documented limitations, never misleading guarantees.

## Installation

```bash
pip install vcoder
```

From source (development):

```bash
git clone https://github.com/bitilia/vcoder
cd vcoder
pip install -e ".[dev]"
```

Requires Python 3.9+.

## Quick tour

### Input functions

```python
from vcoder import vc

vc.text("Name: ", min_length=1)
vc.int("Age: ", min=0, max=120)
vc.float("Ratio: ", min=0.0, max=1.0)
vc.decimal("Price: ")                    # exact, for money
vc.bool("Continue? ")                    # yes/no
vc.choice("Pick: ", ["a", "b", "c"])
vc.list("CSV: ", parser=int)
vc.json("Payload: ")
vc.date("When: ")                        # ISO 8601 by default
vc.uuid("Id: ")
vc.email("Email: ")
vc.url("Site: ")                         # http/https only by default
vc.ip("Addr: ")
vc.port("Port: ")
vc.password("Password: ", min_length=12) # never echoed, never logged
vc.filename("File: ")                    # rejects reserved/illegal names
vc.path("Path: ", within="/srv/uploads") # blocks traversal
```

All 26 input types accept the same keyword contract:
`default`, `optional`, `retries`, `error_message`, `validators`, `reader`.

> The `reader=` keyword lets you inject input (used throughout the tests and in
> the doctests). In real use you omit it and VCoder reads from the terminal.

### Composable validators

```python
from vcoder import Validator, MinLength, Regex, NoControlCharacters, ValidationError

username = Validator(
    MinLength(3),
    Regex(r"[a-z0-9_]+"),
    NoControlCharacters(),
)
username.validate("ada_lovelace")   # ok
username.is_valid("x")              # False

# Extending is just subclassing:
class EvenNumber(Validator):
    def validate(self, value):
        if value % 2:
            raise ValidationError("must be even", value=value)
```

Use any validator with any prompt via `validators=[...]`.

### Security helpers

```python
from vcoder import vc

# Paths — anchored to a root, traversal-aware (raw, %2e-encoded, unicode).
vc.safe_join("/srv/uploads", user_supplied)      # -> Path or UnsafePathError
vc.contains_traversal("../../etc/passwd")        # True

# Subprocess — argument lists only, never a shell.
vc.run(["git", "status"])
vc.run_capture(["echo", user_supplied])          # metacharacters are inert

# SQL — parameterized by construction.
query, params = vc.sql.build_select("users", where={"id": 1})
vc.sql.execute(cursor, query, params)

# HTML — context-aware escaping.
vc.html.escape(user_supplied)                    # for text nodes
vc.html.escape_attribute(user_supplied)          # for quoted attributes

# Passwords — configurable strength, optional HIBP check.
vc.validate_password(pw)                          # PasswordTooWeak on failure
```

### Global configuration

```python
from vcoder import vc

vc.configure(retries=5, strip=True, lowercase=False, logging=True)
```

## What VCoder protects against (and what it does not)

See [`SECURITY.md`](SECURITY.md) for the full, honest breakdown. In short:

- It **reduces** the risk of path traversal, shell injection, accidental SQL
  string-building, XSS from untrusted text, and weak passwords.
- It **cannot** guarantee the absence of any of these. Validation is
  context-dependent, symlinks and TOCTOU races exist, and the program you invoke
  may still mishandle its arguments. Use least privilege and defense in depth.

## Documentation

- [Getting started](docs/getting_started.md)
- [Validators guide](docs/validators.md)
- [Security guide](docs/security.md)
- [API reference](docs/api_reference.md)
- [Examples](examples/)

## Development

```bash
pip install -e ".[dev]"
pytest                 # tests + doctests, 95%+ coverage
mypy                   # strict type checking
ruff check .           # linting
black --check .        # formatting
```

## License

[MIT](LICENSE) © 2026 VCoder contributors.
