指摘とメトリック API の例
これらの例は Python で記述されていますが、この言語の深い知識がなくても理解できるほど簡単なはずです。
以下の例はすべて、<server_install>/samples/demosthenes にある Klocwork サーバー パッケージでインストールされる C/C++ サンプル プロジェクト、demosthenes を使用しています。demosthenes サンプルプロジェクトは、Klocwork サーバーパッケージ全体がインストールされている場合にのみ使用できます。それは、Validate サーバーパッケージには同梱されていません。サンプルプロジェクトの設定方法については、そのディレクトリの README ファイルを参照してください。
サンプルプロジェクトまたは自分のプロジェクトで、サンプルスクリプトを試すことができます。自分のプロジェクトで使用する場合は、projectの値を変更する必要があります。また場合によっては、hostの値を localhost から自分の Klocwork サーバー ホストに変更する必要があります。
リクエストパラメータの詳細情報は以下をご覧ください。http(s)://<klocwork_server_host>:<klocwork_server_port>/review/api.
以下のほとんどの例では、プロジェクトリストの印刷を除いて、プロジェクトフィールドにフルパスを含めることでストリームを指定できます。例: project = "myProj/myStream1/subVariant"
この例でのエラー処理について
curl で Web API を使用して呼び出しが行われると、発生するすべてのエラーが自動的にコンソールに表示されます。このトピックの Python の例では単純なエラー処理について説明していることに注意してください。
builds = report(url, project, user, action)
print("Existing builds:")
for build in builds:
print(build)
独自の Python スクリプトでより適切にエラーを処理するには、try ブロックを使用します。
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)
次の例について
以下の例で使用するこのモジュール (kwutil) では、システムからの ltokens の読み取りを扱います。読みやすいように別々のモジュールになっています。以下のコードを注意してコピーして貼り付け、kwutil モジュールを作成してください。
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()
例: 重大指摘すべての検索
このサンプル スクリプトは、Demosthenes サンプル プロジェクトの最新ビルドに含まれている重大な指摘 (重要度が 1、2、3) すべてを検索します。
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))
例: 検出された指摘のレポート
この例は、検出された指摘をコンポーネント別、ステート別にグループ化した分散を示しています。
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)
例: 指摘情報の検索
この例では、指定された指摘 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)
例: CI 指摘情報の検索
この例では、指定された CI 指摘 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)
例: 指摘ステータスの更新
この例では、特定の指摘の指摘ステータス、コメント、オーナー、バグ追跡システム ID の変更方法を説明しています。
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"
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)
例: プロジェクトリストの表示
この例では、プロジェクト リストの表示方法を示します。
デフォルトでは、クエリはベースプロジェクトのみのリストを返します。include_streams フラグに true の値 (デフォルトは false) を指定することで、クエリにすべてのベースプロジェクトとストリームを表示させることもできます。たとえば、次の値でクエリを含めるようにします。
-
action=projects
-
user=someone
-
include_streams=true
...次の集計結果が生成されて返されます:
{"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)
例: プロジェクトの更新
この例では、指定したプロジェクトの名前および説明の更新方法を示します。
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!")
また、このアクションを使用すると、ビルドの自動削除をオンにし、しきい値パラメーターを使用して保持する数を設定できます。
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!")
例: プロジェクトの作成
この例では、新しいプロジェクトの作成方法を示します。
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!")
例: プロジェクトの削除
この例では、指定されたプロジェクトの削除方法を示します。
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!")
例: プロジェクト構成レポートの生成
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)
例: ビューリストの表示
この例では、ビューリストの表示方法を示します。
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)
例: ビューの作成
この例では、ビューの作成方法を示します。
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!")
例: ビューの更新
この例では、ビューの更新方法を示します。
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!")
例: ビューの削除
この例では、ビューの削除方法を示します。
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!")
例: モジュールリストの表示
この例では、モジュール リストの表示方法を示します。
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)
例: モジュールの作成
この例では、モジュールの作成方法を示します。
アクセス制御メソッドが設定されている場合、モジュールを作成して編集するには、プロジェクト管理者の役割または 'モジュールの管理' パーミッションを持つ必要があります。モジュールでのアクセス パーミッションを追加または変更するには、'役割の割り当て' パーミッションが必要です (デフォルトでプロジェクト管理者が持つ)。
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!")
例: モジュールの更新
この例では、モジュールの更新方法を示します。
アクセス制御メソッドが設定されている場合、モジュールを作成して編集するには、プロジェクト管理者の役割または 'モジュールの管理' パーミッションを持つ必要があります。モジュールでのアクセス パーミッションを追加または変更するには、'役割の割り当て' パーミッションが必要です (デフォルトでプロジェクト管理者が持つ)。
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!")
例: モジュールの削除
この例では、モジュールの削除方法を示します。
アクセス制御メソッドが設定されている場合、モジュールを作成して編集するには、プロジェクト管理者の役割または 'モジュールの管理' パーミッションを持つ必要があります。モジュールでのアクセス パーミッションを追加または変更するには、'役割の割り当て' パーミッションが必要です (デフォルトでプロジェクト管理者が持つ)。
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!")
例: ビルドリストの表示
この例では、ビルド リストの表示方法を示します。ビルドの管理の詳細については、統合ビルドの管理を参照してください。
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)
例: 保存するビルドの指定
このアクションでは、'keepit' オプションを指定することによって特定のビルドを保持するかどうかを指定することもできます。
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)
例: ビルドの削除
この例では、ビルドの削除方法を示します。ビルドの管理の詳細については、統合ビルドの管理を参照してください。
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!")
例: CI ビルドの作成
この例では、CI ビルドの作成方法を示します。
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)
例: CI ビルドの更新
この例では、CI ビルドの更新方法を示します。
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")
例: CI ビルドの削除
この例では、CI ビルドの削除方法を示します。
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!")
例: 有効化されたチェッカーのリストの表示
この例では、有効化されたチェッカーのリストの表示方法を示します。
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)
例: 分類基準のリストの表示
この例では、分類基準のリストの表示方法を示します。
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)
例: チェッカーの有効化および無効化
この例では、チェッカーの有効化および無効化の方法を示します。
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))
例: メトリックのレポート
次の例では、直前のビルドのプロジェクトにおける各ファイルのコメント付きおよびコメントが付いてない行の行数、実行可能ステートメント数、最大のネストレベル、および循環的複雑度メトリックをレポートします。
有効なメトリックコードのリストについては、Klocwork メトリック リファレンスを参照してください。
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())
集約された検索結果
デフォルトでは、メトリック API はファイルごとに結果を生成します。特定のクエリですべてのファイルについて集約された検索結果を生成するには、true (デフォルトは false) の値で aggregate フラグを指定します。次の例では、集約された検索結果を示します。
次の値でのクエリ:
- action=metrics
- user=someone
- query=metric:+LOC_FILE
- project=demosthenes
- aggregate=true
...次の集計結果が生成されて返されます:
{"tag":"LOC_FILE","sum":8113.0,"min":3.0,"max":966.0,"entries":47}
aggregate フラグはデータに関連性がある場合にのみ役立ちます。つまり、メトリックの集約が可能であるか、最大値と最小値を決められる場合です。
システムファイルの検索結果からの除外
デフォルトでは、メトリック API はすべてのファイルに基づいて結果を生成します。クエリオミットシステムファイルは、値 true (デフォルトは false) で exclude_system_files フラグを指定して得ることができます。
次の値でのクエリ:
- action=metrics
- user=someone
- project=demosthenes
- aggregate=true
- exclude_system_files=true
- query=metric:+LOC_FILE
curl 要求の例:
curl --data "action=metrics&user=someone&project=demosthenes&exclude_system_files=true&query=metric:%2bLOC_FILE&aggregate=true" http://localhost:8080/review/api
...次の結果が生成されて返されます:
{"tag":"LOC_FILE","sum":322.0,"min":3.0,"max":68.0,"entries":13}
サーバー設定、プロジェクト、およびコード レビューのインポート
API では、コマンドラインを使用してサーバー設定、プロジェクト、またはコード レビューをインポートすることもできます。これは、次のような各方法で実行できます。
サーバー設定をインポートするには
次の例では、認証構成、パーミッション、カスタム メトリクス、レポート定義、および電子メール購読設定をインポートします。
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())
プロジェクトをインポートするには
次の例では、指定されたプロジェクトについて Klocwork が収集したデータをインポートします。
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())
インポートステータスをチェックするには
この API メソッドを使用すると、サーバー設定、プロジェクト、またはコード レビューのインポートのステータスを確認できます。
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())
Klocwork サーバーのバージョンをチェックするには
curl --data "action=version&user=myself&" http://jsmith.klocwork.com:8080/review/api
1 { 2 majorVersion: "10.1" 3 minorVersion: "1" 4 }
Klocwork サーバーで起動しているすべてのタスクのステータスをリストするには
curl --data "action=task_status&user=myself&" http://jsmith.klocwork.com:8080/review/api