Skip to content

compile

ASSISTANT_ROLE module-attribute

ASSISTANT_ROLE = MessageRole(ASSISTANT)

The assistant role with name not specified.

MaybeOneOrMany module-attribute

MaybeOneOrMany = Union[_T, Sequence[_T], None]

A type that can be either a single item, a sequence of items, or None.

OneOrMany module-attribute

OneOrMany = Union[_T, Sequence[_T]]

A type that can be either a single item or a sequence of items.

SYSTEM_ROLE module-attribute

SYSTEM_ROLE = MessageRole(SYSTEM)

The system role with name not specified.

StrOrImg module-attribute

StrOrImg = Union[String, Image]

A type that can be either a string or an image.

String module-attribute

String = Union[StringFuture, str]

String is a type alias for StringFuture or str.

TOOL_ROLE module-attribute

TOOL_ROLE = MessageRole(TOOL)

The tool role with name not specified.

USER_ROLE module-attribute

USER_ROLE = MessageRole(USER)

The user role with name not specified.

APPLCompiled

APPLCompiled(
    code: CodeType,
    ast: AST,
    original_func: Callable,
    compile_info: Dict,
)

A compiled APPL function that can be called with context.

Parameters:

  • code (CodeType) –

    The compiled code object.

  • ast (AST) –

    The AST of the compiled code.

  • original_func (Callable) –

    The original function.

  • compile_info (Dict) –

    The compile information.

Source code in src/appl/core/compile.py
def __init__(
    self, code: CodeType, ast: AST, original_func: Callable, compile_info: Dict
):
    """Initialize the compiled function.

    Args:
        code: The compiled code object.
        ast: The AST of the compiled code.
        original_func: The original function.
        compile_info: The compile information.
    """
    self._code = code
    self._ast = ast
    self._name = original_func.__name__
    self._original_func = original_func
    self._compile_info = compile_info
    self._docstring_quote_count = _get_docstring_quote_count(compile_info["source"])

freevars property

freevars: Tuple[str, ...]

Get the free variables of the compiled function.

AddCtxToArgs

AddCtxToArgs(compile_info: Dict, *args: Any, **kwargs: Any)

Bases: ApplNodeTransformer

An AST node transformer that adds _ctx to the function arguments.

Source code in src/appl/core/compile.py
def __init__(self, compile_info: Dict, *args: Any, **kwargs: Any) -> None:
    """Initialize the transformer with compile info."""
    super().__init__(*args, **kwargs)
    self._compile_info = compile_info

visit_FunctionDef

visit_FunctionDef(node: FunctionDef) -> FunctionDef

Add _ctx to the function arguments if not present.

Source code in src/appl/core/compile.py
def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef:
    """Add _ctx to the function arguments if not present."""
    # ! only add _ctx to outermost function def, not call generic_visit here.
    # self.generic_visit(node) # !! do not call
    args = node.args
    # add _ctx to kwargs if not present
    if not _has_arg(args.args, "_ctx") and not _has_arg(args.kwonlyargs, "_ctx"):
        args.kwonlyargs.append(CTX_ARG)
        # PromptContext() as default
        args.kw_defaults.append(
            Call(func=Name(id="PromptContext", ctx=Load()), args=[], keywords=[])
        )
    for var in self._compile_info["freevars"]:
        args.kwonlyargs.append(ast.arg(arg=var))
        args.kw_defaults.append(ast.Name(id=var, ctx=Load()))
        logger.debug(f"add freevar {var} to function {node.name} args.")
    return node

AddExecuteWrapper

AddExecuteWrapper(
    compile_info: Dict, *args: Any, **kwargs: Any
)

Bases: ApplNodeTransformer

An AST node transformer that adds the appl.execute wrapper to expression statements.

Source code in src/appl/core/compile.py
def __init__(self, compile_info: Dict, *args: Any, **kwargs: Any) -> None:
    """Initialize the transformer with compile info."""
    super().__init__(*args, **kwargs)
    self._compile_info = compile_info

visit_Expr

visit_Expr(node: Expr) -> Expr

Add appl.execute wrapper to expression statements.

Source code in src/appl/core/compile.py
def visit_Expr(self, node: Expr) -> Expr:
    """Add appl.execute wrapper to expression statements."""
    return Expr(
        Call(
            func=Attribute(
                value=Name(id="appl", ctx=Load()),
                attr="execute",
                ctx=Load(),
            ),
            args=[node.value],
            keywords=[CTX_KEYWORD],  # , GLOBALS_KEYWORD, LOCALS_KEYWORD],
        )
    )

ApplNodeTransformer

ApplNodeTransformer(
    compile_info: Dict, *args: Any, **kwargs: Any
)

Bases: NodeTransformer

A base class for AST node transformers in APPL.

Source code in src/appl/core/compile.py
def __init__(self, compile_info: Dict, *args: Any, **kwargs: Any) -> None:
    """Initialize the transformer with compile info."""
    super().__init__(*args, **kwargs)
    self._compile_info = compile_info

CallFuture

CallFuture(
    func: Callable,
    *args: Any,
    use_process: bool = False,
    lazy_eval: bool = False,
    **kwargs: Any
)

Bases: FutureValue

Represent a function call that may not be ready yet.

Parameters:

  • func (Callable) –

    The function to call.

  • *args (Any, default: () ) –

    The arguments of the function.

  • use_process (bool, default: False ) –

    Whether to use a process pool executor.

  • lazy_eval (bool, default: False ) –

    Whether to delay the start of the call until needed.

  • **kwargs (Any, default: {} ) –

    The keyword arguments of the function.

Source code in src/appl/core/types/futures.py
def __init__(
    self,
    func: Callable,
    *args: Any,
    use_process: bool = False,
    lazy_eval: bool = False,
    **kwargs: Any,
):
    """Initialize the CallFuture.

    Args:
        func: The function to call.
        *args: The arguments of the function.
        use_process: Whether to use a process pool executor.
        lazy_eval: Whether to delay the start of the call until needed.
        **kwargs: The keyword arguments of the function.
    """
    # ? maybe use a global executor from the config, or use thread-level executor if running in multi-threading.
    self._executor = (
        ProcessPoolExecutor(max_workers=1)
        if use_process
        else ThreadPoolExecutor(
            max_workers=1, thread_name_prefix=threading.current_thread().name
        )
    )
    self._submit_fn = lambda: self._executor.submit(func, *args, **kwargs)
    self._submitted = False
    self._info = func.__name__
    # self._debug = False
    # if self._debug:
    #     # arg and kwargs might contains future objects
    #     args_list = [f"{arg}" for arg in args] + [
    #         f"{k}={v!r}" for k, v in kwargs.items()
    #     ]
    #     args_str = ", ".join(args_list)
    #     self._info += f"({args_str})"
    if not lazy_eval:
        # delay the start of the call until needed
        self._submit()

future property

future

The future object of the call.

val property

val

The value of the future.

cancel

cancel() -> bool

Cancel the call.

Source code in src/appl/core/types/futures.py
def cancel(self) -> bool:
    """Cancel the call."""
    # Attempt to cancel the call
    res = self.future.cancel()
    if res:
        self._executor.shutdown()  # the executor is not needed anymore
    return res

done

done() -> bool

Check if the call has completed.

Source code in src/appl/core/types/futures.py
def done(self) -> bool:
    """Check if the call has completed."""
    # Check if the future has completed
    return self.future.done()

result

result(timeout: Optional[float] = None) -> Any

Get the result of the call.

Source code in src/appl/core/types/futures.py
def result(self, timeout: Optional[float] = None) -> Any:
    """Get the result of the call."""
    # This will block until the result is available
    res = self.future.result(timeout)
    self._executor.shutdown()  # the executor is not needed anymore
    return res

CallWithContext

CallWithContext(
    compile_info: Dict, *args: Any, **kwargs: Any
)

Bases: ApplNodeTransformer

An AST node transformer provides the context to function calls.

Source code in src/appl/core/compile.py
def __init__(self, compile_info: Dict, *args: Any, **kwargs: Any) -> None:
    """Initialize the transformer with compile info."""
    super().__init__(*args, **kwargs)
    self._compile_info = compile_info

visit_Call

visit_Call(node: Call) -> Call

Provide context (_ctx) to function calls that needs ctx.

Source code in src/appl/core/compile.py
def visit_Call(self, node: Call) -> Call:
    """Provide context (_ctx) to function calls that needs ctx."""
    self.generic_visit(node)
    # logger.debug(f"visit Call: {ast.dump(node, indent=4)}")
    # * use appl.with_ctx as wrapper for all functions,
    # * pass _ctx to the function annotated with @need_ctx
    new_node = Call(
        Attribute(
            value=Name(id="appl", ctx=Load()),
            attr="with_ctx",
            ctx=Load(),
        ),
        node.args,
        node.keywords,
    )
    new_node.keywords.append(ast.keyword(arg="_func", value=node.func))
    # add _ctx to kwargs if not present
    if not _has_arg(node.keywords, "_ctx"):
        new_node.keywords.append(CTX_KEYWORD)
    new_node.keywords.append(GLOBALS_KEYWORD)
    new_node.keywords.append(LOCALS_KEYWORD)
    return new_node

CmpStringFuture

CmpStringFuture(
    a: StringFuture,
    b: StringFuture,
    op: Callable[[str, str], bool],
)

Bases: FutureValue

Represent a comparison between a StringFuture and another value.

Source code in src/appl/core/types/futures.py
def __init__(
    self, a: "StringFuture", b: "StringFuture", op: Callable[[str, str], bool]
):
    """Initialize the CmpStringFuture."""
    self._a = a
    self._b = b
    self._op = op

val property

val

The value of the future.

ContentList

Bases: BaseModel

Represent a list of contents containing text and images.

append

append(content: StrOrImg) -> None

Append a content to the list.

If the last content is a string, it will be concatenated with the new content.

Source code in src/appl/core/types/content.py
def append(self, content: StrOrImg) -> None:
    """Append a content to the list.

    If the last content is a string, it will be concatenated with the new content.
    """
    if is_string(content) and len(self.contents) and is_string(self.contents[-1]):
        self.contents[-1] += content  # type: ignore
    else:
        self.contents.append(content)

extend

extend(contents: list[StrOrImg]) -> None

Extend the list with multiple contents.

Source code in src/appl/core/types/content.py
def extend(self, contents: list[StrOrImg]) -> None:
    """Extend the list with multiple contents."""
    for content in contents:
        self.append(content)

get_contents

get_contents() -> List[Dict[str, Any]]

Return the contents as a list of dictionaries.

Source code in src/appl/core/types/content.py
def get_contents(self) -> List[Dict[str, Any]]:
    """Return the contents as a list of dictionaries."""

    def get_dict(content):
        if isinstance(content, Image):
            image_args = {"url": content.url}
            if content.detail:
                image_args["detail"] = content.detail
            return {"type": "image_url", "image_url": image_args}
        return {"type": "text", "text": str(content)}

    return [get_dict(c) for c in self.contents]

DedentTripleQuotedString

Bases: CSTTransformer

A CST transformer that dedents triple-quoted strings in the source code.

leave_FormattedString

leave_FormattedString(
    original_node: FormattedString,
    updated_node: FormattedString,
) -> FormattedString

Dedent triple-quoted formatted strings in the source code.

Source code in src/appl/core/compile.py
def leave_FormattedString(
    self, original_node: cst.FormattedString, updated_node: cst.FormattedString
) -> cst.FormattedString:
    """Dedent triple-quoted formatted strings in the source code."""
    if len(original_node.end) != 3:
        return updated_node

    def get_num_leading_whitespace(line: str) -> int:
        """Compute the leading whitespace of this line."""
        if g := re.match(r"^[ \t]*", line):
            return len(g.group())
        return 0

    def dedent_str(text: str) -> str:
        cleaned = inspect.cleandoc(text)
        lines = cleaned.splitlines()
        margin: Optional[int] = None
        for line in lines:
            n = get_num_leading_whitespace(line)
            # try to fix a bug in `libcst.code_for_node``
            # the leading whitespace of '}' is not resumed correctly
            # as well as the contents within `{` and `}` (TODO)
            if len(line) > n and line[n] != "}":
                if margin is None:
                    margin = n
                else:
                    margin = min(margin, n)
        if margin is not None and margin > 0:
            new_lines = []
            for line in lines:
                n = get_num_leading_whitespace(line)
                new_lines.append(line[min(n, margin) :])
            cleaned = os.linesep.join(new_lines)
            cleaned = inspect.cleandoc(cleaned)  # clean again
            logger.warning(
                f"unusual multiline formatted string detected, "
                f"this is a bug related to libcst.code_for_node\n"
                f"The string after manual fix is:\n{cleaned}"
            )
        logger.debug(
            f"multiline formmated string dedented\n"
            f"before:\n{text}\n"
            f"after:\n{cleaned}"
        )
        return cleaned

    original_code = self.module.code_for_node(original_node)
    simple_str = original_code[len(original_node.start) : -len(original_node.end)]
    format_str = f"{original_node.start}{dedent_str(simple_str)}{original_node.end}"
    parsed_cst = cst.parse_expression(format_str)
    if isinstance(parsed_cst, cst.FormattedString):
        return parsed_cst
    raise RuntimeError(
        f"Failed to parse modified formatted string as libcst.FormattedString: {format_str}"
    )

leave_SimpleString

leave_SimpleString(
    original_node: SimpleString, updated_node: SimpleString
) -> SimpleString

Dedent triple-quoted strings in the source code.

Source code in src/appl/core/compile.py
def leave_SimpleString(
    self, original_node: cst.SimpleString, updated_node: cst.SimpleString
) -> cst.SimpleString:
    """Dedent triple-quoted strings in the source code."""
    value = original_node.value
    delim = value[-3:]
    # Check if the string is wrapped by triple quotes (""" or ''')
    if delim in ['"""', "'''"]:
        has_prefix_r = False
        if value.startswith("r" + delim):  # deal with raw string
            has_prefix_r = True
            value = value[1:]

        assert value[:3] == delim
        # Remove the quotes to process the inner string content
        inner_string = value[3:-3]

        # Use the standard of cleandoc to dedent the inner string
        modified_inner_string = inspect.cleandoc(inner_string)

        # Add back the triple quotes to the modified string
        new_value = f"{delim}{modified_inner_string}{delim}"
        if has_prefix_r:
            new_value = "r" + new_value

        logger.debug(
            f"multiline string dedented\n"
            f"before:\n{original_node.value}\n"
            f"after:\n{new_value}"
        )

        # Return the updated SimpleString node with the modified value
        return updated_node.with_changes(value=new_value)

    return updated_node

visit_Module

visit_Module(node: Module) -> bool

Store the module node for later use.

Source code in src/appl/core/compile.py
def visit_Module(self, node: cst.Module) -> bool:
    """Store the module node for later use."""
    self.module = node
    return True

FutureValue

Bases: ABC

Represents a value that may not be ready yet.

val property

val

The value of the future.

Image

Image(url: str, detail: Optional[str] = None)

Bases: BaseModel

Represent an image in the message.

See the guide for more information about the detail level.

Source code in src/appl/core/types/content.py
def __init__(self, url: str, detail: Optional[str] = None) -> None:
    """Initialize the image with the URL and detail level.

    See [the guide](https://platform.openai.com/docs/guides/vision/low-or-high-fidelity-image-understanding)
    for more information about the detail level.
    """
    super().__init__(url=url, detail=detail)

from_file classmethod

from_file(
    file: PathLike, detail: Optional[str] = None
) -> Image

Construct an image prompt from an image file.

Source code in src/appl/core/types/content.py
@classmethod
def from_file(cls, file: PathLike, detail: Optional[str] = None) -> "Image":
    """Construct an image prompt from an image file."""
    image = PIL.Image.open(file)
    return cls.from_image(image, detail)

from_image classmethod

from_image(
    image: ImageFile, detail: Optional[str] = None
) -> Image

Construct an image prompt from a PIL ImageFile.

Source code in src/appl/core/types/content.py
@classmethod
def from_image(cls, image: ImageFile, detail: Optional[str] = None) -> "Image":
    """Construct an image prompt from a PIL ImageFile."""
    buffered = BytesIO()
    # Save the image to the buffer in PNG format
    image.save(buffered, format="PNG")
    # Get the byte data from the buffer
    img_byte = buffered.getvalue()
    img_base64 = base64.b64encode(img_byte).decode("utf-8")
    return cls(url=f"data:image/png;base64,{img_base64}", detail=detail)

MessageRole

MessageRole(
    type: Optional[str] = None, name: Optional[str] = None
)

Bases: BaseModel

The role of the message owner.

Parameters:

  • type (Optional[str], default: None ) –

    The type of the role.

  • name (Optional[str], default: None ) –

    An optional name for the role, differentiate between roles of the same type."

Source code in src/appl/core/types/role.py
def __init__(self, type: Optional[str] = None, name: Optional[str] = None):
    """Initialize the MessageRole object.

    Args:
        type: The type of the role.
        name: An optional name for the role, differentiate between roles of the same type."
    """
    super().__init__(type=type, name=name)

is_assistant property

is_assistant: bool

Whether the role is an assistant role.

is_system property

is_system: bool

Whether the role is a system role.

is_tool property

is_tool: bool

Whether the role is a tool role.

is_user property

is_user: bool

Whether the role is a user role.

get_dict

get_dict() -> Dict[str, Any]

Get the role as a dictionary.

Source code in src/appl/core/types/role.py
def get_dict(self) -> Dict[str, Any]:
    """Get the role as a dictionary."""
    data = {"role": self.type}
    if self.name:
        data["name"] = self.name
    return data

RemoveApplDecorator

RemoveApplDecorator(*args: Any, **kwargs: Any)

Bases: ApplNodeTransformer

An AST node transformer that removes the ppl decorator.

Source code in src/appl/core/compile.py
def __init__(self, *args: Any, **kwargs: Any) -> None:
    """Initialize the transformer with the outmost flag."""
    super().__init__(*args, **kwargs)
    self._outmost = True

visit_FunctionDef

visit_FunctionDef(node)

Remove the ppl decorator from the function definition.

Source code in src/appl/core/compile.py
def visit_FunctionDef(self, node):
    """Remove the ppl decorator from the function definition."""
    if node.decorator_list:
        for decorator in node.decorator_list:
            if self._is_ppl_decorator(decorator):
                if not self._outmost:
                    self._raise_syntax_error(
                        decorator.lineno,
                        decorator.col_offset,
                        "Nested ppl decorator is not allowed yet for APPL.",
                    )
        # all decorators should be removed
        node.decorator_list = []
    if self._outmost:
        self._outmost = False
    self.generic_visit(node)
    return node

ResponseType

Bases: str, Enum

The type of generation response.

IMAGE class-attribute instance-attribute

IMAGE = 'image'

An image.

OBJECT class-attribute instance-attribute

OBJECT = 'obj'

An instance of a response model.

TEXT class-attribute instance-attribute

TEXT = 'text'

A text completion.

TOOL_CALL class-attribute instance-attribute

TOOL_CALL = 'tool_calls'

A list of tool calls.

UNFINISHED class-attribute instance-attribute

UNFINISHED = 'unfinished'

The response is not finished.

SplitString

SplitString(compile_info: Dict, *args: Any, **kwargs: Any)

Bases: ApplNodeTransformer

An AST node transformer that splits the f-string into multiple parts.

Source code in src/appl/core/compile.py
def __init__(self, compile_info: Dict, *args: Any, **kwargs: Any) -> None:
    """Initialize the transformer with compile info."""
    super().__init__(*args, **kwargs)
    self._compile_info = compile_info

visit_Expr

visit_Expr(node: Expr) -> stmt

Split the f-string into multiple parts, so that we can add appl.execute wrapper to each part.

Source code in src/appl/core/compile.py
def visit_Expr(self, node: Expr) -> stmt:
    """Split the f-string into multiple parts, so that we can add appl.execute wrapper to each part."""
    if isinstance(node.value, JoinedStr):
        fstring = node.value
        # logger.debug(f"For joined string: {fstring}")
        body: List[stmt] = []
        for value in fstring.values:
            if isinstance(value, Constant):
                body.append(Expr(value))
            elif isinstance(value, FormattedValue):
                body.extend(self._add_formatted_value(value))
            else:
                raise ValueError(
                    f"Unknown value type in a JoinedStr: {type(value)}"
                )
        if len(body) == 0:  # empty string
            return node
        if len(body) == 1:  # single string
            return body[0]
        return With(
            items=[
                ast.withitem(
                    context_expr=Call(
                        func=Attribute(
                            value=Name(id="appl", ctx=Load()),
                            attr="Str",
                            ctx=Load(),
                        ),
                        args=[],
                        keywords=[],
                    )
                )
            ],
            body=body,
        )
    return node

StringFuture

StringFuture(content: Any = '', set_value: bool = False)

Bases: FutureValue, BaseModel

StringFuture is a string that may not be ready yet.

Source code in src/appl/core/types/futures.py
def __init__(self, content: Any = "", set_value: bool = False):
    """Initialize the StringFuture."""
    if set_value:
        if not isinstance(content, List):
            raise ValueError("Cannot set value to non-list.")
        s = content
    else:
        s = [content]
    super().__init__(s=s)

val property

val

The value of the future.

from_list classmethod

from_list(content: List[Any]) -> StringFuture

Create a StringFuture from a list of content.

Source code in src/appl/core/types/futures.py
@classmethod
def from_list(cls, content: List[Any]) -> "StringFuture":
    """Create a StringFuture from a list of content."""
    return cls(content, set_value=True)

join

join(iterable: Iterable[StringFuture]) -> StringFuture

Concatenate any number of strings.

The StringFuture whose method is called is inserted in between each given StringFuture. The result is returned as a new StringFuture.

Source code in src/appl/core/types/futures.py
def join(self, iterable: Iterable["StringFuture"]) -> "StringFuture":
    """Concatenate any number of strings.

    The StringFuture whose method is called is inserted in between each
    given StringFuture. The result is returned as a new StringFuture.
    """
    result = []
    for i, x in enumerate(iterable):
        if i != 0:
            result.append(self)
        result.append(x)
    return StringFuture.from_list(result)

materialized

materialized() -> StringFuture

Materialize the StringFuture.

Source code in src/appl/core/types/futures.py
def materialized(self) -> "StringFuture":
    """Materialize the StringFuture."""
    self.s = [self._collapse()]
    return self

serialize

serialize() -> str

Serialize the StringFuture.

Source code in src/appl/core/types/futures.py
def serialize(self) -> str:
    """Serialize the StringFuture."""
    return str(self)

appl_compile

appl_compile(func: Callable) -> APPLCompiled

Compile an APPL function.

Source code in src/appl/core/compile.py
def appl_compile(func: Callable) -> APPLCompiled:
    """Compile an APPL function."""
    sourcefile = inspect.getsourcefile(func)
    lines, lineno = inspect.getsourcelines(func)
    source = appl_dedent(inspect.getsource(func))
    key = f"<appl-compiled:{sourcefile}:{lineno}>"
    linecache.cache[key] = (
        len(source),
        None,
        [line + os.linesep for line in source.splitlines()],
        key,
    )

    source = dedent_triple_quoted_string(source)
    parsed_ast = ast.parse(source)
    logger.debug(
        f"\n{'-'*20} code BEFORE appl compile {'-'*20}\n{ast.unparse(parsed_ast)}"
    )

    transformers = [
        RemoveApplDecorator,
        SplitString,
        CallWithContext,
        AddCtxToArgs,
        AddExecuteWrapper,
    ]
    compile_info = {
        "source": source,
        "sourcefile": sourcefile,
        "lineno": lineno,
        "func_name": func.__name__,
        "freevars": func.__code__.co_freevars,
        "docstring": func.__doc__,
    }
    for transformer in transformers:
        parsed_ast = transformer(compile_info).visit(parsed_ast)

    parsed_ast = ast.fix_missing_locations(parsed_ast)
    compiled_ast = compile(parsed_ast, filename=key, mode="exec")
    logger.debug(
        f"\n{'-'*20} code AFTER appl compile {'-'*20}\n{ast.unparse(parsed_ast)}"
    )

    return APPLCompiled(compiled_ast, parsed_ast, func, compile_info)

appl_dedent

appl_dedent(source: str) -> str

Dedent the source code.

Source code in src/appl/core/compile.py
def appl_dedent(source: str) -> str:
    """Dedent the source code."""
    source = textwrap.dedent(source)
    try:
        ast.parse(source)
    except Exception:  # the dedent failed due to multiline string
        logger.warning(
            "The source code contains multiline string that cannot be dedented. "
            "It is recommended to dedent the multiline string aligning with the function, "
            "where APPL will automatically dedent the multiline string "
            "in the same way as cleaning docstring."
        )
        # Compute the dedent and remove the leading whitespace
        leading_whitespace = re.compile("(^[ \t]*)(?:[^ \t\n])", re.MULTILINE)
        indents = leading_whitespace.findall(source)
        margin = indents[0]  # use the first line as the standard
        source = re.sub(r"(?m)^" + margin, "", source)
        logger.warning(f"The source code after workaround:\n{source}")
    return source

dedent_triple_quoted_string

dedent_triple_quoted_string(code: str) -> str

Automatically dedent triple-quoted strings with in the code (with inspect.cleandoc).

Source code in src/appl/core/compile.py
def dedent_triple_quoted_string(code: str) -> str:
    """Automatically dedent triple-quoted strings with in the code (with inspect.cleandoc)."""
    # Parse the source code into a CST
    cst_module = cst.parse_module(code)
    # Apply the transformer to dedent triple-quoted strings
    cst_transformer = DedentTripleQuotedString()
    modified_cst_module = cst_module.visit(cst_transformer)
    # return the modified code
    return modified_cst_module.code

is_string

is_string(s: Any) -> bool

Check if the object is a StringFuture or str.

Source code in src/appl/core/types/futures.py
def is_string(s: Any) -> bool:
    """Check if the object is a StringFuture or str."""
    return isinstance(s, StringFuture) or isinstance(s, str)