Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
commit 69add22b89d742f8df1ae8add0ac088d1bfc7992 Author: Valentin Gologuzov vgologuz@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") + + +@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)
-@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
-@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("/@<groupname>/<coprname>/") +def group_copr_detail(groupname, coprname): + + copr = get_group_copr_safe(groupname, coprname) + return render_copr_detail(copr) + + +@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 + + +@coprs_ns.route("/groups/activate/<fas_group>", methods=["GET", "POST"]) +@login_required +def activate_group(fas_group): + pass + + +@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(