Skip to content

Commit ac49105

Browse files
committed
Initial logic for Model Derivative client.
1 parent 888ba92 commit ac49105

File tree

4 files changed

+87
-2
lines changed

4 files changed

+87
-2
lines changed

src/autodesk_forge_sdk/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from .auth import AuthenticationClient, PassiveTokenProvider, ActiveTokenProvider
2-
from .oss import OSSClient
2+
from .oss import OSSClient
3+
from .md import ModelDerivativeClient, urnify

src/autodesk_forge_sdk/md.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import base64
2+
from urllib.parse import quote
3+
from .auth import BaseOAuthClient
4+
5+
BASE_URL = 'https://developer.api.autodesk.com/modelderivative/v2'
6+
WRITE_SCOPES = ['data:create', 'data:write', 'data:read']
7+
8+
def urnify(str):
9+
"""Converts input string into base64-encoded string (without padding '=' characters)
10+
that can be used as Model Derivative service URN.
11+
"""
12+
base64_bytes = base64.b64encode(str.encode('ascii'))
13+
ascii_output = base64_bytes.decode('ascii')
14+
return ascii_output.rstrip('=')
15+
16+
class ModelDerivativeClient(BaseOAuthClient):
17+
def __init__(self, token_provider, base_url=BASE_URL):
18+
BaseOAuthClient.__init__(self, token_provider, base_url)
19+
20+
def get_formats(self):
21+
"""Returns an up-to-date list of Forge-supported translations, that you can use to identify
22+
which types of derivatives are supported for each source file type.
23+
24+
Returns:
25+
object: Parsed response object. For more information, see https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/formats-GET/#body-structure-200.
26+
"""
27+
return self._get('/designdata/formats', []).json()
28+
29+
def submit_job(self, urn, output_formats, output_region, root_filename=None, workflow_id=None, workflow_attr=None, force=False):
30+
"""Translate a design from one format to another format.
31+
32+
Parameters:
33+
urn (string): Base64-encoded ID of the object to translate.
34+
output_formats (list): List of objects representing all the requested outputs. Each object should have at least 'type' property set to 'svf', 'svf2', etc.
35+
output_region (string): Output region. Allowed values: 'US', 'EMEA'.
36+
root_filename (string): Optional starting filename if the converted file is a ZIP archive.
37+
workflow_id (string): Optional workflow ID.
38+
workflow_attr (object): Optional workflow payload.
39+
40+
Returns:
41+
object: Parsed response object. For more information, see https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/job-POST/#body-structure-200-201.
42+
"""
43+
json = {
44+
'input': {
45+
'urn': urn
46+
},
47+
'output': {
48+
'formats': output_formats,
49+
'destination': {
50+
'region': output_region
51+
}
52+
}
53+
}
54+
if root_filename:
55+
json['input']['compressedUrn'] = True
56+
json['input']['rootFilename'] = root_filename
57+
if workflow_id:
58+
json['misc'] = { 'workflowId': workflow_id }
59+
if workflow_attr:
60+
json['misc']['workflowAttribute'] = workflow_attr
61+
headers = {}
62+
if force:
63+
headers['x-ads-force'] = 'true'
64+
# TODO: what about the EMEA endpoint?
65+
return self._post('/designdata/job', WRITE_SCOPES, json=json, headers=headers).json()

tests/context.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33

44
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src')))
5-
from autodesk_forge_sdk import AuthenticationClient, OSSClient, ActiveTokenProvider, PassiveTokenProvider
5+
from autodesk_forge_sdk import AuthenticationClient, OSSClient, ModelDerivativeClient, urnify, ActiveTokenProvider, PassiveTokenProvider
66

77
FORGE_CLIENT_ID = os.environ["FORGE_CLIENT_ID"]
88
FORGE_CLIENT_SECRET = os.environ["FORGE_CLIENT_SECRET"]

tests/test_md.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import unittest
2+
from .context import ModelDerivativeClient, urnify, ActiveTokenProvider, FORGE_CLIENT_ID, FORGE_CLIENT_SECRET, FORGE_BUCKET
3+
4+
class ModelDerivativeClientTestSuite(unittest.TestCase):
5+
"""Forge Model Derivative client test cases."""
6+
7+
def setUp(self):
8+
self.client = ModelDerivativeClient(ActiveTokenProvider(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET))
9+
10+
def test_get_formats(self):
11+
formats = self.client.get_formats()
12+
assert formats
13+
14+
def test_urnify(self):
15+
urn = urnify('test')
16+
assert urn == 'dGVzdA'
17+
18+
if __name__ == "__main__":
19+
unittest.main()

0 commit comments

Comments
 (0)