Merge pull request #3399 from dato/pylint_useless_suppression_cleanup

pylint suppression cleanup
This commit is contained in:
Mouse Reeve 2024-07-27 09:21:17 -07:00 committed by GitHub
commit f0e5c334e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 31 additions and 86 deletions

View file

@ -14,6 +14,8 @@ disable =
too-many-instance-attributes,
unnecessary-lambda-assignment,
unsubscriptable-object,
enable =
useless-suppression
[FORMAT]
max-line-length=88

View file

@ -67,7 +67,6 @@ class Edition(Book):
type: str = "Edition"
# pylint: disable=invalid-name
@dataclass(init=False)
class Work(Book):
"""work instance of a book object"""

View file

@ -18,7 +18,6 @@ class OrderedCollection(ActivityObject):
type: str = "OrderedCollection"
# pylint: disable=invalid-name
@dataclass(init=False)
class OrderedCollectionPrivate(OrderedCollection):
"""an ordered collection with privacy settings"""

View file

@ -22,7 +22,6 @@ class Verb(ActivityObject):
self.object.to_model(allow_external_connections=allow_external_connections)
# pylint: disable=invalid-name
@dataclass(init=False)
class Create(Verb):
"""Create activity"""
@ -33,7 +32,6 @@ class Create(Verb):
type: str = "Create"
# pylint: disable=invalid-name
@dataclass(init=False)
class Delete(Verb):
"""Create activity"""
@ -63,7 +61,6 @@ class Delete(Verb):
# if we can't find it, we don't need to delete it because we don't have it
# pylint: disable=invalid-name
@dataclass(init=False)
class Update(Verb):
"""Update activity"""
@ -227,7 +224,6 @@ class Like(Verb):
self.to_model(allow_external_connections=allow_external_connections)
# pylint: disable=invalid-name
@dataclass(init=False)
class Announce(Verb):
"""boosting a status"""

View file

@ -32,7 +32,7 @@ class ActivityStream(RedisStore):
stream_id = self.stream_id(user_id)
return f"{stream_id}-unread-by-type"
def get_rank(self, obj): # pylint: disable=no-self-use
def get_rank(self, obj):
"""statuses are sorted by date published"""
return obj.published_date.timestamp()

View file

@ -33,7 +33,6 @@ class BookwyrmConfig(AppConfig):
name = "bookwyrm"
verbose_name = "BookWyrm"
# pylint: disable=no-self-use
def ready(self):
"""set up OTLP and preview image files, if desired"""
if settings.OTEL_EXPORTER_OTLP_ENDPOINT or settings.OTEL_EXPORTER_CONSOLE:

View file

@ -36,7 +36,6 @@ def search(
...
# pylint: disable=arguments-differ
def search(
query: str,
*,

View file

@ -2,7 +2,7 @@
from bookwyrm import models, settings
def site_settings(request): # pylint: disable=unused-argument
def site_settings(request):
"""include the custom info about the site"""
request_protocol = "https://"
if not request.is_secure():

View file

@ -15,7 +15,6 @@ class StyledForm(ModelForm):
css_classes["number"] = "input"
css_classes["checkbox"] = "checkbox"
css_classes["textarea"] = "textarea"
# pylint: disable=super-with-arguments
super().__init__(*args, **kwargs)
for visible in self.visible_fields():
input_type = ""

View file

@ -34,7 +34,6 @@ class LoginForm(CustomForm):
def add_invalid_password_error(self):
"""We don't want to be too specific about this"""
# pylint: disable=attribute-defined-outside-init
self.non_field_errors = _("Username or password are incorrect")

View file

@ -5,8 +5,6 @@ from django import forms
class ArrayWidget(forms.widgets.TextInput):
"""Inputs for postgres array fields"""
# pylint: disable=unused-argument
# pylint: disable=no-self-use
def value_from_datadict(self, data, files, name):
"""get all values for this name"""
return [i for i in data.getlist(name) if i]

View file

@ -36,7 +36,6 @@ class Importer:
"reading": ["currently-reading", "reading", "currently reading"],
}
# pylint: disable=too-many-locals
def create_job(
self, user: User, csv_file: Iterable[str], include_reviews: bool, privacy: str
) -> ImportJob:

View file

@ -20,7 +20,7 @@ class LibrarythingImporter(Importer):
def normalize_row(
self, entry: dict[str, str], mappings: dict[str, Optional[str]]
) -> dict[str, Optional[str]]: # pylint: disable=no-self-use
) -> dict[str, Optional[str]]:
"""use the dataclass to create the formatted row of data"""
normalized = {
k: _remove_brackets(entry.get(v) if v else None)

View file

@ -18,7 +18,7 @@ class ListsStream(RedisStore):
return f"{user}-lists"
return f"{user.id}-lists"
def get_rank(self, obj): # pylint: disable=no-self-use
def get_rank(self, obj):
"""lists are sorted by updated date"""
return obj.updated_date.timestamp()

View file

@ -31,7 +31,7 @@ logger = logging.getLogger(__name__)
PropertyField = namedtuple("PropertyField", ("set_activity_from_field"))
# pylint: disable=invalid-name
def set_activity_from_property_field(activity, obj, field):
"""assign a model property value to the activity json"""
activity[field[1]] = getattr(obj, field[0])

View file

@ -133,7 +133,6 @@ class BookDataModel(ObjectMixin, BookWyrmModel):
related_models = [
(r.remote_field.name, r.related_model) for r in self._meta.related_objects
]
# pylint: disable=protected-access
for related_field, related_model in related_models:
# Skip the ManyToMany fields that arent auto-created. These
# should have a corresponding OneToMany field in the model for

View file

@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
class BookwyrmAwsSession(BotoSession):
"""a boto session that always uses settings.AWS_S3_ENDPOINT_URL"""
def client(self, *args, **kwargs): # pylint: disable=arguments-differ
def client(self, *args, **kwargs):
kwargs["endpoint_url"] = settings.AWS_S3_ENDPOINT_URL
return super().client("s3", *args, **kwargs)

View file

@ -193,8 +193,7 @@ class UsernameField(ActivitypubFieldMixin, models.CharField):
def __init__(self, activitypub_field="preferredUsername", **kwargs):
self.activitypub_field = activitypub_field
# I don't totally know why pylint is mad at this, but it makes it work
super(ActivitypubFieldMixin, self).__init__( # pylint: disable=bad-super-call
super(ActivitypubFieldMixin, self).__init__(
_("username"),
max_length=150,
unique=True,
@ -234,7 +233,6 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField):
def __init__(self, *args, **kwargs):
super().__init__(*args, max_length=255, choices=PrivacyLevels, default="public")
# pylint: disable=invalid-name
def set_field_from_activity(
self, instance, data, overwrite=True, allow_external_connections=True
):
@ -276,7 +274,6 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField):
if hasattr(instance, "mention_users"):
mentions = [u.remote_id for u in instance.mention_users.all()]
# this is a link to the followers list
# pylint: disable=protected-access
followers = instance.user.followers_url
if instance.privacy == "public":
activity["to"] = [self.public]
@ -444,7 +441,7 @@ class ImageField(ActivitypubFieldMixin, models.ImageField):
self.alt_field = alt_field
super().__init__(*args, **kwargs)
# pylint: disable=arguments-differ,arguments-renamed,too-many-arguments
# pylint: disable=arguments-renamed,too-many-arguments
def set_field_from_activity(
self, instance, data, save=True, overwrite=True, allow_external_connections=True
):

View file

@ -352,7 +352,7 @@ def import_item_task(item_id):
try:
item.resolve()
except Exception as err: # pylint: disable=broad-except
except Exception as err:
item.fail_reason = _("Error loading book")
item.save()
item.update_job()

View file

@ -135,7 +135,7 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
status = "follow_request"
activity_serializer = activitypub.Follow
def save(self, *args, broadcast=True, **kwargs): # pylint: disable=arguments-differ
def save(self, *args, broadcast=True, **kwargs):
"""make sure the follow or block relationship doesn't already exist"""
# if there's a request for a follow that already exists, accept it
# without changing the local database state

View file

@ -98,7 +98,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
self.thread_id = self.id
super().save(broadcast=False, update_fields=["thread_id"])
def delete(self, *args, **kwargs): # pylint: disable=unused-argument
def delete(self, *args, **kwargs):
""" "delete" a status"""
if hasattr(self, "boosted_status"):
# okay but if it's a boost really delete it
@ -213,7 +213,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
**kwargs,
).serialize()
def to_activity_dataclass(self, pure=False): # pylint: disable=arguments-differ
def to_activity_dataclass(self, pure=False):
"""return tombstone if the status is deleted"""
if self.deleted:
return activitypub.Tombstone(

View file

@ -409,7 +409,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def delete(self, *args, **kwargs):
"""We don't actually delete the database entry"""
# pylint: disable=attribute-defined-outside-init
self.is_active = False
self.allow_reactivation = False
self.is_deleted = True
@ -452,7 +451,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def deactivate(self):
"""Disable the user but allow them to reactivate"""
# pylint: disable=attribute-defined-outside-init
self.is_active = False
self.deactivation_reason = "self_deactivation"
self.allow_reactivation = True
@ -460,7 +458,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def reactivate(self):
"""Now you want to come back, huh?"""
# pylint: disable=attribute-defined-outside-init
if not self.allow_reactivation:
return
self.is_active = True

View file

@ -420,7 +420,6 @@ def save_and_cleanup(image, instance=None):
return True
# pylint: disable=invalid-name
@app.task(queue=IMAGES)
def generate_site_preview_image_task():
"""generate preview_image for the website"""
@ -445,7 +444,6 @@ def generate_site_preview_image_task():
save_and_cleanup(image, instance=site)
# pylint: disable=invalid-name
@app.task(queue=IMAGES)
def generate_edition_preview_image_task(book_id):
"""generate preview_image for a book"""

View file

@ -6,7 +6,7 @@ from base64 import b64encode, b64decode
from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15 # pylint: disable=no-name-in-module
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
MAX_SIGNATURE_AGE = 300
@ -84,7 +84,6 @@ class Signature:
self.headers = headers
self.signature = signature
# pylint: disable=invalid-name
@classmethod
def parse(cls, request):
"""extract and parse a signature from an http request"""

View file

@ -34,7 +34,6 @@ class SuggestedUsers(RedisStore):
def get_counts_from_rank(self, rank): # pylint: disable=no-self-use
"""calculate mutuals count and shared books count from rank"""
# pylint: disable=c-extension-no-member
return {
"mutuals": math.floor(rank),
# "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1,
@ -128,7 +127,6 @@ def get_annotated_users(viewer, *args, **kwargs):
),
distinct=True,
),
# pylint: disable=line-too-long
# shared_books=Count(
# "shelfbook",
# filter=Q(
@ -202,7 +200,7 @@ def update_suggestions_on_unfollow(sender, instance, **kwargs):
@receiver(signals.post_save, sender=models.User)
# pylint: disable=unused-argument, too-many-arguments
# pylint: disable=unused-argument
def update_user(sender, instance, created, update_fields=None, **kwargs):
"""an updated user, neat"""
# a new user is found, create suggestions for them

View file

@ -115,7 +115,6 @@ class AbstractConnector(TestCase):
@responses.activate
def test_get_or_create_author(self):
"""load an author"""
# pylint: disable=attribute-defined-outside-init
self.connector.author_mappings = [
Mapping("id"),
Mapping("name"),
@ -141,7 +140,6 @@ class AbstractConnector(TestCase):
def test_update_author_from_remote(self):
"""trigger the function that looks up the remote data"""
author = models.Author.objects.create(name="Test", openlibrary_key="OL123A")
# pylint: disable=attribute-defined-outside-init
self.connector.author_mappings = [
Mapping("id"),
Mapping("name"),

View file

@ -20,7 +20,7 @@ from bookwyrm.models.activitypub_mixin import (
from bookwyrm.settings import PAGE_LENGTH
# pylint: disable=invalid-name,too-many-public-methods
# pylint: disable=too-many-public-methods
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class ActivitypubMixins(TestCase):

View file

@ -42,7 +42,7 @@ class BaseModel(TestCase):
def test_remote_id(self):
"""these should be generated"""
self.test_model.id = 1 # pylint: disable=invalid-name
self.test_model.id = 1
expected = self.test_model.get_remote_id()
self.assertEqual(expected, f"{BASE_URL}/bookwyrmtestmodel/1")

View file

@ -13,7 +13,7 @@ from bookwyrm.utils.tar import BookwyrmTarFile
from bookwyrm.models import bookwyrm_import_job
class BookwyrmImport(TestCase): # pylint: disable=too-many-public-methods
class BookwyrmImport(TestCase):
"""testing user import functions"""
def setUp(self):

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, settings
# pylint: disable=unused-argument
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")

View file

@ -10,7 +10,7 @@ class MergeBookDataModel(TestCase):
"""test merging of subclasses of BookDataModel"""
@classmethod
def setUpTestData(cls): # pylint: disable=invalid-name
def setUpTestData(cls):
"""shared data"""
models.SiteSettings.objects.create()

View file

@ -42,7 +42,7 @@ def validate_html(html):
validator.feed(str(html.content))
class HtmlValidator(HTMLParser): # pylint: disable=abstract-method
class HtmlValidator(HTMLParser):
"""Checks for custom html validation requirements"""
def __init__(self):

View file

@ -14,7 +14,6 @@ from bookwyrm.tests.validate_html import validate_html
class ImportUserViews(TestCase):
"""user import views"""
# pylint: disable=invalid-name
def setUp(self):
"""we need basic test data and mocks"""
self.factory = RequestFactory()

View file

@ -11,7 +11,6 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class Inbox(TestCase):
"""readthrough tests"""

View file

@ -7,7 +7,6 @@ import responses
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxAdd(TestCase):
"""inbox tests"""

View file

@ -7,7 +7,6 @@ import responses
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxActivities(TestCase):
"""inbox tests"""

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxBlock(TestCase):
"""inbox tests"""

View file

@ -9,7 +9,6 @@ from bookwyrm import models, views
from bookwyrm.activitypub import ActivitySerializerError
# pylint: disable=too-many-public-methods
class TransactionInboxCreate(TransactionTestCase):
"""readthrough tests"""

View file

@ -7,7 +7,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxActivities(TestCase):
"""inbox tests"""

View file

@ -7,7 +7,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxRelationships(TestCase):
"""inbox tests"""

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxActivities(TestCase):
"""inbox tests"""

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxRemove(TestCase):
"""inbox tests"""

View file

@ -8,7 +8,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxUpdate(TestCase):
"""inbox tests"""
@ -161,7 +160,6 @@ class InboxUpdate(TestCase):
datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_edition.json")
bookdata = json.loads(datafile.read_bytes())
del bookdata["authors"]
# pylint: disable=line-too-long
link_data = {
"href": "https://openlibrary.org/books/OL11645413M/Queen_Victoria/daisy",
"mediaType": "Daisy",

View file

@ -11,7 +11,6 @@ from bookwyrm import forms, models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=too-many-public-methods
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
class LoginViews(TestCase):

View file

@ -11,7 +11,6 @@ from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class ListViews(TestCase):
"""list view"""

View file

@ -11,7 +11,6 @@ from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class ListViews(TestCase):
"""list view"""

View file

@ -13,7 +13,6 @@ from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
# pylint: disable=too-many-public-methods
class ListViews(TestCase):
"""list view"""

View file

@ -7,8 +7,6 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
# pylint: disable=unused-argument
# pylint: disable=too-many-public-methods
class ListItemViews(TestCase):
"""list view"""

View file

@ -11,7 +11,7 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class ListViews(TestCase):
"""lists of lists"""

View file

@ -18,7 +18,7 @@ class ExportViews(TestCase):
"""viewing and creating statuses"""
@classmethod
def setUpTestData(cls): # pylint: disable=invalid-name
def setUpTestData(cls):
"""we need basic test data and mocks"""
with (
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
@ -41,7 +41,6 @@ class ExportViews(TestCase):
bnf_id="beep",
)
# pylint: disable=invalid-name
def setUp(self):
"""individual test setup"""
self.factory = RequestFactory()

View file

@ -11,7 +11,7 @@ from django.test.client import RequestFactory
from bookwyrm import forms, models, views
# pylint: disable=too-many-public-methods
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
class TwoFactorViews(TestCase):

View file

@ -9,7 +9,7 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class DirectoryViews(TestCase):
"""tag views"""

View file

@ -10,7 +10,6 @@ from bookwyrm import models, views
from bookwyrm.settings import USER_AGENT
# pylint: disable=too-many-public-methods
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class OutboxView(TestCase):
"""sends out activities"""

View file

@ -52,7 +52,6 @@ class PartialDate(datetime):
Use subclasses to specify precision. If `dt` is naive, `ValueError`
is raised.
"""
# pylint: disable=invalid-name
if timezone.is_naive(dt):
raise ValueError("naive datetime not accepted")
return cls.combine(dt.date(), dt.time(), tzinfo=dt.tzinfo)

View file

@ -43,7 +43,6 @@ class Dashboard(View):
) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN)
data["email_config_error"] = email_config_error
# pylint: disable=line-too-long
data[
"email_sender"
] = f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}"

View file

@ -152,7 +152,7 @@ class FederatedServer(View):
}
return TemplateResponse(request, "settings/federation/instance.html", data)
def post(self, request, server): # pylint: disable=unused-argument
def post(self, request, server):
"""update note"""
server = get_object_or_404(models.FederatedServer, id=server)
server.notes = request.POST.get("notes")

View file

@ -63,7 +63,6 @@ class ImportList(View):
}
return TemplateResponse(request, "settings/imports/imports.html", data)
# pylint: disable=unused-argument
def post(self, request, import_id):
"""Mark an import as complete"""
import_job = get_object_or_404(models.ImportJob, id=import_id)
@ -95,7 +94,6 @@ def enable_imports(request):
@require_POST
@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
# pylint: disable=unused-argument
def set_import_size_limit(request):
"""Limit the amount of books users can import at once"""
site = models.SiteSettings.objects.get()
@ -120,7 +118,6 @@ def set_user_import_completed(request, import_id):
@require_POST
@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
# pylint: disable=unused-argument
def set_user_import_limit(request):
"""Limit how ofter users can import and export their account"""
site = models.SiteSettings.objects.get()

View file

@ -204,7 +204,6 @@ def resolve_book(request):
@login_required
@require_POST
@permission_required("bookwyrm.edit_book", raise_exception=True)
# pylint: disable=unused-argument
def update_book_from_remote(request, book_id, connector_identifier):
"""load the remote data for this book"""
connector = connector_manager.load_connector(

View file

@ -88,7 +88,6 @@ class CreateBook(View):
data = {"form": forms.EditionForm()}
return TemplateResponse(request, "book/edit/edit_book.html", data)
# pylint: disable=too-many-locals
def post(self, request):
"""create a new book"""
# returns None if no match is found

View file

@ -240,7 +240,7 @@ def redirect_to_referer(request, *args, **kwargs):
return redirect(*args or "/", **kwargs)
# pylint: disable=redefined-builtin,invalid-name
# pylint: disable=redefined-builtin
def get_mergeable_object_or_404(klass, id):
"""variant of get_object_or_404 that also redirects if id has been merged
into another object"""

View file

@ -97,7 +97,7 @@ class Register(View):
class ConfirmEmailCode(View):
"""confirm email address"""
def get(self, request, code): # pylint: disable=unused-argument
def get(self, request, code):
"""you got the code! good work"""
settings = models.SiteSettings.get()
if request.user.is_authenticated:
@ -124,7 +124,7 @@ class ConfirmEmailCode(View):
class ConfirmEmail(View):
"""enter code to confirm email address"""
def get(self, request): # pylint: disable=unused-argument
def get(self, request):
"""you need a code! keep looking"""
settings = models.SiteSettings.get()
if request.user.is_authenticated or not settings.require_confirm_email:

View file

@ -22,7 +22,6 @@ logger = logging.getLogger(__name__)
# pylint: disable=no-self-use
# pylint: disable=too-many-return-statements
@method_decorator(login_required, name="dispatch")
class ReadingStatus(View):
"""consider reading a book"""

View file

@ -7,7 +7,7 @@ from ..models import Review, Quotation, Comment
from .helpers import get_user_from_username
# pylint: disable=no-self-use, unused-argument
# pylint: disable=no-self-use
class RssFeed(Feed):
"""serialize user's posts in rss feed"""

View file

@ -119,7 +119,6 @@ class Shelf(View):
return TemplateResponse(request, "shelf/shelf.html", data)
@method_decorator(login_required, name="dispatch")
# pylint: disable=unused-argument
def post(self, request, username, shelf_identifier):
"""edit a shelf"""
user = get_user_from_username(request.user, username)

View file

@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
class EditStatus(View):
"""the view for *posting*"""
def get(self, request, status_id): # pylint: disable=unused-argument
def get(self, request, status_id):
"""load the edit panel"""
status = get_object_or_404(
models.Status.objects.select_subclasses(), id=status_id