renderplan 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- renderplan/__init__.py +77 -0
- renderplan/__main__.py +3 -0
- renderplan/_toml.py +82 -0
- renderplan/_version.py +24 -0
- renderplan/cli.py +71 -0
- renderplan/codec.py +688 -0
- renderplan/errors.py +10 -0
- renderplan/identity.py +80 -0
- renderplan/model.py +937 -0
- renderplan/py.typed +0 -0
- renderplan/version.py +13 -0
- renderplan-0.1.0.dist-info/METADATA +160 -0
- renderplan-0.1.0.dist-info/RECORD +17 -0
- renderplan-0.1.0.dist-info/WHEEL +5 -0
- renderplan-0.1.0.dist-info/entry_points.txt +2 -0
- renderplan-0.1.0.dist-info/licenses/LICENSE +201 -0
- renderplan-0.1.0.dist-info/top_level.txt +1 -0
renderplan/__init__.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from .codec import (
|
|
2
|
+
load_any,
|
|
3
|
+
load_manifest,
|
|
4
|
+
load_plan,
|
|
5
|
+
load_preflight,
|
|
6
|
+
load_profile,
|
|
7
|
+
save_manifest,
|
|
8
|
+
save_plan,
|
|
9
|
+
save_preflight,
|
|
10
|
+
save_profile,
|
|
11
|
+
)
|
|
12
|
+
from .errors import CodecError, RenderPlanError, ValidationError
|
|
13
|
+
from .model import (
|
|
14
|
+
MANIFEST_FORMAT,
|
|
15
|
+
PLAN_FORMAT,
|
|
16
|
+
PREFLIGHT_FORMAT,
|
|
17
|
+
PROFILE_FORMAT,
|
|
18
|
+
AudioItem,
|
|
19
|
+
CapacityConstraint,
|
|
20
|
+
PauseItem,
|
|
21
|
+
PausePolicy,
|
|
22
|
+
PlanningPolicy,
|
|
23
|
+
PreflightCheck,
|
|
24
|
+
PreflightReport,
|
|
25
|
+
Producer,
|
|
26
|
+
RenderManifest,
|
|
27
|
+
RenderPlan,
|
|
28
|
+
RenderProfile,
|
|
29
|
+
ReplanRequest,
|
|
30
|
+
RoleProfile,
|
|
31
|
+
RoleRequirements,
|
|
32
|
+
SourceSpan,
|
|
33
|
+
SpeechArtifact,
|
|
34
|
+
SpeechControl,
|
|
35
|
+
SpeechItem,
|
|
36
|
+
TokenBundle,
|
|
37
|
+
)
|
|
38
|
+
from .version import __version__
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"MANIFEST_FORMAT",
|
|
42
|
+
"PLAN_FORMAT",
|
|
43
|
+
"PREFLIGHT_FORMAT",
|
|
44
|
+
"PROFILE_FORMAT",
|
|
45
|
+
"AudioItem",
|
|
46
|
+
"CapacityConstraint",
|
|
47
|
+
"CodecError",
|
|
48
|
+
"PauseItem",
|
|
49
|
+
"PausePolicy",
|
|
50
|
+
"PlanningPolicy",
|
|
51
|
+
"PreflightCheck",
|
|
52
|
+
"PreflightReport",
|
|
53
|
+
"Producer",
|
|
54
|
+
"RenderManifest",
|
|
55
|
+
"RenderPlan",
|
|
56
|
+
"RenderPlanError",
|
|
57
|
+
"RenderProfile",
|
|
58
|
+
"ReplanRequest",
|
|
59
|
+
"RoleProfile",
|
|
60
|
+
"RoleRequirements",
|
|
61
|
+
"SourceSpan",
|
|
62
|
+
"SpeechArtifact",
|
|
63
|
+
"SpeechControl",
|
|
64
|
+
"SpeechItem",
|
|
65
|
+
"TokenBundle",
|
|
66
|
+
"ValidationError",
|
|
67
|
+
"__version__",
|
|
68
|
+
"load_any",
|
|
69
|
+
"load_manifest",
|
|
70
|
+
"load_plan",
|
|
71
|
+
"load_preflight",
|
|
72
|
+
"load_profile",
|
|
73
|
+
"save_manifest",
|
|
74
|
+
"save_plan",
|
|
75
|
+
"save_preflight",
|
|
76
|
+
"save_profile",
|
|
77
|
+
]
|
renderplan/__main__.py
ADDED
renderplan/_toml.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
from collections.abc import Mapping, Sequence
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
_BARE_KEY = re.compile(r"^[A-Za-z0-9_-]+$")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _key(value: str) -> str:
|
|
12
|
+
return value if _BARE_KEY.fullmatch(value) else json.dumps(value, ensure_ascii=False)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _path(parts: tuple[str, ...]) -> str:
|
|
16
|
+
return ".".join(_key(part) for part in parts)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _value(value: Any) -> str:
|
|
20
|
+
if isinstance(value, bool):
|
|
21
|
+
return "true" if value else "false"
|
|
22
|
+
if isinstance(value, str):
|
|
23
|
+
return json.dumps(value, ensure_ascii=False)
|
|
24
|
+
if isinstance(value, int):
|
|
25
|
+
return str(value)
|
|
26
|
+
if isinstance(value, float):
|
|
27
|
+
return repr(value)
|
|
28
|
+
if isinstance(value, Sequence) and not isinstance(value, (str, bytes, bytearray)):
|
|
29
|
+
return "[" + ", ".join(_value(item) for item in value) + "]"
|
|
30
|
+
raise TypeError(f"unsupported TOML scalar {type(value).__name__}")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _is_aot(value: Any) -> bool:
|
|
34
|
+
return (
|
|
35
|
+
isinstance(value, list)
|
|
36
|
+
and bool(value)
|
|
37
|
+
and all(isinstance(item, Mapping) for item in value)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _emit_mapping(
|
|
42
|
+
lines: list[str], mapping: Mapping[str, Any], prefix: tuple[str, ...], *, header: bool
|
|
43
|
+
) -> None:
|
|
44
|
+
scalars: list[tuple[str, Any]] = []
|
|
45
|
+
tables: list[tuple[str, Mapping[str, Any]]] = []
|
|
46
|
+
arrays: list[tuple[str, list[Mapping[str, Any]]]] = []
|
|
47
|
+
|
|
48
|
+
for raw_key, value in sorted(mapping.items(), key=lambda entry: str(entry[0])):
|
|
49
|
+
key = str(raw_key)
|
|
50
|
+
if isinstance(value, Mapping):
|
|
51
|
+
tables.append((key, value))
|
|
52
|
+
elif _is_aot(value):
|
|
53
|
+
arrays.append((key, value))
|
|
54
|
+
else:
|
|
55
|
+
scalars.append((key, value))
|
|
56
|
+
|
|
57
|
+
if header:
|
|
58
|
+
if lines and lines[-1] != "":
|
|
59
|
+
lines.append("")
|
|
60
|
+
lines.append(f"[{_path(prefix)}]")
|
|
61
|
+
|
|
62
|
+
for key, value in scalars:
|
|
63
|
+
lines.append(f"{_key(key)} = {_value(value)}")
|
|
64
|
+
|
|
65
|
+
for key, table in tables:
|
|
66
|
+
_emit_mapping(lines, table, prefix + (key,), header=True)
|
|
67
|
+
|
|
68
|
+
for key, entries in arrays:
|
|
69
|
+
path = prefix + (key,)
|
|
70
|
+
for entry in entries:
|
|
71
|
+
if lines and lines[-1] != "":
|
|
72
|
+
lines.append("")
|
|
73
|
+
lines.append(f"[[{_path(path)}]]")
|
|
74
|
+
_emit_mapping(lines, entry, path, header=False)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def dumps(mapping: Mapping[str, Any]) -> str:
|
|
78
|
+
lines: list[str] = []
|
|
79
|
+
_emit_mapping(lines, mapping, (), header=False)
|
|
80
|
+
while lines and lines[-1] == "":
|
|
81
|
+
lines.pop()
|
|
82
|
+
return "\n".join(lines) + "\n"
|
renderplan/_version.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.1.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = 'g7cf517359'
|
renderplan/cli.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .codec import load_any
|
|
7
|
+
from .model import (
|
|
8
|
+
AudioItem,
|
|
9
|
+
PauseItem,
|
|
10
|
+
PreflightReport,
|
|
11
|
+
RenderManifest,
|
|
12
|
+
RenderPlan,
|
|
13
|
+
RenderProfile,
|
|
14
|
+
)
|
|
15
|
+
from .version import __version__
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _summary(value: object) -> str:
|
|
19
|
+
if isinstance(value, RenderProfile):
|
|
20
|
+
fallbacks = ",".join(value.planning.capacity_fallback)
|
|
21
|
+
return (
|
|
22
|
+
f"renderprofile {value.profile_id or value.computed_id()} roles={len(value.roles)} "
|
|
23
|
+
f"split={value.planning.split} fallbacks={fallbacks}"
|
|
24
|
+
)
|
|
25
|
+
if isinstance(value, RenderPlan):
|
|
26
|
+
pauses = sum(isinstance(item, PauseItem) for item in value.flow)
|
|
27
|
+
audio = sum(isinstance(item, AudioItem) for item in value.flow)
|
|
28
|
+
return "\n".join(
|
|
29
|
+
(
|
|
30
|
+
f"renderplan {value.plan_id or value.computed_id()}",
|
|
31
|
+
f" source_plan: {value.source_plan_id}",
|
|
32
|
+
f" profile: {value.render_profile_id}",
|
|
33
|
+
f" speech: {len(value.speech)}",
|
|
34
|
+
f" pauses: {pauses}",
|
|
35
|
+
f" audio: {audio}",
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
if isinstance(value, PreflightReport):
|
|
39
|
+
too_long = sum(check.status == "too_long" for check in value.checks)
|
|
40
|
+
return "\n".join(
|
|
41
|
+
(
|
|
42
|
+
f"renderplan-preflight {value.report_id or value.computed_id()}",
|
|
43
|
+
f" plan: {value.render_plan_id}",
|
|
44
|
+
f" status: {value.status}",
|
|
45
|
+
f" checked: {len(value.checks)}",
|
|
46
|
+
f" too_long: {too_long}",
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
if isinstance(value, RenderManifest):
|
|
50
|
+
return "\n".join(
|
|
51
|
+
(
|
|
52
|
+
f"render-manifest {value.manifest_id or value.computed_id()}",
|
|
53
|
+
f" plan: {value.render_plan_id}",
|
|
54
|
+
f" complete: {str(value.complete).lower()}",
|
|
55
|
+
f" speech: {len(value.speech)}",
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
raise AssertionError(type(value))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def main(argv: list[str] | None = None) -> int:
|
|
62
|
+
parser = argparse.ArgumentParser(prog="renderplan")
|
|
63
|
+
parser.add_argument("--version", action="version", version=__version__)
|
|
64
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
65
|
+
for name in ("validate", "inspect"):
|
|
66
|
+
command = sub.add_parser(name)
|
|
67
|
+
command.add_argument("file", type=Path)
|
|
68
|
+
args = parser.parse_args(argv)
|
|
69
|
+
value = load_any(args.file)
|
|
70
|
+
print(_summary(value))
|
|
71
|
+
return 0
|