From a11c95b576f677f88d2c834dc4883bee111f99b0 Mon Sep 17 00:00:00 2001 From: Kamil Páral Date: Sep 06 2021 10:59:34 +0000 Subject: drop unused models (build, criterion, settings, user), code & assets The 4 mentioned DB models haven't been used in years. Drop them to make the codebase and schema easier to maintain. The related functions (from controllers etc) are dropped as well. This also removes: * `EnumSymbol` and related classes, because it's not used anywhere and we already use SQLAlchemy's provided Enum which seems to work well * `util/koji_interface.py`, no longer required * some outdated images * a few unused javascript files Note that there are still some unused util functions lying around, like `check_api_rights()` or `check_api_key()`, which I decided to keep in case they could still be useful in the future. Merges: https://pagure.io/fedora-qa/blockerbugs/pull-request/204 --- diff --git a/alembic/versions/f8c29e9793f4_drop_unused_models.py b/alembic/versions/f8c29e9793f4_drop_unused_models.py new file mode 100644 index 0000000..1669aed --- /dev/null +++ b/alembic/versions/f8c29e9793f4_drop_unused_models.py @@ -0,0 +1,63 @@ +"""Drop unused models + +Revision ID: f8c29e9793f4 +Revises: 8ec130a51c2b +Create Date: 2021-09-02 15:45:16.177031 +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'f8c29e9793f4' +down_revision = '8ec130a51c2b' + + +def upgrade(): + # The following tables haven't been used in a *long* time, and nothing imported them in code, + # meaning they might exist if the DB was upgraded the whole time, but might not exist, if the + # DB was re-created at some later point. Instead of `op.drop_table()` we need to execute custom + # commands so that we can append `IF EXISTS`. + op.execute('DROP TABLE IF EXISTS "settings"') + op.execute('DROP TABLE IF EXISTS "user"') + op.execute('DROP TABLE IF EXISTS "build"') + op.execute('DROP TABLE IF EXISTS "criterion"') + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('criterion', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('date_created', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('criterion', sa.VARCHAR(length=4096), autoincrement=False, nullable=True), + sa.Column('current', sa.BOOLEAN(), autoincrement=False, nullable=True), + sa.Column('milestone_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('number', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['milestone_id'], ['milestone.id'], name='fk_criterion_milestone_id_milestone'), + sa.PrimaryKeyConstraint('id', name='pk_criterion') + ) + op.create_table('build', + sa.Column('koji_id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('pkg_name', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('version', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('release', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('nvr', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('epoch', sa.INTEGER(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('koji_id', name='pk_build'), + sa.UniqueConstraint('nvr', name='uq_build_nvr'), + sa.UniqueConstraint('pkg_name', 'version', 'release', name='uq_build_pkg_ver_rel') + ) + op.create_table('user', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('username', sa.VARCHAR(length=80), autoincrement=False, nullable=True), + sa.Column('pw_hash', sa.VARCHAR(length=120), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='pk_user'), + sa.UniqueConstraint('username', name='uq_user_username') + ) + op.create_table('settings', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('name', sa.VARCHAR(length=80), autoincrement=False, nullable=True), + sa.Column('value', sa.VARCHAR(length=80), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='pk_settings') + ) + # ### end Alembic commands ### diff --git a/blockerbugs/controllers/admin/__init__.py b/blockerbugs/controllers/admin/__init__.py index 8011914..af539a7 100644 --- a/blockerbugs/controllers/admin/__init__.py +++ b/blockerbugs/controllers/admin/__init__.py @@ -26,11 +26,9 @@ from flask import flash, request, redirect, url_for from flask_admin.babel import gettext import flask_admin from blockerbugs import app, db -from blockerbugs.models.build import Build from blockerbugs.models.release import Release from blockerbugs.models.userinfo import UserInfo from blockerbugs.models.milestone import Milestone -from blockerbugs.controllers.admin.build import BuildView from blockerbugs.controllers.admin.auth import FasAuthModelView from blockerbugs.controllers.users import check_admin_rights @@ -142,4 +140,3 @@ class UserInfoView(FasAuthModelView): admin.add_view(MilestoneView(Milestone, db.session)) admin.add_view(ReleaseView(Release, db.session)) admin.add_view(UserInfoView(UserInfo, db.session)) -admin.add_view(BuildView(Build, db.session)) diff --git a/blockerbugs/controllers/admin/build.py b/blockerbugs/controllers/admin/build.py deleted file mode 100644 index 3f82b85..0000000 --- a/blockerbugs/controllers/admin/build.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2013, Red Hat, Inc -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Authors: -# Tim Flink -# Ilgiz Islamgulov - -"""Build view for admin interface""" - -import koji -from flask import flash, request, url_for, redirect -import flask_wtf -import wtforms -from flask_admin import expose -from flask_admin.babel import gettext - -from blockerbugs.controllers.admin.auth import FasAuthModelView -from blockerbugs.models.build import Build - -class ReadOnlyTextField(wtforms.TextField): - def __init__(self, *args, **kwargs): - self.disabled = kwargs.pop('disabled', True) - super(ReadOnlyTextField, self).__init__(*args, **kwargs) - - def __call__(self, **kwargs): - if self.disabled: - kwargs.setdefault('readonly', True) - return self.widget(self, **kwargs) - - -class BuildForm(flask_wtf.FlaskForm): - nvr = ReadOnlyTextField('NVR', [wtforms.validators.data_required()]) - -class BuildView(FasAuthModelView): - column_searchable_list = (Build.nvr, ) - column_exclude_list = ('nvr', ) - - form = BuildForm - - @expose('/new/', methods=('GET', 'POST')) - def create_view(self): - """ - Create new build by NVR, check build exists in Koji. - """ - return_url = request.args.get('url') or url_for('.index_view') - - if not self.can_create: - return redirect(return_url) - - form = self.form() - form.nvr.disabled = False - - if form.validate_on_submit(): - try: - Build.from_nvr(form.nvr.data) - if '_add_another' in request.form: - flash( - gettext('Model was successfully created.')) - return redirect( - url_for('.create_view', url=return_url)) - else: - return redirect(return_url) - except koji.GenericError as ex: - form.nvr.errors.append(ex.message) - - return self.render(self.create_template, - form=form, - form_widget_args=self.form_widget_args, - return_url=return_url) diff --git a/blockerbugs/controllers/api/utils.py b/blockerbugs/controllers/api/utils.py index e275232..95aa80a 100644 --- a/blockerbugs/controllers/api/utils.py +++ b/blockerbugs/controllers/api/utils.py @@ -30,7 +30,6 @@ import hashlib from flask import Response, request from blockerbugs import app -from blockerbugs.models import EnumSymbol from blockerbugs.models.userinfo import UserInfo from .errors import MalformedJSONError, NoSuchObjectError, AuthFailedError @@ -41,8 +40,6 @@ class JsonEncoder(json.JSONEncoder): """ def default(self, obj): - if isinstance(obj, EnumSymbol): - return obj.description if isinstance(obj, datetime.datetime): r = obj.isoformat() if obj.microsecond: diff --git a/blockerbugs/models/__init__.py b/blockerbugs/models/__init__.py index a62d512..d09755f 100644 --- a/blockerbugs/models/__init__.py +++ b/blockerbugs/models/__init__.py @@ -19,8 +19,6 @@ """Base model classes""" -from sqlalchemy.types import SchemaType, TypeDecorator, Enum # type: ignore[attr-defined] -import re from typing import Any from blockerbugs import db @@ -30,95 +28,3 @@ update_fixes: Any = db.Table( db.Column('update_id', db.Integer, db.ForeignKey('update.id'), primary_key=True), db.Column('bug_id', db.Integer, db.ForeignKey('bug.id'), primary_key=True), ) - - -class EnumSymbol(object): - """Define a fixed symbol tied to a parent class.""" - - def __init__(self, cls_, name, value, description): - self.cls_ = cls_ - self.name = name - self.value = value - self.description = description - - def __reduce__(self): - """Allow unpickling to return the symbol - linked to the DeclEnum class.""" - return getattr, (self.cls_, self.name) - - def __iter__(self): - return iter([self.value, self.description]) - - def __repr__(self): - return "<%s>" % self.name - - def __unicode__(self): - return self.name - - -class EnumMeta(type): - """Generate new DeclEnum classes.""" - - def __init__(cls, classname, bases, dict_): - cls._reg = reg = cls._reg.copy() - for k, v in dict_.items(): - if isinstance(v, tuple): - sym = reg[v[0]] = EnumSymbol(cls, k, *v) - setattr(cls, k, sym) - return type.__init__(cls, classname, bases, dict_) - - def __iter__(cls): - return iter(cls._reg.values()) - - -class DeclEnum(object): - """Declarative enumeration.""" - - __metaclass__ = EnumMeta - _reg: dict[Any, Any] = {} - - @classmethod - def from_string(cls, value): - try: - return cls._reg[value] - except KeyError: - raise ValueError( - "Invalid value for %r: %r" % - (cls.__name__, value) - ) - - @classmethod - def values(cls): - return cls._reg.keys() - - @classmethod - def db_type(cls): - return DeclEnumType(cls) - - -class DeclEnumType(SchemaType, TypeDecorator): - def __init__(self, enum): - self.enum = enum - self.impl = Enum( - *enum.values(), - name="ck%s" % re.sub( - '([A-Z])', - lambda m: "_" + m.group(1).lower(), - enum.__name__) - ) - - def _set_table(self, table, column): - self.impl._set_table(table, column) - - def copy(self): - return DeclEnumType(self.enum) - - def process_bind_param(self, value, dialect): - if value is None: - return None - return value.value - - def process_result_value(self, value, dialect): - if value is None: - return None - return self.enum.from_string(value.strip()) diff --git a/blockerbugs/models/build.py b/blockerbugs/models/build.py deleted file mode 100644 index 52c49fe..0000000 --- a/blockerbugs/models/build.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2013, Red Hat, Inc -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Authors: -# Tim Flink -# Ilgiz Islamgulov - -"""ORM class for build information stored in the database""" - -from sqlalchemy.schema import UniqueConstraint -import koji - -from blockerbugs import db, BaseModel -from blockerbugs.util.koji_interface import get_build_data - - -class Build(BaseModel): - koji_id = db.Column(db.Integer, primary_key=True) - pkg_name = db.Column(db.Text) - version = db.Column(db.Text) - release = db.Column(db.Text) - nvr = db.Column(db.Text, unique=True) - epoch = db.Column(db.Integer, nullable=True) - - __table_args__ = (UniqueConstraint('pkg_name', 'version', 'release', - name='uq_build_pkg_ver_rel'), ) - - def __unicode__(self): - return 'build: %s' % (self.nvr) - - @classmethod - def from_nvr(cls, nvr): - data = get_build_data(nvr) - exists_build = Build.query.get(data['build_id']) - if exists_build is not None: - raise koji.GenericError(u'Build already exists.') - build = Build() - build.koji_id = data['build_id'] - build.epoch = data['epoch'] - build.pkg_name = data['name'] - build.release = data['release'] - build.version = data['version'] - build.nvr = '{b.pkg_name}-{b.version}-{b.release}'.format(b=build) - db.session.add(build) - db.session.commit() diff --git a/blockerbugs/models/criterion.py b/blockerbugs/models/criterion.py deleted file mode 100644 index 347373a..0000000 --- a/blockerbugs/models/criterion.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2012, Red Hat, Inc -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Authors: -# Tim Flink - -"""Database model for release criteria""" - -import datetime - -from blockerbugs import db, BaseModel -import blockerbugs.models.milestone as model_milestone - - -class Criterion(BaseModel): - id = db.Column(db.Integer, primary_key=True) - date_created = db.Column(db.DateTime, unique=False) - criterion = db.Column(db.String(4096), unique=False) - current = db.Column(db.Boolean(create_constraint=True, name='current_bool')) - milestone_id = db.Column(db.Integer, db.ForeignKey('milestone.id')) - milestone: 'model_milestone.Milestone' = db.relationship('Milestone', back_populates='criteria') - number = db.Column(db.Integer, unique=False) - - def __init__(self, criterion, milestone, number, - date_created=datetime.datetime.utcnow(), current=True): - self.criterion = criterion - self.milestone = milestone - self.number = number - self.current = current - self.date_created = date_created - - def __repr__(self): - return "" % (self.release.number, self.release.name, self.number) diff --git a/blockerbugs/models/milestone.py b/blockerbugs/models/milestone.py index c754653..82d0257 100644 --- a/blockerbugs/models/milestone.py +++ b/blockerbugs/models/milestone.py @@ -22,7 +22,7 @@ from typing import Any, Optional from blockerbugs import db, BaseModel -from blockerbugs.models import bug, criterion +from blockerbugs.models import bug from blockerbugs.models import release as model_release @@ -51,8 +51,6 @@ class Milestone(BaseModel): """Current milestone is the most relevant one currently. Usually it is the nearest milestone in the future. There should be at most one milestone marked as current.""" bugs: list['bug.Bug'] = db.relationship('Bug', back_populates='milestone', lazy='dynamic') - criteria: list['criterion.Criterion'] = db.relationship('Criterion', back_populates='milestone', - lazy='dynamic') succeeds_id = db.Column(db.Integer, db.ForeignKey('milestone.id'), nullable=True) succeeds: 'Milestone' = db.relationship('Milestone', back_populates='succeeded_by', lazy='dynamic') diff --git a/blockerbugs/models/settings.py b/blockerbugs/models/settings.py deleted file mode 100644 index efa8b4c..0000000 --- a/blockerbugs/models/settings.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2012, Red Hat, Inc -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Authors: -# Tim Flink - -"""ORM class for settings stored in the database""" - -from blockerbugs import db, BaseModel - - -class Settings(BaseModel): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80)) - value = db.Column(db.String(80)) - - def __init__(self, name, value): - self.name = name - self.value = value - - def __repr__(self): - return "" % (self.name, self.value) diff --git a/blockerbugs/models/user.py b/blockerbugs/models/user.py deleted file mode 100644 index 6601e4d..0000000 --- a/blockerbugs/models/user.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2012, Red Hat, Inc -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Authors: -# Tim Flink - -"""Database model for user""" - -from blockerbugs import db, BaseModel -from werkzeug.security import generate_password_hash, check_password_hash - -############################################################ -# This model is going away once FAS integration is complete. -# It is a pretty dirty hack, but it does work well enough for now -############################################################ - -class User(BaseModel): - id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(80), unique=True) - pw_hash = db.Column(db.String(120), unique=False) - - def __init__(self, username, password): - self.username = username - self.set_password(password) - - def __repr__(self): - return '' % self.username - - def set_password(self, password): - self.pw_hash = generate_password_hash(password) - - def check_password(self, password): - return check_password_hash(self.pw_hash, password) - - def get_id(self): - return self.id - - def is_active(self): - return True - - def is_anonymous(self): - return False - - def is_authenticated(self): - return True diff --git a/blockerbugs/static/img/bg.gif b/blockerbugs/static/img/bg.gif deleted file mode 100644 index fac668f..0000000 Binary files a/blockerbugs/static/img/bg.gif and /dev/null differ diff --git a/blockerbugs/static/img/blockerbugs-logo-light-stg.png b/blockerbugs/static/img/blockerbugs-logo-light-stg.png deleted file mode 100644 index b94f389..0000000 Binary files a/blockerbugs/static/img/blockerbugs-logo-light-stg.png and /dev/null differ diff --git a/blockerbugs/static/img/bodhi_icon.png b/blockerbugs/static/img/bodhi_icon.png deleted file mode 100644 index ffbc6b8..0000000 Binary files a/blockerbugs/static/img/bodhi_icon.png and /dev/null differ diff --git a/blockerbugs/static/img/desc.gif b/blockerbugs/static/img/desc.gif deleted file mode 100644 index 3b30b3c..0000000 Binary files a/blockerbugs/static/img/desc.gif and /dev/null differ diff --git a/blockerbugs/static/img/line-bottom.png b/blockerbugs/static/img/line-bottom.png deleted file mode 100644 index 6c111c3..0000000 Binary files a/blockerbugs/static/img/line-bottom.png and /dev/null differ diff --git a/blockerbugs/static/img/repeater-stg.png b/blockerbugs/static/img/repeater-stg.png deleted file mode 100644 index 24c56fd..0000000 Binary files a/blockerbugs/static/img/repeater-stg.png and /dev/null differ diff --git a/blockerbugs/static/img/repeater.png b/blockerbugs/static/img/repeater.png deleted file mode 100644 index 45d9189..0000000 Binary files a/blockerbugs/static/img/repeater.png and /dev/null differ diff --git a/blockerbugs/static/js/admin.js b/blockerbugs/static/js/admin.js deleted file mode 100644 index 2e0ba96..0000000 --- a/blockerbugs/static/js/admin.js +++ /dev/null @@ -1,21 +0,0 @@ -(function() { - $('[data-role="select2Builds"]').each(function() { - el = $(this); - //make sure that spin have any autocomplition builds - if(el.attr('existing-builds')) - { - el.select2({tags: el.attr('existing-builds').split(','), tokenSeparators: [','], width: 'resolve'}) - } - else - { - if(el.attr('value')) - { - el.select2({tags: el.attr('value').split(','), tokenSeparators: [','], width: 'resolve'}); - } - else - { - el.select2({tokenSeparators: [','], width: 'resolve'}) - } - } - }); -})(); \ No newline at end of file diff --git a/blockerbugs/static/js/app.js b/blockerbugs/static/js/app.js deleted file mode 100644 index 31678f1..0000000 --- a/blockerbugs/static/js/app.js +++ /dev/null @@ -1,9 +0,0 @@ -(function ($) { - - $(function(){ - $(document).foundationAlerts(); - $(document).foundationButtons(); - $(document).foundationNavigation(); - }); - -})(jQuery); diff --git a/blockerbugs/static/js/jquery.foundation.alerts.js b/blockerbugs/static/js/jquery.foundation.alerts.js deleted file mode 100644 index 0233f4f..0000000 --- a/blockerbugs/static/js/jquery.foundation.alerts.js +++ /dev/null @@ -1,19 +0,0 @@ -(function ($) { - - $.fn.foundationAlerts = function (options) { - var settings = $.extend({ - callback: $.noop - }, options); - - $(document).on("click", ".alert-box a.close", function (event) { - event.preventDefault(); - $(this).closest(".alert-box").fadeOut(function (event) { - $(this).remove(); - // Do something else after the alert closes - settings.callback(); - }); - }); - - }; - -})(jQuery); diff --git a/blockerbugs/static/js/jquery.foundation.tooltips.js b/blockerbugs/static/js/jquery.foundation.tooltips.js deleted file mode 100644 index 22b95a4..0000000 --- a/blockerbugs/static/js/jquery.foundation.tooltips.js +++ /dev/null @@ -1,183 +0,0 @@ -/* - * jQuery Foundation Tooltip Plugin 2.0.1 - * http://foundation.zurb.com - * Copyright 2012, ZURB - * Free to use under the MIT license. - * http://www.opensource.org/licenses/mit-license.php -*/ - -/*jslint unparam: true, browser: true, indent: 2 */ - -;(function ($) { - 'use strict'; - var settings = { - bodyHeight : 0, - targetClass : '.has-tip', - tooltipClass : '.tooltip', - tipTemplate : function (selector, content) { - return '' + content + ''; - } - }, - methods = { - init : function (options) { - return this.each(function () { - var $body = $('body'); - - if (Modernizr.touch) { - $body.on('click.tooltip touchstart.tooltip touchend.tooltip', settings.targetClass, function (e) { - e.preventDefault(); - $(settings.tooltipClass).hide(); - methods.showOrCreateTip($(this)); - }); - $body.on('click.tooltip touchstart.tooltip touchend.tooltip', settings.tooltipClass, function (e) { - e.preventDefault(); - $(this).fadeOut(150); - }); - } else { - $body.on('mouseenter.tooltip mouseleave.tooltip', settings.targetClass, function (e) { - var $this = $(this); - - if (e.type === 'mouseenter') { - methods.showOrCreateTip($this); - } else if (e.type === 'mouseleave') { - methods.hide($this); - } - }); - } - }); - }, - showOrCreateTip : function ($target) { - var $tip = methods.getTip($target); - - if ($tip && $tip.length > 0) { - methods.show($target); - } else { - methods.create($target); - } - }, - getTip : function ($target) { - var selector = methods.selector($target), - tip = null; - - if (selector) { - tip = $('span[data-selector=' + selector + ']' + settings.tooltipClass); - } - return (tip.length > 0) ? tip : false; - }, - selector : function ($target) { - var id = $target.attr('id'), - dataSelector = $target.data('selector'); - - if (id === undefined && dataSelector === undefined) { - dataSelector = 'tooltip' + Math.random().toString(36).substring(7); - $target.attr('data-selector', dataSelector); - } - return (id) ? id : dataSelector; - }, - create : function ($target) { - var $tip = $(settings.tipTemplate(methods.selector($target), $('
').text($target.attr('title')).html())), - classes = methods.inheritable_classes($target); - - $tip.addClass(classes).appendTo('body'); - if (Modernizr.touch) { - $tip.append('tap to close '); - } - $target.removeAttr('title'); - methods.show($target); - }, - reposition : function (target, tip, classes) { - var width, nub, nubHeight, nubWidth, column, objPos; - - tip.css('visibility', 'hidden').show(); - - width = target.data('width'); - nub = tip.children('.nub'); - nubHeight = nub.outerHeight(); - nubWidth = nub.outerWidth(); - - objPos = function (obj, top, right, bottom, left, width) { - return obj.css({ - 'top' : top, - 'bottom' : bottom, - 'left' : left, - 'right' : right, - 'width' : (width) ? width : 'auto' - }).end(); - }; - - objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left, width); - objPos(nub, -nubHeight, 'auto', 'auto', 10); - - if ($(window).width() < 767) { - column = target.closest('.columns'); - - if (column.length < 0) { - // if not using Foundation - column = $('body'); - } - tip.width(column.outerWidth() - 25).css('left', 15).addClass('tip-override'); - objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left); - } else { - if (classes.indexOf('tip-top') > -1) { - objPos(tip, (target.offset().top - tip.outerHeight() - nubHeight), 'auto', 'auto', target.offset().left, width) - .removeClass('tip-override'); - objPos(nub, 'auto', 'auto', -nubHeight, 'auto'); - } else if (classes.indexOf('tip-left') > -1) { - objPos(tip, (target.offset().top + (target.outerHeight() / 2) - nubHeight), 'auto', 'auto', (target.offset().left - tip.outerWidth() - 10), width) - .removeClass('tip-override'); - objPos(nub, (tip.outerHeight() / 2) - (nubHeight / 2), -nubHeight, 'auto', 'auto'); - } else if (classes.indexOf('tip-right') > -1) { - objPos(tip, (target.offset().top + (target.outerHeight() / 2) - nubHeight), 'auto', 'auto', (target.offset().left + target.outerWidth() + 10), width) - .removeClass('tip-override'); - objPos(nub, (tip.outerHeight() / 2) - (nubHeight / 2), 'auto', 'auto', -nubHeight); - } - } - tip.css('visibility', 'visible').hide(); - }, - inheritable_classes : function (target) { - var inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'noradius'], - filtered = target.attr('class').split(' ').map(function (el, i) { - if ($.inArray(el, inheritables) !== -1) { - return el; - } - }).join(' '); - - return $.trim(filtered); - }, - show : function ($target) { - var $tip = methods.getTip($target); - - methods.reposition($target, $tip, $target.attr('class')); - $tip.fadeIn(150); - }, - hide : function ($target) { - var $tip = methods.getTip($target); - - $tip.fadeOut(150); - }, - reload : function () { - var $self = $(this); - - return ($self.data('tooltips')) ? $self.tooltips('destroy').tooltips('init') : $self.tooltips('init'); - }, - destroy : function () { - return this.each(function () { - $(window).off('.tooltip'); - $(settings.targetClass).off('.tooltip'); - $(settings.tooltipClass).each(function (i) { - $($(settings.targetClass).get(i)).attr('title', $(this).text()); - }).remove(); - }); - } - }; - - $.fn.tooltips = function (method) { - if (methods[method]) { - return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); - } else if (typeof method === 'object' || !method) { - return methods.init.apply(this, arguments); - } else { - $.error('Method ' + method + ' does not exist on jQuery.tooltips'); - } - }; -}(jQuery)); \ No newline at end of file diff --git a/blockerbugs/util/koji_interface.py b/blockerbugs/util/koji_interface.py deleted file mode 100644 index 45ec809..0000000 --- a/blockerbugs/util/koji_interface.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2013, Red Hat, Inc -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Authors: -# Tim Flink -# Ilgiz Islamgulov - -"""Basic wrapper to work with the Koji API""" - -import koji - -from blockerbugs import app - -KOJIHUB_URL = app.config['KOJI_URL'] + 'kojihub' - - -def get_build_data(build_nvr): - """ - return build information by build NVR - return None if build does not exists - """ - session = koji.ClientSession(KOJIHUB_URL) - resp = session.queryHistory(build=build_nvr) - data = resp['tag_listing'] - if data: - return data[0] - else: #build failed or in building state - raise koji.GenericError(u'Empty response from Koji.') diff --git a/testing/test_api.py b/testing/test_api.py index e1d1e5d..52eeb0c 100644 --- a/testing/test_api.py +++ b/testing/test_api.py @@ -8,7 +8,6 @@ import mock from blockerbugs import db from blockerbugs import app from blockerbugs.models.bug import Bug -from blockerbugs.models.build import Build from blockerbugs.models.userinfo import UserInfo from testing.test_controllers import add_release, add_milestone, \ add_bug, add_update @@ -53,9 +52,6 @@ class TestRestAPI(object): cls.update_pending_stable.request = 'stable' cls.update_pending_stable.title = 'mega fixer' cls.update_testing2 = add_update('test-testing2.fc99', cls.release, 'testing', [bug2]) - build = Build() - build.koji_id = 33 - build.nvr = 'libofx-0.9.9-1.fc20' cls.webhook_data = { 'msg': { diff --git a/testing/testfunc_bugmodel.py b/testing/testfunc_bugmodel.py index fb0579c..193afef 100644 --- a/testing/testfunc_bugmodel.py +++ b/testing/testfunc_bugmodel.py @@ -4,7 +4,6 @@ from blockerbugs.models.milestone import Milestone from blockerbugs.models.release import Release from blockerbugs.models.bug import Bug from blockerbugs.models.update import Update -from blockerbugs.models.criterion import Criterion from blockerbugs import db @@ -153,27 +152,3 @@ class TestfuncBugModel(object): assert len(update.bugs) == 2 assert ref_bugs[0] in update.bugs assert ref_bugs[1] in update.bugs - - def test_add_criterion(self): - db.session.add(self.ref_release) - db.session.add(self.ref_milestone) - db.session.commit() - - ref_criterion = "This is a fancy criterion that makes magic happen" - ref_number = 3 - ref_current = True - - test_criterion = Criterion(ref_criterion, self.ref_milestone, - ref_number) - - db.session.add(test_criterion) - db.session.commit() - - criteria = Criterion.query.filter_by(number=ref_number).all() - assert len(criteria) == 1 - criterion = criteria[0] - - assert criterion.criterion == ref_criterion - assert criterion.number == ref_number - assert criterion.current == ref_current - assert criterion.milestone == self.ref_milestone