-
Notifications
You must be signed in to change notification settings - Fork 406
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
Allow iterables of qualified class names in Stream.__getitem__
searches
#1359
Merged
Merged
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f423601
Allow iterables of qualified class names in `Stream.__getitem__` sear…
jacobtylerwalls c5c15e0
Use implicit tuple
jacobtylerwalls e065756
Merge branch 'master' into gebc-multiple-classes
mscuthbert f4aa42c
Review edits
jacobtylerwalls dcfe23d
Merge branch 'master' into gebc-multiple-classes
jacobtylerwalls 6155e9d
add type changes
mscuthbert File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -434,13 +434,17 @@ def __getitem__(self, k: slice) -> t.List[M21ObjType]: | |
@overload | ||
def __getitem__( | ||
self, | ||
k: t.Type[ChangedM21ObjType] | ||
k: t.Union[t.Type[ChangedM21ObjType], t.Collection[t.Type[ChangedM21ObjType]]] | ||
) -> iterator.RecursiveIterator[ChangedM21ObjType]: | ||
x = t.cast(iterator.RecursiveIterator[ChangedM21ObjType], self.recurse()) | ||
return x # dummy code | ||
|
||
def __getitem__(self, | ||
k: t.Union[str, int, slice, t.Type[ChangedM21ObjType]] | ||
k: t.Union[str, | ||
int, | ||
slice, | ||
t.Type[ChangedM21ObjType], | ||
t.Collection[t.Type[ChangedM21ObjType]]] | ||
) -> t.Union[iterator.RecursiveIterator[M21ObjType], | ||
iterator.RecursiveIterator[ChangedM21ObjType], | ||
M21ObjType, | ||
|
@@ -486,8 +490,8 @@ def __getitem__(self, | |
3.0 | ||
|
||
|
||
If a class is given then an iterator of elements | ||
that match the requested class(es) is returned, similar | ||
If a class is given, then a :class:`~music21.stream.iterator.RecursiveIterator` | ||
of elements matching the requested class is returned, similar | ||
to `Stream().recurse().getElementsByClass()`. | ||
|
||
>>> len(s) | ||
|
@@ -510,6 +514,18 @@ def __getitem__(self, | |
>>> len(s[note.Note]) | ||
7 | ||
|
||
Multiple classes can be provided, separated by commas. Any element matching | ||
any of the requested classes will be matched. | ||
|
||
>>> len(s[note.Note, note.Rest]) | ||
9 | ||
|
||
>>> for note_or_rest in s[note.Note, note.Rest]: | ||
... if isinstance(note_or_rest, note.Note): | ||
... print(note_or_rest.name, end=' ') | ||
... else: | ||
... print("Rest", end = ' ') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. quotes and spacing. (Sorry that the new linter doesn't do doctests. |
||
C C# D E Rest F G Rest A | ||
|
||
The actual object returned by `s[module.Class]` is a | ||
:class:`~music21.stream.iterator.RecursiveIterator` and has all the functions | ||
|
@@ -556,7 +572,8 @@ def __getitem__(self, | |
|
||
>>> s[0.5] | ||
Traceback (most recent call last): | ||
TypeError: Streams can get items by int, slice, class, or string query; got <class 'float'> | ||
TypeError: Streams can get items by int, slice, class, class iterable, or string query; | ||
got <class 'float'> | ||
|
||
Changed in v7: | ||
- out of range indexes now raise an IndexError, not StreamException | ||
|
@@ -573,6 +590,7 @@ def __getitem__(self, | |
.recurse().getElementsByClass to get the earlier behavior. Old behavior | ||
still works until v9. This is an attempt to unify __getitem__ behavior in | ||
StreamIterators and Streams. | ||
- allowed iterables of qualified class names, e.g. `[note.Note, note.Rest]` | ||
''' | ||
# need to sort if not sorted, as this call may rely on index positions | ||
if not self.isSorted and self.autoSort: | ||
|
@@ -607,7 +625,10 @@ def __getitem__(self, | |
|
||
return t.cast(M21ObjType, searchElements[k]) | ||
|
||
elif isinstance(k, type) and issubclass(k, base.Music21Object): | ||
elif isinstance(k, type): | ||
return self.recurse().getElementsByClass(k) | ||
|
||
elif common.isIterable(k) and all(isinstance(maybe_type, type) for maybe_type in k): | ||
return self.recurse().getElementsByClass(k) | ||
|
||
elif isinstance(k, str): | ||
|
@@ -619,7 +640,8 @@ def __getitem__(self, | |
return querySelectorIterator | ||
|
||
raise TypeError( | ||
f'Streams can get items by int, slice, class, or string query; got {type(k)}' | ||
'Streams can get items by int, slice, class, class iterable, or string query; ' | ||
f'got {type(k)}' | ||
) | ||
|
||
def first(self) -> t.Optional[M21ObjType]: | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
does this properly type the output for mypy? (just want to be sure that that was checked)
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.
I think I'm not quite following -- can you explain what you mean? (
mypy
passes, and I didn't touch the return type)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.
What I mean is something like, say you start typing:
will the
el.pitches
line start to auto-suggest .pitches when you've typed .pi... (like does it know that all possible members have .pitches in it), and will mypy choke on theel.recurse()
-- knowing that the union of note.Note and chord.Chord does not have.recurse()
defined on all members -- or even one member.And if you do:
and know that this is fine? I'm just wondering if the typing is inferred from the ChangedM21Type.
And most importantly, does this still raise a mypy error:
while this passes?
I'll just grab the PR and play with it. But I'm wondering if putting the two different types of things in the same
@overload
might cause problems.