`TypeError` in `ChordReducer.run()` on multi-part `stream.Score` without instrument `partId`s

已关闭 适合新手
#2,074 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
62/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
python
领域
data

调研方向

崩溃位于 music21/tree/timespanTree.py(约第 743 行)的 TimespanTree.allParts(),这里按 getInstrument().partId 对声部排序,而该值可能为 None。请从 music21/analysis/reduceChords.py 中的 ChordReducer.run() 开始,运行 issue 中的复现脚本。完成的标准是脚本运行时不再出现 TypeError,且声部保持合理的顺序,例如它们在乐谱中出现的顺序。issue 提出了两种排序方案,因此需要与维护者确认使用哪一种。

由索引模型根据 Issue 内容生成。

描述

music21 version

11.0.0b11

Problem summary

ChordReducer.run() was found to raise a TypeError when given a multi-part stream.Score whose instruments were not assigned partIds.

Steps to reproduce

from music21 import chord, instrument, note, stream
from music21.analysis.reduceChords import ChordReducer

upperInstrument = instrument.Instrument()  
# upperInstrument.partId = 'P1'
lowerInstrument = instrument.Instrument()    
# lowerInstrument.partId = 'P2'

upper = stream.Part([upperInstrument, stream.Measure([chord.Chord('C4 E4', type='whole')])])                                                                                               
lower = stream.Part([lowerInstrument, stream.Measure([note.Note('G4', type='whole')])])                                                                                                    

score = stream.Score([upper, lower])                                                                                                                            
ChordReducer().run(score)
TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'

This error was discovered when calling ChordReducer.run() on scores loaded from MIDI.

Expected vs. actual behavior
Expected ChordReducer.run(score) to complete without error; instead, raises TypeError at music21/tree/timespanTree.py, line 743, in TimespanTree.allParts().

More information
ChordReducer.run() calls TimespanTree.allParts() internally, which returns a list of the tree's parts. This list is ordered by the partId of each part's first instrument, using the following sort:

parts = sorted(parts, key=lambda x: x.getInstrument().partId) 

x.getInstrument() returns the first available instrument in the part, or a new default instrument. In either case, the partId could be None.

One possible fix for the NoneType comparison: having allParts() utilize the input source's ordering to sort the parts. The ordering is available for at least this use case, since ChordReducer.run() already validates that its input is a stream.Score, and the TimespanTree that it uses already keeps track of the source in its source attribute. For just the stream.Score case, allParts() could then return the parts in order of their appearance in the score. Or, more generally, for a solution that works with other stream types that TimespanTree can process, allParts() could always return the list of parts ordered using the source's ordering.

Applying chordify() to the input score beforehand (stream.Score([score.chordify()])), avoids the TypeError being raised, although the chordified score contains just one part.

主要语言
Python
星标
2.6k
派生
459
平均合并
6 小时 22 分钟
30 天内合并 PR
95

环境准备

在 Codespaces 中打开

在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

cuthbertLab/music21 的其他 Issue

查看 cuthbertLab/music21 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。