Skip to content

Commit

Permalink
Merge pull request #1629 from TimFelixBeyer/patch-5
Browse files Browse the repository at this point in the history
  • Loading branch information
mscuthbert authored Jul 14, 2023
2 parents 2a28ab1 + 9f35bbb commit 8baa273
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 24 deletions.
4 changes: 2 additions & 2 deletions music21/analysis/reduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ def _extractNoteReductiveEvent(self, n, infoDict=None, removeAfterParsing=True):
return

removalIndices = []
if m.hasElement(n):
if n in m:
offset = n.getOffsetBySite(m)
else: # it is in a Voice
offset = 0.0
for v in m.voices:
if v.hasElement(n):
if n in v:
offset = n.getOffsetBySite(v)


Expand Down
2 changes: 1 addition & 1 deletion music21/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ def purgeOrphans(self, excludeStorageStreams=True) -> None:
# of the site does not actually have this Music21Object in
# its elements list, it is an orphan and should be removed
# note: this permits non-site context Streams to continue
if s.isStream and not s.hasElement(self):
if s.isStream and self not in s:
if excludeStorageStreams:
# only get those that are not Storage Streams
if ('SpannerStorage' not in s.classes
Expand Down
4 changes: 2 additions & 2 deletions music21/freezeThaw.py
Original file line number Diff line number Diff line change
Expand Up @@ -1193,8 +1193,8 @@ def testSerializationScaffoldA(self):
sf.setupSerializationScaffold()

# test safety
self.assertTrue(s2.hasElement(n1))
self.assertTrue(s1.hasElement(n1))
self.assertTrue(n1 in s2)
self.assertTrue(n1 in s1)

def testJSONPickleSpanner(self):
from music21 import converter
Expand Down
24 changes: 10 additions & 14 deletions music21/stream/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ def last(self) -> M21ObjType | None:
except IndexError:
return None

def __contains__(self, el):
def __contains__(self, el: base.Music21Object) -> bool:
'''
Returns True if `el` is in the stream (compared with Identity) and False otherwise.

Expand Down Expand Up @@ -811,8 +811,11 @@ def __contains__(self, el):
>>> nC2 in s.elements
True
'''
return (any(sEl is el for sEl in self._elements)
or any(sEl is el for sEl in self._endElements))
# Should be the fastest implementation of this naive check, compare with
# https://stackoverflow.com/questions/44802682/python-any-unexpected-performance
return (id(el) in self._offsetDict
or any(True for sEl in self._elements if sEl is el)
or any(True for sEl in self._endElements if sEl is el))

@property
def elements(self) -> tuple[M21ObjType, ...]:
Expand Down Expand Up @@ -1434,6 +1437,8 @@ def mergeAttributes(self, other: base.Music21Object):
if hasattr(other, attr):
setattr(self, attr, getattr(other, attr))

@common.deprecated('v10', 'v11', 'Use `el in stream` instead of '
'`stream.hasElement(el)`')
def hasElement(self, obj: base.Music21Object) -> bool:
'''
Return True if an element, provided as an argument, is contained in
Expand All @@ -1449,16 +1454,7 @@ def hasElement(self, obj: base.Music21Object) -> bool:
>>> s.hasElement(n1)
True
'''
if id(obj) in self._offsetDict:
return True

for e in self._elements:
if e is obj: # pragma: no cover
return True
for e in self._endElements:
if e is obj: # pragma: no cover
return True
return False
return obj in self

def hasElementOfClass(self, className, forceFlat=False):
'''
Expand Down Expand Up @@ -2013,7 +2009,7 @@ def _deepcopySubclassable(self: StreamType,
# must manually add elements to new Stream
for e in self._elements:
# environLocal.printDebug(['deepcopy()', e, 'old', old, 'id(old)', id(old),
# 'new', new, 'id(new)', id(new), 'old.hasElement(e)', old.hasElement(e),
# 'new', new, 'id(new)', id(new), 'e in old', e in old,
# 'e.activeSite', e.activeSite, 'e.getSites()', e.getSites(), 'e.getSiteIds()',
# e.getSiteIds()], format='block')
#
Expand Down
10 changes: 5 additions & 5 deletions music21/test/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,14 +570,14 @@ def testStoreLastDeepCopyOf(self):
n2 = copy.deepcopy(n1)
self.assertEqual(id(n2.derivation.origin), id(n1))

def testHasElement(self):
def testContains(self):
n1 = note.Note()
s1 = stream.Stream()
s1.append(n1)
s2 = copy.deepcopy(s1)
n2 = s2[0] # this is a new instance; not the same as n1
self.assertFalse(s2.hasElement(n1))
self.assertTrue(s2.hasElement(n2))
self.assertFalse(n1 in s2)
self.assertTrue(n2 in s2)

self.assertFalse(s1 in n2.sites)
self.assertTrue(s2 in n2.sites)
Expand Down Expand Up @@ -622,7 +622,7 @@ class Mock:
s.insert(i, el)

for ew in storage:
self.assertTrue(s.hasElement(ew))
self.assertTrue(ew in s)

match = [e.getOffsetBySite(s) for e in storage]
self.assertEqual(match, [0.0, 1.0])
Expand All @@ -648,7 +648,7 @@ def getnchannels(self):
s.insert(i, el)

for ew in storage:
self.assertTrue(s.hasElement(ew))
self.assertTrue(ew in s)

matchOffset = []
matchBeatStrength = []
Expand Down

0 comments on commit 8baa273

Please sign in to comment.