# pydantic-type-chile-rut
[](https://github.com/flolas/pydantic-type-chile-rut/actions/workflows/ci.yml)
[](https://codecov.io/gh/flolas/pydantic-type-chile-rut)
[](https://badge.fury.io/py/pydantic-type-chile-rut)
[](https://pypi.org/project/pydantic-type-chile-rut/)
[](https://opensource.org/licenses/MIT)
A Pydantic custom type for Chilean RUT (Rol Γnico Tributario) validation and formatting.
## Features
- β
**Comprehensive validation**: Validates RUT format, length, and check digit
- π§ **Flexible input**: Accepts RUTs with or without dots and hyphens
- π **Multiple formats**: Provides both compact and formatted output
- π·οΈ **Type-safe**: Full Pydantic v2 integration with proper type hints
- π§ͺ **Well-tested**: Comprehensive test suite with 100% coverage
- π **High performance**: Efficient validation using Pydantic's core schema
## Installation
```bash
pip install pydantic-type-chile-rut
```
Or using uv:
```bash
uv add pydantic-type-chile-rut
```
## Quick Start
```python
from pydantic import BaseModel
from pydantic_type_chile_rut import RutNumber
class Person(BaseModel):
name: str
rut: RutNumber
# Create a person with a valid RUT
person = Person(name="Juan PΓ©rez", rut="12.345.678-5")
print(person.rut) # "12345678-5" (compact format)
print(person.rut.formatted) # "12.345.678-5" (with dots)
print(person.rut.number) # 12345678 (numeric part)
print(person.rut.dv) # "5" (check digit)
```
## RUT Format Support
The library accepts RUTs in various formats:
```python
from pydantic_type_chile_rut import RutNumber
# All these inputs are equivalent and valid:
valid_formats = [
"12.345.678-5", # Standard format with dots and hyphen
"12345678-5", # Without dots
"123456785", # Without dots or hyphen
"12.345.678-5", # With spaces (trimmed automatically)
]
# Case insensitive check digits:
rut_with_k = RutNumber.model_validate("15.345.678-k") # -> "15345678-K"
```
## RutNumber Properties
The `RutNumber` class provides several useful properties and methods:
```python
from pydantic_type_chile_rut import RutNumber
rut = RutNumber(12345678, "5")
# Properties
print(rut.number) # 12345678 (int)
print(rut.dv) # "5" (str)
print(str(rut)) # "12345678-5" (compact format)
# Formatting methods
print(rut.formatted) # "12.345.678-5" (property)
print(rut.with_dots()) # "12.345.678-5" (method)
# Representation
print(repr(rut)) # "RutNumber(number=12345678, dv='5')"
```
## Validation Examples
### Valid RUTs
```python
from pydantic import BaseModel
from pydantic_type_chile_rut import RutNumber
class TestModel(BaseModel):
rut: RutNumber
# These will all validate successfully:
valid_ruts = [
"12.345.678-5", # Standard format
"15.345.678-K", # With K check digit
"1-9", # Short RUT
"0-0", # Zero RUT (special case)
"123456785", # Without punctuation
"00001234-3", # With leading zeros (normalized)
]
for rut_str in valid_ruts:
model = TestModel(rut=rut_str)
print(f"{rut_str} -> {model.rut}")
```
### Invalid RUTs
```python
from pydantic import ValidationError
invalid_ruts = [
"12345678-4", # Wrong check digit
"ABC", # Not numeric
"12.345.678-", # Missing check digit
"", # Empty string
"123.456.789-0", # Too long (> 9 digits)
"12345678-X", # Invalid check digit character
]
for rut_str in invalid_ruts:
try:
TestModel(rut=rut_str)
except ValidationError as e:
print(f"{rut_str} -> {e.errors()[0]['msg']}")
```
## Integration with Pydantic Models
### Basic Usage
```python
from pydantic import BaseModel
from typing import Optional
from pydantic_type_chile_rut import RutNumber
class Employee(BaseModel):
id: int
name: str
rut: RutNumber
supervisor_rut: Optional[RutNumber] = None
employee = Employee(
id=1,
name="MarΓa GonzΓ‘lez",
rut="18.765.432-1",
supervisor_rut="12.345.678-5"
)
# Serialization
employee_dict = employee.model_dump()
print(employee_dict)
# {
# 'id': 1,
# 'name': 'MarΓa GonzΓ‘lez',
# 'rut': '18765432-1',
# 'supervisor_rut': '12345678-5'
# }
```
### JSON Schema Generation
```python
from pydantic import BaseModel
from pydantic_type_chile_rut import RutNumber
class Person(BaseModel):
rut: RutNumber
# Generate JSON schema
schema = Person.model_json_schema()
print(schema)
```
### Using with TypeAdapter
```python
from pydantic import TypeAdapter
from pydantic_type_chile_rut import RutNumber
adapter = TypeAdapter(RutNumber)
# Validate single RUT
rut = adapter.validate_python("12.345.678-5")
print(f"Valid RUT: {rut.formatted}")
# Validate list of RUTs
ruts_adapter = TypeAdapter(list[RutNumber])
ruts = ruts_adapter.validate_python([
"12.345.678-5",
"15.345.678-K",
"1-9"
])
```
## Advanced Usage
### Custom Validation
```python
from pydantic import BaseModel, field_validator
from pydantic_type_chile_rut import RutNumber
class BusinessEntity(BaseModel):
business_rut: RutNumber
legal_rep_rut: RutNumber
@field_validator('business_rut')
@classmethod
def validate_business_rut(cls, v):
# Business RUTs in Chile typically have 8-9 digits
if v.number < 50000000:
raise ValueError('Business RUT seems too low')
return v
entity = BusinessEntity(
business_rut="96.511.760-1",
legal_rep_rut="12.345.678-5"
)
```
### Working with Databases
```python
from pydantic import BaseModel
from sqlalchemy import Column, String, Integer
from pydantic_type_chile_rut import RutNumber
# SQLAlchemy model
class PersonDB:
__tablename__ = 'persons'
id = Column(Integer, primary_key=True)
rut = Column(String(12)) # Store as "12345678-5"
name = Column(String(100))
# Pydantic model for API
class PersonAPI(BaseModel):
id: int
rut: RutNumber
name: str
@classmethod
def from_db(cls, db_person):
return cls(
id=db_person.id,
rut=db_person.rut, # Automatically validates
name=db_person.name
)
```
## Check Digit Algorithm
The library implements the standard Chilean RUT check digit algorithm (modulo 11):
1. Multiply each digit by weights [2, 3, 4, 5, 6, 7] from right to left, cycling
2. Sum all products
3. Calculate `11 - (sum % 11)`
4. If result is 11, use "0"; if 10, use "K"; otherwise use the number
## Development
This project uses [uv](https://docs.astral.sh/uv/) for dependency management and packaging.
### Setup Development Environment
```bash
# Clone the repository
git clone https://github.com/flolas/pydantic-type-chile-rut.git
cd pydantic-type-chile-rut
# Install dependencies
uv sync --dev
# Install pre-commit hooks
uv run pre-commit install
# Run tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=src/pydantic_type_chile_rut --cov-report=html
# Run linting and formatting
uv run pre-commit run --all-files
```
### Project Structure
```
pydantic-type-chile-rut/
βββ src/
β βββ pydantic_type_chile_rut/
β βββ __init__.py
β βββ rut.py
βββ tests/
β βββ __init__.py
β βββ test_rut.py
βββ .github/
β βββ workflows/
β βββ ci.yml
β βββ release.yml
βββ pyproject.toml
βββ README.md
βββ LICENSE
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
### Guidelines
- Add tests for any new features
- Ensure all tests pass
- Follow the existing code style
- Update documentation as needed
## Testing
Run the full test suite:
```bash
uv run pytest tests/ -v
```
Run with coverage:
```bash
uv run pytest tests/ --cov=src/pydantic_type_chile_rut --cov-report=term-missing
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for a history of changes.
## Support
If you encounter any issues or have questions, please [open an issue](https://github.com/flolas/pydantic-type-chile-rut/issues) on GitHub.
## Related Projects
- [pydantic](https://github.com/pydantic/pydantic) - Data validation using Python type hints
- [python-rut](https://github.com/YerkoPalma/python-rut) - Another RUT validation library
- [django-rut](https://github.com/YerkoPalma/django-rut) - RUT field for Django
## Acknowledgments
- Thanks to the Pydantic team for creating an excellent validation library
- Inspired by various Chilean RUT validation implementations
Raw data
{
"_id": null,
"home_page": null,
"name": "pydantic-type-chile-rut",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "chile, pydantic, rut, type, validation",
"author": null,
"author_email": "Felipe Lolas <flolas@alumnos.uai.cl>",
"download_url": "https://files.pythonhosted.org/packages/7b/da/d1d0c0f709b0046f536115519d507d66334c1e07fa991c330e9dcf5bfdcd/pydantic_type_chile_rut-1.0.1.tar.gz",
"platform": null,
"description": "# pydantic-type-chile-rut\n\n[](https://github.com/flolas/pydantic-type-chile-rut/actions/workflows/ci.yml)\n[](https://codecov.io/gh/flolas/pydantic-type-chile-rut)\n[](https://badge.fury.io/py/pydantic-type-chile-rut)\n[](https://pypi.org/project/pydantic-type-chile-rut/)\n[](https://opensource.org/licenses/MIT)\n\nA Pydantic custom type for Chilean RUT (Rol \u00danico Tributario) validation and formatting.\n\n## Features\n\n- \u2705 **Comprehensive validation**: Validates RUT format, length, and check digit\n- \ud83d\udd27 **Flexible input**: Accepts RUTs with or without dots and hyphens\n- \ud83d\udcdd **Multiple formats**: Provides both compact and formatted output\n- \ud83c\udff7\ufe0f **Type-safe**: Full Pydantic v2 integration with proper type hints\n- \ud83e\uddea **Well-tested**: Comprehensive test suite with 100% coverage\n- \ud83d\ude80 **High performance**: Efficient validation using Pydantic's core schema\n\n## Installation\n\n```bash\npip install pydantic-type-chile-rut\n```\n\nOr using uv:\n\n```bash\nuv add pydantic-type-chile-rut\n```\n\n## Quick Start\n\n```python\nfrom pydantic import BaseModel\nfrom pydantic_type_chile_rut import RutNumber\n\nclass Person(BaseModel):\n name: str\n rut: RutNumber\n\n# Create a person with a valid RUT\nperson = Person(name=\"Juan P\u00e9rez\", rut=\"12.345.678-5\")\n\nprint(person.rut) # \"12345678-5\" (compact format)\nprint(person.rut.formatted) # \"12.345.678-5\" (with dots)\nprint(person.rut.number) # 12345678 (numeric part)\nprint(person.rut.dv) # \"5\" (check digit)\n```\n\n## RUT Format Support\n\nThe library accepts RUTs in various formats:\n\n```python\nfrom pydantic_type_chile_rut import RutNumber\n\n# All these inputs are equivalent and valid:\nvalid_formats = [\n \"12.345.678-5\", # Standard format with dots and hyphen\n \"12345678-5\", # Without dots\n \"123456785\", # Without dots or hyphen\n \"12.345.678-5\", # With spaces (trimmed automatically)\n]\n\n# Case insensitive check digits:\nrut_with_k = RutNumber.model_validate(\"15.345.678-k\") # -> \"15345678-K\"\n```\n\n## RutNumber Properties\n\nThe `RutNumber` class provides several useful properties and methods:\n\n```python\nfrom pydantic_type_chile_rut import RutNumber\n\nrut = RutNumber(12345678, \"5\")\n\n# Properties\nprint(rut.number) # 12345678 (int)\nprint(rut.dv) # \"5\" (str)\nprint(str(rut)) # \"12345678-5\" (compact format)\n\n# Formatting methods\nprint(rut.formatted) # \"12.345.678-5\" (property)\nprint(rut.with_dots()) # \"12.345.678-5\" (method)\n\n# Representation\nprint(repr(rut)) # \"RutNumber(number=12345678, dv='5')\"\n```\n\n## Validation Examples\n\n### Valid RUTs\n\n```python\nfrom pydantic import BaseModel\nfrom pydantic_type_chile_rut import RutNumber\n\nclass TestModel(BaseModel):\n rut: RutNumber\n\n# These will all validate successfully:\nvalid_ruts = [\n \"12.345.678-5\", # Standard format\n \"15.345.678-K\", # With K check digit\n \"1-9\", # Short RUT\n \"0-0\", # Zero RUT (special case)\n \"123456785\", # Without punctuation\n \"00001234-3\", # With leading zeros (normalized)\n]\n\nfor rut_str in valid_ruts:\n model = TestModel(rut=rut_str)\n print(f\"{rut_str} -> {model.rut}\")\n```\n\n### Invalid RUTs\n\n```python\nfrom pydantic import ValidationError\n\ninvalid_ruts = [\n \"12345678-4\", # Wrong check digit\n \"ABC\", # Not numeric\n \"12.345.678-\", # Missing check digit\n \"\", # Empty string\n \"123.456.789-0\", # Too long (> 9 digits)\n \"12345678-X\", # Invalid check digit character\n]\n\nfor rut_str in invalid_ruts:\n try:\n TestModel(rut=rut_str)\n except ValidationError as e:\n print(f\"{rut_str} -> {e.errors()[0]['msg']}\")\n```\n\n## Integration with Pydantic Models\n\n### Basic Usage\n\n```python\nfrom pydantic import BaseModel\nfrom typing import Optional\nfrom pydantic_type_chile_rut import RutNumber\n\nclass Employee(BaseModel):\n id: int\n name: str\n rut: RutNumber\n supervisor_rut: Optional[RutNumber] = None\n\nemployee = Employee(\n id=1,\n name=\"Mar\u00eda Gonz\u00e1lez\",\n rut=\"18.765.432-1\",\n supervisor_rut=\"12.345.678-5\"\n)\n\n# Serialization\nemployee_dict = employee.model_dump()\nprint(employee_dict)\n# {\n# 'id': 1,\n# 'name': 'Mar\u00eda Gonz\u00e1lez',\n# 'rut': '18765432-1',\n# 'supervisor_rut': '12345678-5'\n# }\n```\n\n### JSON Schema Generation\n\n```python\nfrom pydantic import BaseModel\nfrom pydantic_type_chile_rut import RutNumber\n\nclass Person(BaseModel):\n rut: RutNumber\n\n# Generate JSON schema\nschema = Person.model_json_schema()\nprint(schema)\n```\n\n### Using with TypeAdapter\n\n```python\nfrom pydantic import TypeAdapter\nfrom pydantic_type_chile_rut import RutNumber\n\nadapter = TypeAdapter(RutNumber)\n\n# Validate single RUT\nrut = adapter.validate_python(\"12.345.678-5\")\nprint(f\"Valid RUT: {rut.formatted}\")\n\n# Validate list of RUTs\nruts_adapter = TypeAdapter(list[RutNumber])\nruts = ruts_adapter.validate_python([\n \"12.345.678-5\",\n \"15.345.678-K\",\n \"1-9\"\n])\n```\n\n## Advanced Usage\n\n### Custom Validation\n\n```python\nfrom pydantic import BaseModel, field_validator\nfrom pydantic_type_chile_rut import RutNumber\n\nclass BusinessEntity(BaseModel):\n business_rut: RutNumber\n legal_rep_rut: RutNumber\n\n @field_validator('business_rut')\n @classmethod\n def validate_business_rut(cls, v):\n # Business RUTs in Chile typically have 8-9 digits\n if v.number < 50000000:\n raise ValueError('Business RUT seems too low')\n return v\n\nentity = BusinessEntity(\n business_rut=\"96.511.760-1\",\n legal_rep_rut=\"12.345.678-5\"\n)\n```\n\n### Working with Databases\n\n```python\nfrom pydantic import BaseModel\nfrom sqlalchemy import Column, String, Integer\nfrom pydantic_type_chile_rut import RutNumber\n\n# SQLAlchemy model\nclass PersonDB:\n __tablename__ = 'persons'\n\n id = Column(Integer, primary_key=True)\n rut = Column(String(12)) # Store as \"12345678-5\"\n name = Column(String(100))\n\n# Pydantic model for API\nclass PersonAPI(BaseModel):\n id: int\n rut: RutNumber\n name: str\n\n @classmethod\n def from_db(cls, db_person):\n return cls(\n id=db_person.id,\n rut=db_person.rut, # Automatically validates\n name=db_person.name\n )\n```\n\n## Check Digit Algorithm\n\nThe library implements the standard Chilean RUT check digit algorithm (modulo 11):\n\n1. Multiply each digit by weights [2, 3, 4, 5, 6, 7] from right to left, cycling\n2. Sum all products\n3. Calculate `11 - (sum % 11)`\n4. If result is 11, use \"0\"; if 10, use \"K\"; otherwise use the number\n\n## Development\n\nThis project uses [uv](https://docs.astral.sh/uv/) for dependency management and packaging.\n\n### Setup Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/flolas/pydantic-type-chile-rut.git\ncd pydantic-type-chile-rut\n\n# Install dependencies\nuv sync --dev\n\n# Install pre-commit hooks\nuv run pre-commit install\n\n# Run tests\nuv run pytest\n\n# Run tests with coverage\nuv run pytest --cov=src/pydantic_type_chile_rut --cov-report=html\n\n# Run linting and formatting\nuv run pre-commit run --all-files\n```\n\n### Project Structure\n\n```\npydantic-type-chile-rut/\n\u251c\u2500\u2500 src/\n\u2502 \u2514\u2500\u2500 pydantic_type_chile_rut/\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u2514\u2500\u2500 rut.py\n\u251c\u2500\u2500 tests/\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u2514\u2500\u2500 test_rut.py\n\u251c\u2500\u2500 .github/\n\u2502 \u2514\u2500\u2500 workflows/\n\u2502 \u251c\u2500\u2500 ci.yml\n\u2502 \u2514\u2500\u2500 release.yml\n\u251c\u2500\u2500 pyproject.toml\n\u251c\u2500\u2500 README.md\n\u2514\u2500\u2500 LICENSE\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n### Guidelines\n\n- Add tests for any new features\n- Ensure all tests pass\n- Follow the existing code style\n- Update documentation as needed\n\n## Testing\n\nRun the full test suite:\n\n```bash\nuv run pytest tests/ -v\n```\n\nRun with coverage:\n\n```bash\nuv run pytest tests/ --cov=src/pydantic_type_chile_rut --cov-report=term-missing\n```\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for a history of changes.\n\n## Support\n\nIf you encounter any issues or have questions, please [open an issue](https://github.com/flolas/pydantic-type-chile-rut/issues) on GitHub.\n\n## Related Projects\n\n- [pydantic](https://github.com/pydantic/pydantic) - Data validation using Python type hints\n- [python-rut](https://github.com/YerkoPalma/python-rut) - Another RUT validation library\n- [django-rut](https://github.com/YerkoPalma/django-rut) - RUT field for Django\n\n## Acknowledgments\n\n- Thanks to the Pydantic team for creating an excellent validation library\n- Inspired by various Chilean RUT validation implementations\n",
"bugtrack_url": null,
"license": null,
"summary": "Pydantic custom type for Chilean RUT validation and formatting",
"version": "1.0.1",
"project_urls": {
"Homepage": "https://github.com/yourusername/pydantic-type-chile-rut",
"Issues": "https://github.com/yourusername/pydantic-type-chile-rut/issues",
"Repository": "https://github.com/yourusername/pydantic-type-chile-rut"
},
"split_keywords": [
"chile",
" pydantic",
" rut",
" type",
" validation"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9595d4b9d9983854611c7548dca466affe0faa5cfb4c737ec71df99ac86e2868",
"md5": "c344a46a2a0e81a9604d5c1dee68ed35",
"sha256": "79a3a78449fd338515c9837551c4a59aa5e934b7083d62f6db54dd082d5dd92c"
},
"downloads": -1,
"filename": "pydantic_type_chile_rut-1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c344a46a2a0e81a9604d5c1dee68ed35",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 7173,
"upload_time": "2025-08-09T17:20:20",
"upload_time_iso_8601": "2025-08-09T17:20:20.654445Z",
"url": "https://files.pythonhosted.org/packages/95/95/d4b9d9983854611c7548dca466affe0faa5cfb4c737ec71df99ac86e2868/pydantic_type_chile_rut-1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "7bdad1d0c0f709b0046f536115519d507d66334c1e07fa991c330e9dcf5bfdcd",
"md5": "0437aeec5e7835cf2064d91686c81489",
"sha256": "2b8f2b102a53787cf7386ad86198d9b4efbb79f722c56430c326e4c509dec3e5"
},
"downloads": -1,
"filename": "pydantic_type_chile_rut-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "0437aeec5e7835cf2064d91686c81489",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 11614,
"upload_time": "2025-08-09T17:20:22",
"upload_time_iso_8601": "2025-08-09T17:20:22.006036Z",
"url": "https://files.pythonhosted.org/packages/7b/da/d1d0c0f709b0046f536115519d507d66334c1e07fa991c330e9dcf5bfdcd/pydantic_type_chile_rut-1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-09 17:20:22",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "pydantic-type-chile-rut",
"github_not_found": true,
"lcname": "pydantic-type-chile-rut"
}