Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 6361440f2f0265c1369374fb457644f98c5c41dc
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Thu Mar 21 11:02:57 2013 +0100
Document models, partially fixes #52
---------------------------------------------------------------
coprs_frontend/coprs/models.py | 78 ++++++++++++++++++++++++++++++++++------
1 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/coprs_frontend/coprs/models.py b/coprs_frontend/coprs/models.py
index 291df11..22e8efe 100644
--- a/coprs_frontend/coprs/models.py
+++ b/coprs_frontend/coprs/models.py
@@ -55,21 +55,30 @@ class Serializer(object):
return map(lambda x: x.name, self.__table__.columns)
class User(db.Model, Serializer):
+ """Represents user of the copr frontend"""
id = db.Column(db.Integer, primary_key = True)
+ # openid_name for fas, e.g.
http://bkabrda.id.fedoraproject.org/
openid_name = db.Column(db.String(100), nullable = False)
+ # just mail :)
mail = db.Column(db.String(150), nullable = False)
+ # is this user proven? proven users can modify builder memory and timeout for single
builds
proven = db.Column(db.Boolean, default = False)
+ # is this user admin of the system?
admin = db.Column(db.Boolean, default = False)
+ # stuff for the cli interface
api_login = db.Column(db.String(40), nullable = False, default = 'abc')
api_token = db.Column(db.String(40), nullable = False, default = 'abc')
api_token_expiration = db.Column(db.Date, nullable = False, default =
datetime.date(2000, 1, 1))
@property
def name(self):
+ """Returns the short username of the user, e.g.
bkabrda"""
return
self.openid_name.replace('.id.fedoraproject.org/';,
'').replace('http://', '')
- def permissions_for_copr(self, copr): # simple caching of permissions for given copr
- # we can't put this into class declaration because the class may be shared by
multiple threads
+ def permissions_for_copr(self, copr):
+ """Get permissions of this user for the given copr.
+ Caches the permission during one request, so use this if you access them multiple
times
+ """
if not hasattr(self, '_permissions_for_copr'):
self._permissions_for_copr = {}
if not copr.name in self._permissions_for_copr:
@@ -77,6 +86,7 @@ class User(db.Model, Serializer):
return self._permissions_for_copr[copr.name]
def can_build_in(self, copr):
+ """Determine if this user can build in the given
copr."""
can_build = False
if copr.owner == self:
can_build = True
@@ -86,6 +96,7 @@ class User(db.Model, Serializer):
return can_build
def can_edit(self, copr):
+ """Determine if this user can edit the given
copr."""
can_edit = False
if copr.owner == self:
can_edit = True
@@ -96,6 +107,11 @@ class User(db.Model, Serializer):
@classmethod
def openidize_name(cls, name):
+ """Creates proper openid_name from short name.
+
+ >>> user.openid_name == User.openidize_name(user.name)
+ True
+ """
return 'http://{0}.id.fedoraproject.org/'.format(name)
@property
@@ -105,14 +121,21 @@ class User(db.Model, Serializer):
@property
def coprs_count(self):
+ """Get number of coprs for this user."""
return Copr.query.filter_by(owner=self).count()
class Copr(db.Model, Serializer):
+ """Represents a single copr (private repo with builds, mock chroots,
etc.)."""
id = db.Column(db.Integer, primary_key = True)
+ # name of the copr, no fancy chars (checked by forms)
name = db.Column(db.String(100), nullable = False)
+ # string containing urls of additional repos (separated by space)
+ # that this copr will pull dependencies from
repos = db.Column(db.Text)
+ # time of creation as returned by int(time.time())
created_on = db.Column(db.Integer)
+ # description and instructions given by copr owner
description = db.Column(db.Text)
instructions = db.Column(db.Text)
# duplicate information, but speeds up a lot and makes queries simpler
@@ -129,6 +152,7 @@ class Copr(db.Model, Serializer):
@property
def repos_list(self):
+ """Returns repos of this copr as a list of
strings"""
return self.repos.split()
@property
@@ -141,12 +165,15 @@ class Copr(db.Model, Serializer):
@property
def active_mock_chroots(self):
+ """Returns list of active mock_chroots of this
copr"""
return filter(lambda x: x.is_active, self.mock_chroots)
class CoprPermission(db.Model, Serializer):
- # 0 = nothing, 1 = asked for, 2 = approved
- # not using enum, as that translates to varchar on some DBs
+ """Association class for Copr<->Permission
relation"""
+ ## see helpers.PermissionEnum for possible values of the fields below
+ # can this user build in the copr?
copr_builder = db.Column(db.SmallInteger, default = 0)
+ # can this user serve as an admin? (-> edit and approve permissions)
copr_admin = db.Column(db.SmallInteger, default = 0)
# relations
@@ -156,19 +183,31 @@ class CoprPermission(db.Model, Serializer):
copr = db.relationship('Copr', backref =
db.backref('copr_permissions'))
class Build(db.Model, Serializer):
+ """Representation of one build in one copr"""
id = db.Column(db.Integer, primary_key = True)
+ # list of space separated urls of packages to build
pkgs = db.Column(db.Text)
+ # was this build canceled by user?
canceled = db.Column(db.Boolean, default = False)
- # These two are present for every build, as they might change in Copr
- # between submitting and starting build => we want to keep them as submitted
+ ## These two are present for every build, as they might change in Copr
+ ## between submitting and starting build => we want to keep them as submitted
+ # list of space separated mock chroot names
chroots = db.Column(db.Text, nullable = False)
+ # list of space separated additional repos
repos = db.Column(db.Text)
+ ## the three below represent time of important events for this build
+ ## as returned by int(time.time())
submitted_on = db.Column(db.Integer, nullable = False)
started_on = db.Column(db.Integer)
ended_on = db.Column(db.Integer)
+ # url of the build results
results = db.Column(db.Text)
+ # status as returned by backend, see build.state for value explanation
+ # (TODO: this would deserve an enum)
status = db.Column(db.Integer)
+ # memory requirements for backend builder
memory_reqs = db.Column(db.Integer, default = constants.DEFAULT_BUILD_MEMORY)
+ # maximum allowed time of build, build will fail if exceeded
timeout = db.Column(db.Integer, default = constants.DEFAULT_BUILD_TIMEOUT)
# relations
@@ -179,6 +218,7 @@ class Build(db.Model, Serializer):
@property
def state(self):
+ """Return text representation of status of this
build"""
if self.status == 1:
return 'succeeded'
elif self.status == 0:
@@ -191,17 +231,26 @@ class Build(db.Model, Serializer):
@property
def cancelable(self):
+ """Find out if this build is cancelable.
+
+ ATM, build is cancelable only if it wasn't grabbed by backend.
+ """
return self.state == 'pending'
class MockChroot(db.Model, Serializer):
+ """Representation of mock chroot"""
id = db.Column(db.Integer, primary_key = True)
- os_release = db.Column(db.String(50), nullable = False) # fedora/epel/...
- os_version = db.Column(db.String(50), nullable = False) # 18/rawhide/...
- arch = db.Column(db.String(50), nullable = False) # x86_64/i686/...
+ # fedora/epel/..., mandatory
+ os_release = db.Column(db.String(50), nullable = False)
+ # 18/rawhide/..., optional (mock chroot doesn't need to have this)
+ os_version = db.Column(db.String(50), nullable = False)
+ # x86_64/i686/..., mandatory
+ arch = db.Column(db.String(50), nullable = False)
is_active = db.Column(db.Boolean, default = True)
@property
def chroot_name(self):
+ """Textual representation of name of this
chroot"""
if self.os_version:
format_string = '{rel}-{ver}-{arch}'
else:
@@ -211,6 +260,7 @@ class MockChroot(db.Model, Serializer):
arch=self.arch)
class CoprChroot(db.Model, Serializer):
+ """Representation of Copr<->MockChroot
relation"""
mock_chroot_id = db.Column(db.Integer, db.ForeignKey('mock_chroot.id'),
primary_key = True)
mock_chroot = db.relationship('MockChroot', backref =
db.backref('copr_chroots'))
copr_id = db.Column(db.Integer, db.ForeignKey('copr.id'), primary_key =
True)
@@ -219,16 +269,22 @@ class CoprChroot(db.Model, Serializer):
cascade='all,delete,delete-orphan'))
class Action(db.Model, Serializer):
+ """Representation of a custom action that needs backends
cooperation"""
id = db.Column(db.Integer, primary_key=True)
- # delete, rename,
+ # delete, rename, ...; see helpers.ActionTypeEnum
action_type = db.Column(db.Integer, nullable=False)
- # copr,
+ # copr, ...; downcase name of class of modified object
object_type = db.Column(db.String(20))
+ # id of the modified object
object_id = db.Column(db.Integer)
+ # old and new values of the changed property
old_value = db.Column(db.String(255))
new_value = db.Column(db.String(255))
+ # backend result, see helpers.BackendResultEnum
backend_result = db.Column(db.Integer,
default=helpers.BackendResultEnum('waiting'))
+ # optional message from the backend
backend_message = db.Column(db.Text)
+ # time created as returned by int(time.time())
created_on = db.Column(db.Integer)
def __str__(self):