Skip to content

python-and-ladder/human-errors-tutorial

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

human errors

humans do make some errors, so we should show it to them, so that it can be fixed

usage:

json/orjson

from human_errors import json_dump
import orjson

try:
  with open("config.json", "r") as file:
    config = orjson.loads(file.read())
except orjson.JSONDecodeError as exc:
  json_dump(exc, "config.json")

Output (error):

    --> C:\Users\<user>\absolute\path\to\config.json:19:5
  17 │       "path": "$DESKTOP"
  18 │     }
╭╴19 │     {
│    │     ↑
│ 20 │       "name": "Pictures",
│ 21 │       "path": "$PICTURES"
╰────❯ unexpected character

tomllib (>=3.14) or toml

if you want to use tomllib, python >= 3.14 must be used so that the message and line + column numbers can be extracted.

from human_errors import toml_dump
import toml
try:
  with open("pyproject.toml", "r") as file:
    config = toml.loads(file.read())
except toml.TomlDecodeError as exc:
  toml_dump(exc, "pyproject.toml")

Output (error):

    --> C:\Users\<user>\path\to\pyproject.toml:9:26
   7 │     { name = "<name>", email = "<email>" }
   8 │ ]
╭╴ 9 │ requires-python = ">=3.12
│    │                          ↑
│ 10 │ dependencies = [
│ 11 │     "rich>=14.2.0",
╰────❯ Unbalanced quotes

pyyaml

from human_errors import yaml_dump
import yaml

try:
  with open("config.yaml", "r") as file:
    config = yaml.safe_load(file.read())
except yaml.YAMLError as exc:
  yaml_dump(exc, "config.yaml")

Output (error):

    --> C:\Users\<user>\absolute\path\to\config.yaml:5:3
  3 │   name: "John"
  4 │   age: 30
╭╴5 │   email: john@example.com
│   │          ↑
│ 6 │     - item1
│ 7 │     - item2
╰────❯ mapping values are not allowed here

Base Renderer (Custom Errors)

For custom error handling or any file-based errors not covered by the built-in renderers:

from human_errors.base_renderer import dump

def validate_config(file_path: str):
    with open(file_path, "r") as f:
        for line_num, line in enumerate(f, start=1):
            if "TODO" in line:
                col = line.index("TODO") + 1
                dump(
                    doc_path=file_path,
                    cause="TODO found in production config",
                    line_number=line_num,
                    column_number=col,
                    context=3,
                    extra=[
                        "Production configs should not contain TODO items",
                        "Please replace with actual values or remove this entry"
                    ]
                )
                exit(1)

Output (error):

     --> C:\Users\<user>\absolute\path\to\config.py:15:9
  12 │ DATABASE_HOST = "localhost"
  13 │ DATABASE_PORT = 5432
  14 │
╭╴15 │ API_KEY = "TODO: add production key"
│    │            ↑
│ 16 │
│ 17 │ CACHE_ENABLED = True
│ 18 │ CACHE_TTL = 3600
╰─────❯ TODO found in production config
    ╭───────────────────────────────────────────────────────────╮
    │ Production configs should not contain TODO items          │
    ├───────────────────────────────────────────────────────────┤
    │ Please replace with actual values or remove this entry    │
    ╰───────────────────────────────────────────────────────────╯

alternate styling

if you dont like human-error's default styling, a miette like version is also available

   ╭─[/path/to/file.json:2:19]
 1 │ {
 2 │   "name": "Alice",,
   ·                   ┬
   ·                   ╰─❯ Expecting property name enclosed in double quotes
 3 │   "age": 30
   ╰────

CLI Tool

A command-line interface is provided to parse files and render errors:

uvx human-errors path/to/file.[json|toml|yaml|yml] [--renderer default|miette]
  • Automatically detects format from file extension
  • On parse errors, uses human_errors' renderer for neater output
  • Optional --renderer selects the output style

Example:

uvx human-errors examples/bad.json

contributing

any extra data format must be in an extra, and also available in the all group

any contributions must pre-lint with ruff and ty

uv run ruff check --unsafe-fixes --fix
uv run ty check

adding support for pytest is also fine

( ̄︶ ̄)↗ give a star

About

Description: everyone makes mistakes, show the errors to them; Project: Test and Documentation

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%