diff options
author | Neil Williams <neil.williams@linaro.org> | 2017-06-19 14:04:22 +0100 |
---|---|---|
committer | Senthil Kumaran Shanmugasundaram <senthil.kumaran@linaro.org> | 2017-06-29 04:56:38 +0000 |
commit | 688113018f14867d351ad46e6dc4a20f593246c2 (patch) | |
tree | 00538f83d8b6e7d092dcedaeec668b9100ac9294 | |
parent | 89b09b9aa2a53fd73701b70a04b7f6b047a9fa3c (diff) |
Handle cancel and list errors cleanly
Debian bugs #864417 and #864418 - catch xmlrpclib
faults and output a clean useful message.
Initial pylint changes and updates
Update the code to be closer to python3 support.
Change-Id: I1abdd427f670d5d42f6c24f8fa0ee0a9e4355c7f
Reviewed-on: https://review.linaro.org/20138
Reviewed-by: lava-bot
Reviewed-by: Senthil Kumaran Shanmugasundaram <senthil.kumaran@linaro.org>
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | lava/helper/command.py | 6 | ||||
-rw-r--r-- | lava/parameter.py | 1 | ||||
-rw-r--r-- | lava_dashboard_tool/commands.py | 5 | ||||
-rw-r--r-- | lava_scheduler_tool/commands.py | 358 | ||||
-rw-r--r-- | lava_scheduler_tool/scheduler.py | 36 | ||||
-rw-r--r-- | lava_tool/__init__.py | 2 | ||||
-rw-r--r-- | lava_tool/authtoken.py | 2 | ||||
-rw-r--r-- | lava_tool/commands/auth.py | 5 |
9 files changed, 240 insertions, 177 deletions
@@ -7,3 +7,5 @@ tags *.egg-info /.ci-build-venv/ man/_build +.eric6project/ +*.e4p diff --git a/lava/helper/command.py b/lava/helper/command.py index 8dc64e9..229184c 100644 --- a/lava/helper/command.py +++ b/lava/helper/command.py @@ -115,7 +115,7 @@ class BaseCommand(Command): "ID {0}.".format(job_id)) return job_id - except xmlrpclib.Fault, exc: + except xmlrpclib.Fault as exc: raise CommandError(str(exc)) else: raise CommandError("Job file '{0}' does not exists, or is not " @@ -161,7 +161,7 @@ class BaseCommand(Command): print >> sys.stdout, "\nJob id: {0}".format(job_id) print >> sys.stdout, "Status: {0}".format(status) print >> sys.stdout, "Bundle: {0}".format(bundle) - except xmlrpclib.Fault, exc: + except xmlrpclib.Fault as exc: raise CommandError(str(exc)) def details(self, job_id): @@ -177,7 +177,7 @@ class BaseCommand(Command): print >> sys.stdout, "\nDetails of job {0}:\n".format(job_id) print >> sys.stdout, job_details - except xmlrpclib.Fault, exc: + except xmlrpclib.Fault as exc: raise CommandError(str(exc)) def create_tar_repo_job(self, job_file, testdef_file, tar_content): diff --git a/lava/parameter.py b/lava/parameter.py index dfb0883..1c68dfe 100644 --- a/lava/parameter.py +++ b/lava/parameter.py @@ -21,7 +21,6 @@ Parameter class and its accessory methods/functions. """ import sys -import types from lava_tool.utils import to_list diff --git a/lava_dashboard_tool/commands.py b/lava_dashboard_tool/commands.py index a45fa30..4e6cfa5 100644 --- a/lava_dashboard_tool/commands.py +++ b/lava_dashboard_tool/commands.py @@ -26,14 +26,11 @@ import argparse import contextlib import errno import os -import re import socket import sys -import urllib import urlparse import xmlrpclib -import simplejson from lava_tool.authtoken import AuthenticatingServerProxy, KeyringAuthBackend from lava.tool.command import Command, CommandGroup @@ -554,7 +551,7 @@ class deserialize(XMLRPCCommand): help="SHA1 of the bundle to deserialize") def invoke_remote(self): - response = self.server.deserialize(self.args.SHA1) + self.server.deserialize(self.args.SHA1) print "Bundle {sha1} deserialized".format( sha1=self.args.SHA1) diff --git a/lava_scheduler_tool/commands.py b/lava_scheduler_tool/commands.py index b2224dc..dac13d3 100644 --- a/lava_scheduler_tool/commands.py +++ b/lava_scheduler_tool/commands.py @@ -16,30 +16,28 @@ # You should have received a copy of the GNU Lesser General Public License # along with lava-scheduler-tool. If not, see <http://www.gnu.org/licenses/>. +# pylint: disable=wrong-import-position + import argparse import difflib import jinja2 import os import re +import sys import signal import subprocess -import sys import time import tempfile -import urlparse -import xmlrpclib import yaml import zmq from lava_tool.authtoken import ( - split_xmlrpc_url, get_server_url, AuthenticatingServerProxy, KeyringAuthBackend ) from lava.tool.command import Command, CommandGroup from lava.tool.errors import CommandError -from lava_dashboard_tool.commands import DataSetRenderer, _get_pretty_renderer from lava_scheduler_tool.scheduler import ( devicedictionary_to_jinja2, jinja2_to_devicedictionary, @@ -48,10 +46,21 @@ from lava_scheduler_tool.scheduler import ( DEFAULT_ARTIFACTS_URL, DEFAULT_ARTIFACTS_UPLOAD_PATH ) -from zmq.utils.strtypes import b, u + +if sys.version_info < (3, 0): + import urlparse + import xmlrpclib + from lava_dashboard_tool.commands import _get_pretty_renderer +# Enable only once python3 support is ready, then switch over. +# else: +# import urllib.parse # pylint: disable=import-error,unused-import,no-name-in-module +# import xmlrpc.client as xmlrclib # pylint: disable=import-error,unused-import + +# pylint: disable=superfluous-parens,too-few-public-methods,too-many-locals +# pylint: disable=too-many-branches,too-many-statements,too-many-return-statements -class Timeout(): +class Timeout(object): """ Timeout error class with ALARM signal. Accepts time in seconds. """ class TimeoutError(Exception): pass @@ -63,26 +72,35 @@ class Timeout(): signal.signal(signal.SIGALRM, self.timeout_raise) signal.alarm(self.sec) - def __exit__(self, *args): + def __exit__(self, *args): # pylint: disable=unused-argument signal.alarm(0) - def timeout_raise(self, *args): + def timeout_raise(self, *args): # pylint: disable=unused-argument,no-self-use raise Timeout.TimeoutError() -class scheduler(CommandGroup): +class scheduler(CommandGroup): # pylint: disable=invalid-name """ Interact with LAVA Scheduler """ namespace = "lava.scheduler.commands" + def invoke(self): + pass -class submit_job(Command): + def reparse_arguments(self, parser, raw_args): + pass + + +class submit_job(Command): # pylint: disable=invalid-name """ Submit a job to lava-scheduler """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(submit_job, cls).register_arguments(parser) @@ -121,26 +139,26 @@ class submit_job(Command): self.args.artifacts_path) validate_urls(command_text) job_ids = server.scheduler.submit_job(command_text) - except xmlrpclib.Fault, e: - raise CommandError(str(e)) + except xmlrpclib.Fault as exc: + raise CommandError(str(exc)) else: # Need to get the host in case of shortcuts usage. host = get_server_url(auth_backend, self.args.SERVER) if isinstance(job_ids, list): - print "submitted as jobs:" + print("submitted as jobs:") for job_id in job_ids: job = server.scheduler.job_details(job_id) if 'absolute_url' in job: - print urlparse.urljoin(host, job["absolute_url"]) + print(urlparse.urljoin(host, job["absolute_url"])) else: - print " -", job_id + print(" - %s" % job_id) else: job = server.scheduler.job_details(job_ids) if 'absolute_url' in job: - print "submitted as job:", urlparse.urljoin( - host, job["absolute_url"]) + print("submitted as job: %s" % urlparse.urljoin( + host, job["absolute_url"])) else: - print "submitted as job:", job_ids + print("submitted as job: %s" % job_ids) job_ids = [job_ids] if self.args.block: @@ -165,10 +183,13 @@ class submit_job(Command): print('Job Status: %s' % job['job_status']) -class resubmit_job(Command): +class resubmit_job(Command): # pylint: disable=invalid-name + + def reparse_arguments(self, parser, raw_args): + pass @classmethod - def register_arguments(self, parser): + def register_arguments(cls, parser): parser.add_argument("SERVER") parser.add_argument("JOB_ID") @@ -181,32 +202,41 @@ class resubmit_job(Command): # Need to get the host in case of shortcuts usage. host = get_server_url(auth_backend, self.args.SERVER) - except xmlrpclib.Fault, e: - raise CommandError(str(e)) + except xmlrpclib.Fault as exc: + raise CommandError(str(exc)) else: job = server.scheduler.job_details(job_id) - print "resubmitted as job:", urlparse.urljoin( - host, job["absolute_url"]) + print("resubmitted as job:", urlparse.urljoin( + host, job["absolute_url"])) -class cancel_job(Command): +class cancel_job(Command): # pylint: disable=invalid-name + + def reparse_arguments(self, parser, raw_args): + pass @classmethod - def register_arguments(self, parser): + def register_arguments(cls, parser): parser.add_argument("SERVER") parser.add_argument("JOB_ID") def invoke(self): server = AuthenticatingServerProxy( self.args.SERVER, auth_backend=KeyringAuthBackend()) - server.scheduler.cancel_job(self.args.JOB_ID) + try: + server.scheduler.cancel_job(self.args.JOB_ID) + except xmlrpclib.Fault as exc: + raise CommandError(str(exc)) -class job_output(Command): +class job_output(Command): # pylint: disable=invalid-name """ Get job output from the scheduler. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(job_output, cls).register_arguments(parser) @@ -225,9 +255,9 @@ class job_output(Command): if self.args.output is None: filename = str(self.args.JOB_ID) + '_output.txt' if os.path.exists(filename) and not self.args.overwrite: - print >> sys.stderr, "File {filename!r} already exists".format( - filename=filename) - print >> sys.stderr, "You may pass --overwrite to write over it" + sys.stderr.write("File {filename!r} already exists\n".format( + filename=filename)) + sys.stderr.write("You may pass --overwrite to write over it\n") return -1 stream = open(filename, "wb") else: @@ -238,18 +268,21 @@ class job_output(Command): self.args.SERVER, auth_backend=KeyringAuthBackend()) try: stream.write(server.scheduler.job_output(self.args.JOB_ID).data) - print "Downloaded job output of {0} to file {1!r}".format( - self.args.JOB_ID, filename) + print("Downloaded job output of {0} to file {1!r}".format( + self.args.JOB_ID, filename)) except xmlrpclib.Fault as exc: - print >> sys.stderr, exc + sys.stderr.write(exc) return -1 -class job_status(Command): +class job_status(Command): # pylint: disable=invalid-name """ Get job status and bundle sha1, if it existed, from the scheduler. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(job_status, cls).register_arguments(parser) @@ -260,18 +293,21 @@ class job_status(Command): def invoke(self): server = AuthenticatingServerProxy( self.args.SERVER, auth_backend=KeyringAuthBackend()) - job_status = server.scheduler.job_status(self.args.JOB_ID) + ret_status = server.scheduler.job_status(self.args.JOB_ID) - print "Job ID: %s\nJob Status: %s\nBundle SHA1: %s" % \ - (str(self.args.JOB_ID), job_status['job_status'], - job_status['bundle_sha1']) + print("Job ID: %s\nJob Status: %s\nBundle SHA1: %s" % + (str(self.args.JOB_ID), ret_status['job_status'], + ret_status['bundle_sha1'])) -class job_details(Command): +class job_details(Command): # pylint: disable=invalid-name """ Get job details, if it existed, from the scheduler. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(job_details, cls).register_arguments(parser) @@ -282,18 +318,17 @@ class job_details(Command): def invoke(self): server = AuthenticatingServerProxy( self.args.SERVER, auth_backend=KeyringAuthBackend()) - job_details = server.scheduler.job_details(self.args.JOB_ID) + ret_details = server.scheduler.job_details(self.args.JOB_ID) - print "Details of job {0}: \n".format(str(self.args.JOB_ID)) - for detail in job_details: - print "%s: %s" % (detail, job_details[detail]) + print("Details of job {0}: \n".format(str(self.args.JOB_ID))) + for detail in ret_details: + print("%s: %s" % (detail, ret_details[detail])) -class jobs_list(Command): +class jobs_list(Command): # pylint: disable=invalid-name """ Get list of running and submitted jobs from the scheduler. """ - renderer = _get_pretty_renderer( order=('id', 'description', 'status', 'actual_device', 'requested_device'), column_map={ @@ -308,6 +343,9 @@ class jobs_list(Command): empty="There are no running or submitted jobs", caption="Jobs list") + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(jobs_list, cls).register_arguments(parser) @@ -316,10 +354,13 @@ class jobs_list(Command): def invoke(self): server = AuthenticatingServerProxy( self.args.SERVER, auth_backend=KeyringAuthBackend()) - jobs_list = server.scheduler.all_jobs() + try: + ret_list = server.scheduler.all_jobs() + except xmlrpclib.Fault as exc: + raise CommandError(str(exc)) data_for_renderer = [] - for row in jobs_list: + for row in ret_list: if row[6]: job_id = row[6] else: @@ -333,13 +374,14 @@ class jobs_list(Command): act_d = row[3]["hostname"] else: act_d = "" - data_for_renderer.append(dict(zip(['id', 'description', 'status', 'actual_device', 'requested_device'], - [job_id, row[1], row[2], act_d, req_d]))) + data_for_renderer.append( + dict(zip(['id', 'description', 'status', 'actual_device', 'requested_device'], + [job_id, row[1], row[2], act_d, req_d]))) self.renderer.render(data_for_renderer) -class devices_list(Command): +class devices_list(Command): # pylint: disable=invalid-name """ Get list of devices from the scheduler. """ @@ -356,6 +398,9 @@ class devices_list(Command): empty="There are no devices", caption="Devices list") + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(devices_list, cls).register_arguments(parser) @@ -372,18 +417,22 @@ class devices_list(Command): job_id = row[3] else: job_id = "" - data_for_renderer.append(dict(zip(['hostname', 'device_type_name', 'status', 'job'], - [row[0], row[1], row[2], job_id]))) + data_for_renderer.append( + dict(zip(['hostname', 'device_type_name', 'status', 'job'], + [row[0], row[1], row[2], job_id]))) self.renderer.render(data_for_renderer) -class get_pipeline_device_config(Command): +class get_pipeline_device_config(Command): # pylint: disable=invalid-name """ Get the pipeline device configuration from scheduler to a local file or stdout. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(get_pipeline_device_config, cls).register_arguments(parser) @@ -406,9 +455,9 @@ class get_pipeline_device_config(Command): if self.args.output is None and not self.args.stdout: filename = str(self.args.DEVICE_HOSTNAME) + '_config.yaml' if os.path.exists(filename) and not self.args.overwrite: - print >> sys.stderr, "File {filename!r} already exists".format( - filename=filename) - print >> sys.stderr, "You may pass --overwrite to write over it" + sys.stderr.write("File {filename!r} already exists\n".format( + filename=filename)) + sys.stderr.write("You may pass --overwrite to write over it\n") return -1 stream = open(filename, "wb") elif self.args.stdout: @@ -423,18 +472,21 @@ class get_pipeline_device_config(Command): try: stream.write(server.scheduler.get_pipeline_device_config( self.args.DEVICE_HOSTNAME).data) - print "Downloaded device config of {0} to file {1!r}".format( - self.args.DEVICE_HOSTNAME, filename) + print("Downloaded device config of {0} to file {1!r}".format( + self.args.DEVICE_HOSTNAME, filename)) except xmlrpclib.Fault as exc: - print >> sys.stderr, exc + sys.stderr.write(exc) return -1 -class compare_device_conf(Command): +class compare_device_conf(Command): # pylint: disable=invalid-name """ Compare device config YAML files. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(compare_device_conf, cls).register_arguments(parser) @@ -459,26 +511,26 @@ class compare_device_conf(Command): # Validate number of arguments depending on the options. if self.args.use_stored is None: if len(self.args.CONFIGS) != 2: - print >> sys.stderr, "Please input two arguments with config file paths" - print >> sys.stderr, "You may use --use-stored with one config file path" + sys.stderr.write("Please input two arguments with config file paths\n") + sys.stderr.write("You may use --use-stored with one config file path\n") return -1 for path in self.args.CONFIGS: if not os.path.exists(path): - print >> sys.stderr, "File {path!r} does not exist".format( - path=path) + sys.stderr.write("File {path!r} does not exist\n".format( + path=path)) return -1 else: if len(self.args.CONFIGS) != 1: - print >> sys.stderr, "Please input one argument with config file path" - print >> sys.stderr, "You may omit --use-stored and use two config file paths" + sys.stderr.write("Please input one argument with config file path\n") + sys.stderr.write("You may omit --use-stored and use two config file paths\n") return -1 path = self.args.CONFIGS[0] if not os.path.exists(path): - print >> sys.stderr, "File {path!r} does not exist".format( - path=path) + sys.stderr.write("File {path!r} does not exist\n".format( + path=path)) return -1 # Run device-dictionary --preview and load it into tmp file. @@ -490,7 +542,7 @@ class compare_device_conf(Command): "--export" ] - config_handle, config_path = tempfile.mkstemp() + _, config_path = tempfile.mkstemp() return_code = subprocess.call( args, @@ -498,7 +550,7 @@ class compare_device_conf(Command): ) if return_code != 0: - print >> sys.stderr, "Device config for {device!r} doesn't exists".format(device=self.args.use_stored) + sys.stderr.write("Device config for {device!r} doesn't exist\n".format(device=self.args.use_stored)) return -1 configs.append(config_path) @@ -530,25 +582,25 @@ class compare_device_conf(Command): else: # 'Extends' not matched. Treat this as a regular config file. try: - yaml.safe_load(file(path, 'r')) + yaml.safe_load(open(path, 'r')) except yaml.YAMLError: - print "Please provide a valid YAML configuration file." + print("Please provide a valid YAML configuration file.") sys.exit(2) device_configuration = [] with open(path) as read_file: - device_configuration = [line.strip('\n') for line in read_file.readlines()] + device_configuration = [dline.strip('\n') for dline in read_file.readlines()] device_confs.append(device_configuration) diff = difflib.unified_diff(device_confs[0], device_confs[1], fromfile=configs[0], tofile=configs[1]) - input = [line for line in diff] + data_input = [iline for iline in diff] if self.args.wdiff: # Pass diff to wdiff for word diff output. - diff_handle, diff_path = tempfile.mkstemp() + tempfile.mkstemp() args = ["wdiff", "-d"] @@ -557,31 +609,31 @@ class compare_device_conf(Command): stdin=subprocess.PIPE, stdout=subprocess.PIPE ) - out, err = proc.communicate("\n".join(input)) + out, _ = proc.communicate("\n".join(data_input)) if out: - print out + print(out) if not self.args.wdiff: - for line in input: - print line + for line in data_input: + print(line) - if not input: - print "Success. The configuration files are identical." + if not data_input: + print("Success. The configuration files are identical.") return 0 - def _parse_template(self, device_file): + def _parse_template(self, device_file): # pylint: disable=no-self-use if not os.path.exists(os.path.realpath(device_file)): - print "Unable to find file '%s'\n" % device_file + print("Unable to find file '%s'\n" % device_file) sys.exit(2) with open(device_file, 'r') as fileh: content = fileh.read() return jinja2_to_devicedictionary(content) -class device_dictionary(Command): +class device_dictionary(Command): # pylint: disable=invalid-name """ Update or export device dictionary data as jinja2 data. [Superusers only.] @@ -589,7 +641,7 @@ class device_dictionary(Command): def invoke(self): if self.args.update and self.args.export: - print >> sys.stderr, "Please use either update or export." + sys.stderr.write("Please use either update or export.\n") return 1 elif self.args.export: hostname = str(self.args.DEVICE_HOSTNAME) @@ -600,7 +652,7 @@ class device_dictionary(Command): try: stream.write(server.scheduler.export_device_dictionary(hostname).data) except xmlrpclib.Fault as exc: - print >> sys.stderr, exc + sys.stderr.write("%s\n" % str(exc)) return -1 elif self.args.update: server = AuthenticatingServerProxy( @@ -608,19 +660,19 @@ class device_dictionary(Command): hostname = str(self.args.DEVICE_HOSTNAME) filename = self.args.update if not os.path.exists(filename): - print >> sys.stderr, "File {filename!r} does not exist".format( - filename=filename) + sys.stderr.write("File {filename!r} does not exist\n".format( + filename=filename)) return -1 with open(filename, "r") as reader: data = reader.read() - print "Updating device dictionary for %s on %s" % (hostname, self.args.SERVER) + print("Updating device dictionary for %s on %s\n" % (hostname, self.args.SERVER)) try: - print server.scheduler.import_device_dictionary(hostname, data) + print(server.scheduler.import_device_dictionary(hostname, data)) except xmlrpclib.Fault as exc: - print >> sys.stderr, exc + sys.stderr.write("%s\n" % str(exc)) return -1 else: - print >> sys.stderr, "Unrecognised options." + sys.stderr.write("Unrecognised options.\n") return 2 def reparse_arguments(self, parser, raw_args): @@ -639,7 +691,7 @@ class device_dictionary(Command): help="Export the device dictionary for this device as jinja2") -class wait_job_events(Command): +class wait_job_events(Command): # pylint: disable=invalid-name """ Wait for job to finish and return job details. """ @@ -647,6 +699,9 @@ class wait_job_events(Command): FINISHED_JOB_STATUS = ["Complete", "Incomplete", "Canceled"] EVENT_SOCKET_PATTERN_SYMBOL = "*" + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(wait_job_events, cls).register_arguments(parser) @@ -693,12 +748,13 @@ class wait_job_events(Command): job = server.scheduler.job_details(self.args.job_id) if job["status"] in self.FINISHED_JOB_STATUS: - print "Job %s already finished with status %s." % ( - self.args.job_id, job["status"]) + print("Job %s already finished with status %s." % ( + self.args.job_id, job["status"])) return - except xmlrpclib.Fault as e: - print "Job details did not found specified job. Please make sure job-id exists or that this job is about to get submitted." + except xmlrpclib.Fault: + print("Job details were not found for the specified job. " + "Please make sure job-id exists or that this job is about to get submitted.") else: if not os.path.exists(self.args.job_definition): @@ -707,8 +763,8 @@ class wait_job_events(Command): try: with open(self.args.job_definition, 'rb') as stream: command_text = stream.read() - except IOError as e: - print >> sys.stderr, e + except IOError as exc: + sys.stderr.write("%s\n" % str(exc)) return -1 try: if self.args.publish_artifacts: @@ -722,13 +778,13 @@ class wait_job_events(Command): if not isinstance(job_ids, list): job_ids = [job_ids] - print "submitted as job(s):" + print("submitted as job(s):") for job_id in job_ids: job = server.scheduler.job_details(job_id) - print urlparse.urljoin(host, job["absolute_url"]) + print(urlparse.urljoin(host, job["absolute_url"])) - except xmlrpclib.Fault, e: - raise CommandError(str(e)) + except xmlrpclib.Fault as exc: + raise CommandError(str(exc)) job_url_template = urlparse.urljoin( host, job["absolute_url"].rsplit("/", 1)[0]) @@ -740,16 +796,16 @@ class wait_job_events(Command): try: with Timeout(self.args.timeout): context = zmq.Context.instance() - sock = context.socket(zmq.SUB) + sock = context.socket(zmq.SUB) # pylint: disable=no-member - sock.setsockopt(zmq.SUBSCRIBE, b"") + sock.setsockopt(zmq.SUBSCRIBE, b"") # pylint: disable=no-member sock.connect(event_socket) - print >> sys.stdout, "Now waiting for job events...\n" + print("Now waiting for job events...\n") while True: msg = sock.recv_multipart() try: - (topic, uuid, dt, username, data) = msg[:] + (topic, uuid, device_type, username, data) = msg[:] # pylint: disable=unused-variable except IndexError: # Droping invalid message continue @@ -762,27 +818,27 @@ class wait_job_events(Command): data["job"] = urlparse.urljoin( job_url_template, str(data["job"])) if data["status"] in self.FINISHED_JOB_STATUS: - print data, "\n" + print(data, "\n") break elif not self.args.quiet: - print data, "\n" + print(data, "\n") - except zmq.error.ZMQError as e: - print >> sys.stderr, "wait_job_events() error: %s" % e + except zmq.error.ZMQError as exc: + sys.stderr.write("wait_job_events() error: %s\n" % exc) return -1 except KeyboardInterrupt: - print >> sys.stderr, "wait_job_events() cancelled" + sys.stderr.write("wait_job_events() cancelled\n") return -1 except Timeout.TimeoutError: - print >> sys.stderr, "wait_job_events() timed out after %s seconds." % self.args.timeout + sys.stderr.write("wait_job_events() timed out after %s seconds.\n" % self.args.timeout) try: for job_id in job_ids: - job_details = server.scheduler.job_details(job_id) - print >> sys.stdout, "Job %s currently has status %s." % ( - job_id, job_details["status"]) - print >> sys.stdout, "You can check the job details with 'lava-tool job-details' command." + ret_details = server.scheduler.job_details(job_id) + print("Job %s currently has status %s." % ( + job_id, ret_details["status"])) + print("You can check the job details with 'lava-tool job-details' command.") return 1 - except xmlrpclib.Fault as e: + except xmlrpclib.Fault: # Keep silent, message about non-existing job is already # printed during first job_details() call. return -1 @@ -790,11 +846,14 @@ class wait_job_events(Command): return 0 -class validate_pipeline_devices(Command): +class validate_pipeline_devices(Command): # pylint: disable=invalid-name """ Validate pipeline devices on the specified server. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(validate_pipeline_devices, cls).register_arguments(parser) @@ -809,17 +868,20 @@ class validate_pipeline_devices(Command): self.args.SERVER, auth_backend=auth_backend) try: - print server.scheduler.validate_pipeline_devices( - self.args.name) - except xmlrpclib.Fault, e: - raise CommandError(str(e)) + print(server.scheduler.validate_pipeline_devices( + self.args.name)) + except xmlrpclib.Fault as exc: + raise CommandError(str(exc)) -class job_results(Command): +class job_results(Command): # pylint: disable=invalid-name """ Get job results as CSV or YAML. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(job_results, cls).register_arguments(parser) @@ -839,18 +901,21 @@ class job_results(Command): try: if self.args.csv: - print server.results.get_testjob_results_csv(self.args.JOB_ID) + print(server.results.get_testjob_results_csv(self.args.JOB_ID)) else: - print server.results.get_testjob_results_yaml(self.args.JOB_ID) - except xmlrpclib.Fault as e: - print "Command did not found specified job. Please make sure JOB_ID exists on the specified SERVER." + print(server.results.get_testjob_results_yaml(self.args.JOB_ID)) + except xmlrpclib.Fault: + print("Command did not found specified job. Please make sure JOB_ID exists on the specified SERVER.") -class test_suite_results(Command): +class test_suite_results(Command): # pylint: disable=invalid-name """ Get test suite results as CSV or YAML. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(test_suite_results, cls).register_arguments(parser) @@ -872,22 +937,26 @@ class test_suite_results(Command): try: if self.args.csv: - print server.results.get_testsuite_results_csv( + print(server.results.get_testsuite_results_csv( self.args.JOB_ID, - self.args.SUITE_NAME) + self.args.SUITE_NAME)) else: - print server.results.get_testsuite_results_yaml( + print(server.results.get_testsuite_results_yaml( self.args.JOB_ID, - self.args.SUITE_NAME) - except xmlrpclib.Fault as e: - print "Command did not found specified job or test suite. Please make sure JOB_ID and SUITE_NAME exist on the specified SERVER." + self.args.SUITE_NAME)) + except xmlrpclib.Fault: + print("Command did not find the specified job or test suite. " + "Please make sure JOB_ID and SUITE_NAME exist on the specified SERVER.") -class test_case_results(Command): +class test_case_results(Command): # pylint: disable=invalid-name """ Get test case results as CSV or YAML. """ + def reparse_arguments(self, parser, raw_args): + pass + @classmethod def register_arguments(cls, parser): super(test_case_results, cls).register_arguments(parser) @@ -911,14 +980,15 @@ class test_case_results(Command): try: if self.args.csv: - print server.results.get_testcase_results_csv( + print(server.results.get_testcase_results_csv( self.args.JOB_ID, self.args.SUITE_NAME, - self.args.TEST_CASE) + self.args.TEST_CASE)) else: - print server.results.get_testcase_results_yaml( + print(server.results.get_testcase_results_yaml( self.args.JOB_ID, self.args.SUITE_NAME, - self.args.TEST_CASE) - except xmlrpclib.Fault as e: - print "Command did not found specified job, test suite or test case. Please make sure JOB_ID, SUITE_NAME and TEST_CASE exist on the specified SERVER." + self.args.TEST_CASE)) + except xmlrpclib.Fault: + print("Command did not find the specified job, test suite or test case. " + "Please make sure JOB_ID, SUITE_NAME and TEST_CASE exist on the specified SERVER.") diff --git a/lava_scheduler_tool/scheduler.py b/lava_scheduler_tool/scheduler.py index 81188c3..e0f68c2 100644 --- a/lava_scheduler_tool/scheduler.py +++ b/lava_scheduler_tool/scheduler.py @@ -38,7 +38,7 @@ def devicedictionary_to_jinja2(data_dict, extends): (including file name extension / suffix) which jinja2 will later assume to be in the jinja2 device_types folder """ - if type(data_dict) is not dict: + if not isinstance(data_dict, dict): return None data = u'{%% extends \'%s\' %%}\n' % extends for key, value in data_dict.items(): @@ -53,7 +53,7 @@ def jinja2_to_devicedictionary(data_dict): Do some string mangling to convert the template to a key value store The reverse of lava_scheduler_app.utils.devicedictionary_to_jinja2 """ - if type(data_dict) is not str: + if not isinstance(data_dict, dict): return None data = {} for line in data_dict.replace('{% ', '').replace(' %}', '').split('\n'): @@ -96,28 +96,28 @@ def validate_single_url(url): for url in urls: if url[1] == 'git': try: - output = subprocess.check_output(['/usr/bin/git', 'ls-remote', - '--exit-code', '-h', url[0]], - stderr=subprocess.STDOUT) + subprocess.check_output(['/usr/bin/git', 'ls-remote', + '--exit-code', '-h', url[0]], + stderr=subprocess.STDOUT) except subprocess.CalledProcessError as exc: - print >> sys.stderr, "Warning: %s" % exc + sys.stderr.write("Warning: %s\n" % exc) else: try: res = requests.head(url[0], allow_redirects=True, timeout=HTTP_DOWNLOAD_TIMEOUT) - if res.status_code != requests.codes.OK: + if res.status_code != requests.codes.OK: # pylint: disable=no-member res = requests.get( url[0], allow_redirects=True, stream=True, timeout=HTTP_DOWNLOAD_TIMEOUT) - if res.status_code != requests.codes.OK: - print >> sys.stderr, "Warning: Resources not available at '%s'" % (url[0]) + if res.status_code != requests.codes.OK: # pylint: disable=no-member + sys.stderr.write("Warning: Resources not available at '%s'\n" % (url[0])) except requests.Timeout: - print >> sys.stderr, "Warning: '%s' timed out" % (url[0]) + sys.stderr.write("Warning: '%s' timed out\n" % (url[0])) except requests.ConnectionError as exc: - print >> sys.stderr, "Warning: failed to connect to %s" % url[0] + sys.stderr.write("Warning: failed to connect to %s\n" % url[0]) except requests.RequestException as exc: - print >> sys.stderr, "Warning: request failed to %s" % url[0] + sys.stderr.write("Warning: %s\n" % exc) def publish_artifacts(definition, artifacts_url=DEFAULT_ARTIFACTS_URL, @@ -126,13 +126,13 @@ def publish_artifacts(definition, artifacts_url=DEFAULT_ARTIFACTS_URL, data = yaml.safe_load(definition) # Check job definition for relevant data. if 'secrets' not in data: - print >> sys.stderr, "Warning: Job definition is missing 'secrets' section. Artifacts will not be published." + sys.stderr.write("Warning: Job definition is missing 'secrets' section. Artifacts will not be published.\n") return if 'API_KEY' not in data["secrets"]: - print >> sys.stderr, "Warning: Job definition 'secrets' section is missing 'API_KEY'. Artifacts will not be published." + sys.stderr.write("Warning: Job definition 'secrets' section is missing 'API_KEY'. Artifacts will not be published.\n") return if 'API_USER' not in data["secrets"]: - print >> sys.stderr, "Warning: Job definition 'secrets' section is missing 'API_USER'. Artifacts will not be published." + sys.stderr.write("Warning: Job definition 'secrets' section is missing 'API_USER'. Artifacts will not be published.\n") return local_urls = re.findall(r'(file:///[^\s]+)', definition) @@ -148,15 +148,15 @@ def publish_artifacts(definition, artifacts_url=DEFAULT_ARTIFACTS_URL, 'token': data["secrets"]["API_KEY"] } - print >> sys.stdout, "Uploading artifact %s" % local_url + print("Uploading artifact %s" % local_url) request = requests.post( urlparse.urljoin(artifacts_url, artifacts_upload_path), files=files, data=post_data) - if request.status_code != requests.codes.OK: - print >> sys.stderr, "File at %s could not be uploaded. Please contact LAVA support team." % local_url + if request.status_code != requests.codes.OK: # pylint: disable=no-member + sys.stderr.write("File at %s could not be uploaded. Please contact LAVA support team.\n" % local_url) continue definition = definition.replace( diff --git a/lava_tool/__init__.py b/lava_tool/__init__.py index f4fdab3..3dea85c 100644 --- a/lava_tool/__init__.py +++ b/lava_tool/__init__.py @@ -19,4 +19,4 @@ def version(): - return "0.21" + return "0.22" diff --git a/lava_tool/authtoken.py b/lava_tool/authtoken.py index a2abd6a..4f03d0d 100644 --- a/lava_tool/authtoken.py +++ b/lava_tool/authtoken.py @@ -197,7 +197,7 @@ class KeyringAuthBackend(AuthBackend): if item[0] == USERNAME_OPTION_DEFAULT and \ item[1] == username: self.config.remove_option(endpoint_url, item[0]) - except NoSectionError: # No shortcut or default, ignore. + except configparser.NoSectionError: # No shortcut or default, ignore. pass else: raise UsernameNotFoundError("Username not found.") diff --git a/lava_tool/commands/auth.py b/lava_tool/commands/auth.py index f465350..9888117 100644 --- a/lava_tool/commands/auth.py +++ b/lava_tool/commands/auth.py @@ -17,7 +17,6 @@ # along with lava-tool. If not, see <http://www.gnu.org/licenses/>. import getpass -import urllib import urlparse import xmlrpclib @@ -28,13 +27,9 @@ from lava_tool.authtoken import ( DuplicateEndpointShortcutError, DuplicateUserShortcutError, EndpointNotFoundError, - UsernameNotFoundError, - ConfigOptionsNotProvidedError, normalize_xmlrpc_url, split_xmlrpc_url, - USERNAME_OPTION_DEFAULT, USERNAME_OPTION_SHORT, - ENDPOINT_OPTION_SHORT, CONFIG_OPTIONS ) from lava_tool.interface import Command, LavaCommandError |