Skip to content

synt.expr.fstring ¤

fstring module-attribute ¤

fstring = FormatString

Alias FormatString.

fnode module-attribute ¤

fnode = FormatNode

Alias FormatNode.

FormatString ¤

Bases: Expression

Format string, aka f-string.

Examples:

string = fstring("sin(1) = ", fnode(id_("sin").expr().call(litint(1))))
assert string.into_code() == 'f"sin(1) = {sin(1)}"'
References

expr.ExprType.FormatString.

Source code in synt/expr/fstring.py
class FormatString(expr.Expression):
    r"""Format string, aka f-string.

    Examples:
        ```python
        string = fstring("sin(1) = ", fnode(id_("sin").expr().call(litint(1))))
        assert string.into_code() == 'f"sin(1) = {sin(1)}"'
        ```

    References:
        [expr.ExprType.FormatString][synt.expr.expr.ExprType.FormatString].
    """

    nodes: list[FormatNode | str]
    """Formatting nodes."""

    precedence = expr.ExprPrecedence.Atom
    expr_type = expr.ExprType.FormatString

    def __init__(self, *nodes: FormatNode | str):
        """Initialize a new format string expression.

        Args:
            nodes: Formatting nodes.
        """
        self.nodes = list(nodes)

    def into_code(self) -> str:
        string = ""
        for item in self.nodes:
            if isinstance(item, str):
                string += item
            else:
                string += item.into_code()
        return f'f"{string}"'

precedence class-attribute instance-attribute ¤

precedence = Atom

expr_type class-attribute instance-attribute ¤

expr_type = FormatString

nodes instance-attribute ¤

nodes: list[FormatNode | str] = list(nodes)

Formatting nodes.

__init__ ¤

__init__(*nodes: FormatNode | str)

Initialize a new format string expression.

Parameters:

Name Type Description Default
nodes FormatNode | str

Formatting nodes.

()
Source code in synt/expr/fstring.py
def __init__(self, *nodes: FormatNode | str):
    """Initialize a new format string expression.

    Args:
        nodes: Formatting nodes.
    """
    self.nodes = list(nodes)

into_code ¤

into_code() -> str
Source code in synt/expr/fstring.py
def into_code(self) -> str:
    string = ""
    for item in self.nodes:
        if isinstance(item, str):
            string += item
        else:
            string += item.into_code()
    return f'f"{string}"'

FormatConversionType ¤

Bases: IntEnum

Format conversion type.

References

FormattedValue.

Source code in synt/expr/fstring.py
class FormatConversionType(IntEnum):
    r"""Format conversion type.

    References:
        [`FormattedValue`](https://docs.python.org/3/library/ast.html#ast.FormattedValue).
    """

    No = -1
    """No formatting."""
    Ascii = 97
    """Ascii representation, aka `!a`."""
    Repr = 114
    """`__repr__` representation, aka `!r`."""
    Str = 115
    """`__str__` representation, aka `!s`."""

    @staticmethod
    def from_str(s: str) -> FormatConversionType:
        """Parse a conversion string.

        | text          | result                       |
        | ------------- | ---------------------------- |
        | `""`, `"!"`   | `FormatConversionType.No`    |
        | `"a"`, `"!a"` | `FormatConversionType.Ascii` |
        | `"r"`, `"!r"` | `FormatConversionType.Repr`  |
        | `"s"`, `"!s"` | `FormatConversionType.Str`   |

        Args:
            s: Conversion string.

        Raises:
            ValueError: If the conversion string is invalid (valid forms are the texts listed above).
        """
        s = s.removeprefix("!")
        match s:
            case "":
                return FormatConversionType.No
            case "a":
                return FormatConversionType.Ascii
            case "r":
                return FormatConversionType.Repr
            case "s":
                return FormatConversionType.Str
            case r:
                raise ValueError(f"Invalid conversion string: {r}")

    def into_str(self) -> str:
        """Converts the conversion type into a string.

        Raises
            ValueError: If the conversion type is not recognized.
        """
        match self:
            case FormatConversionType.No:
                return ""
            case FormatConversionType.Ascii:
                return "!a"
            case FormatConversionType.Repr:
                return "!r"
            case FormatConversionType.Str:
                return "!s"
            case _ as conversion_type:
                raise ValueError(f"Unrecognized conversion type: {conversion_type}")

No class-attribute instance-attribute ¤

No = -1

No formatting.

Ascii class-attribute instance-attribute ¤

Ascii = 97

Ascii representation, aka !a.

Repr class-attribute instance-attribute ¤

Repr = 114

__repr__ representation, aka !r.

Str class-attribute instance-attribute ¤

Str = 115

__str__ representation, aka !s.

from_str staticmethod ¤

from_str(s: str) -> FormatConversionType

Parse a conversion string.

text result
"", "!" FormatConversionType.No
"a", "!a" FormatConversionType.Ascii
"r", "!r" FormatConversionType.Repr
"s", "!s" FormatConversionType.Str

Parameters:

Name Type Description Default
s str

Conversion string.

required

Raises:

Type Description
ValueError

If the conversion string is invalid (valid forms are the texts listed above).

Source code in synt/expr/fstring.py
@staticmethod
def from_str(s: str) -> FormatConversionType:
    """Parse a conversion string.

    | text          | result                       |
    | ------------- | ---------------------------- |
    | `""`, `"!"`   | `FormatConversionType.No`    |
    | `"a"`, `"!a"` | `FormatConversionType.Ascii` |
    | `"r"`, `"!r"` | `FormatConversionType.Repr`  |
    | `"s"`, `"!s"` | `FormatConversionType.Str`   |

    Args:
        s: Conversion string.

    Raises:
        ValueError: If the conversion string is invalid (valid forms are the texts listed above).
    """
    s = s.removeprefix("!")
    match s:
        case "":
            return FormatConversionType.No
        case "a":
            return FormatConversionType.Ascii
        case "r":
            return FormatConversionType.Repr
        case "s":
            return FormatConversionType.Str
        case r:
            raise ValueError(f"Invalid conversion string: {r}")

into_str ¤

into_str() -> str

Converts the conversion type into a string.

Raises ValueError: If the conversion type is not recognized.

Source code in synt/expr/fstring.py
def into_str(self) -> str:
    """Converts the conversion type into a string.

    Raises
        ValueError: If the conversion type is not recognized.
    """
    match self:
        case FormatConversionType.No:
            return ""
        case FormatConversionType.Ascii:
            return "!a"
        case FormatConversionType.Repr:
            return "!r"
        case FormatConversionType.Str:
            return "!s"
        case _ as conversion_type:
            raise ValueError(f"Unrecognized conversion type: {conversion_type}")

FormatNode ¤

Bases: IntoCode

Format node used in FormatString.

Examples:

node = fnode(id_("sin").expr().call(litint(1)), ".2")
assert node.into_code() == "{sin(1):.2}"
Source code in synt/expr/fstring.py
class FormatNode(code.IntoCode):
    r"""Format node used in [`FormatString`][synt.expr.fstring.FormatString].

    Examples:
        ```python
        node = fnode(id_("sin").expr().call(litint(1)), ".2")
        assert node.into_code() == "{sin(1):.2}"
        ```
    """

    value: expr.Expression
    """expr.Expression to be joint with other nodes."""
    format_spec: str | None
    """The formatting of the value.

    Notes:
        Different from Python's behavior, Synt directly use `str` as the type of `format_spec`,
        instead of wrapping it in a `JointStr(Constant(string))`.
    """
    conversion: FormatConversionType
    """The conversion of the expression, e.g. `__str__`, `__repr__`, ..."""

    def __init__(
        self,
        value: expr.IntoExpression,
        format_spec: str | None = None,
        conversion: FormatConversionType | str = FormatConversionType.No,
    ):
        """Initialize a format node.

        Args:
            value: expr.Expression to be joint with other nodes.
            format_spec: The formatting of the value.
            conversion: The conversion of the expression.
        """
        self.value = value.into_expression()
        self.format_spec = format_spec
        self.conversion = (
            FormatConversionType.from_str(conversion)
            if isinstance(conversion, str)
            else conversion
        )

    def into_code(self) -> str:
        fmt_spec = f":{self.format_spec}" if self.format_spec else ""
        return f"{{{self.value.into_code()}{self.conversion.into_str()}{fmt_spec}}}"

value instance-attribute ¤

value: Expression = into_expression()

expr.Expression to be joint with other nodes.

format_spec instance-attribute ¤

format_spec: str | None = format_spec

The formatting of the value.

Notes

Different from Python's behavior, Synt directly use str as the type of format_spec, instead of wrapping it in a JointStr(Constant(string)).

conversion instance-attribute ¤

The conversion of the expression, e.g. __str__, __repr__, ...

__init__ ¤

1
2
3
4
5
6
7
__init__(
    value: IntoExpression,
    format_spec: str | None = None,
    conversion: (
        FormatConversionType | str
    ) = FormatConversionType.No,
)

Initialize a format node.

Parameters:

Name Type Description Default
value IntoExpression

expr.Expression to be joint with other nodes.

required
format_spec str | None

The formatting of the value.

None
conversion FormatConversionType | str

The conversion of the expression.

No
Source code in synt/expr/fstring.py
def __init__(
    self,
    value: expr.IntoExpression,
    format_spec: str | None = None,
    conversion: FormatConversionType | str = FormatConversionType.No,
):
    """Initialize a format node.

    Args:
        value: expr.Expression to be joint with other nodes.
        format_spec: The formatting of the value.
        conversion: The conversion of the expression.
    """
    self.value = value.into_expression()
    self.format_spec = format_spec
    self.conversion = (
        FormatConversionType.from_str(conversion)
        if isinstance(conversion, str)
        else conversion
    )

into_code ¤

into_code() -> str
Source code in synt/expr/fstring.py
def into_code(self) -> str:
    fmt_spec = f":{self.format_spec}" if self.format_spec else ""
    return f"{{{self.value.into_code()}{self.conversion.into_str()}{fmt_spec}}}"