strconv - Data conversion from/to string¶
Overview¶
firebird.base.strconv
¶
This module provides a centralized mechanism for converting various Python data types to and from their string representations. It allows registering custom conversion functions for specific types, making the conversion process extensible and decoupled from the types themselves.
Core features include:
- Registration of type-specific string conversion functions.
- Lookup of convertors based on type or type name (simple or full).
- Helper functions (
convert_to_str,convert_from_str) for easy conversion. - Built-in support for common types (str, int, float, bool, Decimal, UUID, Enum, etc.).
Example
from firebird.base.strconv import convert_to_str, convert_from_str
from decimal import Decimal
# Convert Decimal to string
s = convert_to_str(Decimal('123.45'))
print(s) # Output: 123.45
# Convert string back to Decimal
d = convert_from_str(Decimal, '123.45')
print(d) # Output: Decimal('123.45')
# Boolean conversion
b = convert_from_str(bool, 'yes')
print(b) # Output: True
s = convert_to_str(False)
print(s) # Output: no
While Python types typically support conversion to string via builtin str() function
(and custom __str__ methods), there is no symetric operation that converts string created
by str() back to typed value. This module provides support for such symetric conversion
from/to string for any data type.
Note
Symetric string conversion is used by firebird.base.config module, notably by ListOption and DataclassOption. You can extend the range of data types supported by these options by registering convertors for required data types.
Architecture¶
Module maintains a global registry of convertors associated with a data type. These convertor functions may support conversion for multiple data types, and must have signatures:
# Conversion to string
def value2str(value: Any) -> str:
...
# Conversion from string
def str2value(cls: Type, value: str) -> Any:
...
Convertors should raise ValueError when conversion fails.
Convertors must be registered using register_convertor function, or reassigned using update_convertor.
There are two methods for use of registered convertors:
- By using functions convert_to_str and convert_from_str. These functions use convertor that is registered for particular data type. If there is no such convertor, they use first convertor registered for any base class. The lookup is performed in Method Resolution Order. This method is preferred when you will work with various data types.
- Using get_convertor function to obtain registry entry with convertors.
This method is preferred when you will work with single data type repeatedly.
Important
The convertor registry lookup could be done either for a class, or class name.
Lookup for a class is first performed for specified class. If there is no such entry, all base classes in Method Resolution Order are used for lookup, and the first entry found is returned.
Lookup for a class name could be performed only for a specified class. Because some types could be converted using convertors registered for their base class, such lookup will not find the required convertor entry. To circumvent this issue, it's necessary to register a class for name lookup using register_class function. The registry lookup uses this class registry to use the actual type instead type name.
Registered data types¶
Module registers convertor functions for next data types:
strintfloatcomplexbool. UsesTRUE_STRandFALSE_STRlist for conversion from string (the case is NOT significant). Conversion to string always uses first item in these lists.decimal.Decimaluuid.UUIDMIMEZMQAddressenum.Enumandenum.Flag. Supports conversion for all descendants ofEnum,IntEnum,FlagandIntFlag.
Tip
Functions any2str and str2any
could be used to register conversion for data types that support symetric conversion via
__str__() method and class constructor (__init__() must accept one positional argument
that could be a string and all other arguments must be keyword arguments with default values).
Types for annotations¶
firebird.base.strconv.TConvertToStr: TypeAlias
module-attribute
¶
firebird.base.strconv.TConvertFromStr: TypeAlias
module-attribute
¶
Globals¶
firebird.base.strconv.TRUE_STR: list[str]
module-attribute
¶
Valid string literals for True value.
firebird.base.strconv.FALSE_STR: list[str]
module-attribute
¶
Valid string literals for False value.
Functions¶
firebird.base.strconv.convert_to_str(value: Any) -> str
¶
Converts a value to its string representation using its registered convertor.
Looks up the convertor based on the value's class (value.__class__).
If there is no direct convertor registered for the value's specific class,
it searches the Method Resolution Order (MRO) for a convertor registered
for a base class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
The value to be converted to a string. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If no convertor is found for the value's class or any of its base classes in the MRO. |
Example
from decimal import Decimal
from uuid import uuid4
from firebird.base.strconv import convert_to_str, register_convertor
print(convert_to_str(123)) # Output: '123'
print(convert_to_str(Decimal('1.2'))) # Output: '1.2'
print(convert_to_str(True)) # Output: 'yes'
my_uuid = uuid4()
print(convert_to_str(my_uuid)) # Output: UUID string representation
class MyBase: pass
class MyDerived(MyBase): pass
register_convertor(MyBase, to_str=lambda v: "BaseStr")
instance = MyDerived()
print(convert_to_str(instance)) # Output: 'BaseStr' (uses MyBase convertor)
Source code in firebird/base/strconv.py
firebird.base.strconv.convert_from_str(cls: type | str, value: str) -> Any
¶
Converts a string representation back to a typed value using a registered convertor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type | str
|
The target type object or type name (simple or full) to convert to. |
required |
value
|
str
|
The string value to be converted. |
required |
Note
When cls is a type name:
- If the class name is NOT registered via
register_class(), MRO lookup for base class convertors is not possible if an exact name match isn't found. - If a simple class name is provided and is ambiguous (multiple registered classes with the same name), the first match found is used. Use full names ('module.ClassName') for clarity in such cases.
Raises:
| Type | Description |
|---|---|
TypeError
|
If no convertor is found for |
ValueError
|
Often raised by the underlying |
Example
from decimal import Decimal
from uuid import UUID
from firebird.base.strconv import convert_from_str
num = convert_from_str(int, '123') # Output: 123 (int)
dec = convert_from_str(Decimal, '1.2') # Output: Decimal('1.2')
flag = convert_from_str(bool, 'off') # Output: False (bool)
uid = convert_from_str(UUID, '...') # Output: UUID object
# Using string name
dec_from_name = convert_from_str('Decimal', '3.14') # Output: Decimal('3.14')
try:
convert_from_str(int, 'not-a-number')
except ValueError as e:
print(e) # Example: invalid literal for int() with base 10: 'not-a-number'
Source code in firebird/base/strconv.py
firebird.base.strconv.register_convertor(cls: type, *, to_str: TConvertToStr = any2str, from_str: TConvertFromStr = str2any) -> None
¶
Registers convertor function(s) for a specific data type.
If to_str or from_str are not provided, default convertors (any2str,
str2any) based on str() and cls() are used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
Class to register convertor for. |
required |
to_str
|
TConvertToStr
|
Optional function that converts an instance of |
any2str
|
from_str
|
TConvertFromStr
|
Optional function that converts |
str2any
|
Example
from datetime import date
from firebird.base.strconv import register_convertor, convert_to_str, convert_from_str
# Register custom convertors for date
def date_to_iso(value: date) -> str:
return value.isoformat()
def iso_to_date(cls: type, value: str) -> date:
return cls.fromisoformat(value)
register_convertor(date, to_str=date_to_iso, from_str=iso_to_date)
d = date(2023, 10, 27)
s = convert_to_str(d) # Uses date_to_iso -> '2023-10-27'
d2 = convert_from_str(date, s) # Uses iso_to_date -> date(2023, 10, 27)
Source code in firebird/base/strconv.py
firebird.base.strconv.update_convertor(cls: type | str, *, to_str: TConvertToStr | None = None, from_str: TConvertFromStr | None = None) -> None
¶
Update the to_str and/or from_str functions for an existing convertor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type | str
|
Class or class name whose convertor needs updating. |
required |
to_str
|
TConvertToStr | None
|
Optional new function that converts |
None
|
from_str
|
TConvertFromStr | None
|
Optional new function that converts |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If the data type (or its name) has no registered convertor. |
Example
Source code in firebird/base/strconv.py
firebird.base.strconv.register_class(cls: type) -> None
¶
Registers a class name for lookup, primarily for string-based conversions.
This allows functions like has_convertor, get_convertor, and convert_from_str
to find the correct convertor when given a simple class name (e.g., "MyClass")
as a string, instead of the class object itself. Registration is particularly
useful when:
- Performing lookups based on class names stored as strings.
- Resolving potential ambiguity if multiple classes with the same simple name exist in different modules (though using full names like 'module.MyClass' is generally safer in such cases).
- Enabling MRO (Method Resolution Order) lookup for base class convertors when the lookup starts with a string name.
See Also
has_convertor, get_convertor, convert_from_str
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
Class to be registered. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
When the simple class name ( |
Source code in firebird/base/strconv.py
firebird.base.strconv.has_convertor(cls: type | str) -> bool
¶
Returns True if a convertor is registered for the class or its bases.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type | str
|
Type object or type name. The name could be a simple class name (e.g., "MyClass") or a full name including the module (e.g., "my_module.MyClass"). |
required |
Note
When cls is a name:
- If the class name is NOT registered via
register_class(), it's not possible to perform MRO lookup for base class convertors. Only an exact match on the name (simple or full) will work. - If a simple class name is provided and multiple classes of the same
name but from different modules have registered convertors (or been
registered via
register_class), the lookup might be ambiguous. Using full names is recommended in such scenarios.
Example
from decimal import Decimal
from firebird.base.strconv import register_convertor, has_convertor, register_class
print(has_convertor(Decimal)) # Output: True (built-in)
print(has_convertor('Decimal')) # Output: True (built-in, simple name works)
print(has_convertor('decimal.Decimal')) # Output: True (full name)
class MyData: pass
class MySubData(MyData): pass
register_convertor(MyData)
register_class(MySubData) # Register subclass name
print(has_convertor(MySubData)) # Output: True (finds MyData via MRO)
print(has_convertor('MySubData')) # Output: True (finds MyData via MRO because name is registered)
print(has_convertor('NonExistent')) # Output: False
Source code in firebird/base/strconv.py
firebird.base.strconv.get_convertor(cls: type | str) -> Convertor
¶
"Returns the Convertor object registered for a data type or its bases.
This function performs the lookup based on the type or type name, including
MRO search for base classes if necessary and possible. It is used internally
by convert_to_str and convert_from_str, but can be called directly
if you need access to the Convertor instance itself, for example,
for introspection or direct access to the to_str/from_str functions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type | str
|
Type object or type name. The name could be a simple class name (e.g., "MyClass") or a full name including the module (e.g., "my_module.MyClass"). |
required |
Note
When cls is a name:
- If the class name is NOT registered via
register_class(), MRO lookup for base class convertors is not possible if an exact name match isn't found. - If a simple class name is provided and is ambiguous (multiple registered classes with the same name), the first match found is used. Use full names for clarity.
Raises:
| Type | Description |
|---|---|
TypeError
|
If no convertor is found for |
Example
from decimal import Decimal
from firebird.base.strconv import get_convertor
decimal_conv = get_convertor(Decimal)
print(decimal_conv.name) # Output: Decimal
print(decimal_conv.to_str(Decimal('9.87'))) # Output: 9.87
bool_conv = get_convertor('bool') # Lookup by name
print(bool_conv.from_str(bool, 'TRUE')) # Output: True
Source code in firebird/base/strconv.py
firebird.base.strconv.any2str(value: Any) -> str
¶
Converts value to string using str(value).
This is the default to_str convertor function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
The value to convert. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The string representation of the value. |
Source code in firebird/base/strconv.py
firebird.base.strconv.str2any(cls: type, value: str) -> Any
¶
Converts string to data type value using type(value).
This is the default from_str convertor function. It assumes the
type's constructor can handle a single string argument.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The target data type. |
required |
value
|
str
|
The string representation to convert. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
An instance of |
Source code in firebird/base/strconv.py
Dataclasses¶
firebird.base.strconv.Convertor
dataclass
¶
Bases: Distinct
Data convertor registry entry.
Holds the functions responsible for converting a specific data type to and from its string representation. Instances of this class are stored in the internal registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The data type (class) this convertor handles. |
required |
to_str
|
TConvertToStr
|
The function converting an instance of |
required |
from_str
|
TConvertFromStr
|
The function converting a string back to an instance of |
required |
Source code in firebird/base/strconv.py
cls: type
instance-attribute
¶
The data type (class) this convertor handles.
from_str: TConvertFromStr
instance-attribute
¶
The function converting a string back to an instance of cls.
full_name: str
property
¶
Type name including source module (e.g., decimal.Decimal).
to_str: TConvertToStr
instance-attribute
¶
The function converting an instance of cls to a string.