Skip to main content

Parse strings into Pydantic models using pattern matching

Project description

stringent

CI Python Version License: MIT Code style: ruff

stringent is a powerful Python library that seamlessly parses strings into Pydantic models using flexible pattern matching. Whether you're working with pipe-separated values, space-separated data, JSON strings, or custom formats, stringent makes it easy to convert unstructured strings into validated, type-safe Python objects.

Features

Flexible Pattern Matching - Parse strings using format-like patterns (e.g., {name} | {age} | {city})

🔗 Pattern Chaining - Chain multiple patterns using the | operator to try patterns in order until one matches

🔄 Automatic Input Handling - Seamlessly handles both dictionary and string inputs without code changes

🎯 Pydantic Integration - Built on Pydantic 2.0+ for robust validation and type safety

📦 JSON Support - Built-in JSON parsing with automatic fallback to pattern matching

🚀 JsonParsableModel - Automatic JSON string parsing for API integrations and message queues

🔀 Union Types - Organize parsing strategies using union types for maximum flexibility

🧬 Inheritance Support - Parse patterns are inherited and can be overridden in subclasses

Installation

pip install stringent

Quick Start

from pydantic import BaseModel, EmailStr
from typing import Literal
from stringent import parse, parse_json, ParsableModel

class Info(BaseModel):
    name: str
    age: int
    city: str

class Record(ParsableModel):
    id: int
    info: Info = parse_json() | parse('{name} | {age} | {city}') | parse('{name} {age} {city}')
    email: EmailStr
    status: Literal['Active', 'Inactive']

# Parse the data - handles dicts, strings, and JSON automatically
data = [
    {'id': 1, 'info': {'name': 'Alice', 'age': 30, 'city': 'New York'}, 'email': 'alice@example.com', 'status': 'Active'},
    {'id': 3, 'info': 'Charlie | 27 | Chicago', 'email': 'charlie@example.com', 'status': 'Active'},
    {'id': 5, 'info': 'Eve 35 Dallas', 'email': 'eve@example.com', 'status': 'Inactive'},
    {'id': 8, 'info': '{"name": "Joe", "age": 55, "city": "Tampa"}', 'email': 'joe@example.com', 'status': 'Active'},
]

for item in data:
    record = Record(**item)
    print(record)

Output:

id=1 info=Info(name='Alice', age=30, city='New York') email='alice@example.com' status='Active'
id=3 info=Info(name='Charlie', age=27, city='Chicago') email='charlie@example.com' status='Active'
id=5 info=Info(name='Eve', age=35, city='Dallas') email='eve@example.com' status='Inactive'
id=8 info=Info(name='Joe', age=55, city='Tampa') email='joe@example.com' status='Active'

Why stringent?

Working with mixed data formats is a common challenge in data processing. You might receive:

  • Dictionary objects from APIs
  • Pipe-separated strings from legacy systems
  • Space-separated values from log files
  • JSON strings from message queues

stringent eliminates the need for manual parsing logic by automatically handling all these formats with a single, declarative definition.

Key Use Cases

  • API Integration - Handle inconsistent data formats from different endpoints
  • Data Migration - Parse legacy data formats while maintaining type safety
  • Log Processing - Parse structured log entries into validated models
  • ETL Pipelines - Transform unstructured strings into typed data structures
  • Configuration Parsing - Support multiple configuration formats with fallback patterns

Documentation

Comprehensive documentation is available in the docs directory:

Requirements

  • Python 3.10 or higher
  • Pydantic 2.0 or higher
  • parse 1.20 or higher

Dependencies

  • pydantic>=2.0.0 - For Pydantic model integration and validation
  • parse>=1.20.0 - For string parsing functionality

Examples

Pattern Chaining

Try multiple patterns in order until one matches:

from stringent import parse, ParsableModel
from pydantic import BaseModel

class Info(BaseModel):
    name: str
    age: int
    city: str

class Record(ParsableModel):
    info: Info = parse('{name} | {age} | {city}') | parse('{name} {age} {city}')

# Both formats work automatically
record1 = Record(info="Alice | 30 | NYC")
record2 = Record(info="Bob 25 Chicago")

JSON Parsing

Automatically parse JSON strings with fallback to pattern matching:

from stringent import parse_json, parse, ParsableModel
from pydantic import BaseModel

class Info(BaseModel):
    name: str
    age: int

class Record(ParsableModel):
    info: Info = parse_json() | parse('{name} | {age}')

# JSON string
record1 = Record(info='{"name": "Alice", "age": 30}')

# Pattern string (fallback)
record2 = Record(info="Bob | 25")

Union Types

Use union types to organize parsing strategies:

from typing import Union
from stringent import ParsableModel
from pydantic import BaseModel

class Info(ParsableModel):
    name: str
    age: int

class PipeInfo(Info):
    _model_parse_pattern = '{name} | {age}'

class SpaceInfo(Info):
    _model_parse_pattern = '{name} {age}'

class Record(ParsableModel):
    info: Union[PipeInfo, SpaceInfo]

# Automatically selects the correct type
record1 = Record(info="Alice | 30")  # Uses PipeInfo
record2 = Record(info="Bob 25")      # Uses SpaceInfo

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.

Getting Started

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Open Issues

Looking for something to work on? Check out our open issues! We have many enhancement ideas organized by priority:

Issues labeled with good first issue are great for newcomers. See the full list of enhancement issues for more ideas.

Development

To set up a development environment:

# Clone the repository
git clone https://github.com/eddiethedean/stringent.git
cd stringent

# Create a virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
ruff check .
ruff format .

# Run type checking
mypy stringent/

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Odos Matthews

Acknowledgments

  • Built on Pydantic for robust data validation
  • Uses parse for flexible string parsing

Made with ❤️ for the Python community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stringent-0.3.1.tar.gz (30.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stringent-0.3.1-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file stringent-0.3.1.tar.gz.

File metadata

  • Download URL: stringent-0.3.1.tar.gz
  • Upload date:
  • Size: 30.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for stringent-0.3.1.tar.gz
Algorithm Hash digest
SHA256 fe4dc6d7ec8a3ed5c456aae0deb8688ef4b38c390bb3941621b00ecafe71e453
MD5 1673f6fb63a987d1902043fe2ce13c0e
BLAKE2b-256 6303a05fb643887d1429f76fe315a0237ad0c62be28ee6c9ade3970b96763ffd

See more details on using hashes here.

File details

Details for the file stringent-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: stringent-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for stringent-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b5167825321a5df584e62809d0fd7f5c081440ee97c29299141356cde74a82fb
MD5 7ac588cfd111ddb04e6b08a4aff3be5e
BLAKE2b-256 ec3d5b75bdb11fe7128392ce2f0f8a9d7a761f678e40d48c099825a5fdb1d821

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page