Parser: any class whose base name ends in `Mixin` becomes a model, even a QuerySet or a plain helper

Aperta
#249 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

@noahkhomer18 ci sta già lavorando.

Dal 14/11/2026.

  • #258 di @noahkhomer18 — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
django, python
Ambito
devtools

Direzione di ricerca

Start in cli/orm_lens/parser.py: the Mixin$ branch of _looks_like_model() (around line 442) and where _resolve_and_filter() (around line 829) seeds is_model_name from it. Run the repro from the issue to confirm that only projects.Project should be listed. Done when phantom mixins drop out, the abstract-mixin test in test_abstract_and_auth_user.py and the mezzanine golden snapshot still pass, and pytest, ruff and mypy are clean. Note that open pull request #258 already targets this issue, so check it before starting.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug good first issue python

Source: label-studio — label_studio/projects/models.py:72, label_studio/tasks/models.py; weblate — weblate/trans/mixins.py:74,81,154

What happens

_looks_like_model() returns True as soon as a base's name ends with Mixin. That's a guess for third-party bases we can't see. But it also fires when the mixin is defined right there in the workspace and is a plain class:

  • label-studio: class ProjectQuerySetWithFSM(FSMStateQuerySetMixin, ProjectQuerySet). ProjectQuerySet is a models.QuerySet, FSMStateQuerySetMixin is a plain class. orm-lens lists projects.ProjectQuerySetWithFSM as a model, and drift says blocking: "declared, but no migration creates it". Four of these, so drift fails the build.
  • weblate: class URLMixin(BaseURLMixin), LoggerMixin(BaseURLMixin), PathMixin(LoggerMixin, URLMixin) in trans/mixins.py. BaseURLMixin is class BaseURLMixin:. They're pulled in because Project inherits PathMixin, and then show up as three blocking drift entries.
Repro

projects/mixins.py

class StateQuerySetMixin:
    def with_state(self):
        return self


class URLMixin:
    def get_absolute_url(self):
        return "/"

projects/models.py

from django.db import models

from .mixins import StateQuerySetMixin, URLMixin


class ProjectQuerySet(models.QuerySet):
    pass


class ProjectQuerySetWithState(StateQuerySetMixin, ProjectQuerySet):
    pass


class PathMixin(URLMixin):
    def full_path(self):
        return self.get_absolute_url()


class Project(models.Model, PathMixin):
    title = models.CharField(max_length=100)

    objects = ProjectQuerySetWithState.as_manager()
$ orm-lens list
projects.ProjectQuerySetWithState
projects.PathMixin
projects.Project

Expected: only projects.Project.

Where

cli/orm_lens/parser.py

  • line 442, _looks_like_model(), the re.search(r"Mixin$", tail) branch;
  • line 829, _resolve_and_filter(), which seeds is_model_name from _looks_like_model() and then runs the fixed point over real definitions.
Suggested fix

Use the name guess only for bases we have no definition for. In _resolve_and_filter(), collect defined = {m.name for m in all_defs} and pass it to _looks_like_model(); skip the Mixin$ branch when tail in defined. A mixin that really is a model (class TimeStampMixin(models.Model)) still gets in through the fixed-point loop, because its own base is models.Model.

test_abstract_and_auth_user.py covers abstract mixins and should stay green. The mezzanine golden fixture has *Mixin classes too, so run the golden tests and update the snapshot if a phantom model drops out (say so in the PR).

How to test
  • A test in cli/tests/test_cross_module_bases.py (or a new file) with the repro: only Project is returned.
  • A mixin defined as class OwnedMixin(models.Model) with abstract = True, plus class Doc(OwnedMixin): Doc is still a model and inherits the fields.
  • cd cli && python -m pytest -q, ruff and mypy pass.

Difficulty: good first issue.

Lingua principale
Python
Stelle
84
Fork
13
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di FROWNINGdev/django-orm-lens

Tutte le issue di FROWNINGdev/django-orm-lens

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.