Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 69add22b89d742f8df1ae8add0ac088d1bfc7992
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Thu Oct 1 13:40:11 2015 +0200
[frontend][group projects] added stubs for group management views; first handler for
project details which supports group coprs
---------------------------------------------------------------
frontend/coprs_frontend/coprs/__init__.py | 3 +-
frontend/coprs_frontend/coprs/exceptions.py | 21 ++++++++
frontend/coprs_frontend/coprs/helpers.py | 15 +++++
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 12 ++--
.../coprs/views/coprs_ns/__init__.py | 10 ++++
.../coprs/views/coprs_ns/coprs_general.py | 55 ++++++++++++++------
.../coprs/views/groups_ns/__init__.py | 5 ++
.../coprs/views/groups_ns/groups_general.py | 48 +++++++++++++++++
.../test_views/test_coprs_ns/test_coprs_general.py | 2 +-
9 files changed, 147 insertions(+), 24 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/__init__.py
b/frontend/coprs_frontend/coprs/__init__.py
index 0ffa9af..6d06f34 100644
--- a/frontend/coprs_frontend/coprs/__init__.py
+++ b/frontend/coprs_frontend/coprs/__init__.py
@@ -62,7 +62,7 @@ from coprs.views.recent_ns import recent_general
from coprs.views.stats_ns import stats_receiver
from coprs.views import tmp_ns
from coprs.views.tmp_ns import tmp_general
-
+from coprs.views.groups_ns import groups_ns
from .context_processors import include_banner, inject_fedmenu
@@ -77,6 +77,7 @@ app.register_blueprint(status_ns.status_ns)
app.register_blueprint(recent_ns.recent_ns)
app.register_blueprint(stats_receiver.stats_rcv_ns)
app.register_blueprint(tmp_ns.tmp_ns)
+app.register_blueprint(groups_ns)
app.add_url_rule("/", "coprs_ns.coprs_show",
coprs_general.coprs_show)
diff --git a/frontend/coprs_frontend/coprs/exceptions.py
b/frontend/coprs_frontend/coprs/exceptions.py
index 8216e3a..55e3d19 100644
--- a/frontend/coprs_frontend/coprs/exceptions.py
+++ b/frontend/coprs_frontend/coprs/exceptions.py
@@ -36,3 +36,24 @@ class ActionInProgressException(BaseException):
def formatted_msg(self):
return self.msg.format(action=self.action)
+
+
+class CoprHttpException(Exception):
+
+ _default = "Generic copr exception"
+ code = 500
+
+ def __init__(self, message=None):
+ self.message = message
+
+ def __unicode__(self):
+ return self.message or self._default
+
+ def __str__(self):
+ return self.__unicode__()
+
+
+class ObjectNotFound(CoprHttpException):
+
+ _default = "Requested object was not found"
+ _code = 404
diff --git a/frontend/coprs_frontend/coprs/helpers.py
b/frontend/coprs_frontend/coprs/helpers.py
index ef1a504..7c5e1a8 100644
--- a/frontend/coprs_frontend/coprs/helpers.py
+++ b/frontend/coprs_frontend/coprs/helpers.py
@@ -2,6 +2,7 @@ import math
import random
import string
import urlparse
+from urlparse import urlsplit, urlunsplit
import flask
from dateutil import parser as dt_parser
@@ -376,3 +377,17 @@ def is_ip_from_builder_net(ip):
return True
return False
+
+
+def fixed_redirect(location, code=None):
+ # Workaround to have non-encoded @ symbol in the url path segment
+ response = flask.redirect(location, code or 302)
+
+ loc = response.headers["location"]
+ sr = urlsplit(loc)
+ new_sr = list(sr)
+ new_sr[2] = sr.path.replace("%40", "@")
+ new_loc = urlunsplit(new_sr)
+
+ response.headers["location"] = new_loc
+ return response
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index 03ed0a2..e06b4bf 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -39,14 +39,14 @@ class CoprsLogic(object):
return cls.get_all().filter(models.Copr.id == copr_id)
@classmethod
- def _attach_build(cls, query):
+ def attach_build(cls, query):
query = (query.outerjoin(models.Copr.builds)
.options(db.contains_eager(models.Copr.builds))
.order_by(models.Build.submitted_on.desc()))
return query
@classmethod
- def _attach_mock_chroots(cls, query):
+ def attach_mock_chroots(cls, query):
query = (query.outerjoin(*models.Copr.mock_chroots.attr)
.options(db.contains_eager(*models.Copr.mock_chroots.attr))
.order_by(models.MockChroot.os_release.asc())
@@ -66,10 +66,10 @@ class CoprsLogic(object):
)
if with_builds:
- query = cls._attach_build(query)
+ query = cls.attach_build(query)
if with_mock_chroots:
- query = cls._attach_mock_chroots(query)
+ query = cls.attach_mock_chroots(query)
return query
@@ -85,10 +85,10 @@ class CoprsLogic(object):
)
if with_builds:
- query = cls._attach_build(query)
+ query = cls.attach_build(query)
if with_mock_chroots:
- query = cls._attach_mock_chroots(query)
+ query = cls.attach_mock_chroots(query)
return query
diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
b/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
index 94372a2..048015c 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
@@ -1,3 +1,13 @@
+# coding: utf-8
+
import flask
+from coprs.views.misc import page_not_found
+from coprs.exceptions import ObjectNotFound
+
coprs_ns = flask.Blueprint("coprs_ns", __name__,
url_prefix="/coprs")
+
+
+(a)coprs_ns.app_errorhandler(ObjectNotFound)
+def handle_404(error):
+ return page_not_found(error.message)
diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
index 6c14138..d004103 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -1,3 +1,5 @@
+# coding: utf-8
+
import os
import time
import os
@@ -19,6 +21,7 @@ from coprs import exceptions
from coprs import forms
from coprs import helpers
from coprs import models
+from coprs.exceptions import ObjectNotFound
from coprs.forms import group_managed_form_fabric
from coprs.logic.coprs_logic import CoprsLogic
from coprs.logic.stat_logic import CounterStatLogic
@@ -32,7 +35,8 @@ from coprs.views.misc import login_required, page_not_found
from coprs.views.coprs_ns import coprs_ns
from coprs.logic import builds_logic, coprs_logic, actions_logic, users_logic
-from coprs.helpers import parse_package_name, generate_repo_url, CHROOT_RPMS_DL_STAT_FMT,
CHROOT_REPO_MD_DL_STAT_FMT
+from coprs.helpers import parse_package_name, generate_repo_url, CHROOT_RPMS_DL_STAT_FMT,
CHROOT_REPO_MD_DL_STAT_FMT, \
+ fixed_redirect
@coprs_ns.route("/", defaults={"page": 1})
@@ -218,33 +222,52 @@ def copr_report_abuse(username, coprname):
form=form)
-(a)coprs_ns.route("/g/<groupname>/<coprname>/")
-def group_copr_detail(groupname, coprname):
-
+def get_group_copr_safe(group_name, copr_name):
try:
- group = UsersLogic.get_group_by_alias(groupname).one()
+ group = UsersLogic.get_group_by_alias(group_name).one()
except sqlalchemy.orm.exc.NoResultFound:
- return page_not_found(
- "Group {} does not exist.".format(groupname))
+ raise ObjectNotFound(
+ message="Group {} does not exist.".format(group_name))
try:
- copr = CoprsLogic.get_by_group_id(group.id, coprname).one()
+ copr = CoprsLogic.get_by_group_id(
+ group.id, copr_name, with_mock_chroots=True).one()
except sqlalchemy.orm.exc.NoResultFound:
- return page_not_found(
- "Project {0} does not exist.".format(coprname))
+ raise ObjectNotFound(
+ message="Project {0} does not exist.".format(copr_name))
- return render_copr_detail(copr)
+ return copr
-(a)coprs_ns.route("/<username>/<coprname>/")
-def copr_detail(username, coprname):
- query = coprs_logic.CoprsLogic.get(username, coprname, with_mock_chroots=True)
+def get_copr_safe(user_name, copr_name):
+ query = coprs_logic.CoprsLogic.get(user_name, copr_name, with_mock_chroots=True)
try:
copr = query.one()
except sqlalchemy.orm.exc.NoResultFound:
- return page_not_found(
- "Project {0} does not exist.".format(coprname))
+ raise ObjectNotFound(
+ message="Project {}/{} does not exist.".format(user_name,
copr_name))
+
+ return copr
+
+
+@coprs_ns.route("/(a)<groupname>/<coprname>/")
+def group_copr_detail(groupname, coprname):
+
+ copr = get_group_copr_safe(groupname, coprname)
+ return render_copr_detail(copr)
+
+
+(a)coprs_ns.route("/<username>/<coprname>/")
+def copr_detail(username, coprname):
+ copr = get_copr_safe(username, coprname)
+ # import ipdb; ipdb.set_trace()
+ if copr.is_a_group_project:
+ return fixed_redirect(flask.url_for(
+ endpoint=".group_copr_detail",
+ groupname=copr.group.name,
+ coprname=copr.name,
+ ))
return render_copr_detail(copr)
diff --git a/frontend/coprs_frontend/coprs/views/groups_ns/__init__.py
b/frontend/coprs_frontend/coprs/views/groups_ns/__init__.py
new file mode 100644
index 0000000..88d5e20
--- /dev/null
+++ b/frontend/coprs_frontend/coprs/views/groups_ns/__init__.py
@@ -0,0 +1,5 @@
+# coding: utf-8
+
+import flask
+
+groups_ns = flask.Blueprint("groups_ns", __name__,
url_prefix="/groups")
diff --git a/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py
b/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py
new file mode 100644
index 0000000..9108b34
--- /dev/null
+++ b/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py
@@ -0,0 +1,48 @@
+# coding: utf-8
+
+import os
+import time
+import os
+import re
+import urlparse
+
+import flask
+from flask import render_template
+import platform
+import smtplib
+import sqlalchemy
+from email.mime.text import MIMEText
+from itertools import groupby
+
+from coprs import app
+from coprs import db
+from coprs import rcp
+from coprs import exceptions
+from coprs import forms
+from coprs import helpers
+from coprs import models
+from coprs.forms import group_managed_form_fabric
+from coprs.logic.coprs_logic import CoprsLogic
+from coprs.logic.stat_logic import CounterStatLogic
+from coprs.logic.users_logic import UsersLogic
+from coprs.rmodels import TimedStatEvents
+
+from coprs.logic.complex_logic import ComplexLogic
+
+from coprs.views.misc import login_required, page_not_found
+
+from coprs.views.coprs_ns import coprs_ns
+
+from coprs.logic import builds_logic, coprs_logic, actions_logic, users_logic
+from coprs.helpers import parse_package_name, generate_repo_url, CHROOT_RPMS_DL_STAT_FMT,
CHROOT_REPO_MD_DL_STAT_FMT
+
+
+(a)coprs_ns.route("/groups/activate/<fas_group>", methods=["GET",
"POST"])
+@login_required
+def activate_group(fas_group):
+ pass
+
+
+(a)coprs_ns.route("/groups/by_user/<username>")
+def list_groups_by_user(username):
+ pass
diff --git a/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
b/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
index 91a3afc..f9543ad 100644
--- a/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
+++ b/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
@@ -679,7 +679,7 @@ class TestCoprRepoGeneration(CoprsTestCase):
def test_fail_on_missing_dash(self):
r = self.tc.get("/coprs/reponamewithoutdash/repo/")
assert r.status_code == 404
- assert "Project repo does not exist" in r.data
+ assert "does not exist" in r.data
def test_fail_on_nonexistent_copr(self):
r = self.tc.get(