| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Creates a directory with with the unpacked contents of the remoting webapp. | 6 """Creates a directory with with the unpacked contents of the remoting webapp. |
| 7 | 7 |
| 8 The directory will contain a copy-of or a link-to to all remoting webapp | 8 The directory will contain a copy-of or a link-to to all remoting webapp |
| 9 resources. This includes HTML/JS and any plugin binaries. The script also | 9 resources. This includes HTML/JS and any plugin binaries. The script also |
| 10 massages resulting files appropriately with host plugin data. Finally, | 10 massages resulting files appropriately with host plugin data. Finally, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 service_environment, use_gcd): | 113 service_environment, use_gcd): |
| 114 """Does the main work of building the webapp directory and zipfile. | 114 """Does the main work of building the webapp directory and zipfile. |
| 115 | 115 |
| 116 Args: | 116 Args: |
| 117 buildtype: the type of build ("Official", "Release" or "Dev"). | 117 buildtype: the type of build ("Official", "Release" or "Dev"). |
| 118 destination: A string with path to directory where the webapp will be | 118 destination: A string with path to directory where the webapp will be |
| 119 written. | 119 written. |
| 120 zipfile: A string with path to the zipfile to create containing the | 120 zipfile: A string with path to the zipfile to create containing the |
| 121 contents of |destination|. | 121 contents of |destination|. |
| 122 manifest_template: jinja2 template file for manifest. | 122 manifest_template: jinja2 template file for manifest. |
| 123 webapp_type: webapp type: | 123 webapp_type: webapp type ("v1", "v2", "v2_pnacl" or "app_remoting"). |
| 124 For DesktopRemoting: "v1", "v2" or "v2_pnacl" | |
| 125 For AppRemoting: "app_remoting" or "shared_module" | |
| 126 appid: A string with the Remoting Application Id (only used for app | 124 appid: A string with the Remoting Application Id (only used for app |
| 127 remoting webapps). If supplied, it defaults to using the | 125 remoting webapps). If supplied, it defaults to using the |
| 128 test API server. | 126 test API server. |
| 129 app_client_id: The OAuth2 client ID for the webapp. | 127 app_client_id: The OAuth2 client ID for the webapp. |
| 130 app_name: A string with the name of the application. | 128 app_name: A string with the name of the application. |
| 131 app_description: A string with the description of the application. | 129 app_description: A string with the description of the application. |
| 132 app_capabilities: A set of strings naming the capabilities that should be | 130 app_capabilities: A set of strings naming the capabilities that should be |
| 133 enabled for this application. | 131 enabled for this application. |
| 134 manifest_key: The manifest key for the webapp. | 132 manifest_key: The manifest key for the webapp. |
| 135 files: An array of strings listing the paths for resources to include | 133 files: An array of strings listing the paths for resources to include |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 os.path.split(current_locale)[1]) | 205 os.path.split(current_locale)[1]) |
| 208 os.mkdir(destination_dir, 0775) | 206 os.mkdir(destination_dir, 0775) |
| 209 shutil.copy2(current_locale, destination_file) | 207 shutil.copy2(current_locale, destination_file) |
| 210 elif extension == '.pak': | 208 elif extension == '.pak': |
| 211 destination_file = os.path.join(remoting_locales, | 209 destination_file = os.path.join(remoting_locales, |
| 212 os.path.split(current_locale)[1]) | 210 os.path.split(current_locale)[1]) |
| 213 shutil.copy2(current_locale, destination_file) | 211 shutil.copy2(current_locale, destination_file) |
| 214 else: | 212 else: |
| 215 raise Exception('Unknown extension: ' + current_locale) | 213 raise Exception('Unknown extension: ' + current_locale) |
| 216 | 214 |
| 217 is_app_remoting_webapp = webapp_type == 'app_remoting' | |
| 218 is_app_remoting_shared_module = webapp_type == 'shared_module' | |
| 219 is_app_remoting = is_app_remoting_webapp or is_app_remoting_shared_module | |
| 220 is_prod_service_environment = service_environment == 'vendor' or \ | |
| 221 service_environment == 'prod' or \ | |
| 222 service_environment == 'prod-testing' | |
| 223 is_desktop_remoting = not is_app_remoting | |
| 224 | |
| 225 # Set client plugin type. | 215 # Set client plugin type. |
| 226 # TODO(wez): Use 'native' in app_remoting until b/17441659 is resolved. | 216 # TODO(wez): Use 'native' in app_remoting until b/17441659 is resolved. |
| 227 if not is_app_remoting_webapp: | 217 client_plugin = 'pnacl' if webapp_type == 'v2_pnacl' else 'native' |
| 228 client_plugin = 'pnacl' if webapp_type == 'v2_pnacl' else 'native' | 218 findAndReplace(os.path.join(destination, 'plugin_settings.js'), |
| 229 findAndReplace(os.path.join(destination, 'plugin_settings.js'), | 219 "'CLIENT_PLUGIN_TYPE'", "'" + client_plugin + "'") |
| 230 "'CLIENT_PLUGIN_TYPE'", "'" + client_plugin + "'") | |
| 231 | 220 |
| 232 # Allow host names for google services/apis to be overriden via env vars. | 221 # Allow host names for google services/apis to be overriden via env vars. |
| 233 oauth2AccountsHost = os.environ.get( | 222 oauth2AccountsHost = os.environ.get( |
| 234 'OAUTH2_ACCOUNTS_HOST', 'https://accounts.google.com') | 223 'OAUTH2_ACCOUNTS_HOST', 'https://accounts.google.com') |
| 235 oauth2ApiHost = os.environ.get( | 224 oauth2ApiHost = os.environ.get( |
| 236 'OAUTH2_API_HOST', 'https://www.googleapis.com') | 225 'OAUTH2_API_HOST', 'https://www.googleapis.com') |
| 237 directoryApiHost = os.environ.get( | 226 directoryApiHost = os.environ.get( |
| 238 'DIRECTORY_API_HOST', 'https://www.googleapis.com') | 227 'DIRECTORY_API_HOST', 'https://www.googleapis.com') |
| 239 | 228 |
| 240 if is_app_remoting: | 229 is_app_remoting_webapp = webapp_type == 'app_remoting' |
| 230 is_prod_service_environment = service_environment == 'vendor' or \ |
| 231 service_environment == 'prod' or \ |
| 232 service_environment == 'prod-testing' |
| 233 if is_app_remoting_webapp: |
| 241 appRemotingApiHost = os.environ.get( | 234 appRemotingApiHost = os.environ.get( |
| 242 'APP_REMOTING_API_HOST', None) | 235 'APP_REMOTING_API_HOST', None) |
| 243 appRemotingApplicationId = os.environ.get( | 236 appRemotingApplicationId = os.environ.get( |
| 244 'APP_REMOTING_APPLICATION_ID', None) | 237 'APP_REMOTING_APPLICATION_ID', None) |
| 245 | 238 |
| 246 # Release/Official builds are special because they are what we will upload | 239 # Release/Official builds are special because they are what we will upload |
| 247 # to the web store. The checks below will validate that prod builds are | 240 # to the web store. The checks below will validate that prod builds are |
| 248 # being generated correctly (no overrides) and with the correct buildtype. | 241 # being generated correctly (no overrides) and with the correct buildtype. |
| 249 # They also verify that folks are not accidentally building dev/test/staging | 242 # They also verify that folks are not accidentally building dev/test/staging |
| 250 # apps for release (no impersonation) instead of dev. | 243 # apps for release (no impersonation) instead of dev. |
| 251 if is_prod_service_environment and buildtype == 'Dev': | 244 if is_prod_service_environment and buildtype == 'Dev': |
| 252 raise Exception("Prod environment cannot be built for 'dev' builds") | 245 raise Exception("Prod environment cannot be built for 'dev' builds") |
| 253 | 246 |
| 254 if buildtype != 'Dev': | 247 if buildtype != 'Dev': |
| 255 if not is_prod_service_environment: | 248 if not is_prod_service_environment: |
| 256 raise Exception('Invalid service_environment targeted for ' | 249 raise Exception('Invalid service_environment targeted for ' |
| 257 + buildtype + ': ' + service_environment) | 250 + buildtype + ': ' + service_environment) |
| 258 if appid != None: | 251 if appid != None: |
| 259 raise Exception('Cannot pass in an appid for ' | 252 raise Exception('Cannot pass in an appid for ' |
| 260 + buildtype + ' builds: ' + service_environment) | 253 + buildtype + ' builds: ' + service_environment) |
| 261 if appRemotingApiHost != None: | 254 if appRemotingApiHost != None: |
| 262 raise Exception('Cannot set APP_REMOTING_API_HOST env var for ' | 255 raise Exception('Cannot set APP_REMOTING_API_HOST env var for ' |
| 263 + buildtype + ' builds') | 256 + buildtype + ' builds') |
| 264 if appRemotingApplicationId != None: | 257 if appRemotingApplicationId != None: |
| 265 raise Exception('Cannot set APP_REMOTING_APPLICATION_ID env var for ' | 258 raise Exception('Cannot set APP_REMOTING_APPLICATION_ID env var for ' |
| 266 + buildtype + ' builds') | 259 + buildtype + ' builds') |
| 267 | 260 |
| 268 # If an Application ID was set (either from service_environment variable or | 261 # If an Application ID was set (either from service_environment variable or |
| 269 # from a command line argument), hardcode it, otherwise get it at runtime. | 262 # from a command line argument), hardcode it, otherwise get it at runtime. |
| 270 if is_app_remoting_webapp: | 263 effectiveAppId = appRemotingApplicationId or appid |
| 271 effectiveAppId = appRemotingApplicationId or appid | 264 if effectiveAppId: |
| 272 if effectiveAppId: | 265 appRemotingApplicationId = "'" + effectiveAppId + "'" |
| 273 appRemotingApplicationId = "'" + effectiveAppId + "'" | 266 else: |
| 274 else: | 267 appRemotingApplicationId = "chrome.i18n.getMessage('@@extension_id')" |
| 275 appRemotingApplicationId = "chrome.i18n.getMessage('@@extension_id')" | 268 findAndReplace(os.path.join(destination, 'plugin_settings.js'), |
| 276 findAndReplace(os.path.join(destination, 'arv_main.js'), | 269 "'APP_REMOTING_APPLICATION_ID'", appRemotingApplicationId) |
| 277 "'APP_REMOTING_APPLICATION_ID'", appRemotingApplicationId) | |
| 278 | 270 |
| 279 oauth2BaseUrl = oauth2AccountsHost + '/o/oauth2' | 271 oauth2BaseUrl = oauth2AccountsHost + '/o/oauth2' |
| 280 oauth2ApiBaseUrl = oauth2ApiHost + '/oauth2' | 272 oauth2ApiBaseUrl = oauth2ApiHost + '/oauth2' |
| 281 directoryApiBaseUrl = directoryApiHost + '/chromoting/v1' | 273 directoryApiBaseUrl = directoryApiHost + '/chromoting/v1' |
| 282 | 274 |
| 283 if is_app_remoting: | 275 if is_app_remoting_webapp: |
| 284 # Set the apiary endpoint and then set the endpoint version | 276 # Set the apiary endpoint and then set the endpoint version |
| 285 if not appRemotingApiHost: | 277 if not appRemotingApiHost: |
| 286 if is_prod_service_environment: | 278 if is_prod_service_environment: |
| 287 appRemotingApiHost = 'https://www.googleapis.com' | 279 appRemotingApiHost = 'https://www.googleapis.com' |
| 288 else: | 280 else: |
| 289 appRemotingApiHost = 'https://www-googleapis-test.sandbox.google.com' | 281 appRemotingApiHost = 'https://www-googleapis-test.sandbox.google.com' |
| 290 | 282 |
| 291 # TODO(garykac) Currently, the shared module is always set up for the | 283 if service_environment == 'dev': |
| 292 # dev service_environment. Update build so that the dev environment can | |
| 293 # be controlled by the app stub rather than hard-coded into the shared | |
| 294 # module. | |
| 295 if service_environment == 'dev' or is_app_remoting_shared_module: | |
| 296 appRemotingServicePath = '/appremoting/v1beta1_dev' | 284 appRemotingServicePath = '/appremoting/v1beta1_dev' |
| 297 elif service_environment == 'test': | 285 elif service_environment == 'test': |
| 298 appRemotingServicePath = '/appremoting/v1beta1' | 286 appRemotingServicePath = '/appremoting/v1beta1' |
| 299 elif service_environment == 'staging': | 287 elif service_environment == 'staging': |
| 300 appRemotingServicePath = '/appremoting/v1beta1_staging' | 288 appRemotingServicePath = '/appremoting/v1beta1_staging' |
| 301 elif service_environment == 'vendor': | 289 elif service_environment == 'vendor': |
| 302 appRemotingServicePath = '/appremoting/v1beta1_vendor' | 290 appRemotingServicePath = '/appremoting/v1beta1_vendor' |
| 303 elif service_environment == 'prod': | 291 elif service_environment == 'prod': |
| 304 appRemotingServicePath = '/appremoting/v1beta1' | 292 appRemotingServicePath = '/appremoting/v1beta1' |
| 305 elif service_environment == 'prod-testing': | 293 elif service_environment == 'prod-testing': |
| 306 appRemotingServicePath = '/appremoting/v1beta1_prod_testing' | 294 appRemotingServicePath = '/appremoting/v1beta1_prod_testing' |
| 307 else: | 295 else: |
| 308 raise Exception('Unknown service environment: ' + service_environment) | 296 raise Exception('Unknown service environment: ' + service_environment) |
| 309 appRemotingApiBaseUrl = appRemotingApiHost + appRemotingServicePath | 297 appRemotingApiBaseUrl = appRemotingApiHost + appRemotingServicePath |
| 310 else: | 298 else: |
| 311 appRemotingApiBaseUrl = '' | 299 appRemotingApiBaseUrl = '' |
| 312 | 300 |
| 313 # TODO(garykac) replaceString (et al.) implictly update plugin_settings.js, | 301 replaceBool(destination, 'USE_GCD', use_gcd) |
| 314 # which doesn't exist for the app stub. We need to move app-specific | 302 replaceString(destination, 'OAUTH2_BASE_URL', oauth2BaseUrl) |
| 315 # AppRemoting options into arv_main.js. | 303 replaceString(destination, 'OAUTH2_API_BASE_URL', oauth2ApiBaseUrl) |
| 316 if not is_app_remoting_webapp: | 304 replaceString(destination, 'DIRECTORY_API_BASE_URL', directoryApiBaseUrl) |
| 317 replaceBool(destination, 'USE_GCD', use_gcd) | 305 if is_app_remoting_webapp: |
| 318 replaceString(destination, 'OAUTH2_BASE_URL', oauth2BaseUrl) | 306 replaceString(destination, 'APP_REMOTING_API_BASE_URL', |
| 319 replaceString(destination, 'OAUTH2_API_BASE_URL', oauth2ApiBaseUrl) | 307 appRemotingApiBaseUrl) |
| 320 replaceString(destination, 'DIRECTORY_API_BASE_URL', directoryApiBaseUrl) | |
| 321 if is_app_remoting: | |
| 322 replaceString(destination, 'APP_REMOTING_API_BASE_URL', | |
| 323 appRemotingApiBaseUrl) | |
| 324 | 308 |
| 325 # Substitute hosts in the manifest's CSP list. | 309 # Substitute hosts in the manifest's CSP list. |
| 326 # Ensure we list the API host only once if it's the same for multiple APIs. | 310 # Ensure we list the API host only once if it's the same for multiple APIs. |
| 327 googleApiHosts = ' '.join(set([oauth2ApiHost, directoryApiHost])) | 311 googleApiHosts = ' '.join(set([oauth2ApiHost, directoryApiHost])) |
| 328 | 312 |
| 329 # WCS and the OAuth trampoline are both hosted on talkgadget. Split them into | 313 # WCS and the OAuth trampoline are both hosted on talkgadget. Split them into |
| 330 # separate suffix/prefix variables to allow for wildcards in manifest.json. | 314 # separate suffix/prefix variables to allow for wildcards in manifest.json. |
| 331 talkGadgetHostSuffix = os.environ.get( | 315 talkGadgetHostSuffix = os.environ.get( |
| 332 'TALK_GADGET_HOST_SUFFIX', 'talkgadget.google.com') | 316 'TALK_GADGET_HOST_SUFFIX', 'talkgadget.google.com') |
| 333 talkGadgetHostPrefix = os.environ.get( | 317 talkGadgetHostPrefix = os.environ.get( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 351 oauth2RedirectBaseUrlJson = oauth2RedirectHostJson + oauth2RedirectPath | 335 oauth2RedirectBaseUrlJson = oauth2RedirectHostJson + oauth2RedirectPath |
| 352 if buildtype == 'Official': | 336 if buildtype == 'Official': |
| 353 oauth2RedirectUrlJs = ("'" + oauth2RedirectBaseUrlJs + | 337 oauth2RedirectUrlJs = ("'" + oauth2RedirectBaseUrlJs + |
| 354 "/rel/' + chrome.i18n.getMessage('@@extension_id')") | 338 "/rel/' + chrome.i18n.getMessage('@@extension_id')") |
| 355 oauth2RedirectUrlJson = oauth2RedirectBaseUrlJson + '/rel/*' | 339 oauth2RedirectUrlJson = oauth2RedirectBaseUrlJson + '/rel/*' |
| 356 else: | 340 else: |
| 357 oauth2RedirectUrlJs = "'" + oauth2RedirectBaseUrlJs + "/dev'" | 341 oauth2RedirectUrlJs = "'" + oauth2RedirectBaseUrlJs + "/dev'" |
| 358 oauth2RedirectUrlJson = oauth2RedirectBaseUrlJson + '/dev*' | 342 oauth2RedirectUrlJson = oauth2RedirectBaseUrlJson + '/dev*' |
| 359 thirdPartyAuthUrlJs = oauth2RedirectBaseUrlJs + '/thirdpartyauth' | 343 thirdPartyAuthUrlJs = oauth2RedirectBaseUrlJs + '/thirdpartyauth' |
| 360 thirdPartyAuthUrlJson = oauth2RedirectBaseUrlJson + '/thirdpartyauth*' | 344 thirdPartyAuthUrlJson = oauth2RedirectBaseUrlJson + '/thirdpartyauth*' |
| 345 replaceString(destination, 'TALK_GADGET_URL', talkGadgetBaseUrl) |
| 346 findAndReplace(os.path.join(destination, 'plugin_settings.js'), |
| 347 "'OAUTH2_REDIRECT_URL'", oauth2RedirectUrlJs) |
| 348 |
| 349 # Configure xmpp server and directory bot settings in the plugin. |
| 350 replaceBool( |
| 351 destination, 'XMPP_SERVER_USE_TLS', |
| 352 getenvBool('XMPP_SERVER_USE_TLS', True)) |
| 361 xmppServer = os.environ.get('XMPP_SERVER', 'talk.google.com:443') | 353 xmppServer = os.environ.get('XMPP_SERVER', 'talk.google.com:443') |
| 362 | 354 replaceString(destination, 'XMPP_SERVER', xmppServer) |
| 363 if not is_app_remoting_webapp: | 355 replaceString(destination, 'DIRECTORY_BOT_JID', |
| 364 replaceString(destination, 'TALK_GADGET_URL', talkGadgetBaseUrl) | 356 os.environ.get('DIRECTORY_BOT_JID', |
| 365 findAndReplace(os.path.join(destination, 'plugin_settings.js'), | 357 'remoting@bot.talk.google.com')) |
| 366 "'OAUTH2_REDIRECT_URL'", oauth2RedirectUrlJs) | 358 replaceString(destination, 'THIRD_PARTY_AUTH_REDIRECT_URL', |
| 367 | 359 thirdPartyAuthUrlJs) |
| 368 # Configure xmpp server and directory bot settings in the plugin. | |
| 369 replaceBool( | |
| 370 destination, 'XMPP_SERVER_USE_TLS', | |
| 371 getenvBool('XMPP_SERVER_USE_TLS', True)) | |
| 372 replaceString(destination, 'XMPP_SERVER', xmppServer) | |
| 373 replaceString(destination, 'DIRECTORY_BOT_JID', | |
| 374 os.environ.get('DIRECTORY_BOT_JID', | |
| 375 'remoting@bot.talk.google.com')) | |
| 376 replaceString(destination, 'THIRD_PARTY_AUTH_REDIRECT_URL', | |
| 377 thirdPartyAuthUrlJs) | |
| 378 | 360 |
| 379 # Set the correct API keys. | 361 # Set the correct API keys. |
| 380 # For overriding the client ID/secret via env vars, see google_api_keys.py. | 362 # For overriding the client ID/secret via env vars, see google_api_keys.py. |
| 381 apiClientId = google_api_keys.GetClientID('REMOTING') | 363 apiClientId = google_api_keys.GetClientID('REMOTING') |
| 382 apiClientSecret = google_api_keys.GetClientSecret('REMOTING') | 364 apiClientSecret = google_api_keys.GetClientSecret('REMOTING') |
| 383 apiKey = google_api_keys.GetAPIKeyRemoting() | 365 apiKey = google_api_keys.GetAPIKeyRemoting() |
| 384 | 366 |
| 385 if is_app_remoting_webapp and buildtype != 'Dev': | 367 if is_app_remoting_webapp and buildtype != 'Dev': |
| 386 if not app_client_id: | 368 if not app_client_id: |
| 387 raise Exception('Invalid app_client_id passed in: "' + | 369 raise Exception('Invalid app_client_id passed in: "' + |
| 388 app_client_id + '"') | 370 app_client_id + '"') |
| 389 apiClientIdV2 = app_client_id + '.apps.googleusercontent.com' | 371 apiClientIdV2 = app_client_id + '.apps.googleusercontent.com' |
| 390 else: | 372 else: |
| 391 apiClientIdV2 = google_api_keys.GetClientID('REMOTING_IDENTITY_API') | 373 apiClientIdV2 = google_api_keys.GetClientID('REMOTING_IDENTITY_API') |
| 392 | 374 |
| 393 if not is_app_remoting_webapp: | 375 replaceString(destination, 'API_CLIENT_ID', apiClientId) |
| 394 replaceString(destination, 'API_CLIENT_ID', apiClientId) | 376 replaceString(destination, 'API_CLIENT_SECRET', apiClientSecret) |
| 395 replaceString(destination, 'API_CLIENT_SECRET', apiClientSecret) | 377 replaceString(destination, 'API_KEY', apiKey) |
| 396 replaceString(destination, 'API_KEY', apiKey) | |
| 397 | 378 |
| 398 # Write the application capabilities. | 379 # Write the application capabilities. |
| 399 if is_app_remoting_webapp: | 380 appCapabilities = ','.join( |
| 400 appCapabilities = ','.join( | 381 ['remoting.ClientSession.Capability.' + x for x in app_capabilities]) |
| 401 ['remoting.ClientSession.Capability.' + x for x in app_capabilities]) | 382 findAndReplace(os.path.join(destination, 'app_capabilities.js'), |
| 402 findAndReplace(os.path.join(destination, 'arv_main.js'), | 383 "'APPLICATION_CAPABILITIES'", appCapabilities) |
| 403 "'APPLICATION_CAPABILITIES'", appCapabilities) | |
| 404 | 384 |
| 405 # Use a consistent extension id for dev builds. | 385 # Use a consistent extension id for dev builds. |
| 406 # AppRemoting builds always use the dev app id - the correct app id gets | 386 # AppRemoting builds always use the dev app id - the correct app id gets |
| 407 # written into the manifest later. | 387 # written into the manifest later. |
| 408 if is_app_remoting_webapp: | 388 if is_app_remoting_webapp: |
| 409 if buildtype != 'Dev': | 389 if buildtype != 'Dev': |
| 410 if not manifest_key: | 390 if not manifest_key: |
| 411 raise Exception('Invalid manifest_key passed in: "' + | 391 raise Exception('Invalid manifest_key passed in: "' + |
| 412 manifest_key + '"') | 392 manifest_key + '"') |
| 413 manifestKey = '"key": "' + manifest_key + '",' | 393 manifestKey = '"key": "' + manifest_key + '",' |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 parser.add_argument('--use_gcd', choices=['0', '1'], default='0') | 458 parser.add_argument('--use_gcd', choices=['0', '1'], default='0') |
| 479 | 459 |
| 480 args = parser.parse_args() | 460 args = parser.parse_args() |
| 481 args.use_gcd = (args.use_gcd != '0') | 461 args.use_gcd = (args.use_gcd != '0') |
| 482 args.app_capabilities = set(args.app_capabilities) | 462 args.app_capabilities = set(args.app_capabilities) |
| 483 return buildWebApp(**vars(args)) | 463 return buildWebApp(**vars(args)) |
| 484 | 464 |
| 485 | 465 |
| 486 if __name__ == '__main__': | 466 if __name__ == '__main__': |
| 487 sys.exit(main()) | 467 sys.exit(main()) |
| OLD | NEW |