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

closes #2891

@nicholas-esterer
Copy link
Contributor Author

Do we want something like:

fig.select_annotations(selector='idunno')

to raise ValueError or just return an empty generator?

@nicolaskruchten
Copy link
Contributor

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

@nicholas-esterer
Copy link
Contributor Author

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

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

@nicolaskruchten
Copy link
Contributor

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

@nicolaskruchten
Copy link
Contributor

The behaviour seems like what I want :)

Copy link
Contributor

@jonmmease jonmmease left a comment

Choose a reason for hiding this comment

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

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

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
Contributor

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

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
Contributor

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

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

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 November 18, 2020 15:24
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
@archmoj archmoj deleted the selector-accept-int-string branch November 23, 2021 23:35
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

Successfully merging this pull request may close these issues.

selector should accept integers and strings, for all functions accepting the selector argument
3 participants