Skip to content

Commit 71475e1

Browse files
committed
lint, scoreQuarterLength; rm networkx
1 parent 475fe50 commit 71475e1

File tree

13 files changed

+51
-217
lines changed

13 files changed

+51
-217
lines changed

music21/beam.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class Beams(prebase.ProtoM21Object, EqualSlottedObjectMixin):
219219

220220
# INITIALIZER #
221221

222-
def __init__(self):
222+
def __init__(self) -> None:
223223
# no need for super() call w/ ProtoM21 and EqualSlottedObject
224224
self.beamsList: list[Beam] = []
225225
self.feathered: bool = False

music21/corpus/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,19 @@
4242
import typing as t
4343

4444
from music21 import common
45+
from music21.exceptions21 import CorpusException
4546
from music21 import metadata
4647

4748
from music21.corpus import chorales
4849
from music21.corpus import corpora
4950
from music21.corpus import manager
5051
from music21.corpus import virtual
5152
from music21.corpus import work
52-
5353
from music21.corpus.manager import search
5454
from music21 import environment
5555

5656
__all__ = [
57+
'CorpusException',
5758
'addPath',
5859
'cacheMetadata',
5960
'chorales',
@@ -68,6 +69,7 @@
6869
'noCorpus',
6970
'parse',
7071
# virtual
72+
'search',
7173
'work',
7274
]
7375

-3.17 KB
Binary file not shown.

music21/corpus/corpora.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,15 +811,14 @@ def addPath(self, directoryPath):
811811
Paths added in this way will not be persisted from session to session
812812
unless explicitly saved by a call to ``LocalCorpus.save()``.
813813
'''
814-
from music21 import corpus
815814
if not isinstance(directoryPath, (str, pathlib.Path)):
816-
raise corpus.CorpusException(
815+
raise CorpusException(
817816
f'an invalid file path has been provided: {directoryPath!r}')
818817

819818
directoryPath = common.cleanpath(directoryPath, returnPathlib=True)
820819
if (not directoryPath.exists()
821820
or not directoryPath.is_dir()):
822-
raise corpus.CorpusException(
821+
raise CorpusException(
823822
f'an invalid file path has been provided: {directoryPath!r}')
824823
if self.name not in LocalCorpus._temporaryLocalPaths:
825824
LocalCorpus._temporaryLocalPaths[self.name] = set()

music21/graph/primitives.py

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -579,93 +579,6 @@ def write(self, fp=None): # pragma: no cover
579579
return self.figure
580580

581581

582-
class GraphNetworkxGraph(Graph):
583-
'''
584-
Grid a networkx graph -- which is a graph of nodes and edges.
585-
Requires the optional networkx module.
586-
'''
587-
#
588-
# >>> #_DOCS_SHOW g = graph.primitives.GraphNetworkxGraph()
589-
#
590-
# .. image:: images/GraphNetworkxGraph.*
591-
# :width: 600
592-
_DOC_ATTR: dict[str, str] = {
593-
'networkxGraph': '''An instance of a networkx graph object.''',
594-
'hideLeftBottomSpines': 'bool to hide the left and bottom axis spines; default True',
595-
}
596-
597-
graphType = 'networkx'
598-
keywordConfigurables = Graph.keywordConfigurables + (
599-
'networkxGraph', 'hideLeftBottomSpines',
600-
)
601-
602-
def __init__(self, **keywords):
603-
self.networkxGraph = None
604-
self.hideLeftBottomSpines = True
605-
606-
super().__init__(**keywords)
607-
608-
extm = getExtendedModules()
609-
610-
if 'title' not in keywords:
611-
self.title = 'Network Plot'
612-
613-
elif extm.networkx is not None: # if we have this module
614-
# testing default; temporary
615-
try: # pragma: no cover
616-
g = extm.networkx.Graph()
617-
# g.add_edge('a', 'b',weight=1.0)
618-
# g.add_edge('b', 'c',weight=0.6)
619-
# g.add_edge('c', 'd',weight=0.2)
620-
# g.add_edge('d', 'e',weight=0.6)
621-
self.networkxGraph = g
622-
except NameError:
623-
pass # keep as None
624-
625-
def renderSubplot(self, subplot): # pragma: no cover
626-
# figure size can be set w/ figsize=(5,10)
627-
extm = getExtendedModules()
628-
networkx = extm.networkx
629-
630-
# positions for all nodes
631-
# positions are stored in the networkx graph as a pos attribute
632-
posNodes = {}
633-
posNodeLabels = {}
634-
# returns a data dictionary
635-
for nId, nData in self.networkxGraph.nodes(data=True):
636-
posNodes[nId] = nData['pos']
637-
# shift labels off center of nodes
638-
posNodeLabels[nId] = (nData['pos'][0] + 0.125, nData['pos'][1])
639-
640-
# environLocal.printDebug(['get position', posNodes])
641-
# posNodes = networkx.spring_layout(self.networkxGraph, weighted=True)
642-
# draw nodes
643-
networkx.draw_networkx_nodes(self.networkxGraph, posNodes,
644-
node_size=300, ax=subplot, node_color='#605C7F', alpha=0.5)
645-
646-
for (u, v, d) in self.networkxGraph.edges(data=True):
647-
environLocal.printDebug(['GraphNetworkxGraph', (u, v, d)])
648-
# print(u,v,d)
649-
# adding one at a time to permit individual alpha settings
650-
edgelist = [(u, v)]
651-
networkx.draw_networkx_edges(self.networkxGraph, posNodes, edgelist=edgelist,
652-
width=2, style=d['style'],
653-
edge_color='#666666', alpha=d['weight'], ax=subplot)
654-
655-
# labels
656-
networkx.draw_networkx_labels(self.networkxGraph, posNodeLabels,
657-
font_size=self.labelFontSize,
658-
font_family=self.fontFamily, font_color='#000000',
659-
ax=subplot)
660-
661-
# remove all labels
662-
self.setAxisLabel('y', '')
663-
self.setAxisLabel('x', '')
664-
self.setTicks('y', [])
665-
self.setTicks('x', [])
666-
# turn off grid
667-
self.grid = False
668-
669582

670583
class GraphColorGrid(Graph):
671584
'''
@@ -1848,14 +1761,6 @@ def testGraphVerticalBar(self):
18481761
g.data = data
18491762
g.process()
18501763

1851-
def testGraphNetworkxGraph(self):
1852-
extm = getExtendedModules()
1853-
1854-
if extm.networkx is not None: # pragma: no cover
1855-
b = GraphNetworkxGraph(doneAction=None)
1856-
# b = GraphNetworkxGraph()
1857-
b.process()
1858-
18591764

18601765
if __name__ == '__main__':
18611766
import music21

music21/graph/utilities.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@
3030

3131

3232
ExtendedModules = namedtuple('ExtendedModules',
33-
['matplotlib', 'Axes3D', 'collections', 'patches', 'plt', 'networkx'])
33+
['matplotlib', 'Axes3D', 'collections', 'patches', 'plt'])
3434

3535

3636
def getExtendedModules():
3737
'''
3838
this is done inside a function, so that the slow import of matplotlib is not done
3939
in ``from music21 import *`` unless it's actually needed.
4040
41-
Returns a namedtuple: (matplotlib, Axes3D, collections, patches, plt, networkx)
41+
Returns a namedtuple: (matplotlib, Axes3D, collections, patches, plt)
4242
'''
4343
if 'matplotlib' in _missingImport:
4444
raise GraphException(
@@ -62,13 +62,7 @@ def getExtendedModules():
6262
# from matplotlib.colors import colorConverter
6363
import matplotlib.pyplot as plt # type: ignore
6464

65-
try:
66-
# noinspection PyPackageRequirements
67-
import networkx # type: ignore
68-
except ImportError: # pragma: no cover
69-
networkx = None # use for testing
70-
71-
return ExtendedModules(matplotlib, Axes3D, collections, patches, plt, networkx)
65+
return ExtendedModules(matplotlib, Axes3D, collections, patches, plt)
7266

7367
# ------------------------------------------------------------------------------
7468

music21/ipython21/converters.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def showImageThroughMuseScore(
5656
pngData = base64.b64decode(pngData64)
5757
# noinspection PyTypeChecker
5858
display(Image(data=pngData, retina=True))
59-
return
59+
return None
6060

6161
# hack to make musescore excerpts -- fix with a converter class in MusicXML
6262
# or make a new keyword to ignoreTitles, etc.
@@ -75,7 +75,7 @@ def showImageThroughMuseScore(
7575
multipageWidget=multipageWidget,
7676
**keywords,
7777
)
78-
return
78+
return None
7979

8080
fp = subConverter.write(
8181
obj,
@@ -86,7 +86,7 @@ def showImageThroughMuseScore(
8686
)
8787

8888
if subformats[0] != 'png':
89-
return
89+
return None
9090

9191
last_png = museScore.findLastPNGPath(fp)
9292
last_number, num_digits = museScore.findPNGRange(fp, last_png)
@@ -109,7 +109,7 @@ def showImageThroughMuseScore(
109109
else:
110110
# multi-page png -- use our widget.
111111
# noinspection PyPackageRequirements
112-
from ipywidgets import interact # type: ignore
112+
from ipywidgets import interact # type: ignore # pylint: disable=import-error
113113

114114
@interact(page=(1, last_number))
115115
def page_display(page=1):

music21/metadata/__init__.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@
141141
'properties',
142142
]
143143

144-
from collections import namedtuple
145144
from collections.abc import Iterable
146145
import datetime
147146
import pathlib
@@ -151,6 +150,7 @@
151150

152151
from music21 import base
153152
from music21 import common
153+
from music21.common.types import DocOrder, OffsetQL
154154
from music21 import defaults
155155
from music21 import environment
156156
from music21 import exceptions21
@@ -176,6 +176,13 @@
176176
from music21.metadata import properties
177177
from music21.metadata.properties import PropertyDescription
178178

179+
180+
if t.TYPE_CHECKING:
181+
from music21 import key
182+
from music21 import meter
183+
from music21 import tempo
184+
185+
179186
# -----------------------------------------------------------------------------
180187
environLocal = environment.Environment('metadata')
181188

@@ -2474,8 +2481,14 @@ class RichMetadata(Metadata):
24742481
24752482
>>> richMetadata.additionalRichMetadataAttributes
24762483
('ambitus', 'keySignatureFirst', 'keySignatures', 'noteCount', 'numberOfParts',
2477-
'pitchHighest', 'pitchLowest', 'quarterLength', 'sourcePath', 'tempoFirst',
2484+
'pitchHighest', 'pitchLowest', 'scoreQuarterLength', 'sourcePath', 'tempoFirst',
24782485
'tempos', 'timeSignatureFirst', 'timeSignatures')
2486+
2487+
Changed in v10: renamed `quarterLength` to `scoreQuarterLength`.
2488+
Because RichMetadata is a Music21Object, `quarterLength` is a property that must
2489+
return the length of the RichMetadata object itself and should not have been
2490+
ovewritten
2491+
24792492
'''
24802493

24812494
# CLASS VARIABLES #
@@ -2489,7 +2502,7 @@ class RichMetadata(Metadata):
24892502
'numberOfParts',
24902503
'pitchHighest',
24912504
'pitchLowest',
2492-
'quarterLength',
2505+
'scoreQuarterLength',
24932506
'sourcePath',
24942507
'tempoFirst',
24952508
'tempos',
@@ -2502,18 +2515,18 @@ class RichMetadata(Metadata):
25022515
def __init__(self, **keywords) -> None:
25032516
super().__init__(**keywords)
25042517
self.ambitus: AmbitusShort|None = None
2505-
self.keySignatureFirst = None
2506-
self.keySignatures = []
2507-
self.noteCount = None
2518+
self.keySignatureFirst: key.KeySignature|None = None
2519+
self.keySignatures: list[key.KeySignature] = []
2520+
self.noteCount: int|None = None
25082521
self.numberOfParts = None
25092522
self.pitchHighest: str|None = None
25102523
self.pitchLowest: str|None = None
2511-
self.quarterLength = None
2524+
self.scoreQuarterLength: OffsetQL = 0.0
25122525
self.sourcePath = ''
2513-
self.tempoFirst = None
2514-
self.tempos = []
2515-
self.timeSignatureFirst = None
2516-
self.timeSignatures = []
2526+
self.tempoFirst: tempo.TempoIndication|None = None
2527+
self.tempos: list[tempo.TempoIndication] = []
2528+
self.timeSignatureFirst: meter.TimeSignature|None = None
2529+
self.timeSignatures: list[meter.TimeSignature] = []
25172530

25182531
def _getPluralAttribute(self, attributeName) -> tuple[str, ...]:
25192532
# we have to implement this to add the RichMetadata attributes, since
@@ -2657,7 +2670,7 @@ def update(self, streamObj):
26572670
self.tempoFirst = self.tempos[0]
26582671

26592672
self.noteCount = len(flat.notesAndRests)
2660-
self.quarterLength = flat.highestTime
2673+
self.scoreQuarterLength = flat.highestTime
26612674

26622675
# commenting out temporarily due to memory error
26632676
# with corpus/beethoven/opus132.xml
@@ -2805,7 +2818,7 @@ def _isStandardUniqueName(self, uniqueName: str) -> bool:
28052818

28062819
# -----------------------------------------------------------------------------
28072820
# tests are in test/test_metadata
2808-
_DOC_ORDER: list[type] = [Metadata, RichMetadata, AmbitusShort]
2821+
_DOC_ORDER: DocOrder = [Metadata, RichMetadata, AmbitusShort]
28092822

28102823

28112824
if __name__ == '__main__':

0 commit comments

Comments
 (0)