Bidirectional Patterns
BidirectionalPattern enables round-trip parsing: parse a string, modify the extracted values, and format them back while maintaining the original format constraints.
Basic Usage
Create a BidirectionalPattern and parse a string:
>>> from formatparse import BidirectionalPattern
>>> formatter = BidirectionalPattern("{name:>10}: {value:05d}")
>>> result = formatter.parse(" John: 00042")
>>> result.named['name']
'John'
>>> result.named['value']
42
Formatting Back
The BidirectionalResult object can format itself back using the original pattern:
>>> result.format()
' John: 00042'
Modifying Values
You can modify the extracted values and format them back:
>>> result.named['value'] = 100
>>> result.format()
' John: 00100'
>>> result.named['name'] = "Alice"
>>> result.format()
' Alice: 00100'
Validation
Validate values against the pattern’s constraints:
>>> result.named['value'] = 42
>>> is_valid, errors = result.validate()
>>> is_valid
True
>>> errors
[]
>>> result.named['value'] = "not a number"
>>> is_valid, errors = result.validate()
>>> is_valid
False
>>> len(errors) > 0
True
Using format() Method Directly
You can also use the pattern’s format() method directly:
>>> formatted = formatter.format({"name": "Alice", "value": 42})
>>> formatted.startswith(" Alice")
True
>>> "00042" in formatted
True
Real-World Use Cases
Configuration File Updates
Parse configuration files, modify values, and write them back:
formatter = BidirectionalPattern("PORT={port:05d}")
result = formatter.parse("PORT=00080")
result.named['port'] = 8080
new_config = result.format()
print(new_config)
PORT=08080
Data Transformation Pipelines
Transform data while maintaining format constraints:
>>> formatter = BidirectionalPattern("ID:{id:05d} Name:{name:>10}")
>>> result = formatter.parse("ID:00042 Name: John")
>>> result.named['id']
42
>>> result.named['id'] = 100
>>> result.named['name'] = "Alice"
>>> formatted = result.format()
>>> formatted.startswith("ID:00100 Name:")
True
>>> formatted.endswith("Alice")
True
Form Validation
Validate user input against expected formats:
formatter = BidirectionalPattern("{username:>10}: {score:05d}")
user_input = " alice: 00100"
result = formatter.parse(user_input)
if result:
is_valid, errors = result.validate()
if is_valid:
print(f"Valid input: {result.format()}")
else:
print(f"Validation errors: {errors}")
else:
print("Input does not match pattern")
Valid input: alice: 00100