<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 async def download_artifacts(context, file_urls, parent_dir=None, session=None, download_func=download_file, valid_artifact_task_ids=None):
 """Download artifacts in parallel after validating their URLs. Valid ``taskId``s for download include the task's dependencies and the ``taskGroupId``, which by convention is the ``taskId`` of the decision task. Args: context (scriptworker.context.Context):
 the scriptworker context. file_urls (list):
 the list of artifact urls to download. parent_dir (str, optional):
 the path of the directory to download the artifacts into. If None, defaults to ``work_dir``. Default is None. session (aiohttp.ClientSession, optional):
 the session to use to download. If None, defaults to context.session. Default is None. download_func (function, optional):
 the function to call to download the files. default is ``download_file``. valid_artifact_task_ids (list, optional):
 the list of task ids that are valid to download from. If None, defaults to all task dependencies plus the decision taskId. Defaults to None. Returns: list: the full paths to the files downloaded Raises: scriptworker.exceptions.BaseDownloadError: on download failure after any applicable retries. """

    parent_dir = parent_dir or context.config['work_dir']
    session = session or context.session

    tasks = []
    files = []
    valid_artifact_rules = context.config['valid_artifact_rules']
    # XXX when chain of trust is on everywhere, hardcode the chain of trust task list
    valid_artifact_task_ids = valid_artifact_task_ids or list(context.task['dependencies'] + [get_decision_task_id(context.task)])
    for file_url in file_urls:
        rel_path = validate_artifact_url(valid_artifact_rules, valid_artifact_task_ids, file_url)
        abs_file_path = os.path.join(parent_dir, rel_path)
        files.append(abs_file_path)
        tasks.append(
            asyncio.ensure_future(
                retry_async(
                    download_func, args=(context, file_url, abs_file_path),
                    retry_exceptions=(DownloadError, aiohttp.ClientError, asyncio.TimeoutError),
                    kwargs={'session': session},
                )
            )
        )

    await raise_future_exceptions(tasks)
    return files