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

Any way to preserve signature/docs of an attrs class deriving from Generic? #374

Closed
aldanor opened this issue Apr 27, 2018 · 5 comments
Closed

Comments

@aldanor
Copy link

aldanor commented Apr 27, 2018

It's more of a cosmetic thing, but still; wondering - is this Jupyter being stupid, or is there some way to fix it? Basically, attrs init signature gets shadowed by that of the base class which is pretty sad (plus the class docstring).

E.g., normal attrs class:

@attr.dataclass
class Foo:
    a: int
    b: float = 1
>>> Foo?
Init signature: Foo(a, b=1)
Docstring:      <no docstring>
Type:           type

Derived from Generic:

T = TypeVar('T')

@attr.dataclass
class Foo(Generic[T]):
    a: T
    b: float = 1
>>> Foo?
Init signature: Foo(*args, **kwds)
Docstring:     
Abstract base class for generic types.

A generic type is typically declared by inheriting from
this class parameterized with one or more type variables.
For example, a generic mapping type might be defined as::

  class Mapping(Generic[KT, VT]):
      def __getitem__(self, key: KT) -> VT:
          ...
      # Etc.

This class can then be used as follows::

  def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
      try:
          return mapping[key]
      except KeyError:
          return default
File:           /scratch/env/lib/python3.6/typing.py
Type:           GenericMeta

In the lattesr case the init signature is actually fine:

>>> Foo.__init__?
Signature: Foo.__init__(self, a, b=1)
Docstring: Initialize self.  See help(type(self)) for accurate signature.
File:      /scratch/<attrs generated init b8ff8387a430033a99f7705d8ff940ab1f05b5f0>
Type:      function
@hynek
Copy link
Member

hynek commented Apr 27, 2018

Uh. What does inspect.signature() say?

@aldanor
Copy link
Author

aldanor commented Apr 27, 2018

<Signature (a, b=1)> in the first case, as expected.

<Signature (*args, **kwds)> in the second case :(

@euresti
Copy link
Contributor

euresti commented Apr 27, 2018

inspect.signature is picking up the signature of Generic.__new__ But it's not an issue limited to Generic.

class A:
    def __new__(cls, *args, **kwargs):
        ...

class B:
    def __init__(self, a: int, b: str = 'foo'):
        ...

class C(A):
    def __init__(self, a: int, b: str = 'foo'):
        ...

import inspect
print("A", inspect.signature(A))
print("B", inspect.signature(B))
print("C", inspect.signature(C))

yields:

A (*args, **kwargs)
B (a:int, b:str='foo')
C (*args, **kwargs)

@hynek
Copy link
Member

hynek commented Apr 28, 2018

Yeah, that’s not great but totally not our problem, right?

For posterity, inspect.getfullargspec() does the same:

>>> inspect.getfullargspec(B)
FullArgSpec(args=['cls'], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

@hynek
Copy link
Member

hynek commented May 2, 2018

Closing as Python weirdness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants