Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pylint unable to detect __init__ signature correctly when base class has __init__ #891

Open
ji8er opened this issue Nov 3, 2024 · 1 comment
Labels
question User queries

Comments

@ji8er
Copy link

ji8er commented Nov 3, 2024

I have a pattern where I have a single abstract base class with an __init__. Multiple classes derive from it, overriding some other method of the abstract base class.

Although I am able to instantiate objects correctly, pylint seems to show the squiggly red line below the second argument in the object instantiation call. For example, see below:

import abc
import jax
import jax.numpy as jnp
import jaxtyping as jt
import equinox as eqx

class AbstractClass(eqx.Module, strict=True):
  w1: jt.Float[jt.Array, 'nk']

  def __init__(self, a, b):
    self.w1 = jnp.zeros((a, b))

  @abc.abstractmethod
  def __call__(self, *args, **kwargs):
    raise NotImplementedError

class ConcreteClass(AbstractClass, strict=True):
  def __call__(self, to_add):
    return jnp.sum(self.w1)+to_add

c = ConcreteClass(2, 33333)  # [pylint shows UNEXEPECTED POSITIONAL ARGUMENT]
c(4)

I wonder why this is the case, and if there's a way to resolve?

Thanks for the great package, btw!

@patrick-kidger
Copy link
Owner

So by default, dataclasses actually have rather unusual behaviour around __init__ methods: they actually always automatically create a new one in the subclass, even if it would override one that exists in the base class. I found that this felt bad ergonomically, in precisely the use-case you have here! As such I disabled this behaviour, so that Equinox will only automatically create an __init__ method if no parent class has a user-provided one.

In this case, I suspect pylint is picking up on the usual dataclass behaviour. As such I think the best thing to do is simply to add the appropriate comment to disable pylint from raising the error on the line in which it is raised.

Taking a step back at Equinox's design here: we have precisely two divergences from dataclasses, both of them in the __init__ method. The first is the one mentioned above. The second one is that we allow mutating self during __init__, but not afterwards. In contrast, normal frozen dataclasses will throw an error if you try doing self.w1 = ...! I judged the ergonomic benefits of these two points to be worth the infrequent need to disable a static lint or typing error.

Thanks for the great package, btw!

Thank you!

@patrick-kidger patrick-kidger added the question User queries label Nov 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question User queries
Projects
None yet
Development

No branches or pull requests

2 participants