pyfcstm.utils.parse

String value parsing utilities for CLI option handling.

This module provides utilities for parsing string values from command-line options into appropriate Python types. It supports automatic type inference and explicit type hints for robust CLI argument parsing.

The main public components are:

Supported types:

  • Primitive types: None, bool, int, float, str, auto

  • Container types: tuple[T, ...] (variable length), tuple[T1, T2, ...] (fixed length)

  • Optional types: optional (equivalent to optional[auto]), optional[T]

Example:

>>> from pyfcstm.utils.parse import parse_value, parse_key_value_pairs
>>>
>>> # Auto mode - infer type from value
>>> parse_value('42')
42
>>> parse_value('true')
True
>>> parse_value('"hello world"')
'hello world'
>>>
>>> # Explicit type hints
>>> parse_value('42', 'int')
42
>>> parse_value('name,path', 'tuple[str, ...]')
('name', 'path')
>>>
>>> # Optional types
>>> parse_value('none', 'optional[str]')
None
>>> parse_value('hello', 'optional[str]')
'hello'
>>> parse_value('42', 'optional')
42
>>>
>>> # Parse multiple options
>>> parse_key_value_pairs(
...     ('show_events=true', 'max_depth=2', 'format=name,path'),
...     type_hints={'format': 'tuple[str, ...]', 'max_depth': 'int'}
... )
{'show_events': True, 'max_depth': 2, 'format': ('name', 'path')}

__all__

pyfcstm.utils.parse.__all__ = ['parse_value', 'parse_key_value_pairs']

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

parse_value

pyfcstm.utils.parse.parse_value(value_str: str, expected_type: type | str | None = 'auto') Any[source]

Parse a string value to appropriate Python type.

Supports: None, bool, int, float, str, auto, tuple, and optional types.

Type Inference (Auto Mode)

When expected_type is 'auto' (default), the function attempts to infer the type using the following priority:

  1. int: Try parsing as integer (e.g., '42'42)

  2. float: Try parsing as float (e.g., '3.14'3.14)

  3. str (quoted): Check for quoted strings with escape sequences (e.g., '"hello\nworld"''hello\nworld')

  4. None: Check for 'none' or 'null' (case-insensitive)

  5. bool: Check for 'true'/'yes' or 'false'/'no' (case-insensitive)

  6. str (unquoted): Default to string for everything else

Explicit Type Hints

When expected_type is specified, the value is parsed according to that type:

  • Primitive types: Pass the type directly (int, float, str, bool, None, type(None)) or as string ('int', 'float', 'str', 'bool', 'none', 'auto')

  • Tuple types: Use string notation:

    • 'tuple[str, ...]' - Variable length tuple with single element type

    • 'tuple[str, int]' - Fixed length tuple with specific types for each element

    • 'tuple[auto, ...]' - Variable length tuple with auto type inference for each element

  • Optional types: Use string notation:

    • 'optional' - Equivalent to 'optional[auto]', tries the specified type first, then None

    • 'optional[str]' - Tries to parse as string first, then None if value is ‘none’/’null’

    • 'optional[int]' - Tries to parse as int first, then None if value is ‘none’/’null’

String Handling

  • Quoted strings: Strings enclosed in single or double quotes have the quotes removed and escape sequences processed (\n, \t, \r, \\, \', \", etc.)

  • Unquoted strings: Used as-is when type is str or in auto mode as fallback

param value_str:

String value to parse

type value_str:

str

param expected_type:

Expected type or 'auto' for automatic inference (default). Can be a type (int, float, str, bool, None, type(None)), a string representation ('int', 'float', 'str', 'bool', 'none', 'auto', 'tuple[str, ...]', 'tuple[auto, ...]', 'optional', 'optional[str]'), or 'auto'.

type expected_type:

Union[type, str, None]

return:

Parsed value with appropriate type

rtype:

Any

raises ValueError:

If the value cannot be parsed as the expected type

Example:

>>> # Auto mode - type inference
>>> parse_value('42')
42
>>> parse_value('3.14')
3.14
>>> parse_value('true')
True
>>> parse_value('none')
None
>>> parse_value('hello')
'hello'
>>> parse_value('"hello world"')
'hello world'
>>> parse_value('"hello\nworld"')
'hello\nworld'
>>>
>>> # Explicit type hints (type objects)
>>> parse_value('42', int)
42
>>> parse_value('true', bool)
True
>>> parse_value('none', None)
None
>>> parse_value('none', type(None))
None
>>> parse_value('"hello world"', str)
'hello world'
>>>
>>> # Explicit type hints (string representations)
>>> parse_value('42', 'int')
42
>>> parse_value('3.14', 'float')
3.14
>>> parse_value('true', 'bool')
True
>>> parse_value('none', 'none')
None
>>> parse_value('hello', 'str')
'hello'
>>>
>>> # Tuple types
>>> parse_value('name,path', 'tuple[str, ...]')
('name', 'path')
>>> parse_value('name,42', 'tuple[str, int]')
('name', 42)
>>> parse_value('a,b,c', 'tuple[str, ...]')
('a', 'b', 'c')

parse_key_value_pairs

pyfcstm.utils.parse.parse_key_value_pairs(option_pairs: Tuple[str, ...], type_hints: Dict[str, type | str] | None = None) Dict[str, Any][source]

Parse multiple key=value pairs into a dictionary.

Each pair must be in the format 'key=value'. Values are parsed according to the type hints provided in type_hints. If a key is not in type_hints, its value is parsed in auto mode (type inference).

Parameters:
  • option_pairs (Tuple[str, ...]) – Tuple of ‘key=value’ strings

  • type_hints (Optional[Dict[str, Union[type, str]]]) – Optional dictionary mapping field names to expected types. If a field is not in type_hints, it will be parsed with ‘auto’ mode. Type hints can be Python types (int, float, str, bool, None, type(None)) or string representations ('int', 'float', 'str', 'bool', 'none', 'tuple[str, ...]', 'tuple[str, int]').

Returns:

Dictionary of parsed options

Return type:

Dict[str, Any]

Raises:

ValueError – If a pair is not in ‘key=value’ format or parsing fails

Example:

>>> # Auto mode for all fields
>>> parse_key_value_pairs(('show_events=true', 'max_depth=2'))
{'show_events': True, 'max_depth': 2}
>>>
>>> # With type hints (type objects)
>>> parse_key_value_pairs(
...     ('state_name_format=name,path', 'max_depth=2', 'enabled=true'),
...     type_hints={'state_name_format': 'tuple[str, ...]', 'max_depth': int}
... )
{'state_name_format': ('name', 'path'), 'max_depth': 2, 'enabled': True}
>>>
>>> # With type hints (string representations)
>>> parse_key_value_pairs(
...     ('state_name_format=name,path', 'max_depth=2', 'enabled=true'),
...     type_hints={'state_name_format': 'tuple[str, ...]', 'max_depth': 'int', 'enabled': 'bool'}
... )
{'state_name_format': ('name', 'path'), 'max_depth': 2, 'enabled': True}
>>>
>>> # Complex example with multiple types
>>> parse_key_value_pairs(
...     ('name="My App"', 'version=1.0', 'debug=false', 'ports=8080,8081,8082'),
...     type_hints={'name': str, 'version': float, 'debug': bool, 'ports': 'tuple[int, ...]'}
... )
{'name': 'My App', 'version': 1.0, 'debug': False, 'ports': (8080, 8081, 8082)}