def test_fail_get_single_item_from_sequence( list_, condition, ErrorClass, no_item_error_message, too_many_item_error_message, append_list_to_error_message, has_all_params, expected_message ): with pytest.raises(ErrorClass) as exec_info: if has_all_params: utils.get_single_item_from_sequence(list_, condition, ErrorClass, no_item_error_message, too_many_item_error_message, append_list_to_error_message) else: utils.get_single_item_from_sequence(list_, condition) assert str(exec_info.value) == expected_message
def test_fail_get_single_item_from_sequence( list_, condition, ErrorClass, no_item_error_message, too_many_item_error_message, append_list_to_error_message, has_all_params, expected_message ): with pytest.raises(ErrorClass) as exec_info: if has_all_params: utils.get_single_item_from_sequence( list_, condition, ErrorClass, no_item_error_message, too_many_item_error_message, append_list_to_error_message ) else: utils.get_single_item_from_sequence(list_, condition) assert str(exec_info.value) == expected_message
def task_cert_type(context): """Extract task certificate type. Args: context (Context): the signing context. Raises: TaskVerificationError: if the number of cert scopes is not 1. Returns: str: the cert type. """ if not context.task or not context.task["scopes"]: raise TaskVerificationError("No scopes found") prefixes = _get_cert_prefixes(context) scopes = _extract_scopes_from_unique_prefix(scopes=context.task["scopes"], prefixes=prefixes) return get_single_item_from_sequence( scopes, condition=lambda _: True, # scopes must just contain 1 single item ErrorClass=TaskVerificationError, no_item_error_message="No scope starting with any of these prefixes {} found".format(prefixes), too_many_item_error_message="More than one scope found", )
def get_snap_channel(config, task): if "channel" in task["payload"]: channel = task["payload"]["channel"] scope = SNAP_SCOPES_PREFIX + channel.split("/")[0] if config["push_to_store"] and scope not in task["scopes"]: raise TaskVerificationError( f"Channel {channel} not allowed, missing scope {scope}") else: scope = get_single_item_from_sequence( task["scopes"], lambda scope: scope.startswith(SNAP_SCOPES_PREFIX), ErrorClass=TaskVerificationError, no_item_error_message="No scope starts with {}".format( SNAP_SCOPES_PREFIX), too_many_item_error_message="Too many scopes start with {}".format( SNAP_SCOPES_PREFIX), ) channel = scope[len(SNAP_SCOPES_PREFIX):] channel = "esr/stable" if channel == "esr" else channel if channel not in ALLOWED_CHANNELS: raise TaskVerificationError( 'Channel "{}" is not allowed. Allowed ones are: {}'.format( channel, ALLOWED_CHANNELS)) return channel
def get_snap_channel(config, task): if 'channel' in task['payload']: channel = task['payload']['channel'] scope = SNAP_SCOPES_PREFIX + channel.split('/')[0] if config['push_to_store'] and scope not in task['scopes']: raise TaskVerificationError( f'Channel {channel} not allowed, missing scope {scope}' ) else: scope = get_single_item_from_sequence( task['scopes'], lambda scope: scope.startswith(SNAP_SCOPES_PREFIX), ErrorClass=TaskVerificationError, no_item_error_message='No scope starts with {}'.format(SNAP_SCOPES_PREFIX), too_many_item_error_message='Too many scopes start with {}'.format(SNAP_SCOPES_PREFIX), ) channel = scope[len(SNAP_SCOPES_PREFIX):] channel = 'esr/stable' if channel == 'esr' else channel if channel not in ALLOWED_CHANNELS: raise TaskVerificationError( 'Channel "{}" is not allowed. Allowed ones are: {}'.format(channel, ALLOWED_CHANNELS) ) return channel
def _find_what_version_parser_to_use(file): start_string_then_version_class = get_single_item_from_sequence( sequence=_VERSION_CLASS_PER_BEGINNING_OF_PATH.items(), condition=lambda beginning_of_path_then_version_class: file.startswith( beginning_of_path_then_version_class[0]), ) return start_string_then_version_class[1]
def _get_signing_function_from_format(format): try: _, signing_function = get_single_item_from_sequence(FORMAT_TO_SIGNING_FUNCTION.items(), condition=lambda item: re.match(item[0], format) is not None) return signing_function except ValueError: # Regex may catch several candidate. If so, we fall back to the exact match. # If nothing matches, then we fall back to default return FORMAT_TO_SIGNING_FUNCTION.get(format, FORMAT_TO_SIGNING_FUNCTION["default"])
def _ensure_one_precomplete(tmp_dir, adj): """Ensure we only have one `precomplete` file in `tmp_dir`.""" return get_single_item_from_sequence( glob.glob(os.path.join(tmp_dir, "**", "precomplete"), recursive=True), condition=lambda _: True, ErrorClass=SigningScriptError, no_item_error_message='No `precomplete` file found in "{}"'.format(tmp_dir), too_many_item_error_message='More than one `precomplete` file {} in "{}"'.format(adj, tmp_dir), )
def _get_scope(task): return get_single_item_from_sequence( task["scopes"], condition=lambda scope: scope.startswith(_VALID_SCOPES_PREFIX), ErrorClass=TaskVerificationError, no_item_error_message= 'No valid scope found. Task must have a scope that starts with "{}"'. format(_VALID_SCOPES_PREFIX), too_many_item_error_message="More than one valid scope given", )
def _find_unique_google_play_strings_file_in_dict(artifact_dict): all_paths = [ path for paths in artifact_dict.values() for path in paths ] return get_single_item_from_sequence( all_paths, condition=lambda path: path.endswith(_EXPECTED_L10N_STRINGS_FILE_NAME), ErrorClass=TaskVerificationError, no_item_error_message='Could not find "{}" in upstreamArtifacts: {}'.format(_EXPECTED_L10N_STRINGS_FILE_NAME, artifact_dict), too_many_item_error_message='"{}" is defined too many times among these upstreamArtifacts {}'.format(_EXPECTED_L10N_STRINGS_FILE_NAME, artifact_dict), )
def _get_scope(context, suffix): scope_root = context.config["taskcluster_scope_prefix"] + suffix return get_single_item_from_sequence( context.task["scopes"], condition=lambda scope: scope.startswith(scope_root), ErrorClass=TaskVerificationError, no_item_error_message= 'No valid scope found. Task must have a scope that starts with "{}"'. format(scope_root), too_many_item_error_message="More than one valid scope given", )
def extract_android_product_from_scopes(context): prefixes = _get_scope_prefixes(context) scopes = context.task["scopes"] scope, prefix = get_single_item_from_sequence( sequence=[(scope, prefix) for scope in scopes for prefix in prefixes], condition=lambda scope_then_prefix: scope_then_prefix[0].startswith(scope_then_prefix[1]), ErrorClass=TaskVerificationError, no_item_error_message="No scope starting with any of these prefixes {} found".format(prefixes), too_many_item_error_message="More than one scope matching these prefixes {} found".format(prefixes), ) android_product = scope.split(":")[prefix.count(":")] # the chunk after the prefix is the product name return android_product
def _find_revision_and_version_of_current_snap(metadata_per_revision, current_sha3_384): # Please note we need to create any new channel manually, first. This can be done by opening # a request like this one https://forum.snapcraft.io/t/firefox-please-create-the-track-esr/5006 # and manually release a snap onto this channel item = get_single_item_from_sequence( metadata_per_revision.items(), lambda item: item[1]['download_sha3_384'] == current_sha3_384, ErrorClass=ValueError, no_item_error_message='No revision has sha3_384 "{}"'.format(current_sha3_384), too_many_item_error_message='Too many revisions have sha3_384 "{}"'.format(current_sha3_384), ) revision = item[0] version = item[1]['version'] log.debug('Current snap (version "{}") found on the store at revision {}'.format(version, revision)) return revision, version
def get_flatpak_file_path(context): artifacts_per_task_id, _ = artifacts.get_upstream_artifacts_full_paths_per_task_id( context) all_artifacts = [ artifact for artifacts in artifacts_per_task_id.values() for artifact in artifacts ] return get_single_item_from_sequence( all_artifacts, condition=lambda artifact: artifact.endswith(".flatpak.tar.xz"), ErrorClass=TaskVerificationError, no_item_error_message="No upstream artifact is a tar.xz", too_many_item_error_message="Too many flatpaks detected", )
def get_snap_file_path(context): artifacts_per_task_id, _ = artifacts.get_upstream_artifacts_full_paths_per_task_id( context) all_artifacts = [ artifact for artifacts in artifacts_per_task_id.values() for artifact in artifacts ] return get_single_item_from_sequence( all_artifacts, condition=lambda artifact: artifact.endswith('.snap'), ErrorClass=TaskVerificationError, no_item_error_message='No upstream artifact is a snap', too_many_item_error_message='Too many snaps detected', )
def _pick_revision_and_version_of_latest_released_snap(channel, metadata_per_revision): item = get_single_item_from_sequence( metadata_per_revision.items(), lambda item: channel in item[1]['current_channels'], ErrorClass=ValueError, no_item_error_message='No revision is currently released on channel "{}"'.format(channel), too_many_item_error_message='Too many revisions are released on channel "{}"'.format(channel), ) revision = item[0] version = item[1]['version'] log.debug( 'Found version "{}" (revision {}) to be the latest released on the store'.format( version, revision ) ) return revision, version
def extract_channel(task): scope = get_single_item_from_sequence( task['scopes'], condition=lambda scope: scope.startswith(GOOGLE_PLAY_SCOPE_PREFIX), ErrorClass=TaskVerificationError, no_item_error_message='No valid scope found. Task must have a scope that starts with "{}"'.format(GOOGLE_PLAY_SCOPE_PREFIX), too_many_item_error_message='More than one valid scope given', ) channel = scope[len(GOOGLE_PLAY_SCOPE_PREFIX):] if channel not in SUPPORTED_CHANNELS: raise TaskVerificationError( '"{}" is not a supported channel. Value must be in {}'.format(channel, SUPPORTED_CHANNELS) ) return channel
def get_tag_hash(self, tag_name): """Fetch the commit hash that was tagged with ``tag_name``. Args: tag_name (str): the name of the tag Returns: str: the commit hash linked by the tag """ tag_object = get_single_item_from_sequence( sequence=self._github_repository.tags(), condition=lambda tag: tag.name == tag_name, no_item_error_message='No tag "{}" exist'.format(tag_name), too_many_item_error_message='Too many tags "{}" found'.format(tag_name), ) return tag_object.commit.sha
def get_tag_hash(self, tag_name): """Fetch the commit hash that was tagged with ``tag_name``. Args: tag_name (str): the name of the tag Returns: str: the commit hash linked by the tag """ tag_object = get_single_item_from_sequence( sequence=self._github_repository.tags(), condition=lambda tag: tag.name == tag_name, no_item_error_message='No tag "{}" exist'.format(tag_name), too_many_item_error_message='Too many tags "{}" found'.format(tag_name), ) return tag_object.commit.sha
def pluck_channel(task): scope = get_single_item_from_sequence( task['scopes'], lambda scope: scope.startswith(SNAP_SCOPES_PREFIX), ErrorClass=TaskVerificationError, no_item_error_message='No scope starts with {}'.format( SNAP_SCOPES_PREFIX), too_many_item_error_message='Too many scopes start with {}'.format( SNAP_SCOPES_PREFIX), ) channel = scope[len(SNAP_SCOPES_PREFIX):] if channel not in ALLOWED_CHANNELS: raise TaskVerificationError( 'Channel "{}" is not allowed. Allowed ones are: {}'.format( channel, ALLOWED_CHANNELS)) return channel
def task_cert_type(context): """Extract task certificate type. Args: context (Context): the signing context. Raises: TaskVerificationError: if the number of cert scopes is not 1. Returns: str: the cert type. """ prefix = _get_cert_prefix(context) scopes = context.task['scopes'] return get_single_item_from_sequence( scopes, condition=lambda scope: scope.startswith(prefix), ErrorClass=TaskVerificationError, no_item_error_message='No scope starting with "{}" found'.format( prefix), too_many_item_error_message='More than one scope starting with "{}"'. format(prefix), )
def test_get_single_item_from_sequence(sequence, condition, expected): assert utils.get_single_item_from_sequence(sequence, condition) == expected
def test_get_single_item_from_sequence(sequence, condition, expected): assert utils.get_single_item_from_sequence(sequence, condition) == expected