1"""Alias generators for converting between different capitalization conventions.""" 
    2 
    3import re 
    4 
    5__all__ = ('to_pascal', 'to_camel', 'to_snake') 
    6 
    7# TODO: in V3, change the argument names to be more descriptive 
    8# Generally, don't only convert from snake_case, or name the functions 
    9# more specifically like snake_to_camel. 
    10 
    11 
    12def to_pascal(snake: str) -> str: 
    13    """Convert a snake_case string to PascalCase. 
    14 
    15    Args: 
    16        snake: The string to convert. 
    17 
    18    Returns: 
    19        The PascalCase string. 
    20    """ 
    21    camel = snake.title() 
    22    return re.sub('([0-9A-Za-z])_(?=[0-9A-Z])', lambda m: m.group(1), camel) 
    23 
    24 
    25def to_camel(snake: str) -> str: 
    26    """Convert a snake_case string to camelCase. 
    27 
    28    Args: 
    29        snake: The string to convert. 
    30 
    31    Returns: 
    32        The converted camelCase string. 
    33    """ 
    34    # If the string is already in camelCase and does not contain a digit followed 
    35    # by a lowercase letter, return it as it is 
    36    if re.match('^[a-z]+[A-Za-z0-9]*$', snake) and not re.search(r'\d[a-z]', snake): 
    37        return snake 
    38 
    39    camel = to_pascal(snake) 
    40    return re.sub('(^_*[A-Z])', lambda m: m.group(1).lower(), camel) 
    41 
    42 
    43def to_snake(camel: str) -> str: 
    44    """Convert a PascalCase, camelCase, or kebab-case string to snake_case. 
    45 
    46    Args: 
    47        camel: The string to convert. 
    48 
    49    Returns: 
    50        The converted string in snake_case. 
    51    """ 
    52    # Handle the sequence of uppercase letters followed by a lowercase letter 
    53    snake = re.sub(r'([A-Z]+)([A-Z][a-z])', lambda m: f'{m.group(1)}_{m.group(2)}', camel) 
    54    # Insert an underscore between a lowercase letter and an uppercase letter 
    55    snake = re.sub(r'([a-z])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake) 
    56    # Insert an underscore between a digit and an uppercase letter 
    57    snake = re.sub(r'([0-9])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake) 
    58    # Insert an underscore between a lowercase letter and a digit 
    59    snake = re.sub(r'([a-z])([0-9])', lambda m: f'{m.group(1)}_{m.group(2)}', snake) 
    60    # Replace hyphens with underscores to handle kebab-case 
    61    snake = snake.replace('-', '_') 
    62    return snake.lower()