Bash-style brace expansion for Python
npx @tessl/cli install tessl/pypi-braceexpand@0.1.0Bash-style brace expansion for Python, implementing the same brace expansion logic found in bash(1) with some limitations. This package enables pattern expansion with braces into multiple strings, supporting integer ranges, character ranges, sequences, nested patterns, and various formatting options.
pip install braceexpandfrom braceexpand import braceexpandImport the exception class for error handling:
from braceexpand import UnbalancedBracesErrorImport the alphabet constant:
from braceexpand import alphabetImport all public components:
from braceexpand import braceexpand, UnbalancedBracesError, alphabetfrom braceexpand import braceexpand
# Integer range expansion
result = list(braceexpand('item{1..3}'))
# ['item1', 'item2', 'item3']
# Character range expansion
result = list(braceexpand('{a..c}'))
# ['a', 'b', 'c']
# Sequence expansion
result = list(braceexpand('index.html{,.backup}'))
# ['index.html', 'index.html.backup']
# Nested patterns
result = list(braceexpand('python{2.{5..7},3.{2,3}}'))
# ['python2.5', 'python2.6', 'python2.7', 'python3.2', 'python3.3']Performs bash-style brace expansion on pattern strings, returning an iterator over all expanded strings.
def braceexpand(pattern, escape=True):
"""
Expand braces in a pattern string according to bash(1) rules.
Parameters:
- pattern (str): Pattern string containing braces to expand
- escape (bool): Whether to interpret backslash as escape character (default: True)
Returns:
Iterator over strings resulting from brace expansion
Raises:
UnbalancedBracesError: When pattern contains unbalanced braces
"""Supported Pattern Types:
{1..3} expands to ['1', '2', '3']{a..c} expands to ['a', 'b', 'c']{x,y,z} expands to ['x', 'y', 'z']{a,{b,c}} expands to ['a', 'b', 'c']{07..10} expands to ['07', '08', '09', '10']{1..7..2} expands to ['1', '3', '5', '7']{4..1} expands to ['4', '3', '2', '1']{2..-1} expands to ['2', '1', '0', '-1']Escape Character Handling:
When escape=True (default), backslashes can be used to escape special characters:
# Escape braces to include them literally
result = list(braceexpand(r'{1\{2,3}'))
# ['1{2', '3']
# Double backslash for literal backslash
result = list(braceexpand(r'\\{1,2}'))
# ['\\1', '\\2']When escape=False, backslashes have no special meaning:
result = list(braceexpand(r'\{1,2}', escape=False))
# ['\\1', '\\2']Exception class for unbalanced brace patterns.
class UnbalancedBracesError(ValueError):
"""
Raised when a pattern contains unbalanced braces.
This exception is raised by braceexpand() when the pattern
string contains opening braces without matching closing braces,
or vice versa.
"""Usage example:
from braceexpand import braceexpand, UnbalancedBracesError
try:
result = list(braceexpand('{1{2,3}')) # Missing closing brace
except UnbalancedBracesError as e:
print(f"Error: {e}")
# Error: Unbalanced braces: '{1{2,3}'Constant containing the alphabet string used for character range expansion.
alphabet: strThe alphabet constant contains all uppercase and lowercase ASCII letters ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), used internally for character range operations like {a..c} or {A..Z}.
from typing import Iterator
# Type definitions for the public API
UnbalancedBracesError = ValueError
# Exception raised for unbalanced brace patterns
alphabet: str
# String constant containing A-Z and a-z characters
def braceexpand(pattern: str, escape: bool = True) -> Iterator[str]:
# Returns iterator over expanded stringsThis implementation has some differences from bash brace expansion:
Unbalanced braces: Patterns with unbalanced braces raise UnbalancedBracesError. In bash, these are either partly expanded or ignored.
Mixed-case character ranges: Ranges like {Z..a} or {a..Z} will not include the characters []^_\`` that fall between Zanda` in ASCII order.
from braceexpand import braceexpand
# Generate file paths
paths = list(braceexpand('/path/to/{file1,file2,file3}.txt'))
# ['/path/to/file1.txt', '/path/to/file2.txt', '/path/to/file3.txt']
# Generate numbered sequences
files = list(braceexpand('backup-{001..005}.sql'))
# ['backup-001.sql', 'backup-002.sql', 'backup-003.sql', 'backup-004.sql', 'backup-005.sql']
# Generate test data
coordinates = list(braceexpand('{x,y,z}{1..3}'))
# ['x1', 'x2', 'x3', 'y1', 'y2', 'y3', 'z1', 'z2', 'z3']
# Command line argument expansion
args = list(braceexpand('--{verbose,debug,quiet}'))
# ['--verbose', '--debug', '--quiet']