aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Williams <neil.williams@linaro.org>2017-06-19 14:04:22 +0100
committerSenthil Kumaran Shanmugasundaram <senthil.kumaran@linaro.org>2017-06-29 04:56:38 +0000
commit688113018f14867d351ad46e6dc4a20f593246c2 (patch)
tree00538f83d8b6e7d092dcedaeec668b9100ac9294
parent89b09b9aa2a53fd73701b70a04b7f6b047a9fa3c (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--.gitignore2
-rw-r--r--lava/helper/command.py6
-rw-r--r--lava/parameter.py1
-rw-r--r--lava_dashboard_tool/commands.py5
-rw-r--r--lava_scheduler_tool/commands.py358
-rw-r--r--lava_scheduler_tool/scheduler.py36
-rw-r--r--lava_tool/__init__.py2
-rw-r--r--lava_tool/authtoken.py2
-rw-r--r--lava_tool/commands/auth.py5
9 files changed, 240 insertions, 177 deletions
diff --git a/.gitignore b/.gitignore
index 379a569..6baa716 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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