-
Notifications
You must be signed in to change notification settings - Fork 794
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
perf: Fix issues with Chart|LayerChart.encode
, 1.32x speedup to infer_encoding_types
#3444
Conversation
…dup to `infer_encoding_types` Fixes: - [Sphinx warning](https://altair-viz.github.io/user_guide/generated/toplevel/altair.Chart.html#altair.Chart) on `Chart.encode`. Also incorrectly under `Attributes` section - Preserve static typing previously found in `_encode_signature` but lost after `_EncodingMixin.encode` - Re-running `mypy` output 'Found 63 errors in 47 files (checked 360 source files)', tests/examples Perf: - This was a response to the `TODO` left at the top of `infer_encoding_types` - Will be adding the benchmark to the PR description
Incompatible types in assignment (expression has type "Chart", variable has type "DataFrame")
`Color` -> `Fill` when passed to `fill` channel
… revealed 'error: Argument "color" to "encode" of "_EncodingMixin" has incompatible type "dict[Any, Any] | SchemaBase"; expected "str | Color | dict[Any, Any] | ColorDatum | ColorValue | UndefinedType" [arg-type]'
- New implementation does not use `**kwargs`, which eliminates an entire class of tests based on `.encode(invalidChannel=...)` as these now trigger a runtime error
Chart|LayerChart.encode
, 1.32x speedup to infer_encoding_types
Chart|LayerChart.encode
, 1.32x speedup to infer_encoding_types
return encoding | ||
raise NotImplementedError(f"positional of type {type(tp).__name__!r}") | ||
|
||
def _wrap_in_channel(self, obj: Any, encoding: str, /): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the first time I see a forward slash, /
as argument within a function. Can you explain what that does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure @mattijn
/
is a marker for positional-only parameters. Any parameter to the left of /
is positional-only, and may not be used by name.
In this case, calling self._wrap_in_channel(encoding="enc", obj=[1,2,3])
raises a TypeError
. The python tutorial docs may be helpful for an overview as well.
Personally, I like to use /
in cases like:
- The function/method is not part of the public API, to leave more flexibility in renaming parameters in the future, without introducing a breaking change
- There are a 1-3 parameters
- The function is currently used in one specific way and the function name and parameter order is clear
- In this case,
_wrap_in_channel
could logically be thought of as having parameters_wrap_in_channel(wrappee, wrapper)
.
- In this case,
Looking back at PEP570, I see that this was introduced in python3.8
, which may explain the feature's absence in altair
until now.
Hope all of that was helpful
Much appreciated for this PR @dangotbanned! I cannot really oversee the implications of this PR, but if it solves a todo within the code, resolves the docs issue and introduces a nice performance bump, than I'm really happy you went into that rabbit hole... and came out back again:) All tests are happy already, but if you have a suggestion how I could review this better than looking carefully to the code-diff, that would be much appreciated. Thanks again for this PR! |
Thanks @mattijn I've marked up some comments now with some additional info that may be helpful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! Wasn't aware that the signature for encode
does not work and the new implementation is definitely more robust with the explicit declaration of the kwargs. I'm also glad you went into that rabbit hole ;)
I added some smaller comments. Afterwards, I think this is ready to be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, thanks again! I leave it to @mattijn to merge in case he has any additional comments.
Thanks @binste appreciate the review I'll work on the conflicts today |
I've pushed this with the It seems This has gone unnoticed due to @binste am I understanding this correctly? This example should be enough to repro locally: altair/tests/examples_methods_syntax/airport_connections.py Lines 24 to 50 in 485eae5
|
…t assumes that altair.LookupData comes from core.py instead of api.py
…ey show up only now...
Thanks @binste for the explanation and quick fix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor tweak, but think it would be more maintainable
@binste just to explain this a bit further, the issue (I think) stems from
Lines 689 to 696 in c9106f0
Comparing to
altair/altair/utils/deprecation.py Lines 1 to 94 in c9106f0
A future PR may be helpful, to ensure |
Thanks for the PR and review, LGTM! |
Related to vega#3444 (comment) *Placeholder for screenshot(s) documenting the bug*
I should have updated in vega#3444 but the problem didn't become apparent until running through `ruff`
Was kept, but only needed for tests since vega#3444. As `infer_encoding_types` is not public API - this is a safe remove, no need for deprecation
* test: Monkeypatch channels global Removes the dependency in `test_infer_encoding_types` * refactor: Remove `channels` parameter in `infer_encoding_types` Was kept, but only needed for tests since #3444. As `infer_encoding_types` is not public API - this is a safe remove, no need for deprecation
Background
I stumbled across this issue in the docs during 80a0812 and went down a bit of a rabbit hole
Before
After
Fixes
Chart.encode
. Also incorrectly underAttributes
section_encode_signature
but lost after_EncodingMixin.encode
mypy
output 'Found 63 errors in 47 files (checked 360 source files)', tests/examplesPerf
TODO
left at the top ofinfer_encoding_types
altair/altair/utils/core.py
Lines 785 to 795 in 76a9ce1
Benchmark
Code block
1.32x speedup