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

ux: don't repr expressions as part of SignatureValidationError #10092

Open
jcrist opened this issue Sep 11, 2024 · 0 comments
Open

ux: don't repr expressions as part of SignatureValidationError #10092

jcrist opened this issue Sep 11, 2024 · 0 comments
Milestone

Comments

@jcrist
Copy link
Member

jcrist commented Sep 11, 2024

Ibis raises a SignatureValidationError when creation of a new op node fails due to an invalid call. This is a user facing error that may result from passing an invalid type or value to a user-facing ibis method.

Currently this error reprs the args to the function in a few places, which is non-ideal:

  • In non-interactive mode, the repr of an expression can take up a ton of vertical space, and isn't helpful to the user diagnosing the error.
  • In interactive mode, the repr executes the expression (usually several times) before repring it. This may be both expensive and messes with the formatting of the error.

Ideally our error messages provide hints as to what was expected (type and/or shape), what was received (type and/or shape), but shouldn't need to repr the actual values (except in the case of literal scalars like 1/`"foo"/etc...).

For an example, here's what the user sees when adding an int and string column together:

Non-interactive mode
In [1]: import ibis

In [2]: t = ibis.examples.diamonds.fetch()

In [3]: t.price + t.color  # invalid addition
---------------------------------------------------------------------------
SignatureValidationError                  Traceback (most recent call last)
Cell In[3], line 1
----> 1 t.price + t.color  # invalid addition

File ~/Code/ibis/ibis/expr/types/strings.py:1660, in StringValue.__radd__(self, other)
   1621 def __radd__(self, other: str | StringValue) -> StringValue:
   1622     """Concatenate strings.
   1623 
   1624     Parameters
   (...)
   1658     └────────────────────────┘
   1659     """
-> 1660     return ops.StringConcat((other, self)).to_expr()

File ~/Code/ibis/ibis/common/bases.py:72, in AbstractMeta.__call__(cls, *args, **kwargs)
     52 def __call__(cls, *args, **kwargs):
     53     """Create a new instance of the class.
     54 
     55     The subclass may override the `__create__` classmethod to change the
   (...)
     70 
     71     """
---> 72     return cls.__create__(*args, **kwargs)

File ~/Code/ibis/ibis/common/grounds.py:119, in Annotable.__create__(cls, *args, **kwargs)
    116 @classmethod
    117 def __create__(cls, *args: Any, **kwargs: Any) -> Self:
    118     # construct the instance by passing only validated keyword arguments
--> 119     kwargs = cls.__signature__.validate(cls, args, kwargs)
    120     return super().__create__(**kwargs)

File ~/Code/ibis/ibis/common/annotations.py:501, in Signature.validate(self, func, args, kwargs)
    498         this[name] = result
    500 if errors:
--> 501     raise SignatureValidationError(
    502         "{call} has failed due to the following errors:{errors}\n\nExpected signature: {sig}",
    503         sig=self,
    504         func=func,
    505         args=args,
    506         kwargs=kwargs,
    507         errors=errors,
    508     )
    510 return this

SignatureValidationError: StringConcat((r0 := DatabaseTable: diamonds
  carat   float64
  cut     string
  color   string
  clarity string
  depth   float64
  table   float64
  price   int64
  x       float64
  y       float64
  z       float64

price: r0.price, r0 := DatabaseTable: diamonds
  carat   float64
  cut     string
  color   string
  clarity string
  depth   float64
  table   float64
  price   int64
  x       float64
  y       float64
  z       float64

color: r0.color)) has failed due to the following errors:
  `arg`: (r0 := DatabaseTable: diamonds
  carat   float64
  cut     string
  color   string
  clarity string
  depth   float64
  table   float64
  price   int64
  x       float64
  y       float64
  z       float64

price: r0.price, r0 := DatabaseTable: diamonds
  carat   float64
  cut     string
  color   string
  clarity string
  depth   float64
  table   float64
  price   int64
  x       float64
  y       float64
  z       float64

color: r0.color) is not a tuple of coercibles to a Value[String, DataShape]

Expected signature: StringConcat(arg: tuple[Value[String, DataShape], ...])
Interactive Mode
In [5]: t.price + t.color  # invalid addition
---------------------------------------------------------------------------
SignatureValidationError                  Traceback (most recent call last)
Cell In[5], line 1
----> 1 t.price + t.color  # invalid addition

File ~/Code/ibis/ibis/expr/types/strings.py:1660, in StringValue.__radd__(self, other)
   1621 def __radd__(self, other: str | StringValue) -> StringValue:
   1622     """Concatenate strings.
   1623 
   1624     Parameters
   (...)
   1658     └────────────────────────┘
   1659     """
-> 1660     return ops.StringConcat((other, self)).to_expr()

File ~/Code/ibis/ibis/common/bases.py:72, in AbstractMeta.__call__(cls, *args, **kwargs)
     52 def __call__(cls, *args, **kwargs):
     53     """Create a new instance of the class.
     54 
     55     The subclass may override the `__create__` classmethod to change the
   (...)
     70 
     71     """
---> 72     return cls.__create__(*args, **kwargs)

File ~/Code/ibis/ibis/common/grounds.py:119, in Annotable.__create__(cls, *args, **kwargs)
    116 @classmethod
    117 def __create__(cls, *args: Any, **kwargs: Any) -> Self:
    118     # construct the instance by passing only validated keyword arguments
--> 119     kwargs = cls.__signature__.validate(cls, args, kwargs)
    120     return super().__create__(**kwargs)

File ~/Code/ibis/ibis/common/annotations.py:501, in Signature.validate(self, func, args, kwargs)
    498         this[name] = result
    500 if errors:
--> 501     raise SignatureValidationError(
    502         "{call} has failed due to the following errors:{errors}\n\nExpected signature: {sig}",
    503         sig=self,
    504         func=func,
    505         args=args,
    506         kwargs=kwargs,
    507         errors=errors,
    508     )
    510 return this

SignatureValidationError: StringConcat((┏━━━━━━━┓
┃ price ┃
┡━━━━━━━┩
│ int64 │
├───────┤
│   326 │
│   326 │
│   327 │
│   334 │
│   335 │
│   336 │
│   336 │
│   337 │
│   337 │
│   338 │
│     … │
└───────┘, ┏━━━━━━━━┓
┃ color  ┃
┡━━━━━━━━┩
│ string │
├────────┤
│ E      │
│ E      │
│ E      │
│ I      │
│ J      │
│ J      │
│ I      │
│ H      │
│ E      │
│ H      │
│ …      │
└────────┘)) has failed due to the following errors:
  `arg`: (┏━━━━━━━┓
┃ price ┃
┡━━━━━━━┩
│ int64 │
├───────┤
│   326 │
│   326 │
│   327 │
│   334 │
│   335 │
│   336 │
│   336 │
│   337 │
│   337 │
│   338 │
│     … │
└───────┘, ┏━━━━━━━━┓
┃ color  ┃
┡━━━━━━━━┩
│ string │
├────────┤
│ E      │
│ E      │
│ E      │
│ I      │
│ J      │
│ J      │
│ I      │
│ H      │
│ E      │
│ H      │
│ …      │
└────────┘) is not a tuple of coercibles to a Value[String, DataShape]

Expected signature: StringConcat(arg: tuple[Value[String, DataShape], ...])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: backlog
Development

No branches or pull requests

2 participants