From 2db58aabb7ce5fa5fd23175df1b7dccdd673b1a0 Mon Sep 17 00:00:00 2001 From: Kamil Páral Date: Jun 30 2021 14:46:08 +0000 Subject: fix some linter warnings This fixes all reported mypy warnings, and some flake8 warnings. --- diff --git a/alembic/versions/ea9712463f84_drop_spins_support.py b/alembic/versions/ea9712463f84_drop_spins_support.py index 065bf13..2a6825a 100644 --- a/alembic/versions/ea9712463f84_drop_spins_support.py +++ b/alembic/versions/ea9712463f84_drop_spins_support.py @@ -11,7 +11,6 @@ revision = 'ea9712463f84' down_revision = 'c09a519d5c50' from alembic import op -import sqlalchemy as sa def upgrade(): diff --git a/alembic/versions/f9e369bf00d_added_spin_type_cons.py b/alembic/versions/f9e369bf00d_added_spin_type_cons.py index 0a0d791..87584ba 100644 --- a/alembic/versions/f9e369bf00d_added_spin_type_cons.py +++ b/alembic/versions/f9e369bf00d_added_spin_type_cons.py @@ -11,7 +11,6 @@ revision = 'f9e369bf00d' down_revision = '1162fb4d4358' from alembic import op -import sqlalchemy as sa from sqlalchemy.sql import column diff --git a/blockerbugs/__init__.py b/blockerbugs/__init__.py index 00363bc..ec26695 100644 --- a/blockerbugs/__init__.py +++ b/blockerbugs/__init__.py @@ -1,9 +1,9 @@ -import logging import logging.handlers import os from flask import Flask, render_template from flask_sqlalchemy import SQLAlchemy +from flask_sqlalchemy.model import DefaultMeta from . import config @@ -11,7 +11,7 @@ from . import config __version__ = "1.3.1" # Flask App -app = Flask(__name__) +app: Flask = Flask(__name__) # Is this an OpenShift deployment? openshift = os.getenv('OPENSHIFT_PROD') @@ -103,13 +103,15 @@ setup_logging() # database if app.config['SHOW_DB_URI']: app.logger.debug('using DBURI: %s' % app.config['SQLALCHEMY_DATABASE_URI']) -db = SQLAlchemy(app) +db: SQLAlchemy = SQLAlchemy(app) +# https://stackoverflow.com/questions/63542818/mypy-and-inheriting-from-a-class-that-is-an-attribute-on-an-instance +BaseModel: DefaultMeta = db.Model # "Hotfix" for proxy handling on current deployment, my guess is that the proxy # server is set differently than it was, but what do I know... if app.config["BEHIND_PROXY"]: from werkzeug.middleware.proxy_fix import ProxyFix - app.wsgi_app = ProxyFix(app.wsgi_app, x_host=1) + app.wsgi_app = ProxyFix(app.wsgi_app, x_host=1) # type: ignore[assignment] # === Flask views and stuff === @@ -176,6 +178,7 @@ def updatelabel(bug): return ''.join(label) + @app.template_filter('datetime') def datetime_format(value, format='%Y-%m-%d %H:%M:%S UTC'): if value is not None: @@ -184,14 +187,15 @@ def datetime_format(value, format='%Y-%m-%d %H:%M:%S UTC'): # register blueprints -from blockerbugs.controllers.main import main +from blockerbugs.controllers.main import main # noqa: E402 app.register_blueprint(main) -from blockerbugs.controllers.admin import admin +from blockerbugs.controllers.admin import admin # noqa: F401,E402 -from blockerbugs.controllers.api import api_v0 +from blockerbugs.controllers.api import api_v0 # noqa: E402 app.register_blueprint(api_v0) + # setup error handling @app.errorhandler(404) def page_not_found(e): diff --git a/blockerbugs/controllers/api/__init__.py b/blockerbugs/controllers/api/__init__.py index 030d8f5..6c0ed8c 100644 --- a/blockerbugs/controllers/api/__init__.py +++ b/blockerbugs/controllers/api/__init__.py @@ -1 +1 @@ -from .api import api_v0 \ No newline at end of file +from .api import api_v0 # noqa: F401 diff --git a/blockerbugs/controllers/api/errors.py b/blockerbugs/controllers/api/errors.py index 4923faf..3712f70 100644 --- a/blockerbugs/controllers/api/errors.py +++ b/blockerbugs/controllers/api/errors.py @@ -22,11 +22,7 @@ # Ilgiz Islamgulov # -# First, try to import modern http.client and support also old one on EPEL 7/Python 2 -try: - import http.client as httplib -except ImportError: - import httplib +import http.client as httplib class RestApiError(Exception): diff --git a/blockerbugs/controllers/api/validators.py b/blockerbugs/controllers/api/validators.py index be6bbdb..212af41 100644 --- a/blockerbugs/controllers/api/validators.py +++ b/blockerbugs/controllers/api/validators.py @@ -94,7 +94,7 @@ class NumericValidator(BaseValidator): class IntegerValidator(NumericValidator): - numeric_type = int + numeric_type = int # type: ignore[assignment] class StringValidator(BaseValidator): def _check_data(self): diff --git a/blockerbugs/models/__init__.py b/blockerbugs/models/__init__.py index ead33ee..fd97518 100644 --- a/blockerbugs/models/__init__.py +++ b/blockerbugs/models/__init__.py @@ -21,8 +21,9 @@ # Tim Flink -from sqlalchemy.types import SchemaType, TypeDecorator, Enum +from sqlalchemy.types import SchemaType, TypeDecorator, Enum # type: ignore[attr-defined] import re +from typing import Any class EnumSymbol(object): @@ -68,7 +69,7 @@ class DeclEnum(object): """Declarative enumeration.""" __metaclass__ = EnumMeta - _reg = {} + _reg: dict[Any, Any] = {} @classmethod def from_string(cls, value): diff --git a/blockerbugs/models/bug.py b/blockerbugs/models/bug.py index 00f6f83..086c4cd 100644 --- a/blockerbugs/models/bug.py +++ b/blockerbugs/models/bug.py @@ -19,7 +19,7 @@ """bug.py - ORM class for bug information stored in the database""" -from blockerbugs import db +from blockerbugs import db, BaseModel import datetime import json from typing import Any, Optional @@ -28,7 +28,7 @@ from typing import Any, Optional from blockerbugs.models.milestone import Milestone -class Bug(db.Model): +class Bug(BaseModel): """A representation of a Bugzilla ticket, with some additional attributes. Note: While a particular bug (with a given `bugid`) can exist only once in Bugzilla, a matching diff --git a/blockerbugs/models/build.py b/blockerbugs/models/build.py index 03e51c2..41fd5a8 100644 --- a/blockerbugs/models/build.py +++ b/blockerbugs/models/build.py @@ -24,11 +24,11 @@ from sqlalchemy.schema import UniqueConstraint import koji -from blockerbugs import db +from blockerbugs import db, BaseModel from blockerbugs.util.koji_interface import get_build_data -class Build(db.Model): +class Build(BaseModel): koji_id = db.Column(db.Integer, primary_key=True) pkg_name = db.Column(db.Text) version = db.Column(db.Text) diff --git a/blockerbugs/models/criterion.py b/blockerbugs/models/criterion.py index f45642a..6b35c2c 100644 --- a/blockerbugs/models/criterion.py +++ b/blockerbugs/models/criterion.py @@ -20,11 +20,11 @@ # Authors: # Tim Flink -from blockerbugs import db +from blockerbugs import db, BaseModel import datetime -class Criterion(db.Model): +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) diff --git a/blockerbugs/models/milestone.py b/blockerbugs/models/milestone.py index 63444f1..98d4ed9 100644 --- a/blockerbugs/models/milestone.py +++ b/blockerbugs/models/milestone.py @@ -19,7 +19,7 @@ """milestone.py - ORM class for release milestone info stored in the database""" -from blockerbugs import db +from blockerbugs import db, BaseModel from typing import Any, Optional # unused imports, but required by dynamic relationships: @@ -27,7 +27,7 @@ from blockerbugs.models.criterion import Criterion from blockerbugs.models.release import Release -class Milestone(db.Model): +class Milestone(BaseModel): """A `Milestone` represents e.g. a Beta or a Final milestone, in relation to a certain `Release` (like 35). """ diff --git a/blockerbugs/models/release.py b/blockerbugs/models/release.py index b9d0009..db0024c 100644 --- a/blockerbugs/models/release.py +++ b/blockerbugs/models/release.py @@ -19,12 +19,12 @@ """release.py - database model for releases""" -from blockerbugs import db +from blockerbugs import db, BaseModel from datetime import datetime from typing import Optional -class Release(db.Model): +class Release(BaseModel): """This represents an OS release, primarily determined by its number.""" id = db.Column(db.Integer, primary_key=True) diff --git a/blockerbugs/models/settings.py b/blockerbugs/models/settings.py index bfc6059..1740799 100644 --- a/blockerbugs/models/settings.py +++ b/blockerbugs/models/settings.py @@ -21,10 +21,10 @@ # Tim Flink -from blockerbugs import db +from blockerbugs import db, BaseModel -class Settings(db.Model): +class Settings(BaseModel): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) value = db.Column(db.String(80)) diff --git a/blockerbugs/models/update.py b/blockerbugs/models/update.py index 8b5fae6..df4ad2b 100644 --- a/blockerbugs/models/update.py +++ b/blockerbugs/models/update.py @@ -20,13 +20,12 @@ # Authors: # Tim Flink -from blockerbugs import db -from blockerbugs.models.bug import Bug +from blockerbugs import db, BaseModel -# unused imports, but required by dynamic relationships: +# imports required by dynamic relationships: from blockerbugs.models.bug import Bug -from blockerbugs.models.release import Release -from blockerbugs.models.milestone import Milestone +from blockerbugs.models.release import Release # noqa: F401 +from blockerbugs.models.milestone import Milestone # noqa: F401 update_fixes = db.Table( @@ -42,7 +41,7 @@ update_milestones = db.Table( ) -class Update(db.Model): +class Update(BaseModel): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.Text, unique=False) url = db.Column(db.Text, unique=False) @@ -105,7 +104,7 @@ class Update(db.Model): if not (bug.bugid, bug.milestone) in current_bugkeys: self.bugs.append(bug) current_bugkeys.append((bug.bugid, bug.milestone)) - if bug.milestone and not bug.milestone in self.milestones: + if bug.milestone and bug.milestone not in self.milestones: self.milestones.append(bug.milestone) @classmethod diff --git a/blockerbugs/models/user.py b/blockerbugs/models/user.py index 95115cf..3f2d11a 100644 --- a/blockerbugs/models/user.py +++ b/blockerbugs/models/user.py @@ -20,7 +20,7 @@ # Authors: # Tim Flink -from blockerbugs import db +from blockerbugs import db, BaseModel from werkzeug.security import generate_password_hash, check_password_hash ############################################################ @@ -28,7 +28,7 @@ from werkzeug.security import generate_password_hash, check_password_hash # It is a pretty dirty hack, but it does work well enough for now ############################################################ -class User(db.Model): +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) diff --git a/blockerbugs/models/userinfo.py b/blockerbugs/models/userinfo.py index 26098ce..d6fb8d3 100644 --- a/blockerbugs/models/userinfo.py +++ b/blockerbugs/models/userinfo.py @@ -23,10 +23,10 @@ import string import random import crypt -from blockerbugs import db +from blockerbugs import db, BaseModel -class UserInfo(db.Model): +class UserInfo(BaseModel): id = db.Column(db.Integer, primary_key=True) fas_login = db.Column(db.String(255), unique=True) bz_user = db.Column(db.String(255), unique=True) diff --git a/blockerbugs/util/bug_sync.py b/blockerbugs/util/bug_sync.py index c5b0e1e..b201e57 100644 --- a/blockerbugs/util/bug_sync.py +++ b/blockerbugs/util/bug_sync.py @@ -106,6 +106,8 @@ class BugSync(): return milestone.fe_tracker elif tracker_type == 'PrioritizedBug': return None + else: + raise ValueError(f'Invalid tracker_type: {tracker_type}') def update_milestone(self, milestone: Milestone, tracker_type: str, lastupdate: Optional[datetime] = None) -> None: @@ -119,11 +121,13 @@ class BugSync(): trackerid = self.get_tracker_id(milestone, tracker_type) assert trackerid self.log.info('Updating %s for Fedora %d %s (%d)' % ( - tracker_type, milestone.release.number, milestone.version, trackerid)) + tracker_type, milestone.release.number if milestone.release else -1, + milestone.version, trackerid)) bugs = self.bzinterface.query_tracker(trackerid, last_update=lastupdate) elif tracker_type == 'PrioritizedBug': self.log.info('Updating %s for Fedora %d %s' % ( - tracker_type, milestone.release.number, milestone.version)) + tracker_type, milestone.release.number if milestone.release else -1, + milestone.version)) bugs = self.bzinterface.query_prioritized() else: raise ValueError(f'Invalid tracker_type: {tracker_type}') @@ -163,12 +167,14 @@ class BugSync(): trackerid = self.get_tracker_id(milestone, tracker_type) assert trackerid self.log.info('Cleaning up %s for Fedora %d %s (%d)' % ( - tracker_type, milestone.release.number, milestone.version, trackerid)) + tracker_type, milestone.release.number if milestone.release else -1, + milestone.version, trackerid)) tracker_depends = set(self.bzinterface.get_deps(trackerid)) self.log.debug("Current dependencies for %d: %s" % (trackerid, str(tracker_depends))) elif tracker_type == 'PrioritizedBug': self.log.info('Cleaning up %s for Fedora %d %s' % ( - tracker_type, milestone.release.number, milestone.version)) + tracker_type, milestone.release.number if milestone.release else -1, + milestone.version)) tracker_depends = set() else: raise ValueError(f'Invalid tracker_type: {tracker_type}') diff --git a/blockerbugs/util/bz_interface.py b/blockerbugs/util/bz_interface.py index 5c778ab..a73d3cb 100644 --- a/blockerbugs/util/bz_interface.py +++ b/blockerbugs/util/bz_interface.py @@ -21,7 +21,7 @@ import logging import datetime -from typing import Optional +from typing import Optional, Any import bugzilla from bugzilla.bug import Bug as bzBug @@ -60,7 +60,7 @@ class BlockerBugs(): :param logger: A custom `Logger` instance. Otherwise a default Logger is created. """ self.logger = logger or logging.getLogger('bz_interface') - self.bz = bz + self.bz: bugzilla.Bugzilla = bz if not bz: if not (user and password): self.bz = bugzilla.Bugzilla(url=url, @@ -77,7 +77,7 @@ class BlockerBugs(): # https://partner-bugzilla.redhat.com/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED # &bug_status=POST&bug_status=MODIFIED&classification=Fedora&component=anaconda&f1=component # &o1=changedafter&product=Fedora&query_format=advanced&v1=2013-03-21%2012%3A25&version=19 - def get_bz_query(self, tracker: int, last_update: datetime.datetime = None) -> dict[str, str]: + def get_bz_query(self, tracker: int, last_update: datetime.datetime = None) -> dict[str, Any]: """Build a Bugzilla query to retrieve all necessary info about all bugs which block the `tracker` bug. diff --git a/setup.py b/setup.py index ccd1a70..63b2e39 100644 --- a/setup.py +++ b/setup.py @@ -2,20 +2,19 @@ import codecs import re import os -from setuptools import setup, Command +from setuptools import setup, Command # type: ignore here = os.path.abspath(os.path.dirname(__file__)) class PyTest(Command): - user_options = [] + user_options = [] # type: ignore def initialize_options(self): pass def finalize_options(self): pass def run(self): import subprocess - import sys errno = subprocess.call(['pytest-3']) raise SystemExit(errno) diff --git a/testing/test_api.py b/testing/test_api.py index c584748..e473679 100644 --- a/testing/test_api.py +++ b/testing/test_api.py @@ -1,11 +1,7 @@ from datetime import datetime import json import copy -# First, try to import modern http.client and support also old one on EPEL 7/Python 2 -try: - import http.client as httplib -except ImportError: - import httplib +import http.client as httplib import mock diff --git a/testing/test_bugchange.py b/testing/test_bugchange.py index 9b32ba7..b1f4e38 100644 --- a/testing/test_bugchange.py +++ b/testing/test_bugchange.py @@ -1,11 +1,6 @@ import mock from datetime import datetime - -# First, try to import modern xmlrpc.client and support also old one on EPEL 7/Python 2 -try: - from xmlrpc.client import Fault -except ImportError: - from xmlrpclib import Fault +from xmlrpc.client import Fault import pytest @@ -259,4 +254,3 @@ class TestProposedBug(): test_bz.check_proposed_bug() assert excinfo.value.msg == 'bug does not exist' - diff --git a/testing/test_controllers.py b/testing/test_controllers.py index 5a3c5b3..c5c9d9d 100644 --- a/testing/test_controllers.py +++ b/testing/test_controllers.py @@ -1,7 +1,5 @@ import datetime -from flask import render_template - from blockerbugs.models.milestone import Milestone from blockerbugs.models.release import Release from blockerbugs.models.bug import Bug @@ -122,8 +120,7 @@ class TestNotSyncedMilestone(object): db.drop_all() db.create_all() release = add_release(99) - final_milestone = add_milestone(release, 'final', 100, 101, - '99-final', True) + add_milestone(release, 'final', 100, 101, '99-final', True) add_milestone(release, 'beta', 200, 201, '99-beta') @classmethod diff --git a/testing/testfunc_update_sync.py b/testing/testfunc_update_sync.py index cbd0055..8d32448 100644 --- a/testing/testfunc_update_sync.py +++ b/testing/testfunc_update_sync.py @@ -230,7 +230,7 @@ class TestfuncUpdateSync(object): assert update.pending def test_no_updates_for_bug(self): - bug1 = add_bug(4000, 'testbug1', self.test_milestone99alpha) + add_bug(4000, 'testbug1', self.test_milestone99alpha) self.update_sync.sync_updates(self.test_release99) updates = Update.query.all() assert len(updates) == 0