fedora-updates-system/updatessystem buildsys.py, NONE, 1.1 mail.py, NONE, 1.1 rpc.py, NONE, 1.1 controllers.py, 1.3, 1.4 model.py, 1.3, 1.4 new.py, 1.3, 1.4 release.py, 1.1, 1.2

Luke Macken (lmacken) fedora-extras-commits at redhat.com
Sun Dec 3 19:52:27 UTC 2006


Author: lmacken

Update of /cvs/fedora/fedora-updates-system/updatessystem
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv32115/updatessystem

Modified Files:
	controllers.py model.py new.py release.py 
Added Files:
	buildsys.py mail.py rpc.py 
Log Message:
- Got new/edit update functionality working
- Paginate the update lists
- Add a CVE table
- Add initial push code (NOT COMPLETE)
- Add initial xmlrpc code
- Add initial mail module
- Wrote creation tests for all tables
- Add many global settings to app.cfg




***** Error reading new file: [Errno 2] No such file or directory: 'buildsys.py'

***** Error reading new file: [Errno 2] No such file or directory: 'mail.py'

***** Error reading new file: [Errno 2] No such file or directory: 'rpc.py'

Index: controllers.py
===================================================================
RCS file: /cvs/fedora/fedora-updates-system/updatessystem/controllers.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- controllers.py	24 Nov 2006 08:35:50 -0000	1.3
+++ controllers.py	3 Dec 2006 19:51:51 -0000	1.4
@@ -1,33 +1,34 @@
 # $Id$
 
+import mail
+import util
 import logging
 import cherrypy
-import turbogears
+#import turbogears
 
-from new import NewUpdate
-from model import PackageUpdate
+from new import NewUpdate, update_form
+from push import Pusher
+from model import Package, PackageUpdate, Release, Bugzilla, CVE
+from widgets import PackageUpdateForm
+from sqlobject import SQLObjectNotFound
+from elementtree import ElementTree as ET
 from updatessystem import json
 
-from turbogears import controllers, expose, validate, redirect
-from turbogears import identity
-
-from turbogears.widgets import DataGrid
+from turbogears import (controllers, expose, validate, redirect, identity,
+                        paginate, flash, error_handler)
 
 log = logging.getLogger(__name__)
 
 class Root(controllers.RootController):
 
     new = NewUpdate()
+    push = Pusher()
 
     @expose(template="updatessystem.templates.welcome")
-    def index(self):
-        """
-            TODO
-             - veryify identity
-        """
-        import time
-        log.debug("Happy TurboGears Controller Responding For Duty")
-        return dict(now=time.ctime())
+    def index(self, tg_errors=None):
+        if tg_errors:
+            log.debug("ERROR: %s" % str(tg_errors))
+        return dict()
 
     @expose(template="updatessystem.templates.login")
     def login(self, forward_url=None, previous_url=None, *args, **kw):
@@ -44,7 +45,7 @@
 
         if identity.was_login_attempted():
             msg=_("The credentials you supplied were not correct or "
-                   "did not grant access to this resource.")
+                  "did not grant access to this resource.")
         elif identity.get_identity_errors():
             msg=_("You must provide your credentials before accessing "
                    "this resource.")
@@ -55,28 +56,117 @@
         return dict(message=msg, previous_url=previous_url, logging_in=True,
                     original_parameters=cherrypy.request.params,
                     forward_url=forward_url)
+    @expose()
+    def logout(self):
+        identity.current.logout()
+        raise redirect("/")
 
     @expose(template="updatessystem.templates.list")
+    @paginate('updates', default_order='update_id')
     def list(self, skip=0):
-        """ List all updates. """
+        """ List all updates """
         updates = PackageUpdate.select()
-        table = DataGrid(fields=[('Package', lambda x: x.nvr),
-                                 ('Release', lambda x: x.release.name),
-                                 ('Status', lambda x: x.testing == True and
-                                            'Testing' or 'Final'),
-                                 ('Security', lambda x: x.security),
-                                 ('Embargo', lambda x: x.embargo),
-                                 ('Mail Sent', lambda x: x.mail_sent),
-                                 ('Date', lambda x: x.date_submitted)],
-                         default=updates[skip:skip+15])
-        return dict(updates=table)
+        return dict(updates=updates)
 
     @expose(template='updatessystem.templates.show')
     def show(self, update):
-        update = PackageUpdate.byNvr(update)
+        try:
+            update = PackageUpdate.byNvr(update)
+        except SQLObjectNotFound:
+            flash("Update %s not found" % update)
+            raise redirect("/list")
         return dict(update=update)
 
     @expose()
-    def logout(self):
-        identity.current.logout()
-        raise redirect("/")
+    def delete(self, update):
+        try:
+            up = PackageUpdate.byNvr(update)
+        except SQLObjectNotFound:
+            flash("Update %s not found" % update)
+            raise redirect("/list")
+        if up.pushed:
+            # TODO: Removing pushed updates should essentially unpush?
+            #           - remove from update stage
+            #           - regenerate metadata (remove extended metadata)
+            #           - remove from database
+            #           - sync to mirrors
+            flash("Cannot delete %s; it has already been pushed" % update)
+        else:
+            up.destroySelf()
+            flash("%s deleted" % update)
+        raise redirect("/list")
+
+    @expose(template='updatessystem.templates.form')
+    def edit(self, update):
+        import string
+        try:
+            up = PackageUpdate.byNvr(update)
+        except SQLObjectNotFound:
+            flash("Update %s not found")
+            raise redirect("/list")
+        values = {
+                'nvr'       : up.nvr,
+                'release'   : up.release.name,
+                'testing'   : up.testing,
+                'security'  : up.security,
+                'embargo'   : up.embargo,
+                'notes'     : up.notes,
+                'bugs'      : string.join([str(bug.bz_id) for bug in up.bugs]),
+                'cves'      : string.join([cve.cve_id for cve in up.cves]),
+                'edited'    : up.nvr
+        }
+        return dict(form=update_form, values=values, action='/save')
+
+
+    @expose()
+    @error_handler(new.index)
+    @validate(form=update_form)
+    def save(self, release, bugs, cves, edited, **kw):
+        """ Validate and save data from a PackageUpdateForm. """
+        release = Release.byName(release)
+
+        if edited and kw['nvr'] != edited:
+            flash("You cannot change the package n-v-r after submission")
+            raise redirect('/show/%s' % edited)
+
+        if not edited: # new update
+            try:
+                name = util.get_nvr(kw['nvr'])[0]
+                package = Package.byName(name)
+            except IndexError:
+                flash("Package needs to be in name-ver-rel format")
+                raise redirect('/new')
+            except SQLObjectNotFound:
+                flash("Package %s not found" % name)
+                raise redirect('/new')
+            log.debug("Adding new update %s" % package)
+            p = PackageUpdate(package=package, release=release,
+                              submitter='FIXME', **kw)
+        else: # edited update
+            from datetime import datetime
+            log.debug("Edited update %s" % edited)
+            p = PackageUpdate.byNvr(edited)
+            p.set(release=release, date_modified=datetime.now(), **kw)
+            map(p.removeBugzilla, p.bugs)
+            map(p.removeCVE, p.cves)
+
+        # Add each bug and CVE to this package
+        for bug in bugs.replace(',', ' ').split():
+            bz = None
+            try:
+                bz = Bugzilla.byBz_id(int(bug))
+            except SQLObjectNotFound:
+                bz = Bugzilla(bz_id=int(bug))
+            p.addBugzilla(bz)
+        for cve_id in cves.replace(',', ' ').split():
+            cve = None
+            try:
+                cve = CVE.byCve_id(cve_id)
+            except SQLObjectNotFound:
+                cve = CVE(cve_id=cve_id)
+            p.addCVE(cve)
+
+        if edited:  flash("Update successfully edited")
+        else:       flash("Update successfully added")
+
+        raise redirect('/show/%s' % p.nvr)


Index: model.py
===================================================================
RCS file: /cvs/fedora/fedora-updates-system/updatessystem/model.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- model.py	24 Nov 2006 08:35:50 -0000	1.3
+++ model.py	3 Dec 2006 19:51:51 -0000	1.4
@@ -1,8 +1,6 @@
 #!/usr/bin/env python
 # $Id$
 
-import xmlrpclib
-
 from sqlobject import *
 from datetime import datetime
 
@@ -14,62 +12,66 @@
 
 class Release(SQLObject):
     """ Table of releases that we will be pushing updates for """
-    class sqlmeta:
-        table = 'release_table'
-    name = UnicodeCol(alternateID=True, notNone=True)
-    long_name = UnicodeCol(notNone=True)
-    codename = UnicodeCol()
-    updates = MultipleJoin('PackageUpdate', joinColumn='release_id')
+    name        = UnicodeCol(alternateID=True, notNone=True)
+    long_name   = UnicodeCol(notNone=True)
+    codename    = UnicodeCol()
+    updates     = MultipleJoin('PackageUpdate', joinColumn='release_id')
+    arches      = UnicodeCol()
 
 class Package(SQLObject):
     """
-        Table of packages in Fedora.  We should eventually look into getting
-        this information from the package database instead of defining it
-        here.
+        Table of packages in available for updating.  This table should
+        eventually populate itself from either the package database, or some
+        other reliable source.  For now, they are populated when this model
+        is executed by hand.
     """
-    class sqlmeta:
-        table = 'package_table'
-    package_name = UnicodeCol(alternateID=True, notNone=True)
+    name    = UnicodeCol(alternateID=True, notNone=True)
     updates = MultipleJoin('PackageUpdate', joinColumn='package_id')
 
 class PackageUpdate(SQLObject):
-    class sqlmeta:
-        table = 'package_update'
-    nvr = UnicodeCol(notNone=True, alternateID=True)
-    date_submitted = DateTimeCol(default=datetime.now, notNone=True)
-    package = ForeignKey('Package')
-    submitter = UnicodeCol(notNone=True)
-    update_id = UnicodeCol(notNone=True)
-    cve_ids = UnicodeCol()
-    release = ForeignKey('Release')
-    testing = BoolCol()
-    security = BoolCol()
-    embargo = DateTimeCol(default=None)
-    pushed = BoolCol(default=False)
-    date_pushed = DateTimeCol(default=None)
-    notes = UnicodeCol()
-    mail_sent = BoolCol(default=False)
-    close_bugs = BoolCol(default=False)
-    bug_close_msg = UnicodeCol(default=None)
-    archived_mail = UnicodeCol(default=None)
-    needs_push = BoolCol(default=False)
-    bugs = RelatedJoin("Bugzilla")
-    comments = MultipleJoin('Comment', joinColumn='update_id')
+    """ This class defines an update in our system. """
+    nvr             = UnicodeCol(notNone=True, alternateID=True)
+    date_submitted  = DateTimeCol(default=datetime.now, notNone=True)
+    date_modified   = DateTimeCol(default=None)
+    package         = ForeignKey('Package')
+    submitter       = UnicodeCol(notNone=True)
+    update_id       = UnicodeCol(default=None)
+    security        = BoolCol()
+    embargo         = DateTimeCol(default=None)
+    cves            = RelatedJoin("CVE")
+    bugs            = RelatedJoin("Bugzilla")
+    release         = ForeignKey('Release')
+    testing         = BoolCol()
+    pushed          = BoolCol(default=False)
+    date_pushed     = DateTimeCol(default=None)
+    notes           = UnicodeCol()
+    mail_sent       = BoolCol(default=False)
+    close_bugs      = BoolCol(default=False)
+    bug_close_msg   = UnicodeCol(default=None)
+    archived_mail   = UnicodeCol(default=None)
+    needs_push      = BoolCol(default=False)
+    comments        = MultipleJoin('Comment', joinColumn='update_id')
+
+    # TODO: keep track of all files in this update
 
 class Comment(SQLObject):
-    class sqlmeta:
-        table = 'comment_table'
-    update = ForeignKey('PackageUpdate')
-    user = UnicodeCol(notNone=True)
-    text = UnicodeCol(notNone=True)
+    """ Table of comments on updates. """
+    update  = ForeignKey('PackageUpdate', notNone=True)
+    user    = UnicodeCol(notNone=True)
+    text    = UnicodeCol(notNone=True)
+
+class CVE(SQLObject):
+    """ Table of CVEs fixed within updates that we know of. """
+    cve_id  = UnicodeCol(alternateID=True, notNone=True)
+    updates = RelatedJoin("PackageUpdate")
 
 class Bugzilla(SQLObject):
-    """ TODO: Automatically get title upon changing of bz_id """
-    class sqlmeta:
-        table ='bugzilla_table'
-    bz_id = IntCol(alternateID=True)
-    title = UnicodeCol(default=None)
-    update = RelatedJoin("PackageUpdate")
+    """ Table of Bugzillas that we know about. """
+    bz_id   = IntCol(alternateID=True)
+    title   = UnicodeCol(default=None)
+    updates = RelatedJoin("PackageUpdate")
+
+    # TODO: automatically fetch bugzilla title upon creation
 
     _bz_server = 'https://bugzilla.redhat.com/bugzilla/xmlrpc.cgi'
     _default_closemsg = "%(package)s has been released for %(release)s.  If problems still persist, please make note of it in this bug report."
@@ -93,9 +95,6 @@
         pass
 
 class Visit(SQLObject):
-    class sqlmeta:
-        table = "visit"
-
     visit_key = StringCol(length=40, alternateID=True,
                           alternateMethodName="by_visit_key")
     created = DateTimeCol(default=datetime.now)
@@ -154,12 +153,6 @@
                                alternateMethodName="by_email_address")
     display_name = UnicodeCol(length=255)
     password = UnicodeCol(length=40)
-    created = DateTimeCol(default=datetime.now)
-
-    # groups this user belongs to
-    groups = RelatedJoin("Group", intermediateTable="user_group",
-                         joinColumn="user_id", otherColumn="group_id")
-
     def _get_permissions(self):
         perms = set()
         for g in self.groups:
@@ -183,7 +176,7 @@
     description = UnicodeCol(length=255)
 
     groups = RelatedJoin("Group",
-                        intermediateTable="group_permission",
+                         intermediateTable="group_permission",
                          joinColumn="permission_id", 
                          otherColumn="group_id")
 
@@ -209,8 +202,10 @@
     ## TODO: Add packages from pkgdb ?
 
     releases = (
-        { 'name' : 'fc6', 'long_name' : 'Fedora Core 6', 'codename' : 'Zod' },
-        { 'name' : 'fc5', 'long_name' : 'Fedora Core 5', 'codename' : 'Bordeaux' }
+      { 'name' : 'fc6', 'long_name' : 'Fedora Core 6', 'codename' : 'Zod',
+        'arches' : 'i386 x86_64 ppc' },
+      { 'name' : 'fc5', 'long_name' : 'Fedora Core 5', 'codename' : 'Bordeaux',
+        'arches' : 'i386 x86_64 ppc' }
     )
 
     print "Initializing Release table..."
@@ -219,7 +214,7 @@
         print rel
 
     print "\nAdding packages..."
-    pkg = Package(package_name='foobar')
+    pkg = Package(name='foobar')
     print pkg
 
     hub.commit()


Index: new.py
===================================================================
RCS file: /cvs/fedora/fedora-updates-system/updatessystem/new.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- new.py	24 Nov 2006 08:35:50 -0000	1.3
+++ new.py	3 Dec 2006 19:51:51 -0000	1.4
@@ -2,129 +2,39 @@
 
 import util
 import logging
-import cherrypy
-import turbogears
 
-from model import Package, Release, Bugzilla, PackageUpdate
-from datetime import datetime
+from model import Release, Package, PackageUpdate, Bugzilla, CVE
 from sqlobject import SQLObjectNotFound
-from exceptions import IndexError
-
-from turbogears import expose, controllers, validate, validators, redirect
-from turbogears import flash
-
-from turbogears.widgets import TableForm, TextField, PasswordField, TextArea
-from turbogears.widgets import AutoCompleteField, RadioButtonList, AjaxGrid
-from turbogears.widgets import SingleSelectField, CheckBox
-from turbogears.widgets import CalendarDateTimePicker
+from turbogears import (expose, controllers, validate, validators, flash,
+                        error_handler, redirect)
+from turbogears.widgets import (WidgetsList, TextField, SingleSelectField,
+                                CheckBox, TextArea, CalendarDatePicker,
+                                TableForm, HiddenField)
 
 log = logging.getLogger(__name__)
 
-# XXX: find a better place for these.
-# also, why do these get run twice when starting the server?
-packages = [pkg.package_name for pkg in Package.select()]
-releases = [rel.name for rel in Release.select()]
-
-
-class PackageValidator(validators.FancyValidator):
-    """
-        Validator for package updates.  We can do some trivial QA here to
-        prevent user error.
-
-        TODO: get this working
-    """
-    def _to_python(self, value, state):
-        return value['text'].strip()
-
-    def validate_python(self, value, state):
-        """
-            - check for duplicate update in db
-            - check broken update paths
-            - check cvs tag to make sure we don't push into wrong release
-        """
-        from formencode.api import Invalid
-        log.debug("In PackageValidator.validate_python!!!!")
-        raise Invalid("foo", value, state)
-
-
-class UpdateValidator(validators.Schema):
-    """ Validator for new updates. """
-    pkg = PackageValidator()
-    #rel = validators.OneOf([rel.name for rel in Release.select()])
-    rel = validators.String(not_empty=True)
-    security = validators.Bool()
-    embargo = validators.DateValidator()
-    testing = validators.Bool()
-    bugs = validators.String()
-    cves = validators.String()
-    notes = validators.String()
+def get_releases():
+    return [rel.name for rel in Release.select()]
 
+class UpdateFields(WidgetsList):
+    nvr = TextField(label='Package', validator=validators.NotEmpty)
+    release = SingleSelectField(options=get_releases,
+                                validator=validators.OneOf(get_releases()))
+    testing = CheckBox(validator=validators.Bool)
+    security = CheckBox(validator=validators.Bool)
+    embargo = CalendarDatePicker(validator=validators.DateConverter)
+    bugs = TextField(validator=validators.String)
+    cves = TextField(validator=validators.String)
+    notes = TextArea(validator=validators.String)
+    edited = HiddenField(default=None)
 
-class NewUpdate(controllers.Controller):
-    """ The controller for adding new updates. """
+update_form = TableForm(fields=UpdateFields(), submit_text='Submit')
 
-    def create_update_form(self):
-        fields = [
-            AutoCompleteField(name='pkg', label='Package', search_param='input',
-                              search_controller='search', result_name='pkgs'),
-            SingleSelectField(name='rel', label='Release',
-                              options=releases),
-            CheckBox(name='testing', label='Testing'),
-            CheckBox(name='security', label='Security Update'),
-            CalendarDateTimePicker(name='embargo'),
-            TextField(name='bugs', label='Bugs'),
-            TextField(name='cves', label='CVEs'),
-            TextArea(name='notes', label='Notes')
-        ]
-        return TableForm(fields=fields, name='update_form', action='add',
-                         validators={ 'pkg' : PackageValidator(strip=True) },
-                         submit_text='Submit')
+class NewUpdate(controllers.Controller):
 
-    @expose(template="updatessystem.templates.new")
+    @expose(template="updatessystem.templates.form")
     def index(self, tg_errors=None, *args, **kw):
         if tg_errors:
             flash("Something went wrong!")
-            log.debug("!!! Something went wrong !!!")
-        return dict(update_form=self.create_update_form())
-
-    @expose()
-    @turbogears.error_handler(index)
-    @validate(validators=UpdateValidator())
-    def add(self, pkg, rel, bugs, cves, notes, embargo, security=False,
-            testing=False):
-        """ Add an update to the system. """
-        release = Release.byName(rel)
-
-        try:
-            name = util.get_nvr(pkg)[0]
-            package = Package.byPackage_name(name)
-        except IndexError:
-            flash("Package %s needs to be in name-ver-rel format" % pkg)
-            redirect('/new')
-        except SQLObjectNotFound:
-            flash("Package %s not found" % name)
-            redirect('/new')
-
-        p = PackageUpdate(nvr=pkg, package=package, submitter='FIXME',
-                          update_id='FIXME', cve_ids=cves, release=release,
-                          notes=notes, security=security, testing=testing)
-
-        # Add each bug to this package.  Here we allow the user to enter bugs
-        # separated by spaces or commas.  We also allow bugs to be associated
-        # with multiple updates, so we check if each already exists first.
-        for bug in bugs.replace(',', ' ').split():
-            bz = None
-            try:
-                bz = Bugzilla.byBz_id(int(bug))
-            except SQLObjectNotFound:
-                bz = Bugzilla(bz_id=int(bug))
-            p.addBugzilla(bz)
-
-        flash("Update successfully added!")
-        redirect('/show/%s' % pkg)
-
-    @expose(format="json")
-    @turbogears.error_handler(index)
-    def search(self, input):
-        return dict(pkgs=filter(lambda item: item.lower().startswith(input),
-                                packages))
+            log.debug(tg_errors)
+        return dict(form=update_form, values={}, action="/save")


Index: release.py
===================================================================
RCS file: /cvs/fedora/fedora-updates-system/updatessystem/release.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- release.py	12 Nov 2006 20:07:58 -0000	1.1
+++ release.py	3 Dec 2006 19:51:51 -0000	1.2
@@ -1,4 +1,4 @@
-# $Header$
+# $Id$
 # Release information about Fedora Updates System
 
 version = "1.0"




More information about the scm-commits mailing list