Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 1b17613e93e1f15d050b497e06f55aa9790bb9b1
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Mon Aug 24 17:01:26 2015 +0200
frontend][api2] Creating new project through API, added first test
---------------------------------------------------------------
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 4 +-
.../coprs/rest_api/resources/project.py | 69 ++++++++++++-------
frontend/coprs_frontend/coprs/rest_api/schemas.py | 32 +--------
frontend/coprs_frontend/tests/coprs_test_case.py | 12 ++++
.../tests/test_api/test_project_r.py | 67 +++++++++++++++++++
5 files changed, 127 insertions(+), 57 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index e5b7939..ec93934 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -138,10 +138,10 @@ class CoprsLogic(object):
return query
@classmethod
- def add(cls, user, name, repos, selected_chroots, description=None,
+ def add(cls, user, name, selected_chroots, repos=None, description=None,
instructions=None, check_for_duplicates=False, **kwargs):
copr = models.Copr(name=name,
- repos=repos,
+ repos=repos or u"",
owner_id=user.id,
description=description or u"",
instructions=instructions or u"",
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/project.py
b/frontend/coprs_frontend/coprs/rest_api/resources/project.py
index 720f01f..88544d7 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/project.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/project.py
@@ -50,6 +50,21 @@ def rest_api_auth_required(f):
return decorated_function
+def render_project(copr):
+ return {
+ "copr": mm_serialize_one(ProjectSchema, copr),
+ "_links": {
+ "self": {"href": url_for(".projectr",
project_id=copr.id)},
+ "builds": {"href": url_for(".buildlistr",
project_id=copr.id)},
+ "chroots": {"href":
url_for(".projectchrootlistr", project_id=copr.id)}
+ },
+ # "allowed_methods": [
+ # render_allowed_method("GET", "Get single copr",
require_auth=False),
+ # render_allowed_method("DELETE", "Delete current copr",
require_auth=True),
+ # ]
+ }
+
+
class ProjectListR(Resource):
@rest_api_auth_required
@@ -60,15 +75,38 @@ class ProjectListR(Resource):
owner = flask.g.user
result = mm_deserialize(ProjectSchema(), flask.request.data)
+ if result.errors:
+ return "Failed to parse request", 400
+
# todo check that chroots are available
- pprint(result.data)
+ req = result.data
+
+ extra = {
+ k: req[k]
+ for k in [
+ "description",
+ "instructions",
+ "contact",
+ "homepage",
+ "auto_createrepo",
+ "build_enable_net",
+ ] if k in req
+ }
+ if "repos_list" in req:
+ extra["repos"] = " ".join(req["repos_list"])
+
try:
- CoprsLogic.add(user=owner, check_for_duplicates=True, **result.data)
+ copr = CoprsLogic.add(
+ user=owner, check_for_duplicates=True,
+ name=req["name"],
+ selected_chroots=req["chroots"],
+ **extra
+ )
db.session.commit()
except DuplicateException as error:
raise ObjectAlreadyExists(data=error)
- return "New copr was created", 201
+ return render_project(copr), 201
def get(self):
parser = reqparse.RequestParser()
@@ -103,16 +141,7 @@ class ProjectListR(Resource):
"_links": {
"self": {"href": url_for(".projectlistr",
**req_args)}
},
- "coprs": [
- {
- "copr": mm_serialize_one(ProjectSchema, copr),
- "_links": {
- "self": {"href":
url_for(".projectr", project_id=copr.id)}
- },
- }
- for copr in coprs_list
- ],
-
+ "coprs": [render_project(copr) for copr in coprs_list],
}
# TODO: show only if user provided ?help=true param
@@ -157,19 +186,7 @@ class ProjectR(Resource):
# req_args = parser.parse_args()
copr = get_one_safe(CoprsLogic.get_by_id(int(project_id)))
-
- return {
- "copr": ProjectSchema().dump(copr)[0],
- "_links": {
- "self": {"href": url_for(".projectr",
project_id=copr.id)},
- "builds": {"href": url_for(".buildlistr",
project_id=copr.id)},
- "chroots": {"href":
url_for(".projectchrootlistr", project_id=copr.id)}
- },
- # "allowed_methods": [
- # render_allowed_method("GET", "Get single copr",
require_auth=False),
- # render_allowed_method("DELETE", "Delete current
copr", require_auth=True),
- # ]
- }
+ return render_project(copr)
@rest_api_auth_required
def put(self, project_id):
diff --git a/frontend/coprs_frontend/coprs/rest_api/schemas.py
b/frontend/coprs_frontend/coprs/rest_api/schemas.py
index 4cd0912..222e4fe 100644
--- a/frontend/coprs_frontend/coprs/rest_api/schemas.py
+++ b/frontend/coprs_frontend/coprs/rest_api/schemas.py
@@ -16,6 +16,7 @@ class MockChrootSchema(Schema):
class ProjectSchema(Schema):
+ id = fields.Int()
name = fields.Str(required=True)
owner = fields.Str(attribute="owner_name", dump_only=True)
@@ -28,31 +29,10 @@ class ProjectSchema(Schema):
build_enable_net = fields.Bool()
last_modified = fields.DateTime()
- additional_repos = fields.List(fields.Str(), dump_only=True,
attribute="repos_list")
+ additional_repos = fields.List(fields.Str(), attribute="repos_list")
# used only for creation
- chroots_to_enable = fields.List(fields.Str(), load_only=True)
- additional_repos_input = fields.Str(name="additional_repos",
load_only=True)
-
- _keys_to_make_object = [
- "description",
- "instructions",
- "auto_createrepo"
- ]
-
- def make_object(self, data):
- """
- Create kwargs for CoprsLogic.add
- """
- kwargs = dict(
- name=data["name"].strip(),
- repos=" ".join(data.get("repos", [])),
- selected_chroots=data["chroots"],
- )
- for key in self._keys_to_make_object:
- if key in data:
- kwargs[key] = data[key]
- return kwargs
+ chroots = fields.List(fields.Str(), load_only=True)
class CoprChrootSchema(Schema):
@@ -94,9 +74,3 @@ class BuildSchema(Schema):
source_type = fields.Int()
source_json = fields.Str()
-
- # chroots = fields.List(fields.Nested(BuildChrootSchema))
-
-
-
-
diff --git a/frontend/coprs_frontend/tests/coprs_test_case.py
b/frontend/coprs_frontend/tests/coprs_test_case.py
index 240e117..c268177 100644
--- a/frontend/coprs_frontend/tests/coprs_test_case.py
+++ b/frontend/coprs_frontend/tests/coprs_test_case.py
@@ -4,6 +4,7 @@ import os
import time
import glob
from functools import wraps
+import datetime
import pytest
import decorator
@@ -102,6 +103,17 @@ class CoprsTestCase(object):
self.db.session.add_all([self.u1, self.u2, self.u3])
@pytest.fixture
+ def f_users_api(self):
+ """
+ Requires f_users
+ """
+ for u in [self.u1, self.u2, self.u3]:
+ u.api_login = "foo"
+ u.api_token = "bar"
+
+ u.api_token_expiration = datetime.date.today() +
datetime.timedelta(days=1000)
+
+ @pytest.fixture
def f_coprs(self):
self.c1 = models.Copr(name=u"foocopr", owner=self.u1)
self.c2 = models.Copr(name=u"foocopr", owner=self.u2)
diff --git a/frontend/coprs_frontend/tests/test_api/test_project_r.py
b/frontend/coprs_frontend/tests/test_api/test_project_r.py
new file mode 100644
index 0000000..d57bff8
--- /dev/null
+++ b/frontend/coprs_frontend/tests/test_api/test_project_r.py
@@ -0,0 +1,67 @@
+# coding: utf-8
+
+import base64
+import json
+
+import pytest
+import sqlalchemy
+
+from coprs.logic.users_logic import UsersLogic
+from coprs.logic.coprs_logic import CoprsLogic
+
+from tests.coprs_test_case import CoprsTestCase, TransactionDecorator
+
+
+class TestProjectResource(CoprsTestCase):
+
+ def request_api_with_auth(self, url, content, method="GET"):
+ """
+ :rtype: flask.wrappers.Response
+ """
+
+ userstring = "{}:{}".format(self.u1.api_login, self.u1.api_token)
+ base64string_user = base64.b64encode(userstring)
+ base64string = "Basic " + base64string_user
+
+ kwargs = dict(
+ method=method,
+ content_type="application/json",
+ data=json.dumps(content),
+ headers={
+ "Authorization": base64string
+ }
+ )
+
+ return self.tc.open(url, **kwargs)
+
+ def test_self(self):
+ href = "/api_2/projects"
+ r = self.tc.get(href)
+ assert r.status_code == 200
+ obj = json.loads(r.data)
+ assert obj["_links"]["self"]["href"] == href
+
+ @TransactionDecorator("u1")
+ def test_create_new(self, f_users, f_mock_chroots, f_db, f_users_api):
+ self.db.session.add_all([self.u1, self.mc1])
+
+ chroot_name = self.mc1.name
+ body = {
+ "name": "test_copr",
+ "chroots": [
+ chroot_name,
+ ],
+ "additional_repos": ["copr://bar/zar", ]
+ }
+
+ r = self.request_api_with_auth("/api_2/projects", body,
method="post")
+ assert r.status_code == 201
+ copr_dict = json.loads(r.data)
+ assert copr_dict["copr"]["id"] == 1
+ r2 = self.tc.get("/api_2/projects/1/chroots")
+ copr_chroots_dict = json.loads(r2.data)
+ assert len(copr_chroots_dict["chroots"]) == 1
+ assert
copr_chroots_dict["chroots"][0]["chroot"]["name"] ==
chroot_name
+
+
+