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

Selector accept int string #2894

Merged
merged 11 commits into from Nov 19, 2020
Merged

Selector accept int string #2894

merged 11 commits into from Nov 19, 2020

Conversation

nicholas-esterer
Copy link
Contributor

@nicholas-esterer nicholas-esterer commented Nov 11, 2020

closes #2891

@nicholas-esterer
Copy link
Contributor Author

@nicholas-esterer nicholas-esterer commented Nov 12, 2020

Do we want something like:

fig.select_annotations(selector='idunno')

to raise ValueError or just return an empty generator?

@nicolaskruchten
Copy link
Member

@nicolaskruchten nicolaskruchten commented Nov 12, 2020

I think a ValueError or whatever the equivalent error you'd get from selector=dict(type="idunno")

@nicholas-esterer
Copy link
Contributor Author

@nicholas-esterer nicholas-esterer commented Nov 12, 2020

That doesn't throw an error either, it also just returns an empty generator. So throwing an error in this case might actually break the API.

@nicholas-esterer
Copy link
Contributor Author

@nicholas-esterer nicholas-esterer commented Nov 12, 2020

So other than the uncertainty surrounding raising an error or not, this PR can be reviewed 👍

@nicolaskruchten
Copy link
Member

@nicolaskruchten nicolaskruchten commented Nov 16, 2020

@jonmmease can you give this PR a sanity-check, implementation-wise, please?

@nicolaskruchten
Copy link
Member

@nicolaskruchten nicolaskruchten commented Nov 16, 2020

The behaviour seems like what I want :)

Copy link
Contributor

@jonmmease jonmmease left a comment

Functionality and tests look good!

I left a few comments/suggestions on design.

"""

# if selector is not an int, we call it on each trace to test it for selection
if type(selector) != type(int()):
Copy link
Contributor

@jonmmease jonmmease Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there's a reason not to, I'd recommend if not isinstance(selector, int): for consistency

Copy link
Member

@nicolaskruchten nicolaskruchten Nov 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, along with all the other similar issues flagged by flake8


@staticmethod
def _selector_matches(obj, selector):
if selector is None:
return True
# If selector is a string then put it at the 'type' key of a dictionary
# to select objects where "type":selector
if type(selector) == type(str()):
Copy link
Contributor

@jonmmease jonmmease Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there's a reason not to, I'd recommend if not isinstance(selector, six.string_types): for consistency

Copy link
Member

@nicolaskruchten nicolaskruchten Nov 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

_natural_sort_strings(list(self.layout)),
)
layout_objs = [self.layout[k] for k in layout_keys]
return _generator(self._filter_by_selector(layout_objs, [], selector))
Copy link
Contributor

@jonmmease jonmmease Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reduction over filters approach is clever, but I think it's a bit more opaque than the current paradigm.

Also, before it returns anything this method traverses the full layout and creates several fully instantiated lists and then converts the final list to a generator. While performance probably isn't a major factor here, the original design avoids the creation of any of these lists, and it returns results one at a time as matches are found.

Refactoring stuff into functions is fine, but I'd prefer to keep the original overall structure of:

layout_keys = _natural_sort_strings(list(self.layout))
for k in layout_keys:
   # filter and continue on stuff that doesn't pass filter
     yield self.layout[k]

and (cur[0]["y"][1] == cur[1]),
zip(trs, [10, 20]),
True,
)
Copy link
Contributor

@jonmmease jonmmease Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this check would be a lot clearer using a comprehension inside all instead reduce.

Something like

all(trace["type"] == "bar" and trace["y"][1] == y 
    for trace, y in zip(trc, [10, 20]))

nicholas-esterer and others added 10 commits Nov 18, 2020
If selector is string, transformed to dict(type=selector), if selector
is int, indexes the resulting list of objects filtered down by row, col
and secondary y.
if selector is string, it is converted to dict(type=selector)
e.g., select_xaxes uses this selector

note: need to test new selector argument that is integer or string
string doesn't make sense in this case as they don't have a "type" key.
@nicolaskruchten nicolaskruchten merged commit 600f275 into master Nov 19, 2020
15 of 16 checks passed
@archmoj archmoj deleted the selector-accept-int-string branch Nov 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

3 participants