Issue and metric API examples
These examples are written in Python, but should be simple enough to understand even without an in-depth knowledge of that language.
All of the examples below use demosthenes, a C/C++ sample project installed with the Validate package at <server_install>/samples/demosthenes. The demosthenes sample project is only available when the entire Validate package is installed; it is not included with the Validate Server package. See the README file in that directory for instructions on how to set up the sample project.
You can try out the example scripts on the sample project, or on your own project. If you use them on your own project, you need to change the value for project. You may also need to change the value for host from localhost to your own Klocwork Server host.
For additional information on request parameters, you can visit http(s)://<klocwork_server_host>:<klocwork_server_port>/review/api.
For most of the examples below, with the exception of printing the project list, you can specify a stream by including the full path in the project field. For example: project = "myProj/myStream1/subVariant"
About error handling in these examples
When curl calls are made using the Web API, any errors that are encountered are printed to the console automatically. Note that the Python examples in this topic provide simplified error handling, for example:
builds = report(url, project, user, action)
print("Existing builds:")
for build in builds:
print(build)
To better handle errors in your own Python scripts, use a try block:
try:
builds = report(url, project, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Existing builds:")
for build in builds:
print(build)
About the following examples
This module (kwutil), which is used by the examples below, handles reading ltokens from your system. It has been made into a separate module for readability. Be sure to copy and paste the code below to create the kwutil module.
import os.path
def get_token(host, port, user):
ltoken = os.path.normpath(os.path.expanduser("~/.klocwork/ltoken"))
ltoken_file = open(ltoken, 'r')
for r in ltoken_file:
rd = r.strip().split(';')
if rd[0] == host and rd[1] == str(port) and rd[2] == user:
ltoken_file.close()
return rd[3]
ltoken_file.close()
Example: Search for all critical issues
This example script searches for all critical issues (with severities 1, 2 and 3) in the latest build of the Demosthenes sample project.
import getpass
import json
import time
import urllib.parse
import urllib.request
import kwutil
class Issue(object):
def __init__(self, attrs):
self.id = attrs["id"]
self.message = attrs["message"]
self.file = attrs["file"]
self.method = attrs["method"]
self.code = attrs["code"]
self.severity = attrs["severity"]
self.severityCode = attrs["severityCode"]
self.supportLevel = attrs["supportLevel"]
self.supportLevelCode = attrs["supportLevelCode"]
self.state = attrs["state"]
self.status = attrs["status"]
self.taxonomyName = attrs["taxonomyName"]
self.url = attrs["url"]
self.created = time.ctime(attrs["dateOriginated"] / 1000)
def __str__(self):
return "[%d] %s\n\t%s | %s\n\tCode %s | Severity: %s(%d) | Support Level: %s(%d) | State: %s | Status: %s | Taxonomy: %s | Created: %s\n\t%s" % (
self.id, self.message, self.file, self.method, self.code, self.severity, self.severityCode, self.supportLevel,
self.supportLevelCode, self.state,
self.status, self.taxonomyName, self.created, self.url
)
def from_json(json_object):
if 'id' in json_object:
return Issue(json_object)
return json_object
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
url = "http://%s:%d/review/api" % (host, port)
values = {"project": project, "user": user, "action": "search"}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
values["query"] = "severity:1-3"
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
for record in response:
print(json.loads(record, object_hook=from_json))
Example: Report detected issues
This example shows the distribution of detected issues by component, grouped by state.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Key(object):
def __init__(self, attrs):
self.id = attrs["id"]
self.name = attrs["name"]
def __str__(self):
return "%s (%d)" % (self.name, self.id)
class Report(object):
def __init__(self, attrs):
self.rows = attrs["rows"]
self.columns = attrs["columns"]
self.data = attrs["data"]
def __str__(self):
result = ""
maxRowName = 0
for r in self.rows:
maxRowName = max(len(str(r)), maxRowName)
maxRowName += 1
header = ' ' * maxRowName
colPosition = []
for c in self.columns:
colPosition.append(len(header) + len(str(r)))
header += str(c) + ' '
result += header + '\n'
for x in range(len(self.rows)):
rHead = ('%-' + str(maxRowName) + 's') % str(self.rows[x])
for y in range(len(self.columns)):
rHead += ('%' + str(len(str(self.columns[y]))) + 's') % str(self.data[x][y]) + ' '
result += rHead + '\n'
return result
def from_json(json_object):
if 'rows' in json_object:
return Report(json_object)
if 'id' in json_object:
return Key(json_object)
return json_object
def report(url, project, user, x=None, y=None, view=None, xDrilldown=-1, yDrilldown=-1):
values = {"project": project, "user": user, "action": "report"}
login_token = kwutil.get_token(host, port, user)
if x is not None:
values["x"] = x
if y is not None:
values["y"] = y
if login_token is not None:
values["ltoken"] = login_token
if view is not None:
values["view"] = view
if xDrilldown != -1:
values["xDrilldown"] = xDrilldown
if yDrilldown != -1:
values["yDrilldown"] = yDrilldown
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
for record in response:
return json.loads(record, object_hook=from_json)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
url = "http://%s:%d/review/api" % (host, port)
try:
reports = report(url, project, user, "Component", "State")
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print(reports)
Example: Retrieve issue details
This example shows how to get details about a specified issue ID.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Details(object):
def __init__(self, attrs):
self.id = attrs["id"]
self.code = attrs["code"]
self.name = attrs["name"]
self.location = attrs["location"]
self.build = attrs["build"]
self.severity = attrs["severity"]
self.supportLevel = attrs["supportLevel"]
self.owner = attrs["owner"]
self.state = attrs["state"]
self.status = attrs["status"]
if "history" in attrs:
self.history = attrs["history"]
else:
self.history = None
if "xSync" in attrs:
self.xsync = attrs["xsync"]
else:
self.xsync = None
def __str__(self):
result = "Id:%s, Code:%s, Name:%s, Location:%s, Build:%s, Severity:%s, Support Level%s, Owner:%s, State:%s, Status:%s, History:%s" % (
self.id, self.code, self.name, self.location, self.build, self.severity, self.supportLevel, self.owner,
self.state,
self.status, self.history)
if self.xsync is not None:
result = result + ", XSyncInfo:%s" % self.xsync
return result
def from_json(json_object):
# print json_object
return Details(json_object)
def report(url, user, action, project, id, xsync=None):
values = {"user": user, "action": action, "project": project, "id": id}
if xsync is not None:
values['include_xsync'] = xsync
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
# print "R:" ,record
result.append(from_json(json.loads(record)))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
action = "issue_details"
url = "http://%s:%d/review/api" % (host, port)
project = "demosthenes"
id = "4"
xsync = "false"
try:
issue_details = report(url, user, action, project, id, xsync)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Issue Details:")
for details in issue_details:
print(details)
Example: Retrieve CI issue details
This example shows how to get details about a specified CI issue ID.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Details(object):
def __init__(self, attrs):
self.id = attrs["id"]
self.code = attrs["code"]
self.name = attrs["name"]
self.location = attrs["location"]
self.build = attrs["build"]
self.severity = attrs["severity"]
self.supportLevel = attrs["supportLevel"]
self.owner = attrs["owner"]
self.status = attrs["status"]
if "history" in attrs:
self.history = attrs["history"]
else:
self.history = None
if "xSync" in attrs:
self.xsync = attrs["xsync"]
else:
self.xsync = None
def __str__(self):
result = "Id:%s, Code:%s, Name:%s, Location:%s, Build:%s, Severity:%s, Support Level%s, Owner:%s, State:%s, Status:%s, History:%s" % (
self.id, self.code, self.name, self.location, self.build, self.severity, self.supportLevel, self.owner,
self.state,
self.status, self.history)
if self.xsync is not None:
result = result + ", XSyncInfo:%s" % self.xsync
return result
def from_json(json_object):
# print json_object
return Details(json_object)
def report(url, user, action, project, id, ci_build_name):
values = {"user": user, "action": action, "project": project, "id": id, "ci_build_name": ci_build_name}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
# print "R:" ,record
result.append(from_json(json.loads(record)))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
action = "ci_issue_details"
url = "http://%s:%d/review/api" % (host, port)
project = "demosthenes"
id = "1"
ci_build_name = "ci_build_1"
try:
ci_issue_details = report(url, user, action, project, id, ci_build_name)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Issue Details:")
for details in ci_issue_details:
print(details)
Example: Update issue status
This example shows how to change issue status, comment(s), owner(s), and bug tracker ID for any specified issues.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Status(object):
def __init__(self, attrs):
self.status_message = attrs["status_message"]
def __str__(self):
result = "Status message:%s" % self.status_message
return result
def from_json(json_object):
return Status(json_object)
def update_status(url, user, project, ids, status=None, comment=None, owner=None, bug_tracker_id=None):
values = {'action': 'update_status', 'project': project, 'user': user, 'ids': ids}
if status is not None:
values['status'] = status
if comment is not None:
values['comment'] = comment
if owner is not None:
values['owner'] = owner
if bug_tracker_id is not None:
values['bug_tracker_id'] = bug_tracker_id
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
url = "http://%s:%d/review/api" % (host, port)
project = "demosthenes"
id = "1"
status = "Fix"
comment = "Making a status change"
owner = "jsmith" # pass "unowned" to clear the owner
try:
status_messages = update_status(url, user, project, id, status, comment, owner)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Update Status:")
for message in status_messages:
print(message)
Example: Print the project list
This example shows how to print the list of projects.
By default, the query returns a list of base projects only. You can also have the query show all base projects and streams by specifying the include_streams flag with a value of true (default is false). For example, include a query with the following values:
-
action=projects
-
user=someone
-
include_streams=true
...returns the following aggregate results:
{"id":"project1","name":"project1","creator":"someone","description":""}
{"id":"project1_sub1","name":"project1/sub1","creator":"someone","description":"","tags":["s"]}
{"id":"project1_sub2","name":"project1/sub1/sub2","creator":"someone","description":""}
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class View(object):
def __init__(self, attrs):
self.name = attrs["name"]
def __str__(self):
result = "%s" % self.name
return result
def from_json(json_object):
return View(json_object)
def report(url, user, action):
values = {"user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
action = "projects"
url = "http://%s:%d/review/api" % (host, port)
try:
projects = report(url, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Existing projects:")
for project in projects:
print(project)
Example: Update projects
This example shows how to update the name and description for a specified project.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def update_project(url, name, user, action, description, new_name):
values = {"name": name, "user": user, "action": action, "description": description, "new_name": new_name}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
name = "demosthenes"
action = "update_project"
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
new_name = "demosthenes2"
url = "http://%s:%d/review/api" % (host, port)
try:
update_project(url, name, user, action, description, new_name)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Project updated!")
You can also use this action to turn on auto-deletion of builds and set how many you would like to keep with the threshold parameter.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def update_project(url, name, user, action, auto_delete_builds, auto_delete_threshold):
values = {"name": name, "user": user, "action": action, "auto_delete_builds": auto_delete_builds,
"auto_delete_threshold": auto_delete_threshold}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
name = "demosthenes"
action = "update_project"
auto_delete_builds = "true"
auto_delete_threshold = "30"
url = "http://%s:%d/review/api" % (host, port)
try:
update_project(url, name, user, action, auto_delete_builds, auto_delete_threshold)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Project updated!")
Example: Create a project
This example shows how to create a new project.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def create_project(url, name, user, action):
values = {"name": name, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
name = "demosthenes"
action = "create_project"
url = "http://%s:%d/review/api" % (host, port)
try:
create_project(url, name, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Project created!")
Example: Delete a project
This example shows how to delete a specified project.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def delete_project(url, name, force, user, action):
values = {"name": name, "force": force, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
name = "demosthenes"
force = True
action = "delete_project"
url = "http://%s:%d/review/api" % (host, port)
try:
delete_project(url, name, force, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Project and its streams deleted!")
Example: Generate a Project Configuration report
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Config(object):
def __init__(self, attrs):
self.build = attrs["build"]
self.creationDate = attrs["creationDate"]
self.version = attrs["version"]
self.numberOfFiles = attrs["numberOfFiles"]
self.cFilesAnalyzed = attrs["cFilesAnalyzed"]
self.systemFilesAnalyzed = attrs["systemFilesAnalyzed"]
self.linesOfCode = attrs["linesOfCode"]
self.linesOfComments = attrs["linesOfComments"]
self.numberOfEntities = attrs["numberOfEntities"]
self.numberOfFunctions = attrs["numberOfFunctions"]
self.numberOfClasses = attrs["numberOfClasses"]
self.taxonomies = attrs["taxonomies"]
def __str__(self):
result = "Build:%s, Creation Date:%s, Version:%s, Number of Files:%s, C Files Analyzed:%s, System Files Analyzed:%s, Lines of Code:%s, Lines of Comments:%s. Number of Entities:%s, Number of Functions:%s, Number of Classes:%s, Taxonomies:%s" % (
self.build, self.creationDate, self.version, self.numberOfFiles, self.cFilesAnalyzed,
self.systemFilesAnalyzed,
self.linesOfCode, self.linesOfComments, self.numberOfEntities, self.numberOfFunctions, self.numberOfClasses,
self.taxonomies)
return result
def from_json(json_object):
return Config(json_object)
def report(url, user, action, project, build=None):
values = {"user": user, "action": action, "project": project}
if build is not None:
values['build'] = build
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = json.loads(response.read(), object_hook=from_json)
return result
host = "localhost"
port = 8080
user = getpass.getuser()
action = "project_configuration"
url = "http://%s:%d/review/api" % (host, port)
project = "demosthenes"
build = "build_1"
try:
result = report(url, user, action, project, build)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Project Configuration:")
print(result)
Example: Print the list of views
This example shows how to print the list of views.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class View(object):
def __init__(self, attrs):
self.name = attrs["name"]
self.query = attrs["query"]
self.creator = attrs["creator"]
if "tags" in attrs:
self.tags = attrs["tags"]
else:
self.tags = ""
self.is_public = attrs["is_public"]
def __str__(self):
result = "Name:%s (Query:%s, Creator:%s, Public:%s) Tags: [" % (
self.name, self.query, self.creator, self.is_public)
for x in range(len(self.tags)):
if not x:
result = result + self.tags[x]
else:
result = result + ',' + self.tags[x]
result += ']'
return result
def from_json(json_object):
return View(json_object)
def report(url, project, user):
values = {"project": project, "user": user, "action": "views"}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
url = "http://%s:%d/review/api" % (host, port)
try:
views = report(url, project, user)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
for view in views:
print(view)
Example: Create a view
This example shows how to create views.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def create_view(url, user, project, name, action, query, tags):
values = {"project": project, "user": user, "name": name, "action": action, "query": query, "tags": tags}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
name = "Sample View"
action = "create_view"
query = "severity:1-3"
tags = "c,security"
url = "http://%s:%d/review/api" % (host, port)
try:
create_view(url, user, project, name, action, query, tags)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("View created!")
Example: Update views
This example shows how to update views.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def update_view(url, user, project, name, newname, action, query, is_public, tags):
values = {"project": project,
"user": user,
"name": name,
"new_name": newname,
"action": action,
"query": query,
"is_public": is_public,
"tags": tags}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
name = "Sample View"
newname = "Updated Sample View"
action = "update_view"
query = "severity:1"
tags = "c,security,important"
is_public = "true"
url = "http://%s:%d/review/api" % (host, port)
try:
update_view(url, user, project, name, newname, action, query, is_public, tags)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("View updated!")
Example: Delete a view
This example shows how to delete views.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def delete_view(url, user, name, project, action):
values = {"project": project, "name": name, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
name = "Sample View"
project = "demosthenes"
action = "delete_view"
url = "http://%s:%d/review/api" % (host, port)
try:
delete_view(url, user, name, project, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("View deleted!")
Example: Print the list of modules
This example shows how to print the list of modules.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Module(object):
def __init__(self, attrs):
self.name = attrs["name"]
def __str__(self):
result = "%s" % (self.name)
return result
def from_json(json_object):
return Module(json_object)
def list_modules(url, project, user, action):
values = {"project": project, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
action = "modules"
url = "http://%s:%d/review/api" % (host, port)
try:
modules = list_modules(url, project, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Existing modules:")
for module in modules:
print(module)
Example: Create a module
This example shows how to create modules.
If an access control method has been set, you must have the Project admin role or have the 'manage modules' permission to create and edit modules. In order to add or change access permissions on a module, you need the 'assign role' permission (which a Project admin has by default).
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def create_module(url, user, project, name, action, allow_all, paths):
values = {"project": project, "user": user, "name": name, "action": action, "allow_all": allow_all, "paths": paths}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
name = "mymodule"
action = "create_module"
allow_all = "true"
paths = "**/test/*"
url = "http://%s:%d/review/api" % (host, port)
try:
create_module(url, user, project, name, action, allow_all, paths)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Module created!")
Example: Update a module
This example shows how to update a module.
If an access control method has been set, you must have the Project admin role or have the 'manage modules' permission to create and edit modules. In order to add or change access permissions on a module, you need the 'assign role' permission (which a Project admin has by default).
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def update_module(url, user, project, name, new_name, action, allow_all):
values = {"project": project, "user": user, "name": name, "new_name": new_name, "action": action,
"allow_all": allow_all}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
name = "mymodule"
new_name = "mymodule2"
action = "update_module"
allow_all = "false"
url = "http://%s:%d/review/api" % (host, port)
try:
update_module(url, user, project, name, new_name, action, allow_all)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Module updated!")
Example: Delete a module
This example shows how to delete modules.
If an access control method has been set, you must have the Project admin role or have the 'manage modules' permission to create and edit modules. In order to add or change access permissions on a module, you need the 'assign role' permission (which a Project admin has by default).
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def delete_module(url, user, name, project, action):
values = {"project": project, "name": name, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
name = "mymodule"
project = "demosthenes"
action = "delete_module"
url = "http://%s:%d/review/api" % (host, port)
try:
delete_module(url, user, name, project, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Module deleted!")
Example: Print the list of builds
This example shows how to print the list of builds. For information on build management, see Managing integration builds.
import getpass
import json
import time
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Build(object):
def __init__(self, attrs):
self.id = attrs["id"] # build id
self.name = attrs["name"] # build name
self.date = time.ctime(attrs["date"] / 1000) # build date
self.keepit = attrs["keepit"] # sticky flag
def __str__(self):
result = "%s: %s" % (self.name, self.date)
return result
def from_json(json_object):
return Build(json_object)
def report(url, project, user, action):
values = {"project": project, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
action = "builds"
url = "http://%s:%d/review/api" % (host, port)
try:
builds = report(url, project, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Existing builds:")
for build in builds:
print(build)
Example: Specify which builds to keep
This action also allows you to toggle whether a specific build should be kept by specifying the 'keepit' option.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Build(object):
def __init__(self, attrs):
self.id = attrs["id"]
self.name = attrs["name"]
self.date = attrs["date"]
def __str__(self):
return "Id: %s Name:%s Date:%i" % (self.id, self.name, self.date)
def from_json(json_object):
return Build(json_object)
def keepit(build_name, login_token):
print("retain " + build_name)
values = {"project": project, "user": user, "action": "update_build", "name": build_name, "keepit": "true"}
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
def retain(url, project, user):
values = {"project": project, "user": user, "action": "builds"}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
i = 0
for record in response:
build = json.loads(record, object_hook=from_json)
i += 1
if not i % 2:
keepit(build.name, login_token)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
url = "http://%s:%d/review/api" % (host, port)
retain(url, project, user)
Example: Delete a build
This example shows how to delete builds. For information on build management, see Managing integration builds.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def delete_build(url, user, project, build, action):
values = {"project": project, "name": build, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
build = "demosthenes_3"
action = "delete_build"
url = "http://%s:%d/review/api" % (host, port)
try:
delete_build(url, user, project, build, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Build deleted!")
Example: Create a CI build
This example shows how to create a CI build.
import getpass
import json
import time
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class CiBuild(object):
def __init__(self, attrs):
self.id = attrs["id"] # build id
self.name = attrs["name"] # build name
self.date = time.ctime(attrs["date"] / 1000) # build date
def __str__(self):
result = "%s: %s" % (self.name, self.date)
return result
def from_json(json_object):
return CiBuild(json_object)
def report(url, project, user, action):
values = {"project": project, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
action = "ci_builds"
url = "http://%s:%d/review/api" % (host, port)
try:
ci_builds = report(url, project, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Existing Ci Builds:")
for ci_build in ci_builds:
print(ci_build)
Example: Update a CI build
This example shows how to update a CI build.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def rename(url, user, action, project, old_ci_build_name, new_ci_build_name):
values = {"user": user, "action": action, "project": project, "name": old_ci_build_name, "new_name": new_ci_build_name}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
url = "http://%s:%d/review/api" % (host, port)
action = "update_ci_build"
old_ci_build_name = "ci_build_1"
new_ci_build_name = "win-ci_build_1"
try:
rename(url, user, action, project, old_ci_build_name, new_ci_build_name)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Ci Build successfully renamed")
Example: Delete a CI build
This example shows how to delete CI builds.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def delete_build(url, user, project, build, action):
values = {"project": project, "name": build, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
build = "ci_build_1"
action = "delete_ci_build"
url = "http://%s:%d/review/api" % (host, port)
try:
delete_build(url, user, project, build, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Build deleted!")
Example: Print a list of enabled checkers
This example shows how to print a list of enabled checkers.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class View(object):
def __init__(self, attrs):
self.code = attrs["code"]
self.name = attrs["name"]
self.enabled = attrs["enabled"]
self.severity = attrs["severity"]
self.supportLevel = attrs["supportLevel"]
def __str__(self):
result = "Code: %s\nName: %s\nEnabled: %s\nSeverity: %s\nSupport Level: %s\n" % (
self.code, self.name, self.enabled, self.severity, self.supportLevel)
return result
def from_json(json_object):
return View(json_object)
def report(url, project, user, action):
values = {"project": project, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
action = "defect_types"
taxonomy = "C and C++"
url = "http://%s:%d/review/api" % (host, port)
try:
defects = report(url, project, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Defect types:")
for defect in defects:
print(defect)
Example: Print a list of taxonomies
This example shows how to print a list of taxonomies.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class View(object):
def __init__(self, attrs):
self.name = attrs["name"]
self.is_custom = attrs["is_custom"]
def __str__(self):
result = "Name: %s\nIs Custom: %s\n" % (self.name, self.is_custom)
return result
def from_json(json_object):
return View(json_object)
def report(url, project, user, action):
values = {"project": project, "user": user, "action": action}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
result = []
for record in response:
result.append(json.loads(record, object_hook=from_json))
return result
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
action = "taxonomies"
url = "http://%s:%d/review/api" % (host, port)
try:
taxonomies = report(url, project, user, action)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Taxonomies:")
for taxonomy in taxonomies:
print(taxonomy)
Example: Enable and disable checkers
This example shows how to enable and disable checkers.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def set_defect(url, project, user, action, code, enabled, severity):
values = {"project": project, "user": user, "action": action, "code": code, "enabled": enabled,
"severity": severity}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
action = "update_defect_type"
code = "VOIDRET"
enabled = "True"
severity = "1"
url = "http://%s:%d/review/api" % (host, port)
try:
set_defect(url, project, user, action, code, enabled, severity)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
else:
print("Defect type %s updated!\nEnabled: %s\nSeverity: %s" % (code, enabled, severity))
Example: Report metrics
The following example reports the number of lines of commented and non-commented lines, the number of executable statements, the maximum nesting level, and cyclomatic complexity metrics for each file in project from last build.
See the Klocwork Metrics Reference for a list of valid metric codes.
import getpass
import json
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class Metric(object):
def __init__(self, attrs):
self.file = attrs["filePath"]
self.entity = attrs["entity"]
self.tag = attrs["tag"]
self.value = attrs["metricValue"]
def __str__(self):
return "%s;%s;%d" % (self.file, self.tag, self.value)
def from_json(json_object):
if 'filePath' in json_object:
return Metric(json_object)
return json_object
host = "localhost"
port = 8080
user = getpass.getuser()
project = "demosthenes"
url = "http://%s:%d/review/api" % (host, port)
values = {"project": project, "user": user, "action": "metrics"}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
values["query"] = "metric:+RNOEXSTAT,+LINESCOMM,+NCNBLOC_FILE,+RMAXLEVEL,+RCYCLOMATIC"
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
try:
response = urllib.request.urlopen(req)
for record in response:
print(json.loads(record, object_hook=from_json))
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
Aggregated search results
By default, the metrics API generates results on a per file basis. To generate aggregated search results for all files in a given query, specify the aggregate flag with a value of true (default is false). The following example shows aggregated search results:
A query with the following values:
- action=metrics
- user=someone
- query=metric:+LOC_FILE
- project=demosthenes
- aggregate=true
...returns the following aggregate results:
{"tag":"LOC_FILE","sum":8113.0,"min":3.0,"max":966.0,"entries":47}
The aggregate flag is only really useful for data that has relative meaning. In other words, if a metric can be summed, or if max and min values can be determined.
Excluding system files from search results
By default, the metrics API generates results based on all files. You can have the query omit system files by specifying the exclude_system_files flag with a value of true (default is false), for example:
A query with the following values:
- action=metrics
- user=someone
- project=demosthenes
- aggregate=true
- exclude_system_files=true
- query=metric:+LOC_FILE
Example curl request:
curl --data "action=metrics&user=someone&project=demosthenes&exclude_system_files=true&query=metric:%2bLOC_FILE&aggregate=true" http://localhost:8080/review/api
...returns the following results:
{"tag":"LOC_FILE","sum":322.0,"min":3.0,"max":68.0,"entries":13}
Importing server settings, projects and code review
You can also use the API to import server settings, projects or code reviews via the command line. This can be done for each of these methods as follows:
To import server settings
The following example imports authentication configuration, permissions, custom metrics, reports definitions and e-mail subscription settings.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def import_server_configuration(url, user, sourceURL, sourceAdmin, sourcePassword):
values = {"action": "import_server_configuration",
"user": user,
"sourceURL": sourceURL,
"sourceAdmin": sourceAdmin}
if sourcePassword is not None:
values["sourcePassword"] = sourcePassword
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
sourceURL = "http://oldhost:8080"
sourceAdmin = "old admin user name"
sourcePassword = None
url = "http://%s:%d/review/api" % (host, port)
try:
import_server_configuration(url, user, sourceURL, sourceAdmin, sourcePassword)
print("Imported server configuration!")
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
To import a project
The following example imports data collected by Klocwork for the specified project.
import getpass
import urllib.error
import urllib.parse
import urllib.request
import kwutil
def import_project(url, user, project, sourceURL, sourceAdmin, sourcePassword):
values = {"action": "import_project",
"user": user,
"project": project,
"sourceURL": sourceURL,
"sourceAdmin": sourceAdmin}
if sourcePassword is not None:
values["sourcePassword"] = sourcePassword
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
host = "localhost"
port = 8080
user = getpass.getuser()
project = "projectA"
sourceURL = "http://oldhost:8080"
sourceAdmin = "old admin user name"
sourcePassword = None
url = "http://%s:%d/review/api" % (host, port)
try:
import_project(url, user, project, sourceURL, sourceAdmin, sourcePassword)
print("Imported project!")
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
To check import status
You can use this API method to check the status of importing your server settings, project or code review.
import getpass
import json
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
import kwutil
class ImportStatus(object):
def __init__(self, project, attrs):
self.project = project
self.stage = attrs["stage"]
self.progress = attrs["progress"]
self.failed = attrs["failed"]
self.hasWarnings = attrs["hasWarnings"]
self.projectReady = attrs["projectReady"]
self.complete = attrs["complete"]
def __str__(self):
return "Project: %s\n\tStage: %s | Progress: %s%% | Failed: %s | Warnings: %s | Project Ready: %s | Complete: %s" % (
self.project, self.stage, self.progress, self.failed, self.hasWarnings, self.projectReady, self.complete)
def import_status(url, user):
values = {"action": "import_status", "user": user}
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
importStatus = []
for record in response:
attrs = json.loads(record)
for key in attrs.keys():
importStatus.append(ImportStatus(key, attrs[key]))
return importStatus
def import_project(url, user, project, sourceURL, sourceAdmin, sourcePassword=None, ):
values = {"action": "import_project",
"user": user,
"project": project,
"sourceURL": sourceURL,
"sourceAdmin": sourceAdmin}
if sourcePassword:
values["sourcePassword"] = sourcePassword
login_token = kwutil.get_token(host, port, user)
if login_token is not None:
values["ltoken"] = login_token
data = urllib.parse.urlencode(values)
data = data.encode('utf-8')
req = urllib.request.Request(url, data)
urllib.request.urlopen(req)
def wait_for_import(url, user, project):
is_timeout = False
TIME_OUT = time.time() + 60 * 20
incomplete = [project]
if len(incomplete) == 0:
return
while True:
for status in import_status(url, user):
if status.project != project:
continue
# If all operations are complete then exit the loop
if len(incomplete) == 0:
break
if status.project in incomplete:
is_timeout = time.time() > TIME_OUT
if status.complete or status.failed:
print(status.stage)
incomplete.pop(incomplete.index(status.project))
break
elif is_timeout:
print("Import of project '%s' took longer than expected." % status.project)
print("Check if import is still progressing.")
sys.exit(-1)
# If all projects are complete then exit the loop
if len(incomplete) == 0:
break
time.sleep(10)
host = "localhost"
port = 8080
user = getpass.getuser()
url = "http://%s:%d/review/api" % (host, port)
project = "demosthenes"
sourceURL = "http://oldhost:8080"
sourceAdmin = "old admin user name"
try:
import_project(url, user, project, sourceURL, sourceAdmin)
print("Import started")
wait_for_import(url, user, project)
except urllib.error.HTTPError as e:
print("Request failed:", e.reason, ":", e.read())
To check the Klocwork Server version
curl --data "action=version&user=myself&" http://jsmith.klocwork.com:8080/review/api
1 { 2 majorVersion: "10.1" 3 minorVersion: "1" 4 }
To list the statuses of all tasks running on the Klocwork Server
curl --data "action=task_status&user=myself&" http://jsmith.klocwork.com:8080/review/api