Fix lint issues for some early files.
BUG=chromium:758431
TEST=Ran bin/run_lint.
Change-Id: I8e9182d3cf38cedec6992b14cbd90706bbb9ffbc
diff --git a/build_lib.py b/build_lib.py
index 3676633..09f36d0 100644
--- a/build_lib.py
+++ b/build_lib.py
@@ -3,12 +3,15 @@
# found in the LICENSE file.
"""Module for ChromeOS & Android build related logic in suite scheduler."""
+# pylint: disable=g-bad-import-order
-import apiclient
+from distutils import version
import collections
import logging
import re
+import apiclient
+
# Bare branches
BARE_BRANCHES = ['factory', 'firmware']
@@ -19,190 +22,22 @@
OS_TYPES = [OS_TYPE_CROS, OS_TYPE_BRILLO, OS_TYPE_ANDROID]
OS_TYPES_LAUNCH_CONTROL = [OS_TYPE_BRILLO, OS_TYPE_ANDROID]
-
+# Launch control build's target's information
LaunchControlBuildTargetInfo = collections.namedtuple(
'LaunchControlBuildTargetInfo',
[
- 'target',
- 'type',
+ 'target',
+ 'type',
])
+# ChromeOS build config's information
CrOSBuildConfigInfo = collections.namedtuple(
'CrOSBuildConfigInfo',
[
- 'board',
- 'type',
+ 'board',
+ 'type',
])
-
-class NoBuildError(Exception):
- """Raised when failing to get the required build from Google Storage."""
-
-
-class BuildType(object):
- """Representing the type of test source build.
-
- This is used to identify the test source build for testing.
- """
- FIRMWARE_RW = 'firmware_rw'
- FIRMWARE_RO = 'firmware_ro'
- CROS = 'cros'
-
-
-class BuildVersionKey(object):
- """Keys referring to the builds to install in run_suites."""
-
- CROS_VERSION = 'cros_version'
- ANDROID_BUILD_VERSION = 'android_version'
- TESTBED_BUILD_VERSION = 'testbed_version'
- FW_RW_VERSION = 'fwrw_version'
- FW_RO_VERSION = 'fwro_version'
-
-
-class AndroidBuild(collections.namedtuple(
- '_AndroidBuildBase', ['branch', 'target', 'build_id']), object):
-
- def __str__(self):
- return _ANDROID_BUILD_PATTERN % {'branch': self.branch,
- 'target': self.target,
- 'build_id': self.build_id}
-
-
-class CrOSBuild(collections.namedtuple(
- '_CrOSBuildBase',
- ['board', 'build_type', 'milestone', 'manifest']), object):
-
- def __str__(self):
- return _CROS_BUILD_PATTERN % {'board': self.board,
- 'build_type': self.build_type,
- 'milestone': self.milestone,
- 'manifest': self.manifest}
-
-
-def get_latest_cros_build_from_gs(storage_client, board=None, suffix=None):
- """Get latest build for given board from Google Storage.
-
- Args:
- storage_client: a rest_client.StorageRestClient object.
- board: the board to fetch latest build. Default is 'master'.
- suffix: suffix represents build channel, like '-release'.
- Default is '-paladin'.
-
- Returns:
- a ChromeOS version string, e.g. '59.0.000.0'.
-
- Raises:
- HttpError if error happens in interacting with Google Storage.
- """
- board = board if board is not None else _DEFAULT_MASTER
- suffix = suffix if suffix is not None else _DEFAULT_BUILD_SUFFIX
- file_to_check = _GS_LATEST_MASTER_PATTERN % {
- 'board': board,
- 'suffix': suffix,
- 'name': _LATEST_MASTER}
-
- try:
- return storage_client.ReadObject(_GS_BUCKET, file_to_check)
- except apiclient.errors.HttpError as e:
- raise NoBuildError(
- 'Cannot find latest build for board %s, suffix %s: %s' %
- (board, suffix, str(e)))
-
-
-def get_latest_launch_control_build(android_client, branch, target):
- """Get the latest launch control build from Android Build API.
-
- Args:
- android_client: a rest_client.AndroidBuildRestClient object.
- branch: the launch control branch.
- target: the launch control target.
-
- Returns:
- a string latest launch control build id.
-
- Raises:
- NoBuildError if no latest launch control build is found.
- """
- try:
- latest_build_id = android_client.get_latest_build_id(branch, target)
- if latest_build_id is None:
- raise NoBuildError('No latest builds is found.')
-
- return latest_build_id
- except apiclient.errors.HttpError as e:
- raise NoBuildError('HttpError happened in getting the latest launch '
- 'control build for '
- '%s,%s: %s' % (branch, target, str(e)))
-
-def parse_launch_control_target(target):
- """Parse the build target and type from a Launch Control target.
-
- The Launch Control target has the format of build_target-build_type, e.g.,
- shamu-eng or dragonboard-userdebug. This method extracts the build target
- and type from the target name.
-
- Args:
- target: Name of a Launch Control target, e.g., shamu-userdebug.
-
- Returns:
- a LaunchControlBuildTargetInfo object whose value is like
- (target='shamu',
- type='userdebug')
-
- Raises:
- Raise ValueError if target is not valid.
- """
- match = re.match(_LAUNCH_CONTROL_TARGET_PATTERN, target)
- if not match:
- raise ValueError('target format is not valid')
-
- return LaunchControlBuildTargetInfo(match.group('build_target'),
- match.group('build_type'))
-
-
-def parse_cros_build_config(board, build_config):
- """Parse build_type from a given builder for a given board.
-
- Args:
- board: the prefix of a ChromeOS build_config, representing board.
- build_config: a ChromeOS build_config name, like 'kevin-release'.
-
- Returns:
- a CrOSBuildConfigInfo object whose value is like
- (board='kevin',
- type='release')
-
- Raises:
- Raise ValueError if target is not valid.
- """
- if build_config[0:len(board)] != board:
- raise ValueError('build_config cannot be parsed: %s' % build_config)
-
- match = re.match(_CROS_BUILD_CONFIG_PATTERN, build_config[len(board):])
- if not match:
- raise ValueError('build_config %s is not matched %s' % (
- build_config, _CROS_BUILD_CONFIG_PATTERN))
-
- return CrOSBuildConfigInfo(board, match.groups()[0])
-
-
-def get_board_by_android_target(target):
- """Map a android target to a android board.
-
- # Mapping between an android board name and a build target. This is for
- # special case handling for certain Android board that the board name and
- # build target name does not match.
- # This comes from server/site_utils.py in autotest module.
-
- Args:
- board: an android board.
-
- Returns:
- a string android board mapped by ANDROID_TARGET_TO_BOARD_MAP.
- """
- return _ANDROID_TARGET_TO_BOARD_MAP.get(target, target)
-
-
# The default build type for fetching latest build.
_DEFAULT_BUILD_SUFFIX = '-paladin'
@@ -235,3 +70,282 @@
# The pattern for CrOS build config
_CROS_BUILD_CONFIG_PATTERN = r'-([^-]+)(?:-group)?'
+
+
+class NoBuildError(Exception):
+ """Raised when failing to get the required build from Google Storage."""
+
+
+class BuildType(object):
+ """Representing the type of test source build.
+
+ This is used to identify the test source build for testing.
+ """
+ FIRMWARE_RW = 'firmware_rw'
+ FIRMWARE_RO = 'firmware_ro'
+ CROS = 'cros'
+
+
+class BuildVersionKey(object):
+ """Keys referring to the builds to install in run_suites."""
+
+ CROS_VERSION = 'cros_version'
+ ANDROID_BUILD_VERSION = 'android_version'
+ TESTBED_BUILD_VERSION = 'testbed_version'
+ FW_RW_VERSION = 'fwrw_version'
+ FW_RO_VERSION = 'fwro_version'
+
+
+class AndroidBuild(collections.namedtuple(
+ '_AndroidBuildBase', ['branch', 'target', 'build_id']), object):
+ """Class for constructing android build string."""
+
+ def __str__(self):
+ return _ANDROID_BUILD_PATTERN % {'branch': self.branch,
+ 'target': self.target,
+ 'build_id': self.build_id}
+
+
+class CrOSBuild(collections.namedtuple(
+ '_CrOSBuildBase',
+ ['board', 'build_type', 'milestone', 'manifest']), object):
+ """Class for constructing ChromeOS build string."""
+
+ def __str__(self):
+ return _CROS_BUILD_PATTERN % {'board': self.board,
+ 'build_type': self.build_type,
+ 'milestone': self.milestone,
+ 'manifest': self.manifest}
+
+
+def get_latest_cros_build_from_gs(storage_client, board=None, suffix=None):
+ """Get latest build for given board from Google Storage.
+
+ Args:
+ storage_client: a rest_client.StorageRestClient object.
+ board: the board to fetch latest build. Default is 'master'.
+ suffix: suffix represents build channel, like '-release'.
+ Default is '-paladin'.
+
+ Returns:
+ a ChromeOS version string, e.g. '59.0.000.0'.
+
+ Raises:
+ HttpError if error happens in interacting with Google Storage.
+ """
+ board = board if board is not None else _DEFAULT_MASTER
+ suffix = suffix if suffix is not None else _DEFAULT_BUILD_SUFFIX
+ file_to_check = _GS_LATEST_MASTER_PATTERN % {
+ 'board': board,
+ 'suffix': suffix,
+ 'name': _LATEST_MASTER}
+
+ try:
+ return storage_client.read_object(_GS_BUCKET, file_to_check)
+ except apiclient.errors.HttpError as e:
+ raise NoBuildError(
+ 'Cannot find latest build for board %s, suffix %s: %s' %
+ (board, suffix, str(e)))
+
+
+def get_cros_builds_since_date_from_db(db_client, since_date):
+ """Get branch builds for ChromeOS boards.
+
+ Args:
+ db_client: a cloud_sql_client.CIDBClient object, to read cidb
+ build infos.
+ since_date: a datetime.datetime object in UTC to indicate since when CrOS
+ builds will be fetched.
+
+ Returns:
+ a branch build dict:
+ key: a tuple of (board, build_type, milestone), like:
+ ('wolf', 'release', '58')
+ value: the latest manifest for the given tuple, like:
+ '9242.0.0'.
+ """
+ # CIDB use UTC timezone
+ all_branch_builds = db_client.get_passed_builds_since_date(since_date)
+
+ branch_build_dict = {}
+ for build in all_branch_builds:
+ try:
+ build_config_info = parse_cros_build_config(build.board,
+ build.build_config)
+ except ValueError as e:
+ logging.warning('Failed to parse build config: %s: %s',
+ build.build_config, e)
+ continue
+
+ if build.board != build_config_info.board:
+ logging.warning('Non-matched build_config and board: %s, %s',
+ build.board, build.board)
+ continue
+
+ build_key = (build.board, build_config_info.type, build.milestone)
+ cur_manifest = branch_build_dict.get(build_key)
+ if cur_manifest is not None:
+ branch_build_dict[build_key] = max(
+ [cur_manifest, build.platform], key=version.LooseVersion)
+ else:
+ branch_build_dict[build_key] = build.platform
+
+ return branch_build_dict
+
+
+def get_latest_launch_control_build(android_client, branch, target):
+ """Get the latest launch control build from Android Build API.
+
+ Args:
+ android_client: a rest_client.AndroidBuildRestClient object.
+ branch: the launch control branch.
+ target: the launch control target.
+
+ Returns:
+ a string latest launch control build id.
+
+ Raises:
+ NoBuildError if no latest launch control build is found.
+ """
+ try:
+ latest_build_id = android_client.get_latest_build_id(branch, target)
+ if latest_build_id is None:
+ raise NoBuildError('No latest builds is found.')
+
+ return latest_build_id
+ except apiclient.errors.HttpError as e:
+ raise NoBuildError('HttpError happened in getting the latest launch '
+ 'control build for '
+ '%s,%s: %s' % (branch, target, str(e)))
+
+
+def get_launch_control_builds_by_branch_targets(
+ android_client, android_board_list, launch_control_branch_targets):
+ """Get latest launch_control_builds for android boards.
+
+ For every tasks in this event, if it has settings of launch control
+ branch & target, get the latest launch control build for it.
+
+ Args:
+ android_client: a rest_client.AndroidBuildRestClient object to
+ interact with android build API.
+ android_board_list: a list of Android boards.
+ launch_control_branch_targets: a dict of branch:targets, see property
+ launch_control_branch_targets in base_event.py.
+
+ Returns:
+ a launch control build dict:
+ key: an android board, like 'shamu'.
+ value: a list involves the latest builds for each pair
+ (branch, target) of this board, like:
+ [u'git_nyc-mr2-release/shamu-userdebug/3844975',
+ u'git_nyc-mr1-release/shamu-userdebug/3783920']
+ """
+ launch_control_dict = {}
+ board_to_builds_dict = {}
+ for branch, targets in launch_control_branch_targets.iteritems():
+ for t in targets:
+ try:
+ board = parse_launch_control_target(t).target
+ except ValueError:
+ logging.warning(
+ 'Failed to parse launch control target: %s', t)
+ continue
+
+ if board not in android_board_list:
+ continue
+
+ # Use dict here to reduce the times to call AndroidBuild API
+ if launch_control_dict.get((branch, t)) is None:
+ try:
+ build_id = get_latest_launch_control_build(
+ android_client, branch, t)
+ except NoBuildError as e:
+ logging.warning(e)
+ continue
+
+ build = str(AndroidBuild(branch, t, build_id))
+ launch_control_dict[(branch, t)] = build
+ board_to_builds_dict.setdefault(board, []).append(
+ build)
+
+ for board, in board_to_builds_dict.iteritems():
+ mapped_board = get_board_by_android_target(board)
+ if mapped_board != board:
+ logging.debug('Map board %s to %s', board, mapped_board)
+ if board_to_builds_dict.get(mapped_board) is None:
+ del board_to_builds_dict[board]
+ else:
+ board_to_builds_dict[board] = board_to_builds_dict[
+ mapped_board]
+
+ return board_to_builds_dict
+
+
+def parse_launch_control_target(target):
+ """Parse the build target and type from a Launch Control target.
+
+ The Launch Control target has the format of build_target-build_type, e.g.,
+ shamu-eng or dragonboard-userdebug. This method extracts the build target
+ and type from the target name.
+
+ Args:
+ target: Name of a Launch Control target, e.g., shamu-userdebug.
+
+ Returns:
+ a LaunchControlBuildTargetInfo object whose value is like
+ (target='shamu',
+ type='userdebug')
+
+ Raises:
+ ValueError: if target is not valid.
+ """
+ match = re.match(_LAUNCH_CONTROL_TARGET_PATTERN, target)
+ if not match:
+ raise ValueError('target format is not valid')
+
+ return LaunchControlBuildTargetInfo(match.group('build_target'),
+ match.group('build_type'))
+
+
+def parse_cros_build_config(board, build_config):
+ """Parse build_type from a given builder for a given board.
+
+ Args:
+ board: the prefix of a ChromeOS build_config, representing board.
+ build_config: a ChromeOS build_config name, like 'kevin-release'.
+
+ Returns:
+ a CrOSBuildConfigInfo object whose value is like
+ (board='kevin',
+ type='release')
+
+ Raises:
+ ValueError: if build_config is in invalid form.
+ """
+ if build_config[0:len(board)] != board:
+ raise ValueError('build_config cannot be parsed: %s' % build_config)
+
+ match = re.match(_CROS_BUILD_CONFIG_PATTERN, build_config[len(board):])
+ if not match:
+ raise ValueError('build_config %s is not matched %s' % (
+ build_config, _CROS_BUILD_CONFIG_PATTERN))
+
+ return CrOSBuildConfigInfo(board, match.groups()[0])
+
+
+def get_board_by_android_target(target):
+ """Map a android target to a android board.
+
+ # Mapping between an android board name and a build target. This is for
+ # special case handling for certain Android board that the board name and
+ # build target name does not match.
+ # This comes from server/site_utils.py in autotest module.
+
+ Args:
+ target: an android target.
+
+ Returns:
+ a string android board mapped by ANDROID_TARGET_TO_BOARD_MAP.
+ """
+ return _ANDROID_TARGET_TO_BOARD_MAP.get(target, target)
diff --git a/cloud_sql_client.py b/cloud_sql_client.py
index 37312b0..dce8897 100644
--- a/cloud_sql_client.py
+++ b/cloud_sql_client.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
"""Module for interacting with MySQL database, like cidb."""
+# pylint: disable=g-bad-import-order
import MySQLdb
import collections
@@ -25,133 +26,132 @@
class DBConnection(object):
- """The class for reading ChromeOS lab's db."""
+ """The class for reading ChromeOS lab's db."""
- def __init__(self, db_tag, db_name):
- """Initialize a MySQLdb reader.
+ def __init__(self, db_tag, db_name):
+ """Initialize a MySQLdb reader.
- Args:
- db_tag: a string section name in db config file like
- credentials/cloud_sql_credentials.txt, to get
- db connection info.
- db_name: the database to use.
- """
- self._db_tag = db_tag
- self._read_credentials()
- self._db = self.connect_to_cloudsql()
- self._cursor = self._db.cursor()
+ Args:
+ db_tag: a string section name in db config file, e.g.
+ credentials/cloud_sql_credentials.txt, to get db connection info.
+ db_name: the database to use.
+ """
+ self._db_tag = db_tag
+ self._read_credentials()
+ self._db = self.connect_to_cloudsql()
+ self._cursor = self._db.cursor()
- self._db_name = db_name
- if self._db_name:
- self._select_db(self._db_name)
+ self._db_name = db_name
+ if self._db_name:
+ self._select_db(self._db_name)
- @property
- def cursor(self):
- return self._cursor
+ @property
+ def cursor(self):
+ return self._cursor
- @property
- def db(self):
- return self._db
+ @property
+ def db(self):
+ return self._db
- def connect_to_cloudsql(self):
- """Connect to cloudsql by socket or tcp."""
- cur_env = constants.environment()
- if (cur_env == constants.RunningEnv.ENV_DEVELOPMENT_SERVER or
- cur_env == constants.RunningEnv.ENV_PROD):
- # Running on local development server or app engine
- # Connect using the unix socket located at
- # /cloudsql/cloudsql-connection-name.
- cloudsql_unix_socket = os.path.join(
- '/cloudsql', self._connection_name)
+ def connect_to_cloudsql(self):
+ """Connect to cloudsql by socket or tcp."""
+ cur_env = constants.environment()
+ if (cur_env == constants.RunningEnv.ENV_DEVELOPMENT_SERVER or
+ cur_env == constants.RunningEnv.ENV_PROD):
+ # Running on local development server or app engine
+ # Connect using the unix socket located at
+ # /cloudsql/cloudsql-connection-name.
+ cloudsql_unix_socket = os.path.join(
+ '/cloudsql', self._connection_name)
- db = MySQLdb.connect(
- unix_socket=cloudsql_unix_socket,
- user=self._user,
- passwd=self._pw)
+ db = MySQLdb.connect(
+ unix_socket=cloudsql_unix_socket,
+ user=self._user,
+ passwd=self._pw)
- # If the unix socket is unavailable, then try to connect using TCP.
- # This will work if you're running a local MySQL server or using the
- # Cloud SQL proxy, for example:
- #
- # $ cloud_sql_proxy -instances=your-connection-name=tcp:3306
- #
- else:
- db = MySQLdb.connect(
- host='127.0.0.1', user=self._user, passwd=self._pw)
+ # If the unix socket is unavailable, then try to connect using TCP.
+ # This will work if you're running a local MySQL server or using the
+ # Cloud SQL proxy, for example:
+ #
+ # $ cloud_sql_proxy -instances=your-connection-name=tcp:3306
+ #
+ else:
+ db = MySQLdb.connect(
+ host='127.0.0.1', user=self._user, passwd=self._pw)
- return db
+ return db
- def _read_credentials(self):
- """Read credentials from credentials_path."""
- db_config = config_reader.DBConfig(
- config_reader.ConfigReader(file_getter.SQL_CREDENTIAL_FILE))
- configs = db_config.get_credentials(self._db_tag)
- self._connection_name = configs.connection_name
- self._user = configs.user
- self._pw = configs.password
+ def _read_credentials(self):
+ """Read credentials from credentials_path."""
+ db_config = config_reader.DBConfig(
+ config_reader.ConfigReader(file_getter.SQL_CREDENTIAL_FILE))
+ configs = db_config.get_credentials(self._db_tag)
+ self._connection_name = configs.connection_name
+ self._user = configs.user
+ self._pw = configs.password
- def _select_db(self, db_name):
- self._cursor.execute('USE %s' % db_name)
+ def _select_db(self, db_name):
+ self._cursor.execute('USE %s' % db_name)
class CIDBClient(object):
- """class for interacting with CIDB."""
+ """class for interacting with CIDB."""
- def __init__(self, db_tag, db_name):
- """Initialize a cidb reader."""
- self._connection = DBConnection(db_tag, db_name)
+ def __init__(self, db_tag, db_name):
+ """Initialize a cidb reader."""
+ self._connection = DBConnection(db_tag, db_name)
- def get_passed_builds_since_date(self, since_date):
- """Get passed builds since a given date.
+ def get_passed_builds_since_date(self, since_date):
+ """Get passed builds since a given date.
- Args:
- since_date: a date string, like '2017-02-01 23:00:00'.
+ Args:
+ since_date: a date string, like '2017-02-01 23:00:00'.
- Returns:
- A list of BuildInfo objects.
+ Returns:
+ A list of BuildInfo objects.
- Raises:
- MySQLdb.OperationalError if connection operations are not valid.
- """
+ Raises:
+ MySQLdb.OperationalError if connection operations are not valid.
+ """
- sql = """\
- select bo.board, bu.milestone_version,
- bu.platform_version, bu.build_config
- from buildTable as bu, boardPerBuildTable as bo
- where bu.status='pass' and bu.suite_scheduling=1 and
- bu.finish_time > %s and bu.id=bo.build_id
- """
- logging.info('Get passed builds since %r', since_date)
- self._connection.cursor.execute(sql,
- [since_date.strftime(time_converter.TIME_FORMAT)])
- builds = self._connection.cursor.fetchall()
- return [BuildInfo(board, milestone, platform, build_config)
- for board, milestone, platform, build_config in builds]
+ sql = """\
+ select bo.board, bu.milestone_version,
+ bu.platform_version, bu.build_config
+ from buildTable as bu, boardPerBuildTable as bo
+ where bu.status='pass' and bu.suite_scheduling=1 and
+ bu.finish_time > %s and bu.id=bo.build_id
+ """
+ logging.info('Get passed builds since %r', since_date)
+ self._connection.cursor.execute(
+ sql, [since_date.strftime(time_converter.TIME_FORMAT)])
+ builds = self._connection.cursor.fetchall()
+ return [BuildInfo(board, milestone, platform, build_config)
+ for board, milestone, platform, build_config in builds]
- def get_latest_passed_builds(self, build_config):
- """Get latest passed builds by build_config.
+ def get_latest_passed_builds(self, build_config):
+ """Get latest passed builds by build_config.
- Args:
- build_config: format like '{board}-{build_type}', eg. link-release
+ Args:
+ build_config: format like '{board}-{build_type}', eg. link-release
- Returns:
- A BuildInfo object, represents the latest passed build.
+ Returns:
+ A BuildInfo object, represents the latest passed build.
- Raises:
- MySQLdb.OperationalError if connection operations are not valid.
- """
- sql = """\
- select bo.board, bu.milestone_version, bu.platform_version
- from buildTable as bu, boardPerBuildTable as bo
- where bu.build_config=%s and bu.status='pass' and
- bu.id=bo.build_id order by finish_time desc limit 1
- """
- self._connection.cursor.execute(sql, [build_config])
- version_info = self._connection.cursor.fetchall()
- if not version_info:
- return None
- else:
- return BuildInfo(board=version_info[0][0],
- milestone=version_info[0][1],
- platform=version_info[0][2],
- build_config=build_config)
+ Raises:
+ MySQLdb.OperationalError if connection operations are not valid.
+ """
+ sql = """\
+ select bo.board, bu.milestone_version, bu.platform_version
+ from buildTable as bu, boardPerBuildTable as bo
+ where bu.build_config=%s and bu.status='pass' and
+ bu.id=bo.build_id order by finish_time desc limit 1
+ """
+ self._connection.cursor.execute(sql, [build_config])
+ version_info = self._connection.cursor.fetchall()
+ if not version_info:
+ return None
+ else:
+ return BuildInfo(board=version_info[0][0],
+ milestone=version_info[0][1],
+ platform=version_info[0][2],
+ build_config=build_config)
diff --git a/constants.py b/constants.py
index 281cfdf..bc6cfaa 100644
--- a/constants.py
+++ b/constants.py
@@ -4,98 +4,98 @@
"""Module containing the constants to be reused throughout suite_scheduler."""
-from google.appengine.api import app_identity
from collections import namedtuple
import logging
import os
+from google.appengine.api import app_identity
+
# Namedtuple for storing rest client info.
RestClientInfo = namedtuple(
'RestClientInfo', 'scopes, service_name, service_version')
-
-class RestClient(object):
- """Constants related to rest clients to google service."""
-
- # client info for connecting to android build API.
- ANDROID_BUILD_CLIENT = RestClientInfo._make(
- ['https://www.googleapis.com/auth/androidbuild.internal',
- 'androidbuildinternal',
- 'v2beta1'])
-
- # client info for connecting to google storage API.
- STORAGE_CLIENT = RestClientInfo._make(
- ['https://www.googleapis.com/auth/devstorage.full_control',
- 'storage',
- 'v1'])
-
- # client info for connecting to google calendar API.
- CALENDAR_CLIENT = RestClientInfo._make(
- ['https://www.googleapis.com/auth/calendar',
- 'calendar',
- 'v3'])
-
- SWARMING_CLIENT = RestClientInfo._make(
- ['https://www.googleapis.com/auth/userinfo.email',
- 'swarming',
- 'v1'])
-
-
-class RunningEnv(object):
- """Constants related to app engine running environment."""
-
- # Running this GAE project locally with python.
- ENV_STANDALONE = 0
-
- # Running this GAE project with local development server.
- ENV_DEVELOPMENT_SERVER = 1
-
- # Running this GAE project in app-engine production.
- ENV_PROD = 2
-
-
-class Priorities(object):
- """Constants related to task priority."""
-
- # weekly task's priority
- WEEKLY = 10
-
- # daily task's priority
- DAILY = 20
-
- # postbuild task's priority
- POSTBUILD = 30
-
- # the default task priority
- DEFAULT = 40
-
-
-def environment():
- """Return proper environment settings."""
- if os.getenv(_RUNNING_ENV, '').startswith(_ENV_DEVELOPMENT_STR):
- return RunningEnv.ENV_DEVELOPMENT_SERVER
- elif os.getenv(_RUNNING_ENV, '').startswith(_ENV_APP_ENGINE_STR):
- return RunningEnv.ENV_PROD
- else:
- return RunningEnv.ENV_STANDALONE
-
-
-def application_id():
- """Get current running application id.
-
- Returns:
- If it's a Google internal GAE whose id format is 'google.com:<name>',
- return <name>; Otherwise, return the full id.
- """
- app_id = app_identity.get_application_id()
- logging.info('app_id: %s', app_id)
- if app_id is not None and len(app_id.split(':')) > 1:
- return app_id.split(':')[1]
- else:
- return app_id
-
-
# Constants for detecting the running environment.
_RUNNING_ENV = 'SERVER_SOFTWARE'
_ENV_DEVELOPMENT_STR = 'Development'
_ENV_APP_ENGINE_STR = 'Google App Engine/'
+
+
+class RestClient(object):
+ """Constants related to rest clients to google service."""
+
+ # client info for connecting to android build API.
+ ANDROID_BUILD_CLIENT = RestClientInfo._make(
+ ['https://www.googleapis.com/auth/androidbuild.internal',
+ 'androidbuildinternal',
+ 'v2beta1'])
+
+ # client info for connecting to google storage API.
+ STORAGE_CLIENT = RestClientInfo._make(
+ ['https://www.googleapis.com/auth/devstorage.full_control',
+ 'storage',
+ 'v1'])
+
+ # client info for connecting to google calendar API.
+ CALENDAR_CLIENT = RestClientInfo._make(
+ ['https://www.googleapis.com/auth/calendar',
+ 'calendar',
+ 'v3'])
+
+ SWARMING_CLIENT = RestClientInfo._make(
+ ['https://www.googleapis.com/auth/userinfo.email',
+ 'swarming',
+ 'v1'])
+
+
+class RunningEnv(object):
+ """Constants related to app engine running environment."""
+
+ # Running this GAE project locally with python.
+ ENV_STANDALONE = 0
+
+ # Running this GAE project with local development server.
+ ENV_DEVELOPMENT_SERVER = 1
+
+ # Running this GAE project in app-engine production.
+ ENV_PROD = 2
+
+
+class Priorities(object):
+ """Constants related to task priority."""
+
+ # weekly task's priority
+ WEEKLY = 10
+
+ # daily task's priority
+ DAILY = 20
+
+ # postbuild task's priority
+ POSTBUILD = 30
+
+ # the default task priority
+ DEFAULT = 40
+
+
+def environment():
+ """Return proper environment settings."""
+ if os.getenv(_RUNNING_ENV, '').startswith(_ENV_DEVELOPMENT_STR):
+ return RunningEnv.ENV_DEVELOPMENT_SERVER
+ elif os.getenv(_RUNNING_ENV, '').startswith(_ENV_APP_ENGINE_STR):
+ return RunningEnv.ENV_PROD
+ else:
+ return RunningEnv.ENV_STANDALONE
+
+
+def application_id():
+ """Get current running application id.
+
+ Returns:
+ If it's a Google internal GAE whose id format is 'google.com:<name>',
+ return <name>; Otherwise, return the full id.
+ """
+ app_id = app_identity.get_application_id()
+ logging.info('app_id: %s', app_id)
+ if app_id is not None and len(app_id.split(':')) > 1:
+ return app_id.split(':')[1]
+ else:
+ return app_id
diff --git a/datastore_client.py b/datastore_client.py
index 62ab8cc..5438d47 100644
--- a/datastore_client.py
+++ b/datastore_client.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
"""Module for interacting with datastore."""
+# pylint: disable=g-tzinfo-replace
import pytz
@@ -10,83 +11,83 @@
class LastExecutionRecord(ndb.Model):
- """Models a last_execute_record entry with keyword & exec_time."""
+ """Models a last_execute_record entry with keyword & exec_time."""
- # The keyword represents different types of events, e.g.
- # Key('LastExecutionRecord', 'nightly')
- event_type = ndb.StringProperty()
+ # The keyword represents different types of events, e.g.
+ # Key('LastExecutionRecord', 'nightly')
+ event_type = ndb.StringProperty()
- # The last execute time for a given keyword.
- exec_time = ndb.DateTimeProperty()
+ # The last execute time for a given keyword.
+ exec_time = ndb.DateTimeProperty()
class LastExecutionRecordStore(object):
- """Base class for reading google datastore."""
+ """Base class for reading google datastore."""
- def set_last_execute_time(self, event_type, exec_time):
- """Set the last execute time for the given keyword.
+ def set_last_execute_time(self, event_type, exec_time):
+ """Set the last execute time for the given keyword.
- Args:
- event_type: the keyword for saving last execute time.
- exec_time: The UTC timestamp for last execute time.
+ Args:
+ event_type: the keyword for saving last execute time.
+ exec_time: The UTC timestamp for last execute time.
- Returns:
- The Key('LastExecutionRecord', event_type) to save the exec_time.
- """
- if exec_time.tzinfo is not None:
- exec_time = exec_time.replace(tzinfo=None)
+ Returns:
+ The Key('LastExecutionRecord', event_type) to save the exec_time.
+ """
+ if exec_time.tzinfo is not None:
+ exec_time = exec_time.replace(tzinfo=None)
- cur_record_key = ndb.Key(LastExecutionRecord, event_type)
- cur_record = cur_record_key.get()
- if cur_record is not None:
- cur_record.exec_time = exec_time
- else:
- cur_record = LastExecutionRecord(event_type=event_type,
- exec_time=exec_time)
- cur_record.key = cur_record_key
+ cur_record_key = ndb.Key(LastExecutionRecord, event_type)
+ cur_record = cur_record_key.get()
+ if cur_record is not None:
+ cur_record.exec_time = exec_time
+ else:
+ cur_record = LastExecutionRecord(event_type=event_type,
+ exec_time=exec_time)
+ cur_record.key = cur_record_key
- return cur_record.put()
+ return cur_record.put()
- def get_last_execute_time(self, event_type):
- """Get the last execute time for the given event_type.
+ def get_last_execute_time(self, event_type):
+ """Get the last execute time for the given event_type.
- Args:
- event_type: the keyword to get its last execute time.
+ Args:
+ event_type: the keyword to get its last execute time.
- Returns:
- last_exec_time: an offset-aware datetime object with timezone
- pytz.utc.
- """
- cur_record = ndb.Key(LastExecutionRecord, event_type).get()
- if cur_record is not None:
- return cur_record.exec_time.replace(tzinfo=pytz.utc)
- else:
- return None
+ Returns:
+ last_exec_time: an offset-aware datetime object with timezone
+ pytz.utc.
+ """
+ cur_record = ndb.Key(LastExecutionRecord, event_type).get()
+ if cur_record is not None:
+ return cur_record.exec_time.replace(tzinfo=pytz.utc)
+ else:
+ return None
- def del_last_execute_time(self, event_type):
- """Delete the last execute time for the given event_type.
+ def del_last_execute_time(self, event_type):
+ """Delete the last execute time for the given event_type.
- Args:
- event_type: the keyword to delete its last execute time.
- """
- cur_record_key = ndb.Key(LastExecutionRecord, event_type)
- if cur_record_key.get() is not None:
- cur_record_key.delete()
+ Args:
+ event_type: the keyword to delete its last execute time.
+ """
+ cur_record_key = ndb.Key(LastExecutionRecord, event_type)
+ if cur_record_key.get() is not None:
+ cur_record_key.delete()
- def get_all(self):
- """Get the last execute time for all event_types in datastore.
+ def get_all(self):
+ """Get the last execute time for all event_types in datastore.
- Returns:
- A list of LastExecutionRecord objects, whose exec_time is a
- offset-aware datetime object with timezone pytz.utc.
- """
- qry = LastExecutionRecord.query()
- for q in qry.iter():
- q.exec_time = q.exec_time.replace(tzinfo=pytz.utc)
+ Returns:
+ A list of LastExecutionRecord objects, whose exec_time is a
+ offset-aware datetime object with timezone pytz.utc.
+ """
+ qry = LastExecutionRecord.query()
+ for q in qry.iter():
+ q.exec_time = q.exec_time.replace(tzinfo=pytz.utc)
- return [q for q in qry.iter()]
+ return [q for q in qry.iter()]
- def delete_all(self):
- """Delete the last execute time for all event_types in datastore."""
- for q in LastExecutionRecord.query().iter():
- q.key.delete()
+ def delete_all(self):
+ """Delete the last execute time for all event_types in datastore."""
+ for q in LastExecutionRecord.query().iter():
+ q.key.delete()
diff --git a/datastore_client_unittest.py b/datastore_client_unittest.py
index 815af4b..40a7f83 100644
--- a/datastore_client_unittest.py
+++ b/datastore_client_unittest.py
@@ -3,74 +3,73 @@
# found in the LICENSE file.
"""Module for datastore unittests."""
+# pylint: disable=g-tzinfo-replace,g-bad-import-order
import datetime
+import pytz
import unittest
import datastore_client
-from google.appengine.api import memcache
from google.appengine.ext import ndb
from google.appengine.ext import testbed
-import pytz
class DatastoreTestCase(unittest.TestCase):
- def setUp(self):
- self.testbed = testbed.Testbed()
- self.testbed.activate()
- self.addCleanup(self.testbed.deactivate)
- self.testbed.init_datastore_v3_stub()
- self.testbed.init_memcache_stub()
- ndb.get_context().clear_cache()
+ def setUp(self):
+ self.testbed = testbed.Testbed()
+ self.testbed.activate()
+ self.addCleanup(self.testbed.deactivate)
+ self.testbed.init_datastore_v3_stub()
+ self.testbed.init_memcache_stub()
+ ndb.get_context().clear_cache()
- def testSetLastExec(self):
- last_exec_store = datastore_client.LastExecutionRecordStore()
- exec_time = datetime.datetime(2017, 8, 1, 0)
- last_exec_store.set_last_execute_time('nightly', exec_time)
- self.assertEqual(last_exec_store.get_last_execute_time('nightly'),
- exec_time.replace(tzinfo=pytz.utc))
+ def testSetLastExec(self):
+ last_exec_store = datastore_client.LastExecutionRecordStore()
+ exec_time = datetime.datetime(2017, 8, 1, 0)
+ last_exec_store.set_last_execute_time('nightly', exec_time)
+ self.assertEqual(last_exec_store.get_last_execute_time('nightly'),
+ exec_time.replace(tzinfo=pytz.utc))
- def testDeleteLastExec(self):
- last_exec_store = datastore_client.LastExecutionRecordStore()
- exec_time = datetime.datetime(2017, 8, 1, 0)
- last_exec_store.set_last_execute_time('nightly', exec_time)
- last_exec_store.del_last_execute_time('nightly')
- self.assertEqual(last_exec_store.get_last_execute_time('nightly'),
- None)
+ def testDeleteLastExec(self):
+ last_exec_store = datastore_client.LastExecutionRecordStore()
+ exec_time = datetime.datetime(2017, 8, 1, 0)
+ last_exec_store.set_last_execute_time('nightly', exec_time)
+ last_exec_store.del_last_execute_time('nightly')
+ self.assertEqual(last_exec_store.get_last_execute_time('nightly'),
+ None)
- def testDeleteLastExecWithNonExistentKey(self):
- last_exec_store = datastore_client.LastExecutionRecordStore()
- exec_time = datetime.datetime(2017, 8, 1, 0)
- last_exec_store.del_last_execute_time('nightly')
+ def testDeleteLastExecWithNonExistentKey(self):
+ last_exec_store = datastore_client.LastExecutionRecordStore()
+ last_exec_store.del_last_execute_time('nightly')
- def testGetAllLastExec(self):
- last_exec_store = datastore_client.LastExecutionRecordStore()
- exec_time = datetime.datetime(2017, 8, 1, 0)
- event_types = ['nightly', 'weekly']
- exec_time_records = [datastore_client.LastExecutionRecord(
- key=ndb.Key(datastore_client.LastExecutionRecord, e),
- event_type=e,
- exec_time=exec_time.replace(tzinfo=pytz.utc)) for e in event_types]
+ def testGetAllLastExec(self):
+ last_exec_store = datastore_client.LastExecutionRecordStore()
+ exec_time = datetime.datetime(2017, 8, 1, 0)
+ event_types = ['nightly', 'weekly']
+ exec_time_records = [datastore_client.LastExecutionRecord(
+ key=ndb.Key(datastore_client.LastExecutionRecord, e),
+ event_type=e,
+ exec_time=exec_time.replace(tzinfo=pytz.utc)) for e in event_types]
- for e in event_types:
- last_exec_store.set_last_execute_time(e, exec_time)
+ for e in event_types:
+ last_exec_store.set_last_execute_time(e, exec_time)
- last_exec_times = last_exec_store.get_all()
- self.assertEqual(last_exec_times, exec_time_records)
+ last_exec_times = last_exec_store.get_all()
+ self.assertEqual(last_exec_times, exec_time_records)
- def testDeleteAllLastExec(self):
- last_exec_store = datastore_client.LastExecutionRecordStore()
- exec_time = datetime.datetime(2017, 8, 1, 0)
- event_types = ['nightly', 'weekly']
+ def testDeleteAllLastExec(self):
+ last_exec_store = datastore_client.LastExecutionRecordStore()
+ exec_time = datetime.datetime(2017, 8, 1, 0)
+ event_types = ['nightly', 'weekly']
- for e in event_types:
- last_exec_store.set_last_execute_time(e, exec_time)
+ for e in event_types:
+ last_exec_store.set_last_execute_time(e, exec_time)
- last_exec_store.delete_all()
- for e in event_types:
- self.assertEqual(last_exec_store.get_last_execute_time(e), None)
+ last_exec_store.delete_all()
+ for e in event_types:
+ self.assertEqual(last_exec_store.get_last_execute_time(e), None)
if __name__ == '__main__':
- unittest.main()
+ unittest.main()
diff --git a/file_getter.py b/file_getter.py
index 65b254d..199016e 100644
--- a/file_getter.py
+++ b/file_getter.py
@@ -6,8 +6,6 @@
import os
-import constants
-
# The path to save credentials.
CREDENTIALS_PATH = os.path.join(os.path.dirname(__file__), 'credentials')
diff --git a/rest_client.py b/rest_client.py
index 2092807..345e85c 100644
--- a/rest_client.py
+++ b/rest_client.py
@@ -3,11 +3,11 @@
# found in the LICENSE file.
"""Module for interacting with google APIs."""
+# pylint: disable=g-bad-import-order
+
+import httplib2
import apiclient
-import httplib2
-import os
-
import constants
import file_getter
@@ -16,174 +16,176 @@
class RestClientError(Exception):
- """Raised when there is a general error."""
+ """Raised when there is a general error."""
class NoServiceRestClientError(RestClientError):
- """Raised when there is no ready service for a google API."""
+ """Raised when there is no ready service for a google API."""
class BaseRestClient(object):
- """Base class of REST client for google APIs."""
+ """Base class of REST client for google APIs."""
- def __init__(self, scopes, service_name, service_version):
- """Initialize a REST client to connect to a google API.
+ def __init__(self, scopes, service_name, service_version):
+ """Initialize a REST client to connect to a google API.
- Args:
- scopes: the scopes of the to-be-connected API.
- service_name: the service name of the to-be-connected API.
- service_version: the service version of the to-be-connected API.
- """
- self._running_env = constants.environment()
- self._scopes = scopes
- self._service_name = service_name
- self._service_version = service_version
+ Args:
+ scopes: the scopes of the to-be-connected API.
+ service_name: the service name of the to-be-connected API.
+ service_version: the service version of the to-be-connected API.
+ """
+ self.running_env = constants.environment()
+ self.scopes = scopes
+ self.service_name = service_name
+ self.service_version = service_version
- @property
- def service(self):
- if not self._service:
- raise NoServiceRestClientError('No service created for calling API')
+ @property
+ def service(self):
+ if not self._service:
+ raise NoServiceRestClientError('No service created for calling API')
- return self._service
+ return self._service
- def create_service(self, discovery_url=None):
- """Create the service for a google API."""
- self._init_credentials()
- # Explicitly specify timeout for http to avoid DeadlineExceededError.
- # It's used for services like AndroidBuild API, which raise such error
- # when being triggered too many calls in a short time frame.
- # http://stackoverflow.com/questions/14698119/httpexception-deadline-exceeded-while-waiting-for-http-response-from-url-dead
- http_auth = self._credentials.authorize(httplib2.Http(timeout=30))
- if discovery_url is None:
- self._service = apiclient.discovery.build(
- self._service_name, self._service_version,
- http=http_auth)
- else:
- self._service = apiclient.discovery.build(
- self._service_name, self._service_version, http=http_auth,
- discoveryServiceUrl=discovery_url)
+ def create_service(self, discovery_url=None):
+ """Create the service for a google API."""
+ self._init_credentials()
+ # Explicitly specify timeout for http to avoid DeadlineExceededError.
+ # It's used for services like AndroidBuild API, which raise such error
+ # when being triggered too many calls in a short time frame.
+ # http://stackoverflow.com/questions/14698119/httpexception-deadline-exceeded-while-waiting-for-http-response-from-url-dead
+ http_auth = self._credentials.authorize(httplib2.Http(timeout=30))
+ if discovery_url is None:
+ self._service = apiclient.discovery.build(
+ self.service_name, self.service_version,
+ http=http_auth)
+ else:
+ self._service = apiclient.discovery.build(
+ self.service_name, self.service_version, http=http_auth,
+ discoveryServiceUrl=discovery_url)
- def _init_credentials(self):
- """Initialize the credentials for a google API."""
- if (self._running_env == constants.RunningEnv.ENV_STANDALONE or
- self._running_env == constants.RunningEnv.ENV_DEVELOPMENT_SERVER):
- # Running locally
- service_credentials = service_account.ServiceAccountCredentials
- self._credentials = service_credentials.from_json_keyfile_name(
- file_getter.LOCAL_CLIENT_SECRETS_FILE, self._scopes)
- else:
- # Running in app-engine production
- self._credentials = appengine.AppAssertionCredentials(self._scopes)
+ def _init_credentials(self):
+ """Initialize the credentials for a google API."""
+ if (self.running_env == constants.RunningEnv.ENV_STANDALONE or
+ self.running_env == constants.RunningEnv.ENV_DEVELOPMENT_SERVER):
+ # Running locally
+ service_credentials = service_account.ServiceAccountCredentials
+ self._credentials = service_credentials.from_json_keyfile_name(
+ file_getter.LOCAL_CLIENT_SECRETS_FILE, self.scopes)
+ else:
+ # Running in app-engine production
+ self._credentials = appengine.AppAssertionCredentials(self.scopes)
class AndroidBuildRestClient(object):
- """REST client for android build API."""
+ """REST client for android build API."""
- def __init__(self, rest_client):
- """Initialize a REST client for connecting to Android Build API."""
- self._rest_client = rest_client
- self._rest_client.create_service()
+ def __init__(self, rest_client):
+ """Initialize a REST client for connecting to Android Build API."""
+ self._rest_client = rest_client
+ self._rest_client.create_service()
- def get_latest_build_id(self, branch, target):
- """Get the latest build id for a given branch and target.
+ def get_latest_build_id(self, branch, target):
+ """Get the latest build id for a given branch and target.
- Args:
- branch: an android build's branch
- target: an android build's target
+ Args:
+ branch: an android build's branch
+ target: an android build's target
- Returns:
- A string representing latest build id.
- """
- request = self._rest_client.service.build().list(
- buildType='submitted',
- branch=branch,
- target=target,
- successful=True,
- maxResults=1)
- builds = request.execute(num_retries=10)
- if not builds or not builds['builds']:
- return None
+ Returns:
+ A string representing latest build id.
+ """
+ request = self._rest_client.service.build().list(
+ buildType='submitted',
+ branch=branch,
+ target=target,
+ successful=True,
+ maxResults=1)
+ builds = request.execute(num_retries=10)
+ if not builds or not builds['builds']:
+ return None
- return builds['builds'][0]['buildId']
+ return builds['builds'][0]['buildId']
class StorageRestClient(object):
- """REST client for google storage API."""
+ """REST client for google storage API."""
- def __init__(self, rest_client):
- """Initialize a REST client for connecting to Google storage API."""
- self._rest_client = rest_client
- self._rest_client.create_service()
+ def __init__(self, rest_client):
+ """Initialize a REST client for connecting to Google storage API."""
+ self._rest_client = rest_client
+ self._rest_client.create_service()
- def ReadObject(self, input_bucket, input_object):
- """Read the contents of input_object in input_bucket.
+ def read_object(self, input_bucket, input_object):
+ """Read the contents of input_object in input_bucket.
- Args:
- input_bucket: the bucket for fetching.
- input_object: the object for checking the contents.
+ Args:
+ input_bucket: the bucket for fetching.
+ input_object: the object for checking the contents.
- Returns:
- the stripped string contents of the input object.
+ Returns:
+ the stripped string contents of the input object.
- Raises:
- apiclient.errors.HttpError
- """
- req = self._rest_client.service.objects().get_media(
- bucket=input_bucket,
- object=input_object)
- return req.execute()
+ Raises:
+ apiclient.errors.HttpError
+ """
+ req = self._rest_client.service.objects().get_media(
+ bucket=input_bucket,
+ object=input_object)
+ return req.execute()
class CalendarRestClient(object):
- """Class of REST client for google calendar API."""
+ """Class of REST client for google calendar API."""
- def __init__(self, rest_client):
- """Initialize a REST client for connecting to Google calendar API."""
- self._rest_client = rest_client
- self._rest_client.create_service()
+ def __init__(self, rest_client):
+ """Initialize a REST client for connecting to Google calendar API."""
+ self._rest_client = rest_client
+ self._rest_client.create_service()
- def AddEvent(self, calendar_id, input_event):
- """Add events of a given calendar.
+ def add_event(self, calendar_id, input_event):
+ """Add events of a given calendar.
- Args:
- calendarId: the ID of the given calendar.
- input_event: the event to be added.
- kwargs: the parameters for adding events of the calendar.
- """
- self._rest_client.service.events().insert(
- calendarId=calendar_id,
- body=input_event).execute()
+ Args:
+ calendar_id: the ID of the given calendar.
+ input_event: the event to be added.
+ """
+ self._rest_client.service.events().insert(
+ calendarId=calendar_id,
+ body=input_event).execute()
class SwarmingRestClient(object):
- """REST client for swarming proxy API."""
+ """REST client for swarming proxy API."""
- DISCOVERY_URL_PATTERN = '%s/discovery/v1/apis/%s/%s/rest'
+ DISCOVERY_URL_PATTERN = '%s/discovery/v1/apis/%s/%s/rest'
- def __init__(self, rest_client, service_url):
- self._rest_client = rest_client
- discovery_url = self.DISCOVERY_URL_PATTERN % (
- service_url, service_name, service_version)
- self._rest_client.create_service(discovery_url=discovery_url)
+ def __init__(self, rest_client, service_url):
+ self._rest_client = rest_client
+ discovery_url = self.DISCOVERY_URL_PATTERN % (
+ service_url, rest_client.service_name, rest_client.service_version)
+ self._rest_client.create_service(discovery_url=discovery_url)
- def create_task(self, request):
- """Create new task.
+ def create_task(self, request):
+ """Create new task.
- Args:
- request: a json-compatible dict expected by swarming server.
- See _to_raw_request's output in swarming_lib.py for details.
- """
- return self._rest_client.service.tasks().new(
- fields='request,task_id', body=request).execute()
+ Args:
+ request: a json-compatible dict expected by swarming server.
+ See _to_raw_request's output in swarming_lib.py for details.
- def request_task(self, task_id):
- """Get task details by a given task_id.
+ Returns:
+ A json dict returned by API task.new.
+ """
+ return self._rest_client.service.tasks().new(
+ fields='request,task_id', body=request).execute()
- Args:
- task_id: A string, represents task id.
+ def get_task_result(self, task_id):
+ """Get task results by a given task_id.
- Returns:
- A json dict returned by API task.request.
- """
- return self._rest_client.service.task().request(
- task_id=task_id).execute()
+ Args:
+ task_id: A string, represents task id.
+
+ Returns:
+ A json dict returned by API task.result.
+ """
+ return self._rest_client.service.task().result(
+ task_id=task_id).execute()