23
23
import google .auth .transport .requests
24
24
25
25
26
+ ASSISTANT_API_VERSION = 'v1alpha2'
27
+
28
+
26
29
def failed_request_exception (message , r ):
27
30
"""Build ClickException from a failed request."""
28
31
try :
@@ -37,8 +40,46 @@ def failed_request_exception(message, r):
37
40
r .text ))
38
41
39
42
40
- # Prints out a device model in the terminal by parsing dict
43
+ def resolve_project_id (client_secrets , credentials ):
44
+ """Resolve project ID from client secrets."""
45
+ if client_secrets is None :
46
+ client_secrets = 'client_secret_%s.json' % credentials .client_id
47
+ try :
48
+ with open (client_secrets , 'r' ) as f :
49
+ secret = json .load (f )
50
+ return secret ['installed' ]['project_id' ]
51
+ except Exception as e :
52
+ raise click .ClickException ('Error loading client secret: %s.\n '
53
+ 'Run the device tool '
54
+ 'with --client-secrets '
55
+ 'or --project option.\n '
56
+ 'Or copy the %s file '
57
+ 'in the current directory.'
58
+ % (e , client_secrets ))
59
+
60
+
61
+ def build_api_url (api_endpoint , api_version , project_id ):
62
+ return 'https://%s/%s/projects/%s' % (api_endpoint ,
63
+ api_version ,
64
+ project_id )
65
+
66
+
67
+ def build_client_from_context (ctx ):
68
+ project_id = (ctx .obj ['PROJECT' ]
69
+ or resolve_project_id (ctx .obj ['CLIENT_SECRETS' ],
70
+ ctx .obj ['CREDENTIALS' ]))
71
+ api_url = build_api_url (ctx .obj ['API_ENDPOINT' ],
72
+ ctx .obj ['API_VERSION' ],
73
+ project_id )
74
+ session = (ctx .obj ['SESSION' ] or
75
+ google .auth .transport .requests .AuthorizedSession (
76
+ ctx .obj ['CREDENTIALS' ]
77
+ ))
78
+ return session , api_url , project_id
79
+
80
+
41
81
def pretty_print_model (devicemodel ):
82
+ """Prints out a device model in the terminal by parsing dict."""
42
83
PRETTY_PRINT_MODEL = """Device Model Id: %(deviceModelId)s
43
84
Project Id: %(projectId)s
44
85
Device Type: %(deviceType)s"""
@@ -51,8 +92,8 @@ def pretty_print_model(devicemodel):
51
92
logging .info ('' ) # Newline
52
93
53
94
54
- # Prints out a device instance in the terminal by parsing dict
55
95
def pretty_print_device (device ):
96
+ """Prints out a device instance in the terminal by parsing dict."""
56
97
logging .info ('Device Instance Id: %s' % device ['id' ])
57
98
if 'nickname' in device :
58
99
logging .info (' Nickname: %s' % device ['nickname' ])
@@ -67,8 +108,8 @@ def pretty_print_device(device):
67
108
'use with the registration tool. If you don\' t use this flag, '
68
109
'the tool will use the project listed in the '
69
110
'<client_secret_client-id.json> file you specify with the '
70
- '--client-secret flag.' )
71
- @click .option ('--client-secret ' ,
111
+ '--client-secrets flag.' )
112
+ @click .option ('--client-secrets ' ,
72
113
help = 'Enter the path and filename for the '
73
114
'<client_secret_client-id.json> file you downloaded from your '
74
115
'developer project. This file is used to infer the Google '
@@ -93,7 +134,7 @@ def pretty_print_device(device):
93
134
'API. You can use this flag if the credentials were generated '
94
135
'in a location that is different than the default.' )
95
136
@click .pass_context
96
- def cli (ctx , project , client_secret , verbose , api_endpoint , credentials ):
137
+ def cli (ctx , project , client_secrets , verbose , api_endpoint , credentials ):
97
138
try :
98
139
with open (credentials , 'r' ) as f :
99
140
c = google .oauth2 .credentials .Credentials (token = None ,
@@ -104,25 +145,12 @@ def cli(ctx, project, client_secret, verbose, api_endpoint, credentials):
104
145
raise click .ClickException ('Error loading credentials: %s.\n '
105
146
'Run google-oauthlib-tool to initialize '
106
147
'new OAuth 2.0 credentials.' % e )
107
- if project is None :
108
- if client_secret is None :
109
- client_secret = 'client_secret_%s.json' % c .client_id
110
- try :
111
- with open (client_secret , 'r' ) as f :
112
- secret = json .load (f )
113
- project = secret ['installed' ]['project_id' ]
114
- except Exception as e :
115
- raise click .ClickException ('Error loading client secret: %s.\n '
116
- 'Run the register tool '
117
- 'with --client-secret '
118
- 'or --project option.\n '
119
- 'Or copy the %s file '
120
- 'in the current directory.'
121
- % (e , client_secret ))
122
- ctx .obj ['SESSION' ] = google .auth .transport .requests .AuthorizedSession (c )
123
- ctx .obj ['API_URL' ] = ('https://%s/v1alpha2/projects/%s'
124
- % (api_endpoint , project ))
125
- ctx .obj ['PROJECT_ID' ] = project
148
+ ctx .obj ['API_ENDPOINT' ] = api_endpoint
149
+ ctx .obj ['API_VERSION' ] = ASSISTANT_API_VERSION
150
+ ctx .obj ['SESSION' ] = None
151
+ ctx .obj ['PROJECT' ] = project
152
+ ctx .obj ['CREDENTIALS' ] = c
153
+ ctx .obj ['CLIENT_SECRETS' ] = client_secrets
126
154
logging .basicConfig (format = '' ,
127
155
level = logging .DEBUG if verbose else logging .INFO )
128
156
@@ -174,6 +202,13 @@ def register(ctx, model, type, trait, manufacturer, product_name, description,
174
202
following symbols: period (.), hyphen (-), underscore (_), space ( ) and
175
203
plus (+). The first character of a field must be a letter or number.
176
204
"""
205
+ # cache SESSION and PROJECT so that we don't re-create them between request
206
+ ctx .obj ['SESSION' ] = google .auth .transport .requests .AuthorizedSession (
207
+ ctx .obj ['CREDENTIALS' ]
208
+ )
209
+ ctx .obj ['PROJECT' ] = (ctx .obj ['PROJECT' ]
210
+ or resolve_project_id (ctx .obj ['CLIENT_SECRETS' ],
211
+ ctx .obj ['CREDENTIALS' ]))
177
212
ctx .invoke (register_model ,
178
213
model = model , type = type , trait = trait ,
179
214
manufacturer = manufacturer ,
@@ -218,13 +253,12 @@ def register_model(ctx, model, type, trait,
218
253
following symbols: period (.), hyphen (-), underscore (_), space ( ) and
219
254
plus (+). The first character of a field must be a letter or number.
220
255
"""
221
- session = ctx .obj ['SESSION' ]
222
-
223
- model_base_url = '/' .join ([ctx .obj ['API_URL' ], 'deviceModels' ])
256
+ session , api_url , project_id = build_client_from_context (ctx )
257
+ model_base_url = '/' .join ([api_url , 'deviceModels' ])
224
258
model_url = '/' .join ([model_base_url , model ])
225
259
payload = {
226
260
'device_model_id' : model ,
227
- 'project_id' : ctx . obj [ 'PROJECT_ID' ] ,
261
+ 'project_id' : project_id ,
228
262
'device_type' : 'action.devices.types.' + type ,
229
263
}
230
264
if trait :
@@ -278,9 +312,8 @@ def register_device(ctx, device, model, nickname, client_type):
278
312
following symbols: period (.), hyphen (-), underscore (_), space ( ) and
279
313
plus (+). The first character of a field must be a letter or number.
280
314
"""
281
- session = ctx .obj ['SESSION' ]
282
-
283
- device_base_url = '/' .join ([ctx .obj ['API_URL' ], 'devices' ])
315
+ session , api_url , project_id = build_client_from_context (ctx )
316
+ device_base_url = '/' .join ([api_url , 'devices' ])
284
317
device_url = '/' .join ([device_base_url , device ])
285
318
payload = {
286
319
'id' : device ,
@@ -319,9 +352,8 @@ def get(ctx, resource, id):
319
352
"""Gets all of the information (fields) for a given device model or
320
353
instance.
321
354
"""
322
- session = ctx .obj ['SESSION' ]
323
-
324
- url = '/' .join ([ctx .obj ['API_URL' ], resource , id ])
355
+ session , api_url , project_id = build_client_from_context (ctx )
356
+ url = '/' .join ([api_url , resource , id ])
325
357
r = session .get (url )
326
358
if r .status_code != 200 :
327
359
raise failed_request_exception ('Failed to get resource' , r )
@@ -344,8 +376,8 @@ def get(ctx, resource, id):
344
376
def delete (ctx , resource , id ):
345
377
"""Delete given device model or instance.
346
378
"""
347
- session = ctx . obj [ 'SESSION' ]
348
- url = '/' .join ([ctx . obj [ 'API_URL' ] , resource , id ])
379
+ session , api_url , project_id = build_client_from_context ( ctx )
380
+ url = '/' .join ([api_url , resource , id ])
349
381
r = session .delete (url )
350
382
if r .status_code != 200 :
351
383
raise failed_request_exception ('failed to delete resource' , r )
@@ -361,9 +393,8 @@ def list(ctx, resource):
361
393
current Google Developer project. To change the current project, use the
362
394
devicetool's --project flag.
363
395
"""
364
- session = ctx .obj ['SESSION' ]
365
-
366
- url = '/' .join ([ctx .obj ['API_URL' ], resource ])
396
+ session , api_url , project_id = build_client_from_context (ctx )
397
+ url = '/' .join ([api_url , resource ])
367
398
r = session .get (url )
368
399
if r .status_code != 200 :
369
400
raise failed_request_exception ('Failed to list resources' , r )
0 commit comments