зеркало из
1
0
Форкнуть 0

Retrieve run and runs in async

This commit is contained in:
Troy Dai 2018-04-25 15:00:45 -07:00
Родитель dd8abe6519
Коммит 19ac79f618
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 9608535492BEDAC8
10 изменённых файлов: 150 добавлений и 118 удалений

Просмотреть файл

@ -1 +1,4 @@
from .get_task import get_task
from .get_run import get_run
from .get_runs import get_runs

Просмотреть файл

@ -0,0 +1,53 @@
import sys
import logging
import json
from itertools import zip_longest
from a01.cli import cmd, arg
from a01.output import output_in_table
from a01.models import TaskCollection
from a01.operations import query_tasks_by_run, query_run
import colorama
@cmd('get run', desc='Retrieve a run')
@arg('run_id', help='The run id.', positional=True)
@arg('log', help="Include the failed tasks' logs.", option=('-l', '--log'))
@arg('recording', option=('-r', '--recording'),
help='Download the recording files in recording directory at current working directory. The recordings '
'are flatten with the full test path as the file name if --az-mode is not specified. If --az-mode is '
'set, the recording files are arranged in directory structure mimic Azure CLI source code.')
@arg('show_all', option=['--show-all'], help='Show all the tasks results.')
@arg('recording_az_mode', option=['--az-mode'],
help='When download the recording files the files are arranged in directory structure mimic Azure CLI '
'source code.')
@arg('raw', help='For debug.')
def get_run(run_id: str, log: bool = False, recording: bool = False, recording_az_mode: bool = False,
show_all: bool = False, raw: bool = False) -> None:
logger = logging.getLogger(__name__)
try:
tasks = TaskCollection(query_tasks_by_run(run_id), run_id)
output_in_table(tasks.get_table_view(failed=not show_all), headers=tasks.get_table_header())
output_in_table(tasks.get_summary(), tablefmt='plain')
if log:
for failure in tasks.get_failed_tasks():
output_in_table(zip_longest(failure.get_table_header(), failure.get_table_view()), tablefmt='plain')
output_in_table(failure.get_log_content(), tablefmt='plain', foreground_color=colorama.Fore.CYAN)
output_in_table(tasks.get_summary(), tablefmt='plain')
if recording:
print()
print('Download recordings ...')
for task in tasks.tasks:
task.download_recording(recording_az_mode)
if raw:
run = query_run(run_id=run_id)
print(json.dumps(run.to_dict(), indent=2))
except ValueError as err:
logger.error(err)
sys.exit(1)

Просмотреть файл

@ -0,0 +1,32 @@
import logging
import sys
from a01.auth import AuthSettings, AuthenticationError
from a01.cli import cmd, arg
from a01.operations import query_runs
from a01.output import output_in_table
@cmd('get runs', desc='Retrieve the runs.')
@arg('owner', help='Query runs by owner.')
@arg('me', help='Query runs created by me.')
@arg('last', help='Returns the last NUMBER of records. Default: 20.')
@arg('skip', help='Returns the records after skipping given number of records at the bottom. Default: 0.')
def get_runs(me: bool = False, last: int = 20, skip: int = 0,
owner: str = None) -> None: # pylint: disable=invalid-name
logger = logging.getLogger(__name__)
try:
if me and owner:
raise ValueError('--me and --user are mutually exclusive.')
elif me:
owner = AuthSettings().get_user_name()
runs = query_runs(owner=owner, last=last, skip=skip)
output_in_table(runs.get_table_view(), headers=runs.get_table_header())
except ValueError as err:
logger.error(err)
sys.exit(1)
except AuthenticationError as err:
logger.error(err)
print('You need to login. Usage: a01 login.', file=sys.stderr)
sys.exit(1)

Просмотреть файл

@ -1,5 +1,5 @@
# pylint: disable=unused-import
from .run import Run, RunCollection
from .run import Run, RunsView
from .task import Task
from .task_collection import TaskCollection

Просмотреть файл

@ -1,6 +1,5 @@
import json
import datetime
import urllib
from typing import List, Tuple, Generator
import colorama
@ -94,9 +93,7 @@ class Run(object):
return config.endpoint_uri
class RunCollection(object):
logger = get_logger('RunCollection')
class RunsView(object):
def __init__(self, runs: List[Run]) -> None:
self.runs = runs
@ -117,35 +114,3 @@ class RunCollection(object):
@staticmethod
def get_table_header() -> Tuple:
return 'Id', 'Name', 'Creation', 'Status', 'Remark', 'Owner'
@classmethod
def get(cls, **kwargs) -> 'RunCollection':
try:
url = f'{cls.endpoint_uri()}/runs'
query = {}
for key, value in kwargs.items():
if value is not None:
query[key] = value
if query:
url = f'{url}?{urllib.parse.urlencode(query)}'
resp = session.get(url)
resp.raise_for_status()
runs = [Run.from_dict(each) for each in resp.json()]
runs = sorted(runs, key=lambda r: r.id, reverse=True)
return RunCollection(runs)
except HTTPError:
cls.logger.debug('HttpError', exc_info=True)
raise ValueError('Fail to get runs.')
except (KeyError, json.JSONDecodeError, TypeError):
cls.logger.debug('JsonError', exc_info=True)
raise ValueError('Fail to parse the runs data.')
@staticmethod
def endpoint_uri():
config = A01Config()
config.ensure_config()
return config.endpoint_uri

Просмотреть файл

@ -1 +1,2 @@
from .query_tasks import query_tasks
from .query_tasks import query_tasks, query_tasks_by_run
from .query_runs import query_run, query_runs

Просмотреть файл

@ -0,0 +1,41 @@
from urllib.parse import urlencode
import asyncio
import aiohttp
from a01.auth import AuthSettings
from a01.common import A01Config
from a01.models import Run, RunsView
async def query_run_async(run_id: str) -> Run:
endpoint = A01Config().ensure_config().endpoint_uri
async with aiohttp.ClientSession(headers={'Authorization': AuthSettings().access_token}) as session:
async with session.get(f'{endpoint}/run/{run_id}') as resp:
json_body = await resp.json()
return Run.from_dict(json_body)
async def query_runs_async(**kwargs) -> RunsView:
endpoint = A01Config().ensure_config().endpoint_uri
async with aiohttp.ClientSession(headers={'Authorization': AuthSettings().access_token}) as session:
url = f'{endpoint}/runs'
query = {}
for key, value in kwargs.items():
if value is not None:
query[key] = value
if query:
url = f'{url}?{urlencode(query)}'
async with session.get(url) as resp:
json_body = await resp.json()
return RunsView(runs=[Run.from_dict(each) for each in json_body])
def query_run(run_id: str) -> Run:
return asyncio.get_event_loop().run_until_complete(query_run_async(run_id))
def query_runs(owner: str = None, last: int = 10, skip: int = 0) -> RunsView:
return asyncio.get_event_loop().run_until_complete(query_runs_async(owner=owner, last=last, skip=skip))

Просмотреть файл

@ -3,18 +3,15 @@ from typing import List
import asyncio
import aiohttp
from a01.auth import AuthSettings
from a01.common import A01Config
from a01.models import Task
from a01.auth import AuthSettings
async def query_tasks_async(ids: List[str]) -> List[Task]:
endpoint = A01Config().ensure_config().endpoint_uri
access_token = AuthSettings().access_token
headers = {'Authorization': access_token}
results = []
async with aiohttp.ClientSession(headers=headers) as session:
endpoint = A01Config().ensure_config().endpoint_uri
async with aiohttp.ClientSession(headers={'Authorization': AuthSettings().access_token}) as session:
for task_id in ids:
async with session.get(f'{endpoint}/task/{task_id}') as resp:
json_body = await resp.json()
@ -23,8 +20,17 @@ async def query_tasks_async(ids: List[str]) -> List[Task]:
return results
def query_tasks(ids: List[str]) -> List[Task]:
loop = asyncio.get_event_loop()
tasks = loop.run_until_complete(query_tasks_async(ids))
async def query_tasks_by_run_async(run_id: str) -> List[Task]:
endpoint = A01Config().ensure_config().endpoint_uri
async with aiohttp.ClientSession(headers={'Authorization': AuthSettings().access_token}) as session:
async with session.get(f'{endpoint}/run/{run_id}/tasks') as resp:
json_body = await resp.json()
return [Task.from_dict(data) for data in json_body]
return tasks
def query_tasks(ids: List[str]) -> List[Task]:
return asyncio.get_event_loop().run_until_complete(query_tasks_async(ids))
def query_tasks_by_run(run_id: str) -> List[Task]:
return asyncio.get_event_loop().run_until_complete(query_tasks_by_run_async(run_id))

Просмотреть файл

@ -1,86 +1,17 @@
import json
import sys
from itertools import zip_longest
import colorama
import a01
import a01.models
from a01.common import get_logger, A01Config
from a01.cli import cmd, arg
from a01.communication import session
from a01.auth import AuthSettings, AuthenticationError
from a01.output import output_in_table
from a01.auth import AuthSettings
# pylint: disable=too-many-arguments, invalid-name
logger = get_logger(__name__)
@cmd('get runs', desc='Retrieve the runs.')
@arg('owner', help='Query runs by owner.')
@arg('me', help='Query runs created by me.')
@arg('last', help='Returns the last NUMBER of records. Default: 20.')
@arg('skip', help='Returns the records after skipping given number of records at the bottom. Default: 0.')
def get_runs(me: bool = False, last: int = 20, skip: int = 0,
owner: str = None) -> None: # pylint: disable=invalid-name
try:
if me and owner:
raise ValueError('--me and --user are mutually exclusive.')
elif me:
owner = AuthSettings().get_user_name()
runs = a01.models.RunCollection.get(owner=owner, last=last, skip=skip)
output_in_table(runs.get_table_view(), headers=runs.get_table_header())
except ValueError as err:
logger.error(err)
sys.exit(1)
except AuthenticationError as err:
logger.error(err)
print('You need to login. Usage: a01 login.', file=sys.stderr)
sys.exit(1)
@cmd('get run', desc='Retrieve a run')
@arg('run_id', help='The run id.', positional=True)
@arg('log', help="Include the failed tasks' logs.", option=('-l', '--log'))
@arg('recording', option=('-r', '--recording'),
help='Download the recording files in recording directory at current working directory. The recordings '
'are flatten with the full test path as the file name if --az-mode is not specified. If --az-mode is '
'set, the recording files are arranged in directory structure mimic Azure CLI source code.')
@arg('show_all', option=['--show-all'], help='Show all the tasks results.')
@arg('recording_az_mode', option=['--az-mode'],
help='When download the recording files the files are arranged in directory structure mimic Azure CLI '
'source code.')
@arg('raw', help='For debug.')
def get_run(run_id: str, log: bool = False, recording: bool = False, recording_az_mode: bool = False,
show_all: bool = False, raw: bool = False) -> None:
try:
tasks = a01.models.TaskCollection.get(run_id=run_id)
output_in_table(tasks.get_table_view(failed=not show_all), headers=tasks.get_table_header())
output_in_table(tasks.get_summary(), tablefmt='plain')
if log:
for failure in tasks.get_failed_tasks():
output_in_table(zip_longest(failure.get_table_header(), failure.get_table_view()), tablefmt='plain')
output_in_table(failure.get_log_content(), tablefmt='plain', foreground_color=colorama.Fore.CYAN)
output_in_table(tasks.get_summary(), tablefmt='plain')
if recording:
print()
print('Download recordings ...')
for task in tasks.tasks:
task.download_recording(recording_az_mode)
if raw:
run = a01.models.Run.get(run_id=run_id)
print(json.dumps(run.to_dict(), indent=2))
except ValueError as err:
logger.error(err)
sys.exit(1)
@cmd('create run', desc='Create a new run.')
@arg('image', help='The droid image to run.', positional=True)
@arg('parallelism', option=('-p', '--parallelism'),

Просмотреть файл