Skip to content

Commit a11776c

Browse files
committed
Added more Model Derivative APIs.
1 parent dc6783f commit a11776c

File tree

2 files changed

+185
-3
lines changed

2 files changed

+185
-3
lines changed

src/autodesk_forge_sdk/md.py

Lines changed: 175 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
from .auth import BaseOAuthClient, Scope, TokenProviderInterface, SimpleTokenProvider, OAuthTokenProvider
44

55
BASE_URL = 'https://developer.api.autodesk.com/modelderivative/v2'
6+
READ_SCOPES = [Scope.DataRead, Scope.ViewablesRead]
67
WRITE_SCOPES = [Scope.DataCreate, Scope.DataWrite, Scope.DataRead]
78

89
def urnify(text):
910
"""
10-
Convert input string into base64-encoded string (without padding '=' characters) that can be used as Model Derivative service URN.
11+
Convert input string into base64-encoded string (without padding '=' characters) that can be used
12+
as Model Derivative service URN.
1113
1214
Args:
1315
text (str): Input text.
@@ -104,8 +106,9 @@ def submit_job(self, urn: str, output_formats: list[dict], output_region: str, r
104106
```
105107
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
106108
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
109+
URN = urnify("some-object-id")
107110
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
108-
job = client.submit_job(urn, [{ "type": "svf", views: ["2d", "3d"] }], "US")
111+
job = client.submit_job(URN, [{ "type": "svf", views: ["2d", "3d"] }], "US")
109112
print(job)
110113
```
111114
"""
@@ -131,4 +134,173 @@ def submit_job(self, urn: str, output_formats: list[dict], output_region: str, r
131134
if force:
132135
headers['x-ads-force'] = 'true'
133136
# TODO: what about the EMEA endpoint?
134-
return self._post('/designdata/job', WRITE_SCOPES, json=json, headers=headers).json()
137+
return self._post('/designdata/job', WRITE_SCOPES, json=json, headers=headers).json()
138+
139+
def get_thumbnail(self, urn: str, width: int=None, height: int=None) -> bytes:
140+
"""
141+
Download thumbnail for a source file.
142+
143+
**Documentation**: https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-thumbnail-GET
144+
145+
Args:
146+
urn (str): Base64-encoded ID of the source file.
147+
width (int, optional): Width of thumbnail. Possible values: 100, 200, 400.
148+
149+
If width is omitted, but height is specified, the implicit value for width will match height. If both
150+
width and height are omitted, the server will return a thumbnail closest to a width of 200, if available.
151+
height (int, optional): Height of thumbnail. Possible values: 100, 200, 400.
152+
153+
If height is omitted, but width is specified, the implicit value for height will match width. If both
154+
width and height are omitted, the server will return a thumbnail closest to a width of 200, if available.
155+
156+
Returns:
157+
bytes: buffer containing the thumbnail PNG image.
158+
159+
Examples:
160+
```
161+
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
162+
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
163+
URN = urnify("some-object-id")
164+
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
165+
png = client.get_thumbnail(URN)
166+
with open("thumbnail.png", "wb") as output:
167+
output.write(png)
168+
```
169+
"""
170+
params = {}
171+
if width:
172+
params['width'] = width
173+
if height:
174+
params['height'] = height
175+
# TODO: what about the EMEA endpoint?
176+
resp = self._get('/designdata/{}/thumbnail'.format(urn), READ_SCOPES, params=params)
177+
return resp.content
178+
179+
def get_manifest(self, urn: str) -> dict:
180+
"""
181+
Retrieve the manifest for the source design specified by the urn URI parameter.
182+
The manifest is a list containing information about the derivatives generated while translating a source file.
183+
The manifest contains information such as the URNs of the derivatives, the translation status of each derivative,
184+
and much more.
185+
186+
**Documentation**: https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-manifest-GET
187+
188+
Args:
189+
urn (str): Base64-encoded ID of the source file.
190+
191+
Returns:
192+
dict: Parsed manifest JSON.
193+
194+
Examples:
195+
```
196+
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
197+
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
198+
URN = urnify("some-object-id")
199+
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
200+
manifest = client.get_manifest(URN)
201+
print(manifest)
202+
```
203+
"""
204+
# TODO: what about the EMEA endpoint?
205+
return self._get('/designdata/{}/manifest'.format(urn), READ_SCOPES).json()
206+
207+
def delete_manifest(self, urn: str):
208+
"""
209+
Delete the manifest and all its translated output files (derivatives). However, it does not delete
210+
the design source file.
211+
212+
**Documentation**: https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-manifest-DELETE
213+
214+
Args:
215+
urn (str): Base64-encoded ID of the source file.
216+
217+
Examples:
218+
```
219+
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
220+
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
221+
URN = urnify("some-object-id")
222+
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
223+
client.delete_manifest(URN)
224+
```
225+
"""
226+
# TODO: what about the EMEA endpoint?
227+
self._delete('/designdata/{}/manifest'.format(urn), WRITE_SCOPES)
228+
229+
def get_metadata(self, urn: str) -> dict:
230+
"""
231+
Returns a list of model view (metadata) IDs for a design model. The metadata ID enables end users
232+
to select an object tree and properties for a specific model view.
233+
234+
**Documentation**: https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-metadata-GET
235+
236+
Args:
237+
urn (str): Base64-encoded ID of the source file.
238+
239+
Returns:
240+
dict: Parsed response JSON.
241+
242+
Examples:
243+
```
244+
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
245+
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
246+
URN = urnify("some-object-id")
247+
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
248+
metadata = client.get_metadata(URN)
249+
print(metadata)
250+
```
251+
"""
252+
# TODO: what about the EMEA endpoint?
253+
return self._get('/designdata/{}/metadata'.format(urn), READ_SCOPES).json()
254+
255+
def get_viewable_tree(self, urn: str, guid: str) -> dict:
256+
"""
257+
Return an object tree, i.e., a hierarchical list of objects for a model view.
258+
259+
**Documentation**: https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-metadata-guid-GET
260+
261+
Args:
262+
urn (str): Base64-encoded ID of the source file.
263+
guid (str): ID of one of the viewables extracted from the source file.
264+
265+
Returns:
266+
dict: Parsed response JSON.
267+
268+
Examples:
269+
```
270+
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
271+
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
272+
URN = urnify("some-object-id")
273+
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
274+
tree = client.get_viewable_tree(URN, "some-viewable-guid")
275+
print(tree)
276+
```
277+
"""
278+
# TODO: what about the EMEA endpoint?
279+
return self._get('/designdata/{}/metadata/{}'.format(urn, guid), READ_SCOPES).json()
280+
281+
def get_viewable_properties(self, urn: str, guid: str) -> dict:
282+
"""
283+
Return a list of properties for each object in an object tree. Properties are returned according to object ID
284+
and do not follow a hierarchical structure.
285+
286+
**Documentation**: https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-metadata-guid-properties-GET
287+
288+
Args:
289+
urn (str): Base64-encoded ID of the source file.
290+
guid (str): ID of one of the viewables extracted from the source file.
291+
292+
Returns:
293+
dict: Parsed response JSON.
294+
295+
Examples:
296+
```
297+
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
298+
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]
299+
URN = urnify("some-object-id")
300+
client = ModelDerivativeClient(OAuthTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
301+
props = client.get_viewable_properties(URN, "some-viewable-guid")
302+
print(props)
303+
```
304+
"""
305+
# TODO: what about the EMEA endpoint?
306+
return self._get('/designdata/{}/metadata/{}/properties'.format(urn, guid), READ_SCOPES).json()

tests/test_md.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,15 @@ def test_urnify(self):
1515
urn = urnify('test')
1616
assert urn == 'dGVzdA'
1717

18+
# def test_get_thumbnail(self):
19+
# png = self.client.get_thumbnail('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6cGV0cmJyb3otc2FtcGxlcy9ybWVfYmFzaWNfc2FtcGxlX3Byb2plY3QucnZ0')
20+
# assert png
21+
# with open("thumbnail.png", "wb") as output:
22+
# output.write(png)
23+
24+
# def test_get_manifest(self):
25+
# manifest = self.client.get_manifest('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6cGV0cmJyb3otc2FtcGxlcy9ybWVfYmFzaWNfc2FtcGxlX3Byb2plY3QucnZ0')
26+
# assert manifest
27+
1828
if __name__ == "__main__":
1929
unittest.main()

0 commit comments

Comments
 (0)