Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : python-client
---------------------------------------------------------------
commit b1215c976b39ba2ac6c83276239d4aa1ad8b38ed
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Thu Aug 14 23:07:26 2014 +0200
[python-copr,copr-cli] Copr-cli now uses python-copr-cli package.
[copr-cli] updated .spec to reflect usage of python-copr-client
---------------------------------------------------------------
cli/copr-cli.spec | 8 +-
cli/copr_cli/copr_exceptions.py | 46 ------
cli/copr_cli/main.py | 117 ++++++++++++---
cli/copr_cli/subcommands.py | 307 ------------------------------------
cli/{coprcli-setup.py => setup.py} | 2 +-
python/copr_client/client.py | 61 ++++----
python/copr_client/responses.py | 53 ++++++
7 files changed, 188 insertions(+), 406 deletions(-)
diff --git a/cli/copr-cli.spec b/cli/copr-cli.spec
index d38fe6c..eda40dd 100644
--- a/cli/copr-cli.spec
+++ b/cli/copr-cli.spec
@@ -22,8 +22,8 @@ BuildRequires: asciidoc
BuildRequires: libxslt
BuildRequires: util-linux
BuildRequires: python-setuptools
-BuildRequires: python-requests
BuildRequires: python2-devel
+BuildRequires: python-copr-client
%if 0%{?rhel} < 7 && 0%{?rhel} > 0
BuildRequires: python-argparse
%endif
@@ -31,8 +31,8 @@ BuildRequires: python-argparse
BuildRequires: epydoc
BuildRequires: graphviz
-Requires: python-requests
Requires: python-setuptools
+Requires: python-copr-client
%if 0%{?rhel} < 7 && 0%{?rhel} > 0
Requires: python-argparse
%endif
@@ -60,6 +60,8 @@ only.
%build
+%{__python2} setup.py build
+
mv copr_cli/README.rst ./
# convert manages
@@ -74,7 +76,7 @@ popd
%install
install -d %{buildroot}%{_pkgdocdir}/
-%{__python2} coprcli-setup.py install --root %{buildroot}
+%{__python2} setup.py install --root %{buildroot}
install -d %{buildroot}%{_mandir}/man1
install -p -m 644 man/copr-cli.1 %{buildroot}/%{_mandir}/man1/
diff --git a/cli/copr_cli/copr_exceptions.py b/cli/copr_cli/copr_exceptions.py
deleted file mode 100644
index 1e10678..0000000
--- a/cli/copr_cli/copr_exceptions.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-"""
-Exceptions for copr-cli
-"""
-
-
-class CoprCliException(Exception):
-
- """ Basic exception class for copr-cli. """
- pass
-
-
-class CoprCliNoConfException(CoprCliException):
-
- """ Exception thrown when no config file is found. """
- pass
-
-
-class CoprCliConfigException(CoprCliException):
-
- """ Exception thrown when the config file is incomplete or
- malformated.
- """
- pass
-
-
-class CoprCliRequestException(Exception):
- """ Exception thrown when the request is bad. For example,
- the user provided wrong project name or build ID.
- """
- pass
-
-
-class CoprCliBuildException(Exception):
- """ Exception thrown when one or more builds fail and Cli is waiting
- for the result.
- """
- pass
-
-
-class CoprCliUnknownResponseException(Exception):
- """ Exception thrown when the response is unknown to cli.
- It usualy means that something is broken.
- """
- pass
diff --git a/cli/copr_cli/main.py b/cli/copr_cli/main.py
index 597b57a..a390ceb 100644
--- a/cli/copr_cli/main.py
+++ b/cli/copr_cli/main.py
@@ -1,14 +1,69 @@
#-*- coding: UTF-8 -*-
+__version__ = "0.3.0"
+__description__ = "CLI tool to run copr"
+
import argparse
import sys
import ConfigParser
+import datetime
+import time
+from collections import defaultdict
-import subcommands
-import copr_exceptions
+from copr_client import CoprClient
+import copr_client.exceptions as copr_exceptions
+
+# client = CoprClient.create_from_file_config()
+client = CoprClient(dict(
+ login="Y29wcg==##fragphakffjdnlehuegu",
+ username="vgologuz",
+ token="srkqukvupebdipjfqyncohhvftiksi",
+ copr_url="http://copr-fe-dev.cloud.fedoraproject.org"
+))
-__version__ = "0.2.0"
-__description__ = "CLI tool to run copr"
+
+def _watch_builds(build_ids):
+ print("Watching build(s): (this may be safely interrupted)")
+ prevstatus = defaultdict()
+ failed_ids = []
+ watched_ids = build_ids[:]
+
+ try:
+ while True:
+ for build_id in watched_ids:
+ build_status = client.get_build_status(build_id)
+ if build_status.output != "ok":
+ errmsg = " Build {1}: Unable to get build status:
{0}".format(
+ build_status.error, build_id)
+ raise copr_exceptions.CoprRequestException(errmsg)
+
+ now = datetime.datetime.now()
+ if prevstatus[build_id] != build_status.status:
+ prevstatus[build_id] = build_status.status
+ print(" {0} Build {2}: {1}".format(
+ now.strftime("%H:%M:%S"),
+ build_status.status, build_id))
+
+ if build_status.status in ["failed"]:
+ failed_ids.append(build_id)
+ if build_status.status in ["succeeded", "skipped",
+ "failed", "canceled"]:
+ watched_ids.remove(build_id)
+ if build_status.status == "unknown":
+ raise copr_exceptions.CoprBuildException(
+ "Unknown status.")
+
+ if not watched_ids:
+ break
+ time.sleep(60)
+
+ if failed_ids:
+ raise copr_exceptions.CoprBuildException(
+ "Build(s) {0} failed.".format(
+ ", ".join(str(x) for x in failed_ids)))
+
+ except KeyboardInterrupt:
+ pass
def action_build(args):
@@ -18,8 +73,17 @@ def action_build(args):
:param args: argparse arguments provided by the user
"""
- subcommands.build(args.copr, args.pkgs,
- args.memory, args.timeout, not args.nowait, chroots=args.chroots)
+ result = client.create_new_build(
+ projectname=args.copr, chroots=args.chroots, pkgs=args.pkgs,
+ memory=args.memory, timeout=args.timeout)
+ if result.output != "ok":
+ print(result.error)
+ return
+ print(result.message)
+ print("Created builds: {0}".format(" ".join(map(str,
result.ids))))
+
+ if not args.nowait:
+ _watch_builds(result.ids)
def action_create(args):
@@ -29,9 +93,12 @@ def action_create(args):
:param args: argparse arguments provided by the user
"""
- subcommands.create(args.name, args.chroots, args.description,
- args.instructions, args.repos,
- args.initial_pkgs)
+ result = client.create_project(
+ projectname=args.name, description=args.description,
+ instructions=args.instructions, chroots=args.chroots,
+ repos=args.repos, initial_pkgs=args.initial_pkgs)
+ print(result)
+
def action_delete(args):
""" Method called when the 'delete' action has been selected
by the
@@ -39,7 +106,8 @@ def action_delete(args):
:param args: argparse arguments provided by the user
"""
- subcommands.delete(args.copr)
+ result = client.delete_project(projectname=args.copr)
+ print(result)
def action_list(args):
@@ -49,20 +117,31 @@ def action_list(args):
:param args: argparse arguments provided by the user
"""
- subcommands.listcoprs(args.username)
+ username = args.username or client.username
+ result = client.get_projects_list(username)
+ if result.response["output"] != "ok":
+ print(result.error)
+ print("Un-expected data returned, please report this issue")
+ elif not result.projects:
+ print("No copr retrieved for user: '{0}'".format(username))
+ return
+
+ for prj in result.projects:
+ print(prj)
def action_status(args):
- subcommands.status(args.build_id)
+ result = client.get_build_status(args.build_id)
+ print(result)
+
def action_cancel(args):
""" Method called when the 'cancel' action has been selected
by the
user.
-
:param args: argparse arguments provided by the user
-
"""
- subcommands.cancel(args.build_id)
+ result = client.cancel_build(args.build_id)
+ print(result)
def setup_parser():
"""
@@ -159,24 +238,24 @@ def main(argv=sys.argv[1:]):
except KeyboardInterrupt:
sys.stderr.write("\nInterrupted by user.")
sys.exit(1)
- except copr_exceptions.CoprCliRequestException, e:
+ except copr_exceptions.CoprRequestException, e:
sys.stderr.write("\nSomething went wrong:")
sys.stderr.write("\nError: {0}\n".format(e))
sys.exit(1)
except argparse.ArgumentTypeError, e:
sys.stderr.write("\nError: {0}".format(e))
sys.exit(2)
- except copr_exceptions.CoprCliException, e:
+ except copr_exceptions.CoprException, e:
sys.stderr.write("\nError: {0}\n".format(e))
sys.exit(3)
except ConfigParser.ParsingError, e:
sys.stderr.write("\nError: {0}\n".format(e))
sys.stderr.write("Lines in INI file should not be indented.\n")
sys.exit(3)
- except copr_exceptions.CoprCliBuildException, e:
+ except copr_exceptions.CoprBuildException, e:
sys.stderr.write("\nBuild error: {0}\n".format(e))
sys.exit(4)
- except copr_exceptions.CoprCliUnknownResponseException, e:
+ except copr_exceptions.CoprUnknownResponseException, e:
sys.stderr.write("\nError: {0}\n".format(e))
sys.exit(5)
# except Exception as e:
diff --git a/cli/copr_cli/subcommands.py b/cli/copr_cli/subcommands.py
deleted file mode 100644
index ab72f59..0000000
--- a/cli/copr_cli/subcommands.py
+++ /dev/null
@@ -1,307 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-"""
-Function actually doing the work of calling the API and handling the
-output.
-"""
-
-import ConfigParser
-import datetime
-import json
-import os
-import re
-import requests
-import sys
-import time
-
-import copr_exceptions
-
-
-def _get_data(req, user, copr=None):
- """ Wrapper around response from server
-
- checks data and raises a CoprCliRequestException with nice error message
- or CoprCliUnknownResponseException in case of some some error.
- Otherwise return json object.
- """
- if "<title>Sign in Coprs</title>" in req.text:
- raise copr_exceptions.CoprCliRequestException("Invalid API token\n")
- return
-
- if req.status_code == 404:
- if copr is None:
- raise copr_exceptions.CoprCliRequestException(
- "User {0} is
unknown.\n".format(user["username"]))
- else:
- raise copr_exceptions.CoprCliRequestException(
- "Project {0}/{1} not found.\n".format(
- user["username"], copr))
- try:
- output = json.loads(req.text)
- except ValueError:
- raise copr_exceptions.CoprCliUnknownResponseException(
- "Unknown response from the server.")
- if req.status_code != 200:
- raise copr_exceptions.CoprCliRequestException(output["error"])
-
- if output is None:
- raise copr_exceptions.CoprCliUnknownResponseException(
- "No response from the server.")
- return output
-
-
-def get_user():
- """ Retrieve the user information from the config file.
"""
- config = ConfigParser.ConfigParser()
- if not config.read(
- os.path.join(os.path.expanduser("~"), ".config",
"copr")):
- raise copr_exceptions.CoprCliNoConfException(
- "No configuration file '~/.config/copr' found. "
- "See man copr-cli for more information")
- try:
- username = config.get("copr-cli", "username", None)
- login = config.get("copr-cli", "login", None)
- token = config.get("copr-cli", "token", None)
- except ConfigParser.Error as err:
- raise copr_exceptions.CoprCliConfigException(
- "Bad configuration file: {0}".format(err))
- return {"username": username, "token": token, "login":
login}
-
-
-def get_api_url():
- """ Retrieve the user information from the config file.
"""
- config = ConfigParser.ConfigParser()
- config.read(
- os.path.join(os.path.expanduser("~"), ".config",
"copr")
- )
-
- # Default copr_url:
- copr_url = "http://copr.fedoraproject.org/"
- if (config.has_section("copr-cli") and
- config.has_option("copr-cli", "copr_url")):
-
- copr_url = config.get("copr-cli", "copr_url")
- return "{0}/api".format(copr_url)
-
-
-def listcoprs(username=None):
- """ List all the copr of a user. """
- user = {}
- if not username:
- user = get_user()
- del(user["token"])
-
- if username:
- user["username"] = username
-
- copr_api_url = get_api_url()
- url = "{0}/coprs/{1}/".format(copr_api_url, user["username"])
-
- req = requests.get(url)
- output = _get_data(req, user)
- if output is None:
- return
- elif "repos" in output:
- PAD = " " * 2
- if output["repos"]:
- for repo in output["repos"]:
- print("Name: {0}".format(repo["name"]))
-
- if "description" in repo:
- desc = repo["description"]
- print(PAD + "Description: {0}".format(desc))
-
- if "yum_repos" in repo:
- yum_repos = repo["yum_repos"]
- print(PAD + "Yum repo(s):")
- for k in sorted(yum_repos.keys()):
- print(PAD * 2 + "{0}: {1}".format(k, yum_repos[k]))
-
- if "additional_repos" in repo:
- add_repos = repo["additional_repos"]
- print(PAD + "Additional repos: {0}".format(add_repos))
-
- if "instructions" in repo:
- instructions = repo["instructions"]
- print(PAD + "Instructions: {0}".format(instructions))
- else:
- print("No copr retrieved for user: '{0}'".format(
- user["username"]))
- else:
- print("Un-expected data returned, please report this issue")
-
-
-def create(name, chroots=[], description=None, instructions=None,
- repos=None, initial_pkgs=None):
- """ Create a new copr. """
- if chroots is None:
- raise copr_exceptions.CoprCliRequestException(
- "At least one chroot must be selected")
-
- user = get_user()
- copr_api_url = get_api_url()
- URL = "{0}/coprs/{1}/new/".format(copr_api_url,
user["username"])
-
- if type(repos) == list():
- repos = " ".join(repos)
-
- if type(initial_pkgs) == list():
- initial_pkgs = " ".join(initial_pkgs)
-
- data = {"name": name,
- "repos": repos,
- "initial_pkgs": initial_pkgs,
- "description": description,
- "instructions": instructions
- }
- for chroot in chroots:
- data[chroot] = "y"
-
- req = requests.post(URL,
- auth=(user["login"], user["token"]),
- data=data)
- output = _get_data(req, user)
- if output is not None:
- print(output["message"])
-
-
-def delete(copr):
- """ Delete the entire project.
- """
- user = get_user()
- username = user["username"]
-
- copr_api_url = get_api_url()
- URL = "{0}/coprs/{1}/{2}/delete/".format(
- copr_api_url,
- username,
- copr)
-
- data = {"verify": "yes"}
-
- req = requests.post(URL,
- auth=(user["login"], user["token"]),
- data=data)
- output = _get_data(req, user, copr)
-
-
-def _fetch_status(build_id):
- user = get_user()
- copr_api_url = get_api_url()
- URL = "{0}/coprs/build_status/{1}/".format(
- copr_api_url,
- build_id)
-
- req = requests.get(URL, auth=(user["login"], user["token"]))
- output = _get_data(req, user)
- if output is None:
- return (False, "Error occurred.")
- elif "status" in output:
- return (True, output["status"])
- else:
- return (False, output["error"])
-
-
-def status(build_id):
- """ Return status of build """
- (ret, value) = _fetch_status(build_id)
- print(value)
-
-def cancel(build_id):
- """ Cancel specified build_id """
- user = get_user()
- copr_api_url = get_api_url()
- #/coprs/rhscl/nodejs010/cancel_build/4060/
- URL = "{0}/coprs/cancel_build/{1}/".format(
- copr_api_url,
- build_id)
- req = requests.post(URL, auth=(user["login"], user["token"]))
- output = _get_data(req, user)
- if output is None:
- return (False, "Error occurred.")
- elif "status" in output:
- return (True, output["status"])
- else:
- return (False, output["error"])
-
-def build(copr, pkgs, memory, timeout, wait=True, result=None, chroots=None):
- """ Build a new package into a given copr.
-
- Result is dictionary where is returned "errmsg" in case of error.
- And "id" and "status" otherwise.
- """
- user = get_user()
- username = user["username"]
-
- # if you specify copr as username/foo, retrieve and cut username
- m = re.match(r"(.+)/(.+)", copr)
- if m:
- username = m.group(1)
- copr = m.group(2)
-
- copr_api_url = get_api_url()
- URL = "{0}/coprs/{1}/{2}/new_build/".format(
- copr_api_url,
- username,
- copr)
-
- data = {"pkgs": " ".join(pkgs),
- "memory_reqs": memory,
- "timeout": timeout
- }
-
- if chroots is not None:
- for chroot in chroots:
- data[chroot] = "y"
-
- req = requests.post(URL,
- auth=(user["login"], user["token"]),
- data=data)
- output = _get_data(req, user, copr)
- print("{1}:\n {0} build(s) were added
successfully\n".format(len(output["ids"]), copr))
-
- if wait:
- print("Watching build(s): (this may be safely interrupted)")
- prevstatus = {}
- failed_ids = []
- for id in output["ids"]:
- prevstatus[id] = None
- if result is not None:
- result[id] = {}
- try:
- while True:
- for id in output["ids"]:
- (ret, status) = _fetch_status(id)
- if not ret:
- errmsg = " Build {1}: Unable to get build status:
{0}".format(status,id)
- if result is not None:
- result[id]['errmsg'] = errmsg
- raise copr_exceptions.CoprCliRequestException(errmsg)
-
- now = datetime.datetime.now()
- if prevstatus[id] != status:
- print(" {0} Build {2}:
{1}".format(now.strftime("%H:%M:%S"), status, id))
- prevstatus[id] = status
-
- if status in ["succeeded", "skipped",
"failed", "canceled"]:
- if result is not None:
- result[id]['status'] = status
- if status in ["failed"]:
- failed_ids.append(id)
- output["ids"].remove(id)
-
- if status == "unknown":
- raise copr_exceptions.CoprCliBuildException(
- "Unknown status.")
-
- if not output["ids"]:
- break
- time.sleep(60)
-
- if failed_ids:
- raise copr_exceptions.CoprCliBuildException(
- "Build(s) {0} failed.".format(
- ", ".join(str(x) for x in failed_ids)))
-
- except KeyboardInterrupt:
- pass
diff --git a/cli/coprcli-setup.py b/cli/setup.py
similarity index 98%
rename from cli/coprcli-setup.py
rename to cli/setup.py
index fa67387..68369f7 100644
--- a/cli/coprcli-setup.py
+++ b/cli/setup.py
@@ -14,7 +14,7 @@ This part is a command line interface to use copr."""
from copr_cli.main import __description__, __version__
requires = [
- 'requests',
+ 'copr-client'
]
diff --git a/python/copr_client/client.py b/python/copr_client/client.py
index 33082c3..56d34a2 100644
--- a/python/copr_client/client.py
+++ b/python/copr_client/client.py
@@ -1,6 +1,7 @@
#-*- coding: UTF-8 -*-
import json
+from pprint import pprint
import os
import sys
import ConfigParser
@@ -69,7 +70,7 @@ class CoprClient(object):
"Bad configuration file: {0}".format(err))
return CoprClient(config=config)
- def _fetch(self, url, data=None, copr=None, method=None,
+ def _fetch(self, url, data=None, projectname=None, method=None,
skip_auth=False, on_error_response=None):
""" Fetch data from server,
checks response and raises a CoprCliRequestException with nice error message
@@ -79,7 +80,7 @@ class CoprClient(object):
:param url: formed url to fetch
:param data: serialised data to send
:param skip_auth: don't send auth credentials
- :param copr: name of the copr project
+ :param projectname: name of the copr project
:param on_error_response: function to handle responses with bad status code
"""
if method is None:
@@ -113,24 +114,24 @@ class CoprClient(object):
#TODO: better status code handling
if response.status_code == 404:
- if copr is None:
+ if projectname is None:
raise exceptions.CoprRequestException(
"User {0} is unknown.\n".format(self.username))
else:
raise exceptions.CoprRequestException(
"Project {0}/{1} not found.\n".format(
- self.username, copr))
+ self.username, projectname))
if 400 <= response.status_code < 500:
- raise Exception("Bad request, raw response body:
{0}".format(response.text))
+ log.error("Bad request, raw response body:
{0}".format(response.text))
elif response.status_code >= 500:
#import ipdb; ipdb.set_trace()
- raise Exception("Server error, raw response body:
{0}".format(response.text))
+ log.error("Server error, raw response body:
{0}".format(response.text))
try:
output = json.loads(response.text)
except ValueError:
- import ipdb; ipdb.set_trace()
+ #import ipdb; ipdb.set_trace()
raise exceptions.CoprUnknownResponseException(
"Unknown response from the server.")
if response.status_code != 200:
@@ -162,30 +163,30 @@ class CoprClient(object):
response = self._fetch(url, method="post")
return CancelBuildResponse(self, response, build_id)
- def delete_project(self, name):
+ def delete_project(self, projectname):
"""
Delete the entire project
"""
url = "{0}/coprs/{1}/{2}/delete/".format(
- self.api_url, self.username, name
+ self.api_url, self.username, projectname
)
response = self._fetch(
url, data={"verify": "yes"}, method="post")
- return DeleteProjectResponse(self, response, name)
+ return DeleteProjectResponse(self, response, projectname)
- def get_project_details(self, name):
+ def get_project_details(self, projectname):
"""
Get project details
"""
url = "{0}/coprs/{1}/{2}/detail/".format(
- self.api_url, self.username, name
+ self.api_url, self.username, projectname
)
response = self._fetch(url, skip_auth=True)
- return ProjectDetailsResponse(self, response, name)
+ return ProjectDetailsResponse(self, response, projectname)
def create_project(
- self, name,
+ self, projectname,
description=None, instructions=None,
chroots=None, repos=None, initial_pkgs=None
):
@@ -202,7 +203,7 @@ class CoprClient(object):
if type(initial_pkgs) == list():
initial_pkgs = " ".join(initial_pkgs)
- data = {"name": name,
+ data = {"name": projectname,
"repos": repos,
"initial_pkgs": initial_pkgs,
"description": description,
@@ -215,15 +216,16 @@ class CoprClient(object):
response = self._fetch(url, data=data, method="post")
return CreateProjectResponse(
self, response,
- name=name, description=description, instructions=instructions,
+ name=projectname, description=description, instructions=instructions,
repos=repos, chroots=chroots, initial_pkgs=initial_pkgs
)
- def get_projects_list(self):
+ def get_projects_list(self, username=None):
"""
Get list of projects created by the user
"""
- url = "{0}/coprs/{1}/".format(self.api_url, self.username)
+ url = "{0}/coprs/{1}/".format(
+ self.api_url, username or self.username)
response = self._fetch(url)
return GetProjectsListResponse(self, response)
@@ -234,12 +236,12 @@ class CoprClient(object):
response = self._fetch(url, skip_auth=True)
return BaseResponse(self, response)
- def modify_project_chroot_details(self, name, chroot, pkgs=None):
+ def modify_project_chroot_details(self, projectname, chroot, pkgs=None):
if pkgs is None:
pkgs = []
url = "{0}/coprs/{1}/{2}/modify/{3}/".format(
- self.api_url, self.username, name, chroot
+ self.api_url, self.username, projectname, chroot
)
data = {
"buildroot_pkgs": " ".join(pkgs)
@@ -247,19 +249,19 @@ class CoprClient(object):
response = self._fetch(url, data=data, method="post")
return BaseResponse(self, response)
- def modify_project(self, name, description=None,
+ def modify_project(self, projectname, description=None,
instructions=None, repos=None):
"""
Modifies main project settings
- :param name:
+ :param projectname:
:param description:
:param instructions:
:param repos:
:return:
"""
url = "{0}/coprs/{1}/{2}/modify/".format(
- self.api_url, self.username, name
+ self.api_url, self.username, projectname
)
data = {}
if description:
@@ -270,15 +272,14 @@ class CoprClient(object):
data["repos"] = repos
response = self._fetch(url, data=data, method="post")
- return ModifyProjectResponse(self, response, name, description,
+ return ModifyProjectResponse(self, response, projectname, description,
instructions, repos)
- def create_new_build(self, copr_project,
- pkgs, timeout, memory,
- wait=True, result=None, chroots=None):
+ def create_new_build(self, projectname, pkgs,
+ timeout=None, memory=None, chroots=None):
"""
- :param copr_project: name of copr project (without user namespace)
+ :param projectname: name of copr project (without user namespace)
:param pkgs: list of packages to include in build
:param timeout: ?? build timeout
@@ -291,7 +292,7 @@ class CoprClient(object):
"""
url = "{0}/coprs/{1}/{2}/new_build/".format(
- self.api_url, self.username, copr_project
+ self.api_url, self.username, projectname
)
data = {
"pkgs": " ".join(pkgs),
@@ -304,7 +305,7 @@ class CoprClient(object):
response = self._fetch(url, data, method="post")
return BuildRequestResponse(
self, response,
- copr_project, pkgs, memory, timeout, chroots)
+ projectname, pkgs, memory, timeout, chroots)
def search_projects(self, query):
url = "{0}/coprs/search/{1}/".format(
diff --git a/python/copr_client/responses.py b/python/copr_client/responses.py
index a4e6e2a..0dea83d 100644
--- a/python/copr_client/responses.py
+++ b/python/copr_client/responses.py
@@ -46,9 +46,60 @@ class ProjectMixin(object):
return self.client.delete_project(self.project_name)
+class ProjectWrapper(object):
+ def __init__(self, username, projectname,
+ description=None, instructions=None,
+ yum_repos=None, additional_repos=None):
+
+ self.username = username
+ self.projectname = projectname
+ self.description = description or "<No description provided>"
+ self.instructions = instructions
+ self.yum_repos = yum_repos or {}
+ self.additional_repos = additional_repos or {}
+
+ def __str__(self):
+ out = list()
+ out.append("Name: {0}".format(self.projectname))
+ out.append(" Description: {0}".format(self.description))
+
+ if self.yum_repos:
+ out.append(" Yum repo(s)")
+ for k in sorted(self.yum_repos.keys()):
+ out.append(" {0}: {1}".format(k, self.yum_repos[k]))
+ if self.additional_repos:
+ out.append(" Additional repo: {0}".format(self.additional_repos))
+ if self.instructions:
+ out.append(" Instructions: {0}".format(self.instructions))
+
+ out.append("")
+ return "\n".join(out)
+
+
class GetProjectsListResponse(BaseResponse):
_simple_fields = ["output", "repos"]
+ def __init__(self, client, response, username=None):
+ super(GetProjectsListResponse, self).__init__(client, response)
+ self.username = username or self.client.username
+
+ @property
+ def projects(self):
+ if not self.response or \
+ self.response.get("output", None) != "ok" or \
+ not self.response.get("repos"):
+ return None
+ else:
+ return [
+ ProjectWrapper(
+ username=self.username,
+ projectname=prj.get("name"),
+ description=prj.get("description"),
+ yum_repos=prj.get("yum_repos"),
+ additional_repos=prj.get("additional_repos"),
+ ) for prj in self.response["repos"]
+ ]
+
class CreateProjectResponse(BaseResponse, ProjectMixin):
_simple_fields = ["message", "output"]
@@ -183,6 +234,8 @@ class CancelBuildResponse(BaseResponse, BuildMixin):
class BuildRequestResponse(BaseResponse, ProjectMixin):
+ _simple_fields = ["message", "output", "error",
"ids"]
+
def __init__(self, client, response,
copr_project, pkgs, memory, timeout, chroots):
super(BuildRequestResponse, self).__init__(client, response)