# Path: valohai_cli/api.py
# def request(self, method, url, **kwargs) -> Response:  # type: ignore
#     api_error_class = kwargs.pop('api_error_class', APIError)
#     handle_errors = bool(kwargs.pop('handle_errors', True))
#     try:
#         resp = super().request(method, url, **kwargs)
#     except requests.ConnectionError as ce:
#         host = urlparse(ce.request.url).netloc
#         if 'Connection refused' in str(ce):
#             raise CLIException(
#                 f'Unable to connect to {host} (connection refused); try again soon.'
#             ) from ce
#         raise
# 
#     if handle_errors and resp.status_code >= 400:
#         cls = (APINotFoundError if resp.status_code == 404 else api_error_class)
#         raise cls(resp)
#     return resp
# 
# Path: valohai_cli/consts.py

# 
# Path: valohai_cli/ctx.py
# @overload
# def get_project(dir: Optional[str] = None, require: Literal[True] = True) -> ProjectOrRemoteProject:
#     ...
# 
# Path: valohai_cli/messages.py
# def info(message: str, err: bool = True) -> None:
#     click.echo(_format_message(message, ['=>'], color='cyan'), err=err)
# 
# def success(message: str, err: bool = True) -> None:
#     click.echo(_format_message(message, SUCCESS_EMOJI, 'Success!', 'green'), err=err)
# 
# def warn(message: str, err: bool = True) -> None:
#     click.echo(_format_message(message, WARN_EMOJI, 'Warning:', 'yellow'), err=err)
# 
# Path: valohai_cli/table.py
# def print_table(
#     data: Any,
#     columns: Sequence[str] = (),
#     headers: Optional[Sequence[str]] = None,
#     format: Optional[str] = None,
#     **kwargs: Any,
# ) -> None:
#     if isinstance(data, dict) and not columns:
#         data = [{'key': key, 'value': value} for (key, value) in sorted(data.items())]
#         columns = ('key', 'value')
#     if not columns:
#         columns = sorted(data[0].keys())
#     if not headers:
#         headers = columns
#     assert len(headers) == len(columns), 'Must have equal amount of columns and headers'
# 
#     if not format:  # Auto-determine format from settings
#         format = settings.output_format
# 
#     if format == 'human':
#         htf = HumanTableFormatter(data=data, columns=columns, headers=headers, **kwargs)
#         htf.echo()
#     elif format == 'json':
#         print_json(data)
#     elif format in SV_SEPARATORS:
#         import csv
#         writer = csv.writer(sys.stdout, delimiter=SV_SEPARATORS[format], quoting=csv.QUOTE_MINIMAL)
#         writer.writerow(headers)
#         writer.writerows(pluck_printable_data(data, columns, lambda col_val: (n_str(col_val), str)))
#     else:
#         raise RuntimeError(f'Unknown print_table format: {format}')
# 
# Path: valohai_cli/utils/cli_utils.py
# def counter_argument(fn: FuncT) -> FuncT:
#     # Extra gymnastics needed because `click.arguments` mutates the kwargs here
#     arg = click.argument('counter', help=EXECUTION_COUNTER_HELP, cls=HelpfulArgument)
#     return arg(fn)  # type: ignore[return-value]


import os
import time
import click
import requests
from fnmatch import fnmatch
from typing import List, Optional
from valohai_cli.api import request
from valohai_cli.consts import complete_execution_statuses
from valohai_cli.ctx import get_project
from valohai_cli.messages import info, success, warn
from valohai_cli.table import print_table
from valohai_cli.utils.cli_utils import counter_argument

    if sync:
        watch(counter, force, filter_download, download_directory)
        return

    project = get_project(require=True)
    assert project
    execution = project.get_execution_from_counter(
        counter=counter,
        params={'exclude': 'outputs'},
    )
    outputs = get_execution_outputs(execution)
    if not outputs:
        warn('The execution has no outputs.')
        return
    for output in outputs:
        output['datum_url'] = f"datum://{output['id']}"
    print_table(outputs, ('name', 'datum_url', 'size'))
    if download_directory:
        outputs = filter_outputs(outputs, download_directory, filter_download, force)
        download_outputs(outputs, download_directory, show_success_message=True)


def watch(counter: str, force: bool, filter_download: Optional[str], download_directory: Optional[str]) -> None:
    if download_directory:
        info(f"Downloading to: {download_directory}\nWaiting for new outputs...")
    else:
        warn('Target folder is not set. Use --download to set it.')
        return


# Path: valohai_cli/api.py
# def request(self, method, url, **kwargs) -> Response:  # type: ignore
#     api_error_class = kwargs.pop('api_error_class', APIError)
#     handle_errors = bool(kwargs.pop('handle_errors', True))
#     try:
#         resp = super().request(method, url, **kwargs)
#     except requests.ConnectionError as ce:
#         host = urlparse(ce.request.url).netloc
#         if 'Connection refused' in str(ce):
#             raise CLIException(
#                 f'Unable to connect to {host} (connection refused); try again soon.'
#             ) from ce
#         raise
# 
#     if handle_errors and resp.status_code >= 400:
#         cls = (APINotFoundError if resp.status_code == 404 else api_error_class)
#         raise cls(resp)
#     return resp
# 
# Path: valohai_cli/consts.py

# 
# Path: valohai_cli/ctx.py
# @overload
# def get_project(dir: Optional[str] = None, require: Literal[True] = True) -> ProjectOrRemoteProject:
#     ...
# 
# Path: valohai_cli/messages.py
# def info(message: str, err: bool = True) -> None:
#     click.echo(_format_message(message, ['=>'], color='cyan'), err=err)
# 
# def success(message: str, err: bool = True) -> None:
#     click.echo(_format_message(message, SUCCESS_EMOJI, 'Success!', 'green'), err=err)
# 
# def warn(message: str, err: bool = True) -> None:
#     click.echo(_format_message(message, WARN_EMOJI, 'Warning:', 'yellow'), err=err)
# 
# Path: valohai_cli/table.py
# def print_table(
#     data: Any,
#     columns: Sequence[str] = (),
#     headers: Optional[Sequence[str]] = None,
#     format: Optional[str] = None,
#     **kwargs: Any,
# ) -> None:
#     if isinstance(data, dict) and not columns:
#         data = [{'key': key, 'value': value} for (key, value) in sorted(data.items())]
#         columns = ('key', 'value')
#     if not columns:
#         columns = sorted(data[0].keys())
#     if not headers:
#         headers = columns
#     assert len(headers) == len(columns), 'Must have equal amount of columns and headers'
# 
#     if not format:  # Auto-determine format from settings
#         format = settings.output_format
# 
#     if format == 'human':
#         htf = HumanTableFormatter(data=data, columns=columns, headers=headers, **kwargs)
#         htf.echo()
#     elif format == 'json':
#         print_json(data)
#     elif format in SV_SEPARATORS:
#         import csv
#         writer = csv.writer(sys.stdout, delimiter=SV_SEPARATORS[format], quoting=csv.QUOTE_MINIMAL)
#         writer.writerow(headers)
#         writer.writerows(pluck_printable_data(data, columns, lambda col_val: (n_str(col_val), str)))
#     else:
#         raise RuntimeError(f'Unknown print_table format: {format}')
# 
# Path: valohai_cli/utils/cli_utils.py
# def counter_argument(fn: FuncT) -> FuncT:
#     # Extra gymnastics needed because `click.arguments` mutates the kwargs here
#     arg = click.argument('counter', help=EXECUTION_COUNTER_HELP, cls=HelpfulArgument)
#     return arg(fn)  # type: ignore[return-value]


# Path: valohai_cli/commands/execution/outputs.py
import os
import time
import click
import requests
from fnmatch import fnmatch
from typing import List, Optional
from valohai_cli.api import request
from valohai_cli.consts import complete_execution_statuses
from valohai_cli.ctx import get_project
from valohai_cli.messages import info, success, warn
from valohai_cli.table import print_table
from valohai_cli.utils.cli_utils import counter_argument


    if sync:
        watch(counter, force, filter_download, download_directory)
        return

    project = get_project(require=True)
    assert project
    execution = project.get_execution_from_counter(
        counter=counter,
        params={'exclude': 'outputs'},
    )
    outputs = get_execution_outputs(execution)
    if not outputs:
        warn('The execution has no outputs.')
        return
    for output in outputs:
        output['datum_url'] = f"datum://{output['id']}"
    print_table(outputs, ('name', 'datum_url', 'size'))
    if download_directory:
        outputs = filter_outputs(outputs, download_directory, filter_download, force)
        download_outputs(outputs, download_directory, show_success_message=True)


def watch(counter: str, force: bool, filter_download: Optional[str], download_directory: Optional[str]) -> None:
    if download_directory:
        info(f"Downloading to: {download_directory}\nWaiting for new outputs...")
    else:
        warn('Target folder is not set. Use --download to set it.')
        return


    project = get_project(require=True)