Skip to content

Communication

This modules handles the WebSocket client and automatically connect to the server running in TVPaint.

It also has crucial functions like send_cmd that send George commands and get the result.

try_cmd(raise_exc: type[Exception] = GeorgeError, catch_exc: type[Exception] = GeorgeError, exception_msg: str | None = None) -> Callable[[T], T]

Decorator that does a try/except with GeorgeError by default.

It raises the error with the custom exception message provided.

Parameters:

Name Type Description Default
raise_exc type[Exception]

the exception to raise. Defaults to GeorgeError.

pytvpaint.george.exceptions.GeorgeError
catch_exc type[Exception]

the exception to catch. Defaults to GeorgeError.

pytvpaint.george.exceptions.GeorgeError
exception_msg str | None

Custom exception message. Defaults to None.

None

Returns:

Type Description
typing.Callable[[pytvpaint.george.client.T], pytvpaint.george.client.T]

the decorated function

Source code in pytvpaint/george/client/__init__.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def try_cmd(
    raise_exc: type[Exception] = GeorgeError,
    catch_exc: type[Exception] = GeorgeError,
    exception_msg: str | None = None,
) -> Callable[[T], T]:
    """Decorator that does a try/except with GeorgeError by default.

    It raises the error with the custom exception message provided.

    Args:
        raise_exc: the exception to raise. Defaults to GeorgeError.
        catch_exc: the exception to catch. Defaults to GeorgeError.
        exception_msg: Custom exception message. Defaults to None.

    Returns:
        the decorated function
    """

    def decorate(func: T) -> T:
        @functools.wraps(func)
        def applicator(*args: Any, **kwargs: Any) -> Any:
            try:
                return func(*args, **kwargs)
            except catch_exc as e:
                raise raise_exc(exception_msg or e)

        return cast(T, applicator)

    return decorate

send_cmd(command: str, *args: Any, error_values: list[Any] | None = None, handle_string: bool = True) -> str

Send a George command with the provided arguments to TVPaint.

Catch basic ERROR XX errors returned from George, but you can provide your own error values.

Parameters:

Name Type Description Default
command str

the George command to send

required
*args typing.Any

pass any arguments you want to that function

()
error_values list[typing.Any] | None

a list of error values to catch from George. Defaults to None.

None
handle_string bool

control the quote wrapping of string with spaces. Defaults to True.

True

Raises:

Type Description
pytvpaint.george.exceptions.GeorgeError

if we received ERROR XX or any of the custom error codes

Returns:

Type Description
str

the George return string

Source code in pytvpaint/george/client/__init__.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def send_cmd(
    command: str,
    *args: Any,
    error_values: list[Any] | None = None,
    handle_string: bool = True,
) -> str:
    """Send a George command with the provided arguments to TVPaint.

    Catch basic `ERROR XX` errors returned from George, but you can provide your own error values.

    Args:
        command: the George command to send
        *args: pass any arguments you want to that function
        error_values: a list of error values to catch from George. Defaults to None.
        handle_string: control the quote wrapping of string with spaces. Defaults to True.

    Raises:
        GeorgeError: if we received `ERROR XX` or any of the custom error codes

    Returns:
        the George return string
    """
    tv_args = [
        tv_handle_string(arg) if handle_string and isinstance(arg, str) else arg
        for arg in args
    ]
    cmd_str = " ".join([str(arg) for arg in [command, *tv_args]])

    is_undo_stack = command in [
        "tv_UndoOpenStack",
        "tv_UpdateUndo",
        "tv_UndoCloseStack",
    ]

    if not is_undo_stack:
        log.debug(f"[RPC] >> {cmd_str}")

    response = rpc_client.execute_remote("execute_george", [cmd_str])
    result = response["result"]

    if not is_undo_stack:
        log.debug(f"[RPC] << {result}")

    # Test for basic ERROR X values and user provided custom errors
    res_in_error_values = error_values and result in list(map(str, error_values))
    if res_in_error_values or re.match(r"ERROR -?\d+", result, re.IGNORECASE):
        msg = f"Received value: '{result}' considered as an error"
        raise GeorgeError(msg, error_value=result)

    return result

run_script(script: Path | str) -> None

Execute a George script from a .grg file.

Parameters:

Name Type Description Default
script pathlib.Path | str

the path to the script

required

Raises:

Type Description
ValueError

if the script was not found

Source code in pytvpaint/george/client/__init__.py
153
154
155
156
157
158
159
160
161
162
163
164
165
def run_script(script: Path | str) -> None:
    """Execute a George script from a .grg file.

    Args:
        script: the path to the script

    Raises:
        ValueError: if the script was not found
    """
    script = Path(script)
    if not script.exists():
        raise ValueError(f"Script not found at : {script.as_posix()}")
    send_cmd("tv_RunScript", script.as_posix())