Skip to content

Commit de94fea

Browse files
committed
add template recordings to python sdk
1 parent c489014 commit de94fea

15 files changed

Lines changed: 653 additions & 49 deletions

‎fishjam/_fishjam_openapi_client/api/recordings/create_recording.py‎

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55

66
from ... import errors
77
from ...client import AuthenticatedClient, Client
8+
from ...models.create_recording_files_body import CreateRecordingFilesBody
89
from ...models.error import Error
910
from ...models.recording_config import RecordingConfig
1011
from ...models.recording_details_response import RecordingDetailsResponse
11-
from ...types import Response
12+
from ...types import UNSET, Response, Unset
1213

1314

1415
def _get_kwargs(
1516
*,
16-
body: RecordingConfig,
17+
body: RecordingConfig | CreateRecordingFilesBody | Unset = UNSET,
1718
) -> dict[str, Any]:
1819
headers: dict[str, Any] = {}
1920

@@ -22,9 +23,12 @@ def _get_kwargs(
2223
"url": "/recordings",
2324
}
2425

25-
_kwargs["json"] = body.to_dict()
26+
if isinstance(body, RecordingConfig):
27+
_kwargs["json"] = body.to_dict()
2628

27-
headers["Content-Type"] = "application/json"
29+
headers["Content-Type"] = "application/json"
30+
if isinstance(body, CreateRecordingFilesBody):
31+
_kwargs["files"] = body.to_multipart()
2832

2933
_kwargs["headers"] = headers
3034
return _kwargs
@@ -78,14 +82,18 @@ def _build_response(
7882
def sync_detailed(
7983
*,
8084
client: AuthenticatedClient,
81-
body: RecordingConfig,
85+
body: RecordingConfig | CreateRecordingFilesBody | Unset = UNSET,
8286
) -> Response[Error | RecordingDetailsResponse]:
8387
"""Create a recording
8488
8589
Create a recording resource. Capturing starts synchronously, so it is returned with status `active`.
90+
A source naming an `outputId` records an output the composition already has and is sent as JSON. A
91+
template source renders its own scene and has to be sent as `multipart/form-data`: the configuration
92+
in a `config` part, the React bundle in a `template` part.
8693
8794
Args:
8895
body (RecordingConfig): Recording configuration
96+
body (CreateRecordingFilesBody):
8997
9098
Raises:
9199
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
@@ -109,14 +117,18 @@ def sync_detailed(
109117
def sync(
110118
*,
111119
client: AuthenticatedClient,
112-
body: RecordingConfig,
120+
body: RecordingConfig | CreateRecordingFilesBody | Unset = UNSET,
113121
) -> Error | RecordingDetailsResponse | None:
114122
"""Create a recording
115123
116124
Create a recording resource. Capturing starts synchronously, so it is returned with status `active`.
125+
A source naming an `outputId` records an output the composition already has and is sent as JSON. A
126+
template source renders its own scene and has to be sent as `multipart/form-data`: the configuration
127+
in a `config` part, the React bundle in a `template` part.
117128
118129
Args:
119130
body (RecordingConfig): Recording configuration
131+
body (CreateRecordingFilesBody):
120132
121133
Raises:
122134
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
@@ -135,14 +147,18 @@ def sync(
135147
async def asyncio_detailed(
136148
*,
137149
client: AuthenticatedClient,
138-
body: RecordingConfig,
150+
body: RecordingConfig | CreateRecordingFilesBody | Unset = UNSET,
139151
) -> Response[Error | RecordingDetailsResponse]:
140152
"""Create a recording
141153
142154
Create a recording resource. Capturing starts synchronously, so it is returned with status `active`.
155+
A source naming an `outputId` records an output the composition already has and is sent as JSON. A
156+
template source renders its own scene and has to be sent as `multipart/form-data`: the configuration
157+
in a `config` part, the React bundle in a `template` part.
143158
144159
Args:
145160
body (RecordingConfig): Recording configuration
161+
body (CreateRecordingFilesBody):
146162
147163
Raises:
148164
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
@@ -164,14 +180,18 @@ async def asyncio_detailed(
164180
async def asyncio(
165181
*,
166182
client: AuthenticatedClient,
167-
body: RecordingConfig,
183+
body: RecordingConfig | CreateRecordingFilesBody | Unset = UNSET,
168184
) -> Error | RecordingDetailsResponse | None:
169185
"""Create a recording
170186
171187
Create a recording resource. Capturing starts synchronously, so it is returned with status `active`.
188+
A source naming an `outputId` records an output the composition already has and is sent as JSON. A
189+
template source renders its own scene and has to be sent as `multipart/form-data`: the configuration
190+
in a `config` part, the React bundle in a `template` part.
172191
173192
Args:
174193
body (RecordingConfig): Recording configuration
194+
body (CreateRecordingFilesBody):
175195
176196
Raises:
177197
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.

‎fishjam/_fishjam_openapi_client/models/__init__.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .audio_sample_rate import AudioSampleRate
66
from .composition_info import CompositionInfo
77
from .composition_source import CompositionSource
8+
from .create_recording_files_body import CreateRecordingFilesBody
89
from .error import Error
910
from .list_recordings_metadata import ListRecordingsMetadata
1011
from .moq_access import MoqAccess
@@ -52,6 +53,8 @@
5253
from .subscribe_mode import SubscribeMode
5354
from .subscribe_tracks_body import SubscribeTracksBody
5455
from .subscriptions import Subscriptions
56+
from .template_source import TemplateSource
57+
from .template_source_resolution import TemplateSourceResolution
5558
from .track import Track
5659
from .track_forwarding import TrackForwarding
5760
from .track_forwarding_info import TrackForwardingInfo
@@ -69,6 +72,7 @@
6972
"AudioSampleRate",
7073
"CompositionInfo",
7174
"CompositionSource",
75+
"CreateRecordingFilesBody",
7276
"Error",
7377
"ListRecordingsMetadata",
7478
"MoqAccess",
@@ -116,6 +120,8 @@
116120
"SubscribeMode",
117121
"SubscribeTracksBody",
118122
"Subscriptions",
123+
"TemplateSource",
124+
"TemplateSourceResolution",
119125
"Track",
120126
"TrackForwarding",
121127
"TrackForwardingInfo",

‎fishjam/_fishjam_openapi_client/models/composition_source.py‎

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from typing import Any, TypeVar
55

66
from attrs import define as _attrs_define
7-
from attrs import field as _attrs_field
87

98
from ..types import UNSET, Unset
109

@@ -25,7 +24,6 @@ class CompositionSource:
2524
composition_url: str
2625
output_id: str
2726
scale_ratio: float | Unset = 1.0
28-
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
2927

3028
def to_dict(self) -> dict[str, Any]:
3129
composition_url = self.composition_url
@@ -35,7 +33,7 @@ def to_dict(self) -> dict[str, Any]:
3533
scale_ratio = self.scale_ratio
3634

3735
field_dict: dict[str, Any] = {}
38-
field_dict.update(self.additional_properties)
36+
3937
field_dict.update({
4038
"compositionURL": composition_url,
4139
"outputId": output_id,
@@ -60,21 +58,4 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
6058
scale_ratio=scale_ratio,
6159
)
6260

63-
composition_source.additional_properties = d
6461
return composition_source
65-
66-
@property
67-
def additional_keys(self) -> list[str]:
68-
return list(self.additional_properties.keys())
69-
70-
def __getitem__(self, key: str) -> Any:
71-
return self.additional_properties[key]
72-
73-
def __setitem__(self, key: str, value: Any) -> None:
74-
self.additional_properties[key] = value
75-
76-
def __delitem__(self, key: str) -> None:
77-
del self.additional_properties[key]
78-
79-
def __contains__(self, key: str) -> bool:
80-
return key in self.additional_properties
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from __future__ import annotations
2+
3+
import json
4+
from collections.abc import Mapping
5+
from io import BytesIO
6+
from typing import TYPE_CHECKING, Any, TypeVar
7+
8+
from attrs import define as _attrs_define
9+
from attrs import field as _attrs_field
10+
11+
from .. import types
12+
from ..types import File
13+
14+
if TYPE_CHECKING:
15+
from ..models.recording_config import RecordingConfig
16+
17+
18+
T = TypeVar("T", bound="CreateRecordingFilesBody")
19+
20+
21+
@_attrs_define
22+
class CreateRecordingFilesBody:
23+
"""
24+
Attributes:
25+
config (RecordingConfig): Recording configuration
26+
template (File): The React template bundle to render, at most 1 MiB
27+
"""
28+
29+
config: RecordingConfig
30+
template: File
31+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
32+
33+
def to_dict(self) -> dict[str, Any]:
34+
config = self.config.to_dict()
35+
36+
template = self.template.to_tuple()
37+
38+
field_dict: dict[str, Any] = {}
39+
field_dict.update(self.additional_properties)
40+
field_dict.update({
41+
"config": config,
42+
"template": template,
43+
})
44+
45+
return field_dict
46+
47+
def to_multipart(self) -> types.RequestFiles:
48+
files: types.RequestFiles = []
49+
50+
files.append((
51+
"config",
52+
(None, json.dumps(self.config.to_dict()).encode(), "application/json"),
53+
))
54+
55+
files.append(("template", self.template.to_tuple()))
56+
57+
for prop_name, prop in self.additional_properties.items():
58+
files.append((prop_name, (None, str(prop).encode(), "text/plain")))
59+
60+
return files
61+
62+
@classmethod
63+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
64+
from ..models.recording_config import RecordingConfig
65+
66+
d = dict(src_dict)
67+
config = RecordingConfig.from_dict(d.pop("config"))
68+
69+
template = File(payload=BytesIO(d.pop("template")))
70+
71+
create_recording_files_body = cls(
72+
config=config,
73+
template=template,
74+
)
75+
76+
create_recording_files_body.additional_properties = d
77+
return create_recording_files_body
78+
79+
@property
80+
def additional_keys(self) -> list[str]:
81+
return list(self.additional_properties.keys())
82+
83+
def __getitem__(self, key: str) -> Any:
84+
return self.additional_properties[key]
85+
86+
def __setitem__(self, key: str, value: Any) -> None:
87+
self.additional_properties[key] = value
88+
89+
def __delitem__(self, key: str) -> None:
90+
del self.additional_properties[key]
91+
92+
def __contains__(self, key: str) -> bool:
93+
return key in self.additional_properties

‎fishjam/_fishjam_openapi_client/models/recording.py‎

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from ..models.composition_source import CompositionSource
1414
from ..models.recording_file import RecordingFile
1515
from ..models.recording_metadata_type_0 import RecordingMetadataType0
16+
from ..models.template_source import TemplateSource
1617

1718

1819
T = TypeVar("T", bound="Recording")
@@ -26,20 +27,21 @@ class Recording:
2627
files (list[RecordingFile]): Media files of the recording, in playback order. Empty until the recording is
2728
`available`.
2829
id (str): Assigned recording id
29-
source (CompositionSource): Recording source coming from composition
30+
source (CompositionSource | TemplateSource): The source for the recording
3031
status (RecordingStatus): Lifecycle status of a recording
3132
metadata (None | RecordingMetadataType0 | Unset): Free-form, user-supplied metadata used to organize and filter
3233
recordings
3334
"""
3435

3536
files: list[RecordingFile]
3637
id: str
37-
source: CompositionSource
38+
source: CompositionSource | TemplateSource
3839
status: RecordingStatus
3940
metadata: None | RecordingMetadataType0 | Unset = UNSET
4041
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
4142

4243
def to_dict(self) -> dict[str, Any]:
44+
from ..models.composition_source import CompositionSource
4345
from ..models.recording_metadata_type_0 import RecordingMetadataType0
4446

4547
files = []
@@ -49,7 +51,11 @@ def to_dict(self) -> dict[str, Any]:
4951

5052
id = self.id
5153

52-
source = self.source.to_dict()
54+
source: dict[str, Any]
55+
if isinstance(self.source, CompositionSource):
56+
source = self.source.to_dict()
57+
else:
58+
source = self.source.to_dict()
5359

5460
status = self.status.value
5561

@@ -79,6 +85,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
7985
from ..models.composition_source import CompositionSource
8086
from ..models.recording_file import RecordingFile
8187
from ..models.recording_metadata_type_0 import RecordingMetadataType0
88+
from ..models.template_source import TemplateSource
8289

8390
d = dict(src_dict)
8491
files = []
@@ -90,7 +97,24 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
9097

9198
id = d.pop("id")
9299

93-
source = CompositionSource.from_dict(d.pop("source"))
100+
def _parse_source(data: object) -> CompositionSource | TemplateSource:
101+
try:
102+
if not isinstance(data, dict):
103+
raise TypeError()
104+
componentsschemas_recording_source_type_0 = CompositionSource.from_dict(
105+
data
106+
)
107+
108+
return componentsschemas_recording_source_type_0
109+
except (TypeError, ValueError, AttributeError, KeyError):
110+
pass
111+
if not isinstance(data, dict):
112+
raise TypeError()
113+
componentsschemas_recording_source_type_1 = TemplateSource.from_dict(data)
114+
115+
return componentsschemas_recording_source_type_1
116+
117+
source = _parse_source(d.pop("source"))
94118

95119
status = RecordingStatus(d.pop("status"))
96120

0 commit comments

Comments
 (0)