[copr] python_copr_apiv2: [python][api_v2] refactored inderect handlers calls; moved ListResource creation code to the classmethods (9c63bcb)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : python_copr_apiv2
>---------------------------------------------------------------
commit 9c63bcbb8fc3d2d5a9b1e8dd205e0641af83d14b
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Sep 30 16:48:55 2015 +0200
[python][api_v2] refactored inderect handlers calls; moved ListResource creation code to the classmethods
>---------------------------------------------------------------
python/copr/client_v2/handlers.py | 94 ++++-------------------------------
python/copr/client_v2/resources.py | 75 +++++++++++++++++++++++++++-
python/run_tmp.py | 12 ++++-
3 files changed, 92 insertions(+), 89 deletions(-)
diff --git a/python/copr/client_v2/handlers.py b/python/copr/client_v2/handlers.py
index 03eb7c3..c7b7434 100644
--- a/python/copr/client_v2/handlers.py
+++ b/python/copr/client_v2/handlers.py
@@ -68,23 +68,7 @@ class BuildHandle(AbstractHandle):
}
response = self.nc.request(self.get_base_url(), query_params=options)
- data_dict = response.json
- result = BuildList(
- self,
- response=response,
- links=Link.from_dict(data_dict["_links"], {
- "self": EntityTypes.BUILD,
- }),
- individuals=[
- Build.from_response(
- handle=self,
- response=None,
- data_dict=dict_part,
- )
- for dict_part in data_dict["builds"]
- ]
- )
- return result
+ return BuildList.from_response(self, response, options)
def cancel(self, build_entity):
"""
@@ -221,24 +205,7 @@ class ProjectHandle(AbstractHandle):
}
response = self.nc.request(self.get_base_url(), query_params=options)
- data_dict = response.json
- result = ProjectsList(
- self,
- response=response,
- links=Link.from_dict(data_dict["_links"], {
- "self": EntityTypes.PROJECT,
- }),
- individuals=[
- Project.from_response(
- handle=self,
- response=None,
- data_dict=dict_part,
- )
- for dict_part in data_dict["projects"]
- ],
- options=None
- )
- return result
+ return ProjectsList.from_response(self, response, options)
def get_one(self, project_id, show_builds=False, show_chroots=False):
"""
@@ -273,44 +240,18 @@ class ProjectHandle(AbstractHandle):
response = self.nc.request(url, method="delete", do_auth=True)
return OperationResult(self, response)
- def get_project_chroot(self, project, name):
- """
- :type project: copr.client_v2.resources.Project
- :param str name: chroot name
- :rtype: copr.client_v2.resources.ProjectChroot
- """
- return self.client.project_chroots.get_one(project, name)
-
- def get_project_chroot_list(self, project):
- """
- :type project: copr.client_v2.resources.Project
- """
- return self.client.project_chroots.get_list(project)
-
- def enable_chroot(self, project, *args, **kwargs):
- """
- :type project: copr.client_v2.resources.Project
- """
- return self.client.project_chroots.enable(project, *args, **kwargs)
-
- # def create_build_from_file(self, project, *args, **kwargs):
- # """
- # See additional options `:py:method:BuildHandle.create_from_file:`
- # """
- # return self.client.builds.create_from_file(project.id, *args, **kwargs)
- #
- # def create_build_from_url(self, project, *args, **kwargs):
- # """
- # See additional options `:py:method:BuildHandle.create_from_url:`
- # """
- # return self.client.builds.create_from_url(project.id, *args, **kwargs)
-
def get_builds_handle(self):
"""
:rtype: BuildHandle
"""
return self.client.builds
+ def get_project_chroots_handle(self):
+ """
+ :rtype: ProjectChrootHandle
+ """
+ return self.client.project_chroots
+
class ProjectChrootHandle(AbstractHandle):
@@ -341,23 +282,10 @@ class ProjectChrootHandle(AbstractHandle):
:type project: copr.client_v2.resources.Project
"""
response = self.nc.request(self.get_base_url(project))
- data_dict = response.json
- return ProjectChrootList(
- self,
- project=project,
+ return ProjectChrootList.from_response(
+ handle=self,
response=response,
- links=Link.from_dict(data_dict["_links"], {
- "self": EntityTypes.PROJECT_CHROOT,
- }),
- individuals=[
- ProjectChroot.from_response(
- handle=self,
- response=None,
- data_dict=dict_part,
- project=project
- )
- for dict_part in data_dict["chroots"]
- ]
+ project=project
)
def disable(self, project, name):
diff --git a/python/copr/client_v2/resources.py b/python/copr/client_v2/resources.py
index fa40551..e8f258b 100644
--- a/python/copr/client_v2/resources.py
+++ b/python/copr/client_v2/resources.py
@@ -129,13 +129,16 @@ class Project(IndividualResource):
return self._handle.get_one(self.id, **self._options)
def get_project_chroot(self, name):
- return self._handle.get_project_chroot(self, name)
+ handle = self._handle.get_project_chroots_handle()
+ return handle.get_one(self, name)
def get_project_chroot_list(self):
- return self._handle.get_project_chroot_list(self)
+ handle = self._handle.get_project_chroots_handle()
+ return handle.get_list(self)
def enable_project_chroot(self, *args, **kwargs):
- return self._handle.enable_chroot(self, *args, **kwargs)
+ handle = self._handle.get_project_chroots_handle()
+ return handle.enable(self, *args, **kwargs)
# TODO: remove proxy methods on the handle classes
def create_build_from_file(self, *args, **kwargs):
@@ -279,6 +282,10 @@ class CollectionResource(Iterable, UnicodeMixin):
"""
return iter(self._individuals)
+ @classmethod
+ def from_response(cls, handle, response, options):
+ raise NotImplementedError
+
# todo: add classmethod from response
@@ -295,6 +302,27 @@ class ProjectsList(CollectionResource):
def projects(self):
return self._individuals
+ @classmethod
+ def from_response(cls, handle, response, options):
+ data_dict = response.json
+ result = ProjectsList(
+ handle,
+ response=response,
+ links=Link.from_dict(data_dict["_links"], {
+ "self": EntityTypes.PROJECT,
+ }),
+ individuals=[
+ Project.from_response(
+ handle=handle,
+ response=None,
+ data_dict=dict_part,
+ )
+ for dict_part in data_dict["projects"]
+ ],
+ options=None
+ )
+ return result
+
class BuildList(CollectionResource):
"""
@@ -308,6 +336,26 @@ class BuildList(CollectionResource):
def builds(self):
return self._individuals
+ @classmethod
+ def from_response(cls, handle, response, options):
+ data_dict = response.json
+ result = BuildList(
+ handle,
+ response=response,
+ links=Link.from_dict(data_dict["_links"], {
+ "self": EntityTypes.BUILD,
+ }),
+ individuals=[
+ Build.from_response(
+ handle=handle,
+ response=None,
+ data_dict=dict_part,
+ )
+ for dict_part in data_dict["builds"]
+ ]
+ )
+ return result
+
class ProjectChrootList(CollectionResource):
"""
@@ -326,6 +374,27 @@ class ProjectChrootList(CollectionResource):
def enable(self, name):
return self._handle.enable(self._project, name)
+ @classmethod
+ def from_response(cls, handle, response, project):
+ data_dict = response.json
+ return ProjectChrootList(
+ handle,
+ project=project,
+ response=response,
+ links=Link.from_dict(data_dict["_links"], {
+ "self": EntityTypes.PROJECT_CHROOT,
+ }),
+ individuals=[
+ ProjectChroot.from_response(
+ handle=handle,
+ response=None,
+ data_dict=dict_part,
+ project=project
+ )
+ for dict_part in data_dict["chroots"]
+ ]
+ )
+
class MockChrootList(CollectionResource):
"""
diff --git a/python/run_tmp.py b/python/run_tmp.py
index cc630b1..780db44 100644
--- a/python/run_tmp.py
+++ b/python/run_tmp.py
@@ -70,6 +70,8 @@ def main():
for pc in project.get_project_chroot_list():
print(pc)
+ t4()
+
def t5():
build = client.builds.get_one(117578)
#build._handle.cancel(build._entity)
@@ -82,7 +84,7 @@ def main():
def t6():
- project = client.projects.get_one("4642")
+ project = client.projects.get_one(3554)
print(project)
# new_c = project.get_project_chroot("epel-5-x86_64")
@@ -92,12 +94,13 @@ def main():
for pc in project.get_project_chroot_list():
print(pc)
- pc.disable()
+ # pc.disable()
x = 2
+ t6()
#
def t7():
@@ -132,7 +135,10 @@ def main():
for mc in mcl:
print(mc)
- t9()
+ # t9()
+
+ def t10():
+ pass
if __name__ == "__main__":
try:
8 years, 6 months
[copr] python_copr_apiv2: [python][api_v2] added support for MockChroot resource (e0ca760)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : python_copr_apiv2
>---------------------------------------------------------------
commit e0ca7601cb06ba17cfa11d8739cef20e8bab60ad
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Sep 30 14:35:20 2015 +0200
[python][api_v2] added support for MockChroot resource
>---------------------------------------------------------------
python/copr/client_v2/client.py | 22 +++++++-
python/copr/client_v2/common.py | 13 +++++
python/copr/client_v2/entities.py | 73 ++++++++++++++++++-------
python/copr/client_v2/handlers.py | 45 +++++++++++++++-
python/copr/client_v2/net_client.py | 4 +-
python/copr/client_v2/resources.py | 45 ++++++++++++++-
python/copr/client_v2/schemas.py | 16 +-----
python/copr/test/client_v2/test_net_client.py | 1 +
python/run_tmp.py | 9 +++-
9 files changed, 185 insertions(+), 43 deletions(-)
diff --git a/python/copr/client_v2/client.py b/python/copr/client_v2/client.py
index be05dae..9035d5e 100644
--- a/python/copr/client_v2/client.py
+++ b/python/copr/client_v2/client.py
@@ -20,7 +20,7 @@ from six.moves import configparser
# from requests_toolbelt.multipart.encoder import MultipartEncoder
from .resources import Root
-from .handlers import ProjectHandle, ProjectChrootHandle, BuildHandle
+from .handlers import ProjectHandle, ProjectChrootHandle, BuildHandle, MockChrootHandle
from .common import EntityTypes
from .net_client import NetClient
@@ -68,6 +68,14 @@ class HandlersProvider(with_metaclass(ABCMeta)):
# def build_tasks(self):
# pass
+ @abstractproperty
+ def mock_chroots(self):
+ """
+ :rtype: MockChrootHandle
+ """
+ pass
+
+
class CoprClient(UnicodeMixin, HandlersProvider):
""" Main interface to the copr service
@@ -100,6 +108,7 @@ class CoprClient(UnicodeMixin, HandlersProvider):
self._projects = None
self._project_chroots = None
self._builds = None
+ self._mock_chroots = None
def _check_client_init(self):
if not self._post_init_done:
@@ -121,6 +130,11 @@ class CoprClient(UnicodeMixin, HandlersProvider):
self._check_client_init()
return self._builds
+ @property
+ def mock_chroots(self):
+ self._check_client_init()
+ return self._mock_chroots
+
def __unicode__(self):
return (
u"<Copr client. api root url: {}, config provided: {}, net client: {}>"
@@ -203,9 +217,15 @@ class CoprClient(UnicodeMixin, HandlersProvider):
projects_href=self.root.get_href_by_name(u"projects"),)
self._project_chroots = ProjectChrootHandle(
weakref.proxy(self), self.nc, root_url=self.root_url)
+
self._builds = BuildHandle(
weakref.proxy(self), self.nc, root_url=self.root_url,
builds_href=self.root.get_href_by_name(u"builds"),)
+ # self._build_chroots = BuildTaskHandle()
+ self._mock_chroots = MockChrootHandle(
+ weakref.proxy(self), self.nc, root_url=self.root_url,
+ href=self.root.get_href_by_name(u"mock_chroots")
+ )
self._post_init_done = True
diff --git a/python/copr/client_v2/common.py b/python/copr/client_v2/common.py
index 4e96bf5..8f64195 100644
--- a/python/copr/client_v2/common.py
+++ b/python/copr/client_v2/common.py
@@ -1,4 +1,7 @@
# coding: utf-8
+from copr.util import UnicodeMixin
+
+
class EntityTypes(object):
ROOT = "root"
PROJECT = "project"
@@ -6,3 +9,13 @@ class EntityTypes(object):
BUILD = "build"
BUILD_TASK = "build_task"
MOCK_CHROOT = "mock_chroot"
+
+
+class BuiltPackage(UnicodeMixin):
+
+ def __init__(self, name, version):
+ self.name = name
+ self.version = version
+
+ def __unicode__(self):
+ return u"{} {}".format(self.name, self.version)
diff --git a/python/copr/client_v2/entities.py b/python/copr/client_v2/entities.py
index 6789872..b39aa12 100644
--- a/python/copr/client_v2/entities.py
+++ b/python/copr/client_v2/entities.py
@@ -1,11 +1,10 @@
# coding: utf-8
from ..util import UnicodeMixin
-from .schemas import ProjectSchema, EmptySchema, ProjectChrootSchema, BuildSchema, BuildTaskSchema
+from .schemas import ProjectSchema, EmptySchema, ProjectChrootSchema, BuildSchema, BuildTaskSchema, MockChrootSchema
class Link(UnicodeMixin):
-
def __init__(self, role, href, target_type):
self.role = role
self.href = href
@@ -44,9 +43,12 @@ class Link(UnicodeMixin):
class Entity(UnicodeMixin):
-
_schema = EmptySchema()
+ def __init__(self, **kwargs):
+ for field in self._schema.fields.keys():
+ setattr(self, field, kwargs.get(field))
+
def to_dict(self):
return self._schema.dump(self).data
@@ -54,52 +56,83 @@ class Entity(UnicodeMixin):
return self._schema.dumps(self).data
@classmethod
- def constructor(cls, **kwargs):
- return cls.from_dict(kwargs)
-
- @classmethod
def from_dict(cls, raw_dict):
parsed = cls._schema.load(raw_dict)
- obj = cls()
- for field, value in parsed.data.items():
- setattr(obj, field, value)
- return obj
+ return cls(**parsed.data)
class ProjectEntity(Entity):
-
_schema = ProjectSchema(strict=True)
+ # def __init__(self, **kwargs):
+ # self.id = kwargs["id"]
+ # self.name = kwargs["name"]
+ #
+ # self.owner = kwargs["owner"]
+ # self.description = kwargs.get("description")
+ # self.instructions = kwargs.get("instructions")
+ # self.homepage = kwargs.get("homepage")
+ # self.contact = kwargs.get("contact")
+ #
+ # self.disable_createrepo = kwargs.get("disable_createrepo")
+ # self.build_enable_net = kwargs.get("build_enable_net")
+ # self.last_modified = kwargs.get("last_modified")
+ #
+ # self.repos = kwargs.get("repos", list())
+
def __unicode__(self):
return "<Project #{}: {}/{}>".format(self.id, self.owner, self.name)
class ProjectChrootEntity(Entity):
-
_schema = ProjectChrootSchema(strict=True)
+ # def __init__(self, **kwargs):
+ # self.name = kwargs["name"]
+ # self.buildroot_pkgs = kwargs.get("buildroot_pkgs", list())
+ #
+ # self.comps = kwargs.get("comps")
+ # self.comps_name = kwargs.get("comps_name")
+ # self.comps_len = kwargs.get("comps_len")
+
def __unicode__(self):
return "<Project chroot: {}, additional " \
- "packages: {}, comps size if any: {}>".format(
- self.name,
- self.buildroot_pkgs,
- self.comps_len,
- )
+ "packages: {}, comps size if any: {}>"\
+ .format(self.name, self.buildroot_pkgs, self.comps_len,)
class BuildEntity(Entity):
-
_schema = BuildSchema(strict=True)
+ # def __init__(self, **kwargs):
+ #
+ # self.id = kwargs["id"]
+ # self.state = kwargs["state"]
+ #
+ # self.submitter = kwargs["submitter"]
+ #
+ # self.built_packages = kwargs["built_packages"]
+ #
+ #
+
def __unicode__(self):
return "<Build #{} state: {}>".format(self.id, self.state)
class BuildTaskEntity(Entity):
-
_schema = BuildTaskSchema(strict=True)
def __unicode__(self):
return "<Build task #{}-{}, state: {}>".format(
self.build_id, self.chroot_name, self.state
)
+
+
+class MockChrootEntity(Entity):
+
+ _schema = MockChrootSchema(strict=True)
+
+ def __unicode__(self):
+ return "<Mock chroot: {} is active: {}>".format(
+ self.name, self.is_active
+ )
diff --git a/python/copr/client_v2/handlers.py b/python/copr/client_v2/handlers.py
index d590f75..03eb7c3 100644
--- a/python/copr/client_v2/handlers.py
+++ b/python/copr/client_v2/handlers.py
@@ -6,7 +6,8 @@ import os
from .common import EntityTypes
from copr.client_v2.net_client import RequestError, MultiPartTuple
from .entities import Link, ProjectChrootEntity
-from .resources import Project, OperationResult, ProjectsList, ProjectChroot, ProjectChrootList, Build, BuildList
+from .resources import Project, OperationResult, ProjectsList, ProjectChroot, ProjectChrootList, Build, BuildList, \
+ MockChroot, MockChrootList
class AbstractHandle(object):
@@ -373,7 +374,7 @@ class ProjectChrootHandle(AbstractHandle):
:type project: copr.client_v2.resources.Project
"""
- new_entity = ProjectChrootEntity.constructor(
+ new_entity = ProjectChrootEntity(
name=name,
buildroot_pkgs=buildroot_pkgs or list()
)
@@ -398,3 +399,43 @@ class ProjectChrootHandle(AbstractHandle):
do_auth=True
)
return OperationResult(self, response)
+
+
+class MockChrootHandle(AbstractHandle):
+
+ def __init__(self, client, nc, root_url, href):
+ super(MockChrootHandle, self).__init__(client, nc, root_url)
+ self._href = href
+ self._base_url = "{}{}".format(self.root_url, href)
+
+ def get_base_url(self):
+ return self._base_url
+
+ def get_one(self, name):
+ url = "{}/{}".format(self.get_base_url(), name)
+ response = self.nc.get(url)
+ return MockChroot.from_response(self, response, response.json)
+
+ def get_list(self, active_only=True):
+ options = dict(active_only=active_only)
+
+ response = self.nc.get(
+ self.get_base_url(),
+ query_params=options
+ )
+ data_dict = response.json
+ return MockChrootList(
+ self,
+ response=response,
+ links=Link.from_dict(data_dict["_links"], {
+ "self": EntityTypes.MOCK_CHROOT,
+ }),
+ individuals=[
+ MockChroot.from_response(
+ handle=self,
+ response=None,
+ data_dict=dict_part,
+ )
+ for dict_part in data_dict["chroots"]
+ ]
+ )
diff --git a/python/copr/client_v2/net_client.py b/python/copr/client_v2/net_client.py
index 676d4f6..74b66b0 100644
--- a/python/copr/client_v2/net_client.py
+++ b/python/copr/client_v2/net_client.py
@@ -24,9 +24,9 @@ class RequestError(Exception, UnicodeMixin):
@property
def response_json(self):
- if self.response.headers["content-type"] == "application/json":
- if self.response is None:
+ if self.response is None:
raise ValueError("No response")
+ if self.response.headers["content-type"] == "application/json":
try:
result = json.loads(self.response.text)
except (ValueError, AttributeError):
diff --git a/python/copr/client_v2/resources.py b/python/copr/client_v2/resources.py
index ac0537d..fa40551 100644
--- a/python/copr/client_v2/resources.py
+++ b/python/copr/client_v2/resources.py
@@ -4,7 +4,7 @@ from collections import Iterable
from ..util import UnicodeMixin
from .common import EntityTypes
-from .entities import Link, ProjectEntity, ProjectChrootEntity, BuildEntity
+from .entities import Link, ProjectEntity, ProjectChrootEntity, BuildEntity, MockChrootEntity
from .schemas import EmptySchema
@@ -143,7 +143,7 @@ class Project(IndividualResource):
See additional options `:py:method:BuildHandle.create_from_file:`
"""
builds = self._handle.get_builds_handle()
- builds.create_from_file(self.id, *args, **kwargs)
+ return builds.create_from_file(self.id, *args, **kwargs)
@classmethod
def from_response(cls, handle, response, data_dict, options=None):
@@ -186,6 +186,29 @@ class ProjectChroot(IndividualResource):
return self._handle.update(self._project, self._entity)
+class MockChroot(IndividualResource):
+ """
+ :type entity: copr.client_v2.entities.MockChrootEntity
+ :type handle: copr.client_v2.handlers.MockChrootHandle
+ """
+
+ def __init__(self, entity, handle, **kwargs):
+ super(MockChroot, self).__init__(
+ entity=entity,
+ handle=handle,
+ **kwargs
+ )
+
+ @classmethod
+ def from_response(cls, handle, response, data_dict, options=None):
+ links = Link.from_dict(data_dict["_links"], {
+ "self": EntityTypes.MOCK_CHROOT,
+ })
+ entity = MockChrootEntity.from_dict(data_dict["chroot"])
+ return cls(entity=entity, handle=handle,
+ response=response, links=links, options=options)
+
+
class OperationResult(IndividualResource):
# TODO: app param expected_status=200 and method is_successful() which would compare
@@ -256,6 +279,8 @@ class CollectionResource(Iterable, UnicodeMixin):
"""
return iter(self._individuals)
+ # todo: add classmethod from response
+
class ProjectsList(CollectionResource):
"""
@@ -286,7 +311,7 @@ class BuildList(CollectionResource):
class ProjectChrootList(CollectionResource):
"""
- :type handle: coprclient_v2.handlers.ProjectChrootHandle
+ :type handle: copr.client_v2.handlers.ProjectChrootHandle
"""
def __init__(self, handle, project, **kwargs):
@@ -300,3 +325,17 @@ class ProjectChrootList(CollectionResource):
def enable(self, name):
return self._handle.enable(self._project, name)
+
+
+class MockChrootList(CollectionResource):
+ """
+ :type handle: copr.client_v2.handlers.MockChrootHandle
+ """
+
+ def __init__(self, handle, **kwargs):
+ super(MockChrootList, self).__init__(**kwargs)
+ self._handle = handle
+
+ @property
+ def chroots(self):
+ return self._individuals
diff --git a/python/copr/client_v2/schemas.py b/python/copr/client_v2/schemas.py
index c4c780c..68ca2b4 100644
--- a/python/copr/client_v2/schemas.py
+++ b/python/copr/client_v2/schemas.py
@@ -1,14 +1,12 @@
# coding: utf-8
-from collections import Iterable
-from marshmallow import Schema, fields, post_load
-from marshmallow import Schema, fields, validates_schema, ValidationError, validate
+from marshmallow import Schema, fields
# todo: maybe define schemas for Link sets in each indvidual/collection
# class LinkSchema(Schema):
# href = fields.Str()
#
-from copr.util import UnicodeMixin
+from .common import BuiltPackage
class EmptySchema(Schema):
@@ -43,16 +41,6 @@ class ProjectChrootSchema(Schema):
comps_len = fields.Int(load_only=True, allow_none=True)
-class BuiltPackage(UnicodeMixin):
-
- def __init__(self, name, version):
- self.name = name
- self.version = version
-
- def __unicode__(self):
- return u"{} {}".format(self.name, self.version)
-
-
class BuiltPackageSchema(Schema):
name = fields.Str()
diff --git a/python/copr/test/client_v2/test_net_client.py b/python/copr/test/client_v2/test_net_client.py
index ba9113f..7cca53a 100644
--- a/python/copr/test/client_v2/test_net_client.py
+++ b/python/copr/test/client_v2/test_net_client.py
@@ -66,4 +66,5 @@ class TestNetClient(object):
# some coverage for Request error
s = str(exc_info.value)
with pytest.raises(ValueError):
+ # import ipdb; ipdb.set_trace()
x = exc_info.value.response_json
diff --git a/python/run_tmp.py b/python/run_tmp.py
index 6347eb8..cc630b1 100644
--- a/python/run_tmp.py
+++ b/python/run_tmp.py
@@ -124,8 +124,15 @@ def main():
b = b.get_self()
print(b)
- t8()
+ # t8()
+ def t9():
+
+ mcl = client.mock_chroots.get_list(active_only=False)
+ for mc in mcl:
+ print(mc)
+
+ t9()
if __name__ == "__main__":
try:
8 years, 6 months
[copr] frontend-python3: [frontend] more py2/py3 compatibile strings magic (cea2c35)
by frostyx@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : frontend-python3
>---------------------------------------------------------------
commit cea2c3532e4613c3aae1c60c127caa0290f94cbc
Author: Jakub Kadlčík <jkadlcik(a)redhat.com>
Date: Wed Sep 30 12:32:15 2015 +0200
[frontend] more py2/py3 compatibile strings magic
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/models.py | 2 +-
frontend/coprs_frontend/coprs/rest_api/common.py | 2 +-
frontend/coprs_frontend/coprs/rest_api/schemas.py | 3 ++-
.../tests/test_api/test_project_chroot_r.py | 4 ++--
.../test_views/test_coprs_ns/test_coprs_general.py | 2 +-
5 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index 63ef2bd..5f04a6e 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -646,7 +646,7 @@ class CoprChroot(db.Model, helpers.Serializer):
comps_name = db.Column(db.String(127), nullable=True)
def update_comps(self, comps_xml):
- self.comps_zlib = zlib.compress(comps_xml)
+ self.comps_zlib = zlib.compress(comps_xml.encode("utf-8"))
@property
def buildroot_pkgs_list(self):
diff --git a/frontend/coprs_frontend/coprs/rest_api/common.py b/frontend/coprs_frontend/coprs/rest_api/common.py
index 6be90b2..d554369 100644
--- a/frontend/coprs_frontend/coprs/rest_api/common.py
+++ b/frontend/coprs_frontend/coprs/rest_api/common.py
@@ -91,7 +91,7 @@ def rest_api_auth_required(f):
base64string = flask.request.headers["Authorization"]
base64string = base64string.split()[1].strip()
userstring = base64.b64decode(base64string)
- (api_login, token) = userstring.split(b":")
+ (api_login, token) = userstring.decode("utf-8").split(":")
except Exception:
log.exception("Failed to get auth token from headers")
api_login = token = None
diff --git a/frontend/coprs_frontend/coprs/rest_api/schemas.py b/frontend/coprs_frontend/coprs/rest_api/schemas.py
index 2144b54..05cc5be 100644
--- a/frontend/coprs_frontend/coprs/rest_api/schemas.py
+++ b/frontend/coprs_frontend/coprs/rest_api/schemas.py
@@ -3,6 +3,7 @@
from collections import Iterable
from marshmallow import Schema, fields
from marshmallow import Schema, fields, validates_schema, ValidationError, validate
+from six import string_types
def validate_any(fn_list):
@@ -37,7 +38,7 @@ class SpaceSeparatedList(fields.Field):
def _deserialize(self, value):
if value is None:
return ""
- elif not isinstance(value, Iterable) or isinstance(value, basestring):
+ elif not isinstance(value, Iterable) or isinstance(value, string_types):
raise ValidationError("Value `{}` is not a list of strings"
.format(value))
else:
diff --git a/frontend/coprs_frontend/tests/test_api/test_project_chroot_r.py b/frontend/coprs_frontend/tests/test_api/test_project_chroot_r.py
index 054b37f..0562737 100644
--- a/frontend/coprs_frontend/tests/test_api/test_project_chroot_r.py
+++ b/frontend/coprs_frontend/tests/test_api/test_project_chroot_r.py
@@ -93,7 +93,7 @@ class TestProjectChrootResource(CoprsTestCase):
for k, v in data.items():
assert response_data.get(k) == v
- assert_content(json.loads(r2.data)["chroot"])
+ assert_content(json.loads(r2.data.decode("utf-8"))["chroot"])
# test idempotency
self.request_rest_api_with_auth(
@@ -103,7 +103,7 @@ class TestProjectChrootResource(CoprsTestCase):
)
r3 = self.tc.get("/api_2/projects/1/chroots/{}".format(chroot_name))
assert r3.status_code == 200
- assert_content(json.loads(r3.data)["chroot"])
+ assert_content(json.loads(r3.data.decode("utf-8"))["chroot"])
# test put with excessive name field
data["name"] = chroot_name
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 e34e971..64c6bb2 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
@@ -501,7 +501,7 @@ class TestCoprUpdatePermissions(CoprsTestCase):
'<option selected value="2">approved</option>'
'</select>'
)
- assert check_string not in r.data
+ assert check_string.encode("utf-8") not in r.data
@TransactionDecorator("u2")
def test_update_more_permissions(self, f_users, f_coprs,
8 years, 6 months
[copr] frontend-python3: [frontend] sort by argument 'key' instead of 'cmp' (6d7747b)
by frostyx@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : frontend-python3
>---------------------------------------------------------------
commit 6d7747b1f68aa62bc4834a73453c031e026bb1bc
Author: Jakub Kadlčík <jkadlcik(a)redhat.com>
Date: Tue Sep 29 12:46:13 2015 +0200
[frontend] sort by argument 'key' instead of 'cmp'
>---------------------------------------------------------------
.../coprs/views/coprs_ns/coprs_general.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
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 bf37527..c6a5d18 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -453,7 +453,7 @@ def copr_update_permissions(username, coprname):
# if admin is changing his permissions, his must be changed last
# so that we don't get InsufficientRightsException
permissions.sort(
- cmp=lambda x, y: -1 if y.user_id == flask.g.user.id else 1)
+ key=lambda x: -1 if x.user_id == flask.g.user.id else 1)
for perm in permissions:
old_builder = perm.copr_builder
old_admin = perm.copr_admin
8 years, 6 months
[copr] frontend-python3: [frontend] more py2/py3 compatibile strings magic (c8822b8)
by frostyx@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : frontend-python3
>---------------------------------------------------------------
commit c8822b855fb6947d3b095294b8bad34f794a7d44
Author: Jakub Kadlčík <jkadlcik(a)redhat.com>
Date: Tue Sep 29 12:29:26 2015 +0200
[frontend] more py2/py3 compatibile strings magic
>---------------------------------------------------------------
.../test_views/test_coprs_ns/test_coprs_builds.py | 4 ++--
.../test_views/test_coprs_ns/test_coprs_general.py | 14 +++++++-------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py b/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
index 2fa1290..02ef73a 100644
--- a/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
+++ b/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
@@ -236,7 +236,7 @@ class TestCoprRepeatBuild(CoprsTestCase):
assert r.status_code == 200
# no longer using URL
#assert self.b_few_chroots.pkgs in r.data
- assert b"Resubmit build {}".format(self.b_few_chroots.id) in r.data
+ assert "Resubmit build {}".format(self.b_few_chroots.id).encode("utf-8") in r.data
# TODO: maybe test, that only failed chroots are selected
@@ -264,7 +264,7 @@ class TestCoprRepeatBuild(CoprsTestCase):
data={},
follow_redirects=True)
- assert b"Resubmit build {}".format(self.b1.id) in r.data
+ assert "Resubmit build {}".format(self.b1.id).encode("utf-8") in r.data
assert r.status_code == 200
# assert "Build was resubmitted" in r.data
# assert len(self.models.Build.query
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 ca0ab85..e34e971 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
@@ -100,7 +100,7 @@ class TestCoprNew(CoprsTestCase):
assert self.models.Copr.query.filter(
self.models.Copr.name == "foo").first()
- assert self.success_string in r.data
+ assert self.success_string.encode("utf-8") in r.data
# make sure no initial build was submitted
assert self.models.Build.query.first() is None
@@ -124,7 +124,7 @@ class TestCoprNew(CoprsTestCase):
assert len(self.models.Copr.query.filter(
self.models.Copr.name == self.c1.name).all()) == foocoprs + 1
- assert self.success_string in r.data
+ assert self.success_string.encode("utf-8") in r.data
@TransactionDecorator("u1")
def test_copr_new_exists_for_this_user(self, f_users, f_coprs,
@@ -159,7 +159,7 @@ class TestCoprNew(CoprsTestCase):
copr = self.models.Copr.query.filter(
self.models.Copr.name == "foo").first()
assert copr
- assert self.success_string in r.data
+ assert self.success_string.encode("utf-8") in r.data
assert self.models.Build.query.first().copr == copr
assert self.models.Build.query.first().enable_net is True
@@ -181,7 +181,7 @@ class TestCoprNew(CoprsTestCase):
copr = self.models.Copr.query.filter(
self.models.Copr.name == "foo").first()
assert copr
- assert self.success_string in r.data
+ assert self.success_string.encode("utf-8") in r.data
assert self.models.Build.query.first().copr == copr
assert self.models.Build.query.first().enable_net is False
@@ -210,7 +210,7 @@ class TestCoprNew(CoprsTestCase):
self.c1.name)
.filter(self.models.Copr.owner == self.u1)
.all()) == 2
- assert self.success_string in r.data
+ assert self.success_string.encode("utf-8") in r.data
class TestCoprDetail(CoprsTestCase):
@@ -292,8 +292,8 @@ class TestCoprEdit(CoprsTestCase):
# TODO: use some kind of html parsing library to look
# for the hidden input, this ties us
# to the precise format of the tag
- assert (b'<input hidden id="id" name="id" type="hidden" value="{0}">'
- .format(self.c1.id) in r.data)
+ assert ('<input hidden id="id" name="id" type="hidden" value="{0}">'
+ .format(self.c1.id).encode("utf-8") in r.data)
class TestCoprUpdate(CoprsTestCase):
8 years, 6 months
[copr] frontend-python3: [frontend] explicitly cast map results to list On python3, the result of a map function is an iterator, not list (df35612)
by frostyx@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : frontend-python3
>---------------------------------------------------------------
commit df35612db1f517f0f72abf52d721006d3cbd1861
Author: Jakub Kadlčík <jkadlcik(a)redhat.com>
Date: Tue Sep 29 12:21:37 2015 +0200
[frontend] explicitly cast map results to list
On python3, the result of a map function is an iterator, not list
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/forms.py | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/forms.py b/frontend/coprs_frontend/coprs/forms.py
index 9e9feda..b42d05a 100644
--- a/frontend/coprs_frontend/coprs/forms.py
+++ b/frontend/coprs_frontend/coprs/forms.py
@@ -227,10 +227,10 @@ class CoprFormFactory(object):
have_any = True
return have_any
- F.chroots_list = map(lambda x: x.name,
+ F.chroots_list = list(map(lambda x: x.name,
models.MockChroot.query.filter(
models.MockChroot.is_active == True
- ).all())
+ ).all()))
F.chroots_list.sort()
# sets of chroots according to how we should print them in columns
F.chroots_sets = {}
@@ -300,7 +300,7 @@ class BuildFormFactory(object):
enable_net = wtforms.BooleanField()
- F.chroots_list = map(lambda x: x.name, active_chroots)
+ F.chroots_list = list(map(lambda x: x.name, active_chroots))
F.chroots_list.sort()
F.chroots_sets = {}
for ch in F.chroots_list:
@@ -392,7 +392,7 @@ class BuildFormRebuildFactory(object):
enable_net = wtforms.BooleanField()
- F.chroots_list = map(lambda x: x.name, active_chroots)
+ F.chroots_list = list(map(lambda x: x.name, active_chroots))
F.chroots_list.sort()
F.chroots_sets = {}
for ch in F.chroots_list:
8 years, 6 months
[copr] master: [frontend][groups support] fix html (0f03dba)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 0f03dba8aabaa9910bd358a5b9da94fda23c4cd9
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Sep 30 11:26:16 2015 +0200
[frontend][groups support] fix html
>---------------------------------------------------------------
.../coprs/templates/coprs/detail/overview.html | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html b/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
index c4f69e9..d055f0e 100644
--- a/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
+++ b/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
@@ -169,7 +169,7 @@
<h3 class="panel-title"> Other Actions </h3>
</div>
<div class="panel-body">
- {% if user.can_edit(copr) and not copr.is_a_group_project %}
+ {% if user and user.can_edit(copr) and not copr.is_a_group_project %}
<a href="{{ url_for('coprs_ns.copr_group_managed', username = copr.owner.name, coprname = copr.name) }}">
Change to a group project
</a>
8 years, 6 months
[copr] master: [frontend][rhbz: #1266750] Unable to view second, third, ��� page of search results: " Search string must have at least 3 characters " (cf27a99)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit cf27a994b3885aac31cd2f2f816a0e541bc66fb8
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Sep 30 11:21:27 2015 +0200
[frontend][rhbz: #1266750] Unable to view second, third, … page of search results: " Search string must have at least 3 characters "
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/helpers.py | 6 +++++-
.../coprs/views/coprs_ns/coprs_general.py | 4 +++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/helpers.py b/frontend/coprs_frontend/coprs/helpers.py
index f3406b4..ef1a504 100644
--- a/frontend/coprs_frontend/coprs/helpers.py
+++ b/frontend/coprs_frontend/coprs/helpers.py
@@ -110,13 +110,16 @@ class FailTypeEnum(object):
class Paginator(object):
def __init__(self, query, total_count, page=1,
- per_page_override=None, urls_count_override=None):
+ per_page_override=None, urls_count_override=None,
+ additional_params=None):
self.query = query
self.total_count = total_count
self.page = page
self.per_page = per_page_override or constants.ITEMS_PER_PAGE
self.urls_count = urls_count_override or constants.PAGES_URLS_COUNT
+ self.additional_params = additional_params or dict()
+
self._sliced_query = None
def page_slice(self, page):
@@ -155,6 +158,7 @@ class Paginator(object):
def url_for_other_page(self, request, page):
args = request.view_args.copy()
args["page"] = page
+ args.update(self.additional_params)
return flask.url_for(request.endpoint, **args)
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 2891ca8..6c14138 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -123,7 +123,8 @@ def coprs_fulltext_search(page=1):
return flask.redirect(flask.request.referrer or
flask.url_for("coprs_ns.coprs_show"))
- paginator = helpers.Paginator(query, query.count(), page)
+ paginator = helpers.Paginator(query, query.count(), page,
+ additional_params={"fulltext": fulltext})
coprs = paginator.sliced_query
return render_template("coprs/show/fulltext.html", coprs=coprs,
@@ -358,6 +359,7 @@ def _check_rpmfusion(repos):
message = flask.Markup('Using rpmfusion as dependency is nearly always wrong. Please see <a href="https://fedorahosted.org/copr/wiki/UserDocs#WhatIcanbuildinCopr">What I can build in Copr</a>.')
flask.flash(message, "error")
+
@coprs_ns.route("/<username>/<coprname>/update/", methods=["POST"])
@login_required
def copr_update(username, coprname):
8 years, 6 months
[copr] master: [frontend] Support group projects, Work In progress (f990384)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit f990384a5f964780edb71557007b963713e1e4aa
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Tue Sep 29 17:29:19 2015 +0200
[frontend] Support group projects, Work In progress
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/forms.py | 14 ++++
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 46 +++++++++++--
frontend/coprs_frontend/coprs/logic/users_logic.py | 33 +++++++++-
frontend/coprs_frontend/coprs/models.py | 25 ++++++-
frontend/coprs_frontend/coprs/redis_session.py | 1 +
.../templates/coprs/detail/make_group_project.html | 35 ++++++++++
.../coprs/templates/coprs/detail/overview.html | 16 +++++
.../coprs/views/coprs_ns/coprs_general.py | 68 ++++++++++++++++++--
frontend/coprs_frontend/coprs/views/misc.py | 2 +-
9 files changed, 221 insertions(+), 19 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/forms.py b/frontend/coprs_frontend/coprs/forms.py
index 7ffe436..ea8f795 100644
--- a/frontend/coprs_frontend/coprs/forms.py
+++ b/frontend/coprs_frontend/coprs/forms.py
@@ -506,3 +506,17 @@ class AdminPlaygroundForm(wtf.Form):
class AdminPlaygroundSearchForm(wtf.Form):
project = wtforms.TextField("Project")
+
+
+def group_managed_form_fabric(available_fas_groups):
+ """
+ :type available_fas_groups: list of str
+ """
+ choices = [(x, x) for x in available_fas_groups]
+
+ class GroupManagedForm(wtf.Form):
+
+ name = wtforms.StringField()
+ fas_name = wtforms.SelectField(choices=choices)
+
+ return GroupManagedForm()
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index ec56f0a..03ed0a2 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -39,6 +39,22 @@ class CoprsLogic(object):
return cls.get_all().filter(models.Copr.id == copr_id)
@classmethod
+ 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):
+ query = (query.outerjoin(*models.Copr.mock_chroots.attr)
+ .options(db.contains_eager(*models.Copr.mock_chroots.attr))
+ .order_by(models.MockChroot.os_release.asc())
+ .order_by(models.MockChroot.os_version.asc())
+ .order_by(models.MockChroot.arch.asc()))
+ return query
+
+ @classmethod
def get(cls, username, coprname, **kwargs):
with_builds = kwargs.get("with_builds", False)
with_mock_chroots = kwargs.get("with_mock_chroots", False)
@@ -50,19 +66,33 @@ class CoprsLogic(object):
)
if with_builds:
- query = (query.outerjoin(models.Copr.builds)
- .options(db.contains_eager(models.Copr.builds))
- .order_by(models.Build.submitted_on.desc()))
+ query = cls._attach_build(query)
+
+ if with_mock_chroots:
+ query = cls._attach_mock_chroots(query)
+
+ return query
+
+ @classmethod
+ def get_by_group_id(cls, group_id, coprname, **kwargs):
+ with_builds = kwargs.get("with_builds", False)
+ with_mock_chroots = kwargs.get("with_mock_chroots", False)
+
+ query = (
+ cls.get_all()
+ .filter(models.Copr.group_id == group_id)
+ .filter(models.Copr.name == coprname)
+ )
+
+ if with_builds:
+ query = cls._attach_build(query)
if with_mock_chroots:
- query = (query.outerjoin(*models.Copr.mock_chroots.attr)
- .options(db.contains_eager(*models.Copr.mock_chroots.attr))
- .order_by(models.MockChroot.os_release.asc())
- .order_by(models.MockChroot.os_version.asc())
- .order_by(models.MockChroot.arch.asc()))
+ query = cls._attach_mock_chroots(query)
return query
+
@classmethod
def get_multiple(cls, include_deleted=False):
query = (
diff --git a/frontend/coprs_frontend/coprs/logic/users_logic.py b/frontend/coprs_frontend/coprs/logic/users_logic.py
index 3d494e8..68092a4 100644
--- a/frontend/coprs_frontend/coprs/logic/users_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/users_logic.py
@@ -1,6 +1,7 @@
from coprs import exceptions
-from coprs.models import User
+from coprs import db
+from coprs.models import User, Group
class UsersLogic(object):
@@ -34,3 +35,33 @@ class UsersLogic(object):
if not user.can_build_in(copr):
raise exceptions.InsufficientRightsException(message)
+
+ @classmethod
+ def get_group_by_alias(cls, name):
+ return Group.query.filter(Group.name == name)
+
+ @classmethod
+ def get_group_by_fas_name(cls, fas_name):
+ return Group.query.filter(Group.fas_name == fas_name)
+
+ @classmethod
+ def create_group_by_fas_name(cls, fas_name, alias=None):
+ if alias is None:
+ alias = fas_name
+
+ group = Group(
+ fas_name=fas_name,
+ name=alias,
+ )
+ db.session.add(group)
+ return group
+
+ @classmethod
+ def get_group_by_fas_name_or_create(cls, fas_name, alias=None):
+ mb_group = cls.get_group_by_fas_name(fas_name).first()
+ if mb_group is not None:
+ return mb_group
+
+ group = cls.create_group_by_fas_name(fas_name, alias)
+ db.session.flush()
+ return group
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index dac42fd..2a6db9b 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -2,6 +2,7 @@ import copy
import datetime
import json
import os
+import flask
from sqlalchemy.ext.associationproxy import association_proxy
from libravatar import libravatar_url
@@ -87,6 +88,11 @@ class User(db.Model, helpers.Serializer):
can_build = True
+ # a bit dirty code, here we access flask.session object
+ if copr.group is not None and \
+ copr.group.fas_name in flask.session.get("teams", []):
+ return True
+
return can_build
def can_edit(self, copr):
@@ -94,16 +100,20 @@ class User(db.Model, helpers.Serializer):
Determine if this user can edit the given copr.
"""
- can_edit = False
if copr.owner == self or self.admin:
- can_edit = True
+ return True
if (self.permissions_for_copr(copr) and
self.permissions_for_copr(copr).copr_admin ==
helpers.PermissionEnum("approved")):
- can_edit = True
+ return True
- return can_edit
+ # a bit dirty code, here we access flask.session object
+ if copr.group is not None and \
+ copr.group.fas_name in flask.session.get("teams", []):
+ return True
+
+ return False
@property
def serializable_attributes(self):
@@ -173,6 +183,10 @@ class Copr(db.Model, helpers.Serializer):
}
@property
+ def is_a_group_project(self):
+ return self.group_id is not None
+
+ @property
def owner_name(self):
return self.owner.name
@@ -855,12 +869,15 @@ class CounterStat(db.Model, helpers.Serializer):
counter = db.Column(db.Integer, default=0, server_default="0")
+
class Group(db.Model, helpers.Serializer):
"""
Represents FAS groups and their aliases in Copr
"""
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(127))
+
+ # TODO: add unique=True
fas_name = db.Column(db.String(127))
def __str__(self):
diff --git a/frontend/coprs_frontend/coprs/redis_session.py b/frontend/coprs_frontend/coprs/redis_session.py
index d345777..5ec89b6 100644
--- a/frontend/coprs_frontend/coprs/redis_session.py
+++ b/frontend/coprs_frontend/coprs/redis_session.py
@@ -54,6 +54,7 @@ class RedisSessionInterface(SessionInterface):
return self.session_class(sid=sid, new=True)
def save_session(self, app, session, response):
+ # print("String session: {}".format(session))
domain = self.get_cookie_domain(app)
if not session:
self.redis.delete(self.prefix + session.sid)
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/detail/make_group_project.html b/frontend/coprs_frontend/coprs/templates/coprs/detail/make_group_project.html
new file mode 100644
index 0000000..e1fb714
--- /dev/null
+++ b/frontend/coprs_frontend/coprs/templates/coprs/detail/make_group_project.html
@@ -0,0 +1,35 @@
+{% extends "coprs/detail.html" %}
+
+{% from "_helpers.html" import render_field, render_form_errors %}
+
+{% block title %}
+ Change project {{ copr.owner.name }}/{{ copr.name }} into a group managed one/
+
+{% endblock %}
+{%block project_breadcrumb %}
+{#
+<!--<li>-->
+ <!--<a href="{{ url_for('coprs_ns.copr_builds', username=copr.owner.name, coprname=copr.name) }}">Packages</a>-->
+<!--</li>-->
+#}
+<li class="active">
+
+</li>
+{%endblock%}
+
+{% block detail_body %}
+ <h3>
+ Select Fas project to bound project
+ </h3>
+ <form class="form-horizontal"
+ action="{{ url_for('coprs_ns.copr_group_managed', username=copr.owner.name, coprname=copr.name) }}"
+ method="post" enctype="multipart/form-data">
+ {{ form.csrf_token }}
+
+ {{ render_field(form.name, label="Group alias to use in the Copr") }}
+ {{ render_field(form.fas_name) }}
+
+ <input class="btn btn-primary" type="submit" value="Submit">
+ </form>
+
+{% endblock %}
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html b/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
index d5254cc..c4f69e9 100644
--- a/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
+++ b/frontend/coprs_frontend/coprs/templates/coprs/detail/overview.html
@@ -25,6 +25,13 @@
The following unofficial repositories are provided as-is by owner of this project.
Contact the owner directly for bugs or issues (IE: not bugzilla).
</p>
+
+ <p>
+ {% if copr.is_a_group_project %}
+ This project is managed by FAS group {{ copr.group.fas_name }}
+ {% endif %}
+ </p>
+
<table class="table table-striped table-bordered">
<thead>
<tr>
@@ -162,9 +169,18 @@
<h3 class="panel-title"> Other Actions </h3>
</div>
<div class="panel-body">
+ {% if user.can_edit(copr) and not copr.is_a_group_project %}
+ <a href="{{ url_for('coprs_ns.copr_group_managed', username = copr.owner.name, coprname = copr.name) }}">
+ Change to a group project
+ </a>
+ {% endif %}
+
+
<a href="{{ url_for('coprs_ns.copr_report_abuse', username = copr.owner.name, coprname = copr.name) }}">
<small class="pficon pficon-warning-triangle-o"> Report Abuse </small></a>
+
</div>
+
</div>
</div>
</div>
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 7d90c0b..2891ca8 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -19,8 +19,10 @@ 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
@@ -215,18 +217,40 @@ def copr_report_abuse(username, coprname):
form=form)
+(a)coprs_ns.route("/g/<groupname>/<coprname>/")
+def group_copr_detail(groupname, coprname):
+
+ try:
+ group = UsersLogic.get_group_by_alias(groupname).one()
+ except sqlalchemy.orm.exc.NoResultFound:
+ return page_not_found(
+ "Group {} does not exist.".format(groupname))
+
+ try:
+ copr = CoprsLogic.get_by_group_id(group.id, coprname).one()
+ except sqlalchemy.orm.exc.NoResultFound:
+ return page_not_found(
+ "Project {0} does not exist.".format(coprname))
+
+ return render_copr_detail(copr)
+
+
@coprs_ns.route("/<username>/<coprname>/")
def copr_detail(username, coprname):
query = coprs_logic.CoprsLogic.get(username, coprname, with_mock_chroots=True)
- form = forms.CoprLegalFlagForm()
+
try:
copr = query.one()
except sqlalchemy.orm.exc.NoResultFound:
return page_not_found(
"Project {0} does not exist.".format(coprname))
- repo_dl_stat = CounterStatLogic.get_copr_repo_dl_stat(copr)
+ return render_copr_detail(copr)
+
+def render_copr_detail(copr):
+ repo_dl_stat = CounterStatLogic.get_copr_repo_dl_stat(copr)
+ form = forms.CoprLegalFlagForm()
repos_info = {}
for chroot in copr.active_chroots:
# chroot_rpms_dl_stat_key = CHROOT_REPO_MD_DL_STAT_FMT.format(
@@ -260,14 +284,12 @@ def copr_detail(username, coprname):
else:
repos_info[chroot.name_release]["arch_list"].append(chroot.arch)
repos_info[chroot.name_release]["rpm_dl_stat"][chroot.arch] = chroot_rpms_dl_stat
-
repos_info_list = sorted(repos_info.values(), key=lambda rec: rec["name_release"])
-
builds = builds_logic.BuildsLogic.get_multiple_by_copr(copr=copr).limit(1).all()
-
return flask.render_template(
"coprs/detail/overview.html",
copr=copr,
+ user=flask.g.user,
form=form,
repo_dl_stat=repo_dl_stat,
repos_info_list=repos_info_list,
@@ -706,3 +728,39 @@ def copr_build_monitor_detailed(username, coprname):
monitor=monitor,
oses=oses_grouped,
archs=archs)
+
+
+(a)coprs_ns.route("/<username>/<coprname>/group_managed", methods=["GET", "POST"])
+def copr_group_managed(username, coprname):
+ try:
+ copr = coprs_logic.CoprsLogic.get(username, coprname, with_mock_chroots=True).one()
+ except sqlalchemy.orm.exc.NoResultFound:
+ return page_not_found(
+ "Project {0} does not exist.".format(coprname))
+
+ form = group_managed_form_fabric(flask.session.get("teams"))
+
+ if form.validate_on_submit():
+ group = UsersLogic.get_group_by_fas_name_or_create(
+ form.fas_name.data, form.name.data)
+
+ copr.group_id = group.id
+ db.session.add(copr)
+ db.session.commit()
+
+ flask.flash(
+ "Project is now managed by {} FAS group, "
+ "main url to the project: {}"
+ .format(
+ form.fas_name.data,
+ "group url todo:"
+ )
+ )
+ return flask.redirect(flask.url_for(
+ "coprs_ns.copr_detail", username=username, coprname=coprname))
+
+ else:
+ return flask.render_template(
+ "coprs/detail/make_group_project.html",
+ copr=copr, form=form,
+ )
diff --git a/frontend/coprs_frontend/coprs/views/misc.py b/frontend/coprs_frontend/coprs/views/misc.py
index f0eb45c..440f051 100644
--- a/frontend/coprs_frontend/coprs/views/misc.py
+++ b/frontend/coprs_frontend/coprs/views/misc.py
@@ -149,7 +149,7 @@ def login():
return flask.redirect(oid.get_next_url())
else:
# todo: ask puiterwijk to enable "magic" group
- team_req = TeamsRequest(["fi-apprentice", "_FAS_ALL_GROUPS_"])
+ team_req = TeamsRequest(["fi-apprentice", "packager", "_FAS_ALL_GROUPS_"])
return oid.try_login("https://id.fedoraproject.org/",
ask_for=["email", "timezone"],
extensions=[team_req])
8 years, 6 months
[copr] master: minor fix in Vagrantfile (2885f1e)
by asamalik@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 2885f1e66954d8e3262bf77f42dfdd58cd192178
Author: Adam Samalik <asamalik(a)redhat.com>
Date: Tue Sep 29 15:17:00 2015 +0200
minor fix in Vagrantfile
>---------------------------------------------------------------
Vagrantfile | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/Vagrantfile b/Vagrantfile
index 52212e1..0adc8b9 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -53,7 +53,8 @@ Vagrant.configure(2) do |config|
# ..
config.vm.provision "shell",
- inline: "sudo systemctl start postgresql"
+ inline: "sudo systemctl start postgresql",
+ run: "always"
# ..
config.vm.provision "shell",
8 years, 6 months