OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

1 out of many calls to overridden django `Model.save()` generates a pylint `unexpected-keyword-arg` error - how do I satisfy it?

  • Thread starter Thread starter hepcat72
  • Start date Start date
H

hepcat72

Guest
I implemented and have been using this model (super)class I created for years, and it is completely stable on an active site. I just made a small minor tweak to some completely unrelated portion of its code, and checked my work (on my machine) with the latest superlinter. Our CI tests on github currently use an old superlinter and it has never complained, so I was surprised to see a linting error on code I haven't touched in years.

My model class has an overridden save() method, which adds a few extra arguments that it pops off kwargs before calling super().save(). I have a number of calls to save inside the class, and the linter is fine with thos extra arguments everywhere else, except in 1 spot (an override of from_db):

Code:
@classmethod
def from_db(cls, *args, **kwargs):
    # Instantiate the model object
    rec = super().from_db(*args, **kwargs)

    # If autoupdates are not enabled (i.e. we're not in "lazy" mode)
    if not cls.get_coordinator().are_lazy_updates_enabled():
        return rec

    # Get the field names
    queryset_fields = set(args[1])  # field_names

    # Intersect the queryset fields with the maintained fields
    common_fields = set(cls.get_my_update_fields()).intersection(queryset_fields)

    # Look for maintained field values that are None
    lazy_update_fields = [fld for fld in common_fields if getattr(rec, fld) is None]

    if len(lazy_update_fields) > 0:
        # Trigger a lazy auto-update
        rec.save(fields_to_autoupdate=lazy_update_fields, via_query=True)

    return rec

I tried typehinting rec when it's assigned, but that didn't satisfy the linter. I figure it's the call to super().from_db() that is setting a type that doesn't include my args... but my save overload is definitely called.

So how do I satisfy pylint here?

ADDENDUM:

Incidentally, I confirmed that the old pylint/superlinter still doesn't complain about the call to save. I pushed the code despite my local newer superlinter's complaint.

I looked at the base class's from_db method (below). It's pretty simple. Perhaps I could just copy the code into my method and not call super().from_db (even though that seems ridiculous)...

Code:
@classmethod
def from_db(cls, db, field_names, values):
    if len(values) != len(cls._meta.concrete_fields):
        values_iter = iter(values)
        values = [
            next(values_iter) if f.attname in field_names else DEFERRED
            for f in cls._meta.concrete_fields
        ]
    new = cls(*values)
    new._state.adding = False
    new._state.db = db
    return new
<p>I implemented and have been using this model (super)class I created for years, and it is completely stable on an active site. I just made a small minor tweak to some completely unrelated portion of its code, and checked my work (on my machine) with the latest superlinter. Our CI tests on github currently use an old superlinter and it has never complained, so I was surprised to see a linting error on code I haven't touched in years.</p>
<p>My model class has an overridden <code>save()</code> method, which adds a few extra arguments that it pops off <code>kwargs</code> before calling <code>super().save()</code>. I have a number of calls to save inside the class, and the linter is fine with thos extra arguments everywhere else, except in 1 spot (an override of <code>from_db</code>):</p>
<pre class="lang-py prettyprint-override"><code>@classmethod
def from_db(cls, *args, **kwargs):
# Instantiate the model object
rec = super().from_db(*args, **kwargs)

# If autoupdates are not enabled (i.e. we're not in "lazy" mode)
if not cls.get_coordinator().are_lazy_updates_enabled():
return rec

# Get the field names
queryset_fields = set(args[1]) # field_names

# Intersect the queryset fields with the maintained fields
common_fields = set(cls.get_my_update_fields()).intersection(queryset_fields)

# Look for maintained field values that are None
lazy_update_fields = [fld for fld in common_fields if getattr(rec, fld) is None]

if len(lazy_update_fields) > 0:
# Trigger a lazy auto-update
rec.save(fields_to_autoupdate=lazy_update_fields, via_query=True)

return rec
</code></pre>
<p>I tried typehinting <code>rec</code> when it's assigned, but that didn't satisfy the linter. I figure it's the call to <code>super().from_db()</code> that is setting a type that doesn't include my args... but my save overload is definitely called.</p>
<p>So how do I satisfy <code>pylint</code> here?</p>
<p><strong>ADDENDUM</strong>:</p>
<p>Incidentally, I confirmed that the old pylint/superlinter still doesn't complain about the call to save. I pushed the code despite my local newer superlinter's complaint.</p>
<p>I looked at the base class's <code>from_db</code> method (below). It's pretty simple. Perhaps I could just copy the code into my method and not call <code>super().from_db</code> (even though that seems ridiculous)...</p>
<pre class="lang-py prettyprint-override"><code>@classmethod
def from_db(cls, db, field_names, values):
if len(values) != len(cls._meta.concrete_fields):
values_iter = iter(values)
values = [
next(values_iter) if f.attname in field_names else DEFERRED
for f in cls._meta.concrete_fields
]
new = cls(*values)
new._state.adding = False
new._state.db = db
return new
</code></pre>
 
Top